From: Christian Bauer Date: Mon, 8 Jul 2002 19:19:17 +0000 (+0000) Subject: synced to 1.0 with respect to dummy index repositioning X-Git-Tag: release_1-1-0~90 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?a=commitdiff_plain;h=7b893f734acba558b958244084366f5284984209;p=ginac.git synced to 1.0 with respect to dummy index repositioning --- diff --git a/check/exam_indexed.cpp b/check/exam_indexed.cpp index 90197c08..4d09bdff 100644 --- a/check/exam_indexed.cpp +++ b/check/exam_indexed.cpp @@ -136,8 +136,10 @@ static unsigned epsilon_check(void) // contraction with symmetric tensor is zero result += check_equal_simplify(lorentz_eps(mu, nu, rho, sigma) * indexed(d, sy_symm(), mu_co, nu_co), 0); result += check_equal_simplify(lorentz_eps(mu, nu, rho, sigma) * indexed(d, sy_symm(), nu_co, sigma_co, rho_co), 0); - ex e = lorentz_eps(mu, nu, rho, sigma) * indexed(d, sy_symm(), mu_co, tau); - result += check_equal_simplify(e, e); + result += check_equal_simplify(lorentz_eps(mu, nu, rho, sigma) * indexed(d, mu_co) * indexed(d, nu_co), 0); + result += check_equal_simplify(lorentz_eps(mu_co, nu, rho, sigma) * indexed(d, mu) * indexed(d, nu_co), 0); + ex e = lorentz_eps(mu, nu, rho, sigma) * indexed(d, mu_co) - lorentz_eps(mu_co, nu, rho, sigma) * indexed(d, mu); + result += check_equal_simplify(e, 0); // contractions of epsilon tensors result += check_equal_simplify(lorentz_eps(mu, nu, rho, sigma) * lorentz_eps(mu_co, nu_co, rho_co, sigma_co), -24); @@ -153,7 +155,7 @@ static unsigned symmetry_check(void) unsigned result = 0; idx i(symbol("i"), 3), j(symbol("j"), 3), k(symbol("k"), 3), l(symbol("l"), 3); - symbol A("A"), B("B"); + symbol A("A"), B("B"), C("C"); ex e; result += check_equal(indexed(A, sy_symm(), i, j), indexed(A, sy_symm(), j, i)); @@ -185,6 +187,9 @@ static unsigned symmetry_check(void) result += check_equal(symmetrize(e), 0); result += check_equal(antisymmetrize(e), e); + e = (indexed(A, sy_anti(), i, j, k, l) * (indexed(B, j) * indexed(C, k) + indexed(B, k) * indexed(C, j)) + indexed(B, i, l)).expand(); + result += check_equal_simplify(e, indexed(B, i, l)); + return result; } @@ -305,7 +310,7 @@ static unsigned spinor_check(void) unsigned result = 0; symbol psi("psi"); - spinidx A(symbol("A"), 2), B(symbol("B"), 2), C(symbol("C"), 2); + spinidx A(symbol("A")), B(symbol("B")), C(symbol("C")), D(symbol("D")); ex A_co = A.toggle_variance(), B_co = B.toggle_variance(); ex e; @@ -327,13 +332,15 @@ static unsigned spinor_check(void) result += check_equal_simplify(e, -indexed(psi, A_co)); e = spinor_metric(A_co, B_co) * indexed(psi, A); result += check_equal_simplify(e, indexed(psi, B_co)); + e = spinor_metric(D, A) * spinor_metric(A_co, B_co) * spinor_metric(B, C) - spinor_metric(D, A_co) * spinor_metric(A, B_co) * spinor_metric(B, C); + result += check_equal_simplify(e, 0); return result; } static unsigned dummy_check(void) { - // check dummy index renaming + // check dummy index renaming/repositioning unsigned result = 0; @@ -352,6 +359,15 @@ static unsigned dummy_check(void) e = indexed(p, mu, mu.toggle_variance()) - indexed(p, nu, nu.toggle_variance()); result += check_equal_simplify(e, 0); + e = indexed(p, mu.toggle_variance(), nu, mu) * indexed(q, i) + - indexed(p, mu, nu, mu.toggle_variance()) * indexed(q, i); + result += check_equal_simplify(e, 0); + + e = indexed(p, mu, mu.toggle_variance()) - indexed(p, nu.toggle_variance(), nu); + result += check_equal_simplify(e, 0); + e = indexed(p, mu.toggle_variance(), mu) - indexed(p, nu, nu.toggle_variance()); + result += check_equal_simplify(e, 0); + return result; } diff --git a/ginac/indexed.cpp b/ginac/indexed.cpp index 12561cf1..d1e9efaa 100644 --- a/ginac/indexed.cpp +++ b/ginac/indexed.cpp @@ -29,6 +29,7 @@ #include "mul.h" #include "ncmul.h" #include "power.h" +#include "relational.h" #include "symmetry.h" #include "operators.h" #include "lst.h" @@ -491,7 +492,7 @@ exvector power::get_free_indices(void) const /** Rename dummy indices in an expression. * - * @param e Expression to be worked on + * @param e Expression to work on * @param local_dummy_indices The set of dummy indices that appear in the * expression "e" * @param global_dummy_indices The set of dummy indices that have appeared @@ -552,6 +553,80 @@ static ex rename_dummy_indices(const ex & e, exvector & global_dummy_indices, ex } } +/** Given a set of indices, extract those of class varidx. */ +static void find_variant_indices(const exvector & v, exvector & variant_indices) +{ + exvector::const_iterator it1, itend; + for (it1 = v.begin(), itend = v.end(); it1 != itend; ++it1) { + if (is_exactly_a(*it1)) + variant_indices.push_back(*it1); + } +} + +/** Raise/lower dummy indices in a single indexed objects to canonicalize their + * variance. + * + * @param e Object to work on + * @param variant_dummy_indices The set of indices that might need repositioning (will be changed by this function) + * @param moved_indices The set of indices that have been repositioned (will be changed by this function) + * @return true if 'e' was changed */ +bool reposition_dummy_indices(ex & e, exvector & variant_dummy_indices, exvector & moved_indices) +{ + bool something_changed = false; + + // If a dummy index is encountered for the first time in the + // product, pull it up, otherwise, pull it down + exvector::const_iterator it2, it2start, it2end; + for (it2start = ex_to(e).seq.begin(), it2end = ex_to(e).seq.end(), it2 = it2start + 1; it2 != it2end; ++it2) { + if (!is_exactly_a(*it2)) + continue; + + exvector::iterator vit, vitend; + for (vit = variant_dummy_indices.begin(), vitend = variant_dummy_indices.end(); vit != vitend; ++vit) { + if (it2->op(0).is_equal(vit->op(0))) { + if (ex_to(*it2).is_covariant()) { + e = e.subs(lst( + *it2 == ex_to(*it2).toggle_variance(), + ex_to(*it2).toggle_variance() == *it2 + )); + something_changed = true; + it2 = ex_to(e).seq.begin() + (it2 - it2start); + it2start = ex_to(e).seq.begin(); + it2end = ex_to(e).seq.end(); + } + moved_indices.push_back(*vit); + variant_dummy_indices.erase(vit); + goto next_index; + } + } + + for (vit = moved_indices.begin(), vitend = moved_indices.end(); vit != vitend; ++vit) { + if (it2->op(0).is_equal(vit->op(0))) { + if (ex_to(*it2).is_contravariant()) { + e = e.subs(*it2 == ex_to(*it2).toggle_variance()); + something_changed = true; + it2 = ex_to(e).seq.begin() + (it2 - it2start); + it2start = ex_to(e).seq.begin(); + it2end = ex_to(e).seq.end(); + } + goto next_index; + } + } + +next_index: ; + } + + return something_changed; +} + +/* Ordering that only compares the base expressions of indexed objects. */ +struct ex_base_is_less : public std::binary_function { + bool operator() (const ex &lh, const ex &rh) const + { + return (is_a(lh) ? lh.op(0) : lh).compare(is_a(rh) ? rh.op(0) : rh) < 0; + } +}; + /** Simplify product of indexed expressions (commutative, noncommutative and * simple squares), return list of free indices. */ ex simplify_indexed_product(const ex & e, exvector & free_indices, exvector & dummy_indices, const scalar_products & sp) @@ -669,8 +744,7 @@ contraction_done: // Find free indices (concatenate them all and call find_free_and_dummy()) // and all dummy indices that appear exvector un, individual_dummy_indices; - it1 = v.begin(); itend = v.end(); - while (it1 != itend) { + for (it1 = v.begin(), itend = v.end(); it1 != itend; ++it1) { exvector free_indices_of_factor; if (is_a(*it1)) { exvector dummy_indices_of_factor; @@ -679,12 +753,35 @@ contraction_done: } else free_indices_of_factor = it1->get_free_indices(); un.insert(un.end(), free_indices_of_factor.begin(), free_indices_of_factor.end()); - it1++; } exvector local_dummy_indices; find_free_and_dummy(un, free_indices, local_dummy_indices); local_dummy_indices.insert(local_dummy_indices.end(), individual_dummy_indices.begin(), individual_dummy_indices.end()); + // Filter out the dummy indices with variance + exvector variant_dummy_indices; + find_variant_indices(local_dummy_indices, variant_dummy_indices); + + // Any indices with variance present at all? + if (!variant_dummy_indices.empty()) { + + // Yes, bring the product into a canonical order that only depends on + // the base expressions of indexed objects + if (!non_commutative) + std::sort(v.begin(), v.end(), ex_base_is_less()); + + exvector moved_indices; + + // Iterate over all indexed objects in the product + for (it1 = v.begin(), itend = v.end(); it1 != itend; ++it1) { + if (!is_a(*it1)) + continue; + + if (reposition_dummy_indices(*it1, variant_dummy_indices, moved_indices)) + something_changed = true; + } + } + ex r; if (something_changed) r = non_commutative ? ex(ncmul(v, true)) : ex(mul(v)); @@ -722,11 +819,27 @@ ex simplify_indexed(const ex & e, exvector & free_indices, exvector & dummy_indi ex e_expanded = e.expand(); // Simplification of single indexed object: just find the free indices - // and perform dummy index renaming + // and perform dummy index renaming/repositioning if (is_a(e_expanded)) { + + // Find the dummy indices const indexed &i = ex_to(e_expanded); exvector local_dummy_indices; find_free_and_dummy(i.seq.begin() + 1, i.seq.end(), free_indices, local_dummy_indices); + + // Filter out the dummy indices with variance + exvector variant_dummy_indices; + find_variant_indices(local_dummy_indices, variant_dummy_indices); + + // Any indices with variance present at all? + if (!variant_dummy_indices.empty()) { + + // Yes, reposition them + exvector moved_indices; + reposition_dummy_indices(e_expanded, variant_dummy_indices, moved_indices); + } + + // Rename the dummy indices return rename_dummy_indices(e_expanded, dummy_indices, local_dummy_indices); } @@ -756,6 +869,27 @@ ex simplify_indexed(const ex & e, exvector & free_indices, exvector & dummy_indi } } + if (sum.is_zero()) { + free_indices.clear(); + return sum; + } + + // Symmetrizing over the dummy indices may cancel terms + int num_terms_orig = (is_a(sum) ? sum.nops() : 1); + if (num_terms_orig > 1 && dummy_indices.size() >= 2) { + lst dummy_syms; + for (int i=0; i(sum_symm) ? sum_symm.nops() : 1); + if (num_terms < num_terms_orig) + return sum_symm; + } + return sum; }