Dear All, I am sending once more patch to clifford.cpp. Now it closes all bugs which I was aware of in clifford_to_lst(). It also add some more flexibility to parameters of clifford_moebius_map(). I think that it will be nice if clifford_to_lst() can handle integrals and power series as well, but this requires some more includes to clifford.cpp. If there is no objection against it please uncomment this line in the patch: if (is_a<add>(e) || is_a<lst>(e) // || is_a<pseries>(e) || is_a<integral>(e) (and add includes by hands). I also finally wrote an addition to tutorial. This is my first experience with Texinfo, please feel free to edit it as you wish. Best wishes, Vladimir -- Vladimir V. Kisil email: kisilv@maths.leeds.ac.uk -- www: http://maths.leeds.ac.uk/~kisilv/ Index: doc/tutorial/ginac.texi =================================================================== RCS file: /home/cvs/GiNaC/doc/tutorial/ginac.texi,v retrieving revision 1.156 diff -r1.156 ginac.texi 2985a2986,2990
Clifford algebras are supported in two flavours: Dirac gamma matrices (more physical) and generic Clifford algebras (more mathematical).
2987,2990c2992,2997 < Clifford algebra elements (also called Dirac gamma matrices, although GiNaC < doesn't treat them as matrices) are designated as @samp{gamma~mu} and satisfy < @samp{gamma~mu*gamma~nu + gamma~nu*gamma~mu = 2*eta~mu~nu} where @samp{eta~mu~nu} < is the Minkowski metric tensor. Dirac gammas are constructed by the function ---
@subsubsection Dirac gamma matrices Dirac gamma matrices (note that GiNaC doesn't treat them as matrices) are designated as @samp{gamma~mu} and satisfy @samp{gamma~mu*gamma~nu + gamma~nu*gamma~mu = 2*eta~mu~nu} where @samp{eta~mu~nu} is the Minkowski metric tensor. Dirac gammas are constructed by the function 3161a3169,3321
@cindex @code{clifford_unit()} @subsubsection A generic Clifford algebra
A generic Clifford algebra, i.e. @math{2^n} dimensional algebra with generators @samp{e~k} satisfying the identities @samp{e~i e~j+e~j e~i = B(i, j)} for some symmetric matrix (@code{metric}) @math{B(i, j)}. Such generators are created by the function
@example ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl = 0); @end example
where @code{mu} should be @code{varidx} class object indexing the generators, @code{metr} defines the metric @math{B(i, j)} and can be represented by square @code{matrix}, @code{tensormetric} or @code{indexed} class object, optional parameter @code{rl} allows to distinguish different Clifford algebras (which will commute each other). Note that the call @code{clifford_unit(mu, minkmetric())} creates something very close to @code{dirac_gamma(mu)}. The method @code{clifford::get_metric()} returns metric defining this Clifford number.
Individual generators of a Clifford algebra can be accessed in several ways. For example
@example @{ ... varidx nu(symbol(``nu''), 3); matrix M(3, 3) = 1, 0, 0, 0, -1, 0, 0, 0, 0; ex e = clifford_unit(nu, M); ex e0 = e.subs(nu == 0); ex e1 = e.subs(nu == 1); ex e2 = e.subs(nu == 2); ... @} @end example
will produce three generators of a Clifford algebra with properties @code{pow(e0, 2) = 1}, @code{pow(e1, 2) = -1} and @code{pow(e2, 2) = 0}.
@cindex @code{lst_to_clifford()} A similar effect can be achieved from the function
@example ex lst_to_clifford(const ex & v, const ex & mu, const ex & metr, unsigned char rl = 0); @end example
which converts a list or vector @code{v}@samp{ = (v~0, v~1, ..., v~n)} into the Clifford number @samp{v~0 e.0+v~1 e.1+... + v~n e.n} with @samp{e.k} being created by @code{clifford_unit(mu, metr, rl)}. The previous code may be rewritten with help of @code{lst_to_clifford()} as follows
@example @{ ... varidx nu(symbol(``nu''), 3); matrix M(3, 3) = 1, 0, 0, 0, -1, 0, 0, 0, 0; ex e0 = lst_to_clifford(lst(1, 0, 0), nu, M); ex e1 = lst_to_clifford(lst(0, 1, 0), nu, M); ex e2 = lst_to_clifford(lst(0, 0, 1), nu, M); ... @} @end example
@cindex @code{clifford_to_lst()} There is the inverse function
@example lst clifford_to_lst(const ex & e, const ex & c, bool algebraic = true); @end example
which took an expression @code{e} and tries to find such a list @code{v}@samp{ = (v~0, v~1, ..., v~n)} that @samp{e = v~0c.0 + v~1c.1 + ... + v~nc.n} with respect to given Clifford units @code{c} and none of @samp{v~k} contains the Clifford units @code{c} (of course, this may be impossible). This function can use an @code{algebraic} method (default) or a symbolic one. In @code{algebraic} method @samp{v~k} are calculated as @samp{(e c.k + c.k e)/pow(c.k, 2)}. If @samp{pow(c.k, 2) = 0} for some @samp{k} then the method will be automatically changed to symbolic. The same effect is obtained by the assignment (@code{algebraic = false}) in the procedure call.
@cindex @code{clifford_prime()} @cindex @code{clifford_star()} @cindex @code{clifford_bar()} There are several functions for (anti-)automorphisms of Clifford algebras:
@example ex clifford_prime(const ex & e) inline ex clifford_star(const ex & e) @{ return e.conjugate(); @} inline ex clifford_bar(const ex & e) @{ return clifford_prime(e.conjugate()); @} @end example
The automorphism of a Clifford algebra @code{clifford_prime()} simply changes signs of all Clifford units in the expression. The reversion of a Clifford algebra @code{clifford_star()} coincides with @code{conjugate()} method and effectively reverses the order of Clifford units in any product. Finally the main anti-automorphism of a Clifford algebra @code{clifford_bar()} is the composition of two previous, i.e. makes the reversion and changes signs of all Clifford units in a product. Names for this functions corresponds to notations @math{e'}, @math{e^*} and @math{\bar{e}} used in Clifford algebra textbooks.
@cindex @code{clifford_norm()} The function
@example ex clifford_norm(const ex & e); @end example
@cindex @code{clifford_inverse()} calculates the norm of Clifford number from the expression @math{||e||^2 = e\bar{e}}. The inverse of a Clifford expression is returned by the function
@example ex clifford_inverse(const ex & e); @end example
which calculates it as @math{e^{-1} = e/||e||^2}. If @math{||e|| = 0} then an exception is raised.
@cindex @code{remove_dirac_ONE()} If a Clifford number happens to be a factor of @code{dirac_ONE()} then we can convert it to a ``real'' (non-Clifford) expression by the function
@example ex remove_dirac_ONE(const ex & e); @end example
@cindex @code{canonicalize_clifford()} The function @code{canonicalize_clifford()} works for a generic Clifford algebra in a similar way as for Dirac gammas.
The last provided function is
@cindex @code{clifford_moebius_map()} @example ex clifford_moebius_map(const ex & a, const ex & b, const ex & c, const ex & d, const ex & v, const ex & G); @end example
It takes a list or vector @code{v} and makes the Moebius (conformal or linear-fractional) transformation @samp{v -> (av+b)/(cv+d)} defined by the matrix @samp{[[a, b], [c, d]]}. The last parameter @code{G} define the metric of the surrounding (pseudo-)Euclidean space. The returned value of this function is a list of components of the resulting vector. Index: ginac/clifford.cpp =================================================================== RCS file: /home/cvs/GiNaC/ginac/clifford.cpp,v retrieving revision 1.80 diff -r1.80 clifford.cpp 1080a1081 int ival = ex_to<numeric>(ex_to<varidx>(c.op(1)).get_value()).to_int(); 1082c1083,1084 < if (is_a<add>(e))
if (is_a<add>(e) || is_a<lst>(e) // || is_a<pseries>(e) || is_a<integral>(e) || is_a<matrix>(e)) 1086d1087 < int ival = ex_to<numeric>(ex_to<varidx>(c.op(1)).get_value()).to_int(); 1095a1097,1100 bool same_value_index, found_dummy; same_value_index = ( ex_to<varidx>(e.op(ind).op(1)).is_numeric() && (ival == ex_to<numeric>(ex_to<varidx>(e.op(ind).op(1)).get_value()).to_int()) ); found_dummy = same_value_index; 1097,1105c1102,1103 < if (j != ind) { < exvector ind_vec = ex_to<indexed>(e.op(j)).get_dummy_indices(ex_to<indexed>(e.op(ind))); < if (ind_vec.size() > 0) { < exvector::const_iterator it = ind_vec.begin(), itend = ind_vec.end(); < while (it != itend) { < S = S * e.op(j).subs(lst(ex_to<varidx>(*it) == ival, ex_to<varidx>(*it).toggle_variance() == ival), subs_options::no_pattern); < it++; < } < } else
if (j != ind) if (same_value_index)
1107,1108c1105,1117 < } < return S; ---
else { exvector ind_vec = ex_to<indexed>(e.op(j)).get_dummy_indices(ex_to<indexed>(e.op(ind))); if (ind_vec.size() > 0) { found_dummy = true; exvector::const_iterator it = ind_vec.begin(), itend = ind_vec.end(); while (it != itend) { S = S * e.op(j).subs(lst(ex_to<varidx>(*it) == ival, ex_to<varidx>(*it).toggle_variance() == ival), subs_options::no_pattern); it++; } } else S = S * e.op(j); } return (found_dummy? S : 0);
1113c1122,1128 < else ---
else if (is_a<clifford>(e)) if ( ex_to<varidx>(e.op(1)).is_numeric() && (ival != ex_to<numeric>(ex_to<varidx>(e.op(1)).get_value()).to_int()) ) return 0; else return 1; else 1115d1129 < 1150c1164,1166 < D = ex_to<varidx>(G.op(1));
D = ex_to<varidx>(G.op(1)).get_dim(); else if (is_a<matrix>(G)) D = ex_to<matrix>(G).rows();
1152c1168 < throw(std::invalid_argument("metric should be an indexed object")); ---
throw(std::invalid_argument("metric should be an indexed object or matrix"));
1154c1170 < varidx mu ((new symbol)->setflag(status_flags::dynallocated), ex_to<varidx>(D).get_dim()); ---
varidx mu ((new symbol)->setflag(status_flags::dynallocated), D); 1157a1174
participants (1)
-
Vladimir Kisil