[GiNaC-devel] Clifford update
Vladimir Kisil
kisilv at maths.leeds.ac.uk
Fri Oct 15 12:55:04 CEST 2004
Dear All,
In extension my yesterday post. I propose to include in
clifford.cpp the second form of clifford_moebius_map() which takes whole
matrix M rather then its four elements as a parameter. The cumulative
patch for ginac.texi, clifford.h and clifford.cpp is included.
Best wishes,
Vladimir
--
Vladimir V. Kisil email: kisilv at maths.leeds.ac.uk
-- www: http://maths.leeds.ac.uk/~kisilv/
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
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.h
===================================================================
RCS file: /home/cvs/GiNaC/ginac/clifford.h,v
retrieving revision 1.52
diff -r1.52 clifford.h
319a320,327
>
> /** The second form of Moebius transformations defined by a 2x2 Clifford matrix M
> * This function took the transformation matrix M as a single entity.
> *
> * @param M the defining matrix
> * @param v Vector to be transformed
> * @param G Metric of the surrounding space */
> ex clifford_moebius_map(const ex & M, const ex & v, const ex & G);
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) && ex_to<clifford>(e).same_metric(c))
> 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);
1158a1175
>
1163a1181,1190
>
> ex clifford_moebius_map(const ex & M, const ex & v, const ex & G)
> {
> if (is_a<matrix>(M))
> return clifford_moebius_map(ex_to<matrix>(M)(0,0), ex_to<matrix>(M)(0,1),
> ex_to<matrix>(M)(1,0), ex_to<matrix>(M)(1,1), v, G);
> else
> throw(std::invalid_argument("parameter M should be a matrix"));
> }
>
More information about the GiNaC-devel
mailing list