X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fclifford.cpp;h=b337cd70c6c848490cba467236eac6c8bc86f487;hp=b2e56224e11ee9518ccfe87fdffea1968686591c;hb=1431a02f0f4a6acacce20282a1431bdf0097b482;hpb=ba0b56c5ac76274c5d748eaa29fbd83cb1d4fb9e diff --git a/ginac/clifford.cpp b/ginac/clifford.cpp index b2e56224..b337cd70 100644 --- a/ginac/clifford.cpp +++ b/ginac/clifford.cpp @@ -3,7 +3,7 @@ * Implementation of GiNaC's clifford algebra (Dirac gamma) objects. */ /* - * GiNaC Copyright (C) 1999-2004 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2005 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -155,7 +155,7 @@ DEFAULT_ARCHIVING(diracgammaR) ex clifford::get_metric(const ex & i, const ex & j) const { - return indexed(metric, symmetric2(), i, j); + return indexed(metric, i, j); } bool clifford::same_metric(const ex & other) const @@ -213,8 +213,10 @@ void clifford::do_print_latex(const print_latex & c, unsigned level) const c.s << "{"; seq[0].print(c, level); c.s << "\\hspace{-1.0ex}/}"; - } else + } else { + c.s << "\\clifford[" << int(representation_label) << "]"; this->print_dispatch(c, level); + } } DEFAULT_COMPARE(diracone) @@ -224,7 +226,7 @@ DEFAULT_COMPARE(diracgamma5) DEFAULT_COMPARE(diracgammaL) DEFAULT_COMPARE(diracgammaR) -DEFAULT_PRINT_LATEX(diracone, "ONE", "\\mathbb{1}") +DEFAULT_PRINT_LATEX(diracone, "ONE", "\\mathbf{1}") DEFAULT_PRINT_LATEX(cliffordunit, "e", "e") DEFAULT_PRINT_LATEX(diracgamma, "gamma", "\\gamma") DEFAULT_PRINT_LATEX(diracgamma5, "gamma5", "{\\gamma^5}") @@ -402,7 +404,7 @@ bool cliffordunit::contract_with(exvector::iterator self, exvector::iterator oth // Find if a previous contraction produces the square of self int prev_square = find_same_metric(v, self[0]); - varidx d((new symbol)->setflag(status_flags::dynallocated), ex_to(ex_to(self->op(1)).get_dim())); + varidx d((new symbol)->setflag(status_flags::dynallocated), ex_to(self->op(1)).get_dim()); ex squared_metric = unit.get_metric(self->op(1), d) * unit.get_metric(d.toggle_variance(), other->op(1)); // e~mu e.mu = Tr ONE @@ -677,7 +679,12 @@ ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl) if (!is_a(mu)) throw(std::invalid_argument("index of Clifford unit must be of type varidx")); - return clifford(unit, mu, metr, rl); + if (is_a(metr)) + return clifford(unit, mu, metr.op(0), rl); + else if(is_a(metr) || is_a(metr)) + return clifford(unit, mu, metr, rl); + else + throw(std::invalid_argument("metric for Clifford unit must be of type indexed, tensormetric or matrix")); } ex dirac_gamma(const ex & mu, unsigned char rl) @@ -932,69 +939,76 @@ ex dirac_trace(const ex & e, unsigned char rl, const ex & trONE) } -ex canonicalize_clifford(const ex & e) +ex canonicalize_clifford(const ex & e_) { - // Scan for any ncmul objects - exmap srl; - ex aux = e.to_rational(srl); - for (exmap::iterator i = srl.begin(); i != srl.end(); ++i) { - - ex lhs = i->first; - ex rhs = i->second; - - if (is_exactly_a(rhs) - && rhs.return_type() == return_types::noncommutative - && is_clifford_tinfo(rhs.return_type_tinfo())) { - - // Expand product, if necessary - ex rhs_expanded = rhs.expand(); - if (!is_a(rhs_expanded)) { - i->second = canonicalize_clifford(rhs_expanded); - continue; - - } else if (!is_a(rhs.op(0))) - continue; - - exvector v; - v.reserve(rhs.nops()); - for (size_t j=0; j(it->op(0)) || is_a(it->op(0)) || is_a(it->op(0))) - ++it; - while (it != next_to_last) { - if (it[0].compare(it[1]) > 0) { - ex save0 = it[0], save1 = it[1]; - ex b1, i1, b2, i2; - base_and_index(it[0], b1, i1); - base_and_index(it[1], b2, i2); - it[0] = (ex_to(save0).get_metric(i1, i2) * b1 * b2).simplify_indexed(); - it[1] = v.size() == 2 ? _ex2 * dirac_ONE(ex_to(it[1]).get_representation_label()) : _ex2; - ex sum = ncmul(v); - it[0] = save1; - it[1] = save0; - sum -= ncmul(v, true); - i->second = canonicalize_clifford(sum); - goto next_sym; + pointer_to_map_function fcn(canonicalize_clifford); + + if (is_a(e_) // || is_a(e) || is_a(e) + || is_a(e_)) { + return e_.map(fcn); + } else { + ex e=simplify_indexed(e_); + // Scan for any ncmul objects + exmap srl; + ex aux = e.to_rational(srl); + for (exmap::iterator i = srl.begin(); i != srl.end(); ++i) { + + ex lhs = i->first; + ex rhs = i->second; + + if (is_exactly_a(rhs) + && rhs.return_type() == return_types::noncommutative + && is_clifford_tinfo(rhs.return_type_tinfo())) { + + // Expand product, if necessary + ex rhs_expanded = rhs.expand(); + if (!is_a(rhs_expanded)) { + i->second = canonicalize_clifford(rhs_expanded); + continue; + + } else if (!is_a(rhs.op(0))) + continue; + + exvector v; + v.reserve(rhs.nops()); + for (size_t j=0; j(it->op(0)) || is_a(it->op(0)) || is_a(it->op(0))) + ++it; + while (it != next_to_last) { + if (it[0].compare(it[1]) > 0) { + ex save0 = it[0], save1 = it[1]; + ex b1, i1, b2, i2; + base_and_index(it[0], b1, i1); + base_and_index(it[1], b2, i2); + it[0] = (ex_to(save0).get_metric(i1, i2) * b1 * b2).simplify_indexed(); + it[1] = v.size() == 2 ? _ex2 * dirac_ONE(ex_to(it[1]).get_representation_label()) : _ex2; + ex sum = ncmul(v); + it[0] = save1; + it[1] = save0; + sum -= ncmul(v, true); + i->second = canonicalize_clifford(sum); + goto next_sym; + } + ++it; } - ++it; - } next_sym: ; + } } + return aux.subs(srl, subs_options::no_pattern).simplify_indexed(); } - return aux.subs(srl, subs_options::no_pattern).simplify_indexed(); } -ex clifford_prime(const ex &e) +ex clifford_prime(const ex & e) { pointer_to_map_function fcn(clifford_prime); if (is_a(e) && is_a(e.op(0))) { return -e; - } else if (is_a(e)) { - return e.map(fcn); - } else if (is_a(e)) { + } else if (is_a(e) || is_a(e) || is_a(e) //|| is_a(e) || is_a(e) + || is_a(e) || is_a(e)) { return e.map(fcn); } else if (is_a(e)) { return pow(clifford_prime(e.op(0)), e.op(1)); @@ -1002,68 +1016,195 @@ ex clifford_prime(const ex &e) return e; } -ex delete_ONE(const ex &e) +ex remove_dirac_ONE(const ex & e, unsigned char rl) { - pointer_to_map_function fcn(delete_ONE); - if (is_a(e) && is_a(e.op(0))) { - return 1; - } else if (is_a(e)) { - return e.map(fcn); - } else if (is_a(e)) { - return e.map(fcn); - } else if (is_a(e)) { + pointer_to_map_function_1arg fcn(remove_dirac_ONE, rl); + if (is_a(e) && ex_to(e).get_representation_label() >= rl) { + if (is_a(e.op(0))) + return 1; + else + throw(std::invalid_argument("Expression is a non-scalar Clifford number!")); + } else if (is_a(e) || is_a(e) || is_a(e) // || is_a(e) || is_a(e) + || is_a(e) || is_a(e)) { return e.map(fcn); } else if (is_a(e)) { - return pow(delete_ONE(e.op(0)), e.op(1)); + return pow(remove_dirac_ONE(e.op(0)), e.op(1)); } else return e; } -ex clifford_norm(const ex &e) +ex clifford_norm(const ex & e) { - return sqrt(delete_ONE((e * clifford_bar(e)).simplify_indexed())); + return sqrt(remove_dirac_ONE(canonicalize_clifford(e * clifford_bar(e)).simplify_indexed())); } -ex clifford_inverse(const ex &e) +ex clifford_inverse(const ex & e) { ex norm = clifford_norm(e); if (!norm.is_zero()) return clifford_bar(e) / pow(norm, 2); + else + throw(std::invalid_argument("Cannot find inverse of Clifford number with zero norm!")); } ex lst_to_clifford(const ex & v, const ex & mu, const ex & metr, unsigned char rl) { - unsigned min, max; if (!ex_to(mu).is_dim_numeric()) throw(std::invalid_argument("Index should have a numeric dimension")); - unsigned dim = (ex_to(ex_to(mu).get_dim())).to_int(); - ex c = clifford_unit(mu, metr, rl); + ex e = clifford_unit(mu, metr, rl); + return lst_to_clifford(v, e); +} - if (is_a(v)) { - if (ex_to(v).cols() > ex_to(v).rows()) { - min = ex_to(v).rows(); - max = ex_to(v).cols(); - } else { - min = ex_to(v).cols(); - max = ex_to(v).rows(); - } - if (min == 1) { - if (dim == max) - if (is_a(mu)) // need to swap variance - return indexed(v, ex_to(mu).toggle_variance()) * c; +ex lst_to_clifford(const ex & v, const ex & e) { + unsigned min, max; + + if (is_a(e)) { + varidx mu = ex_to(e.op(1)); + unsigned dim = (ex_to(mu.get_dim())).to_int(); + + if (is_a(v)) { + if (ex_to(v).cols() > ex_to(v).rows()) { + min = ex_to(v).rows(); + max = ex_to(v).cols(); + } else { + min = ex_to(v).cols(); + max = ex_to(v).rows(); + } + if (min == 1) { + if (dim == max) + return indexed(v, ex_to(mu).toggle_variance()) * e; else - return indexed(v, mu) * c; + throw(std::invalid_argument("Dimensions of vector and clifford unit mismatch")); + } else + throw(std::invalid_argument("First argument should be a vector vector")); + } else if (is_a(v)) { + if (dim == ex_to(v).nops()) + return indexed(matrix(dim, 1, ex_to(v)), ex_to(mu).toggle_variance()) * e; else - throw(std::invalid_argument("Dimensions of vector and clifford unit mismatch")); + throw(std::invalid_argument("List length and dimension of clifford unit mismatch")); } else - throw(std::invalid_argument("First argument should be a vector vector")); - } else if (is_a(v)) { - if (dim == ex_to(v).nops()) - return indexed(matrix(dim, 1, ex_to(v)), ex_to(mu).toggle_variance()) * c; - else - throw(std::invalid_argument("List length and dimension of clifford unit mismatch")); + throw(std::invalid_argument("Cannot construct from anything but list or vector")); } else - throw(std::invalid_argument("Cannot construct from anything but list or vector")); + throw(std::invalid_argument("The second argument should be a Clifford unit")); } - + +/** Auxiliary structure to define a function for striping one Clifford unit + * from vectors. Used in clifford_to_lst(). */ +static ex get_clifford_comp(const ex & e, const ex & c) +{ + pointer_to_map_function_1arg fcn(get_clifford_comp, c); + int ival = ex_to(ex_to(c.op(1)).get_value()).to_int(); + + if (is_a(e) || is_a(e) // || is_a(e) || is_a(e) + || is_a(e)) + return e.map(fcn); + else if (is_a(e) || is_a(e)) { + // find a Clifford unit with the same metric, delete it and substitute its index + size_t ind = e.nops() + 1; + for (size_t j = 0; j < e.nops(); j++) + if (is_a(e.op(j)) && ex_to(c).same_metric(e.op(j))) + if (ind > e.nops()) + ind = j; + else + throw(std::invalid_argument("Expression is a Clifford multi-vector")); + if (ind < e.nops()) { + ex S = 1; + bool same_value_index, found_dummy; + same_value_index = ( ex_to(e.op(ind).op(1)).is_numeric() + && (ival == ex_to(ex_to(e.op(ind).op(1)).get_value()).to_int()) ); + found_dummy = same_value_index; + for(size_t j=0; j < e.nops(); j++) + if (j != ind) + if (same_value_index) + S = S * e.op(j); + else { + exvector ind_vec = ex_to(e.op(j)).get_dummy_indices(ex_to(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(*it) == ival, ex_to(*it).toggle_variance() == ival), subs_options::no_pattern); + ++it; + } + } else + S = S * e.op(j); + } + return (found_dummy ? S : 0); + } else + throw(std::invalid_argument("Expression is not a Clifford vector to the given units")); + } else if (e.is_zero()) + return e; + else if (is_a(e) && ex_to(e).same_metric(c)) + if ( ex_to(e.op(1)).is_numeric() && + (ival != ex_to(ex_to(e.op(1)).get_value()).to_int()) ) + return 0; + else + return 1; + else + throw(std::invalid_argument("Expression is not usable as a Clifford vector")); +} + + +lst clifford_to_lst(const ex & e, const ex & c, bool algebraic) +{ + GINAC_ASSERT(is_a(c)); + varidx mu = ex_to(c.op(1)); + if (! mu.is_dim_numeric()) + throw(std::invalid_argument("Index should have a numeric dimension")); + unsigned int D = ex_to(mu.get_dim()).to_int(); + + if (algebraic) // check if algebraic method is applicable + for (unsigned int i = 0; i < D; i++) + if (pow(c.subs(mu == i), 2).is_zero() + or (not is_a(pow(c.subs(mu == i), 2)))) + algebraic = false; + lst V; + if (algebraic) + for (unsigned int i = 0; i < D; i++) + V.append(remove_dirac_ONE( + simplify_indexed(canonicalize_clifford(e * c.subs(mu == i) + c.subs(mu == i) * e)) + / (2*pow(c.subs(mu == i), 2)))); + else { + ex e1 = canonicalize_clifford(e); + for (unsigned int i = 0; i < D; i++) + V.append(get_clifford_comp(e1, c.subs(c.op(1) == i))); + } + return V; +} + + +ex clifford_moebius_map(const ex & a, const ex & b, const ex & c, const ex & d, const ex & v, const ex & G, unsigned char rl) +{ + ex x, D, cu; + + if (! is_a(v) && ! is_a(v)) + throw(std::invalid_argument("parameter v should be either vector or list")); + + if (is_a(G)) { + cu = G; + } else { + if (is_a(G)) + D = ex_to(G.op(1)).get_dim(); + else if (is_a(G)) + D = ex_to(G).rows(); + else throw(std::invalid_argument("metric should be an indexed object, matrix, or a Clifford unit")); + + varidx mu((new symbol)->setflag(status_flags::dynallocated), D); + cu = clifford_unit(mu, G, rl); + } + + x = lst_to_clifford(v, cu); + ex e = simplify_indexed(canonicalize_clifford((a * x + b) * clifford_inverse(c * x + d))); + return clifford_to_lst(e, cu, false); +} + +ex clifford_moebius_map(const ex & M, const ex & v, const ex & G, unsigned char rl) +{ + if (is_a(M)) + return clifford_moebius_map(ex_to(M)(0,0), ex_to(M)(0,1), + ex_to(M)(1,0), ex_to(M)(1,1), v, G, rl); + else + throw(std::invalid_argument("parameter M should be a matrix")); +} + } // namespace GiNaC