]> www.ginac.de Git - ginac.git/blobdiff - ginac/indexed.cpp
- epsilon*epsilon contractions work
[ginac.git] / ginac / indexed.cpp
index 4bbeeee1c181e406546ed5b33bd454f9d54fda8f..bc6aa838303f0a9d1df8af635b8fe1cc878e41d0 100644 (file)
@@ -187,7 +187,7 @@ void indexed::archive(archive_node &n) const
 DEFAULT_UNARCHIVE(indexed)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 void indexed::print(const print_context & c, unsigned level) const
@@ -201,7 +201,6 @@ void indexed::print(const print_context & c, unsigned level) const
                    << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
                    << ", " << seq.size()-1 << " indices"
                    << ", symmetry=" << symtree << std::endl;
-               c.s << std::endl;
                unsigned delta_indent = static_cast<const print_tree &>(c).delta_indent;
                seq[0].print(c, level + delta_indent);
                printindices(c, level + delta_indent);
@@ -535,8 +534,8 @@ exvector power::get_free_indices(void) const
  *    by the function */
 static ex rename_dummy_indices(const ex & e, exvector & global_dummy_indices, exvector & local_dummy_indices)
 {
-       int global_size = global_dummy_indices.size(),
-           local_size = local_dummy_indices.size();
+       unsigned global_size = global_dummy_indices.size(),
+                local_size = local_dummy_indices.size();
 
        // Any local dummy indices at all?
        if (local_size == 0)
@@ -546,6 +545,7 @@ static ex rename_dummy_indices(const ex & e, exvector & global_dummy_indices, ex
 
                // More local indices than we encountered before, add the new ones
                // to the global set
+               int old_global_size = global_size;
                int remaining = local_size - global_size;
                exvector::const_iterator it = local_dummy_indices.begin(), itend = local_dummy_indices.end();
                while (it != itend && remaining > 0) {
@@ -556,26 +556,35 @@ static ex rename_dummy_indices(const ex & e, exvector & global_dummy_indices, ex
                        }
                        it++;
                }
-       }
+               shaker_sort(global_dummy_indices.begin(), global_dummy_indices.end(), ex_is_less(), ex_swap());
 
-       // Replace index symbols in expression
-       GINAC_ASSERT(local_size <= global_size);
-       bool all_equal = true;
-       lst local_syms, global_syms;
-       for (unsigned i=0; i<local_size; i++) {
-               ex loc_sym = local_dummy_indices[i].op(0);
-               ex glob_sym = global_dummy_indices[i].op(0);
-               if (!loc_sym.is_equal(glob_sym)
-                && ex_to<idx>(local_dummy_indices[i]).get_dim().is_equal(ex_to<idx>(global_dummy_indices[i]).get_dim())) {
-                       all_equal = false;
-                       local_syms.append(loc_sym);
-                       global_syms.append(glob_sym);
-               }
+               // If this is the first set of local indices, do nothing
+               if (old_global_size == 0)
+                       return e;
        }
-       if (all_equal)
+       GINAC_ASSERT(local_size <= global_size);
+
+       // Construct lists of index symbols
+       exlist local_syms, global_syms;
+       for (unsigned i=0; i<local_size; i++)
+               local_syms.push_back(local_dummy_indices[i].op(0));
+       shaker_sort(local_syms.begin(), local_syms.end(), ex_is_less(), ex_swap());
+       for (unsigned i=0; i<global_size; i++)
+               global_syms.push_back(global_dummy_indices[i].op(0));
+
+       // Remove common indices
+       exlist local_uniq, global_uniq;
+       set_difference(local_syms.begin(), local_syms.end(), global_syms.begin(), global_syms.end(), std::back_insert_iterator<exlist>(local_uniq), ex_is_less());
+       set_difference(global_syms.begin(), global_syms.end(), local_syms.begin(), local_syms.end(), std::back_insert_iterator<exlist>(global_uniq), ex_is_less());
+
+       // Replace remaining non-common local index symbols by global ones
+       if (local_uniq.empty())
                return e;
-       else
-               return e.subs(local_syms, global_syms);
+       else {
+               while (global_uniq.size() > local_uniq.size())
+                       global_uniq.pop_back();
+               return e.subs(lst(local_uniq), lst(global_uniq));
+       }
 }
 
 /** Simplify product of indexed expressions (commutative, noncommutative and
@@ -596,7 +605,7 @@ ex simplify_indexed_product(const ex & e, exvector & free_indices, exvector & du
                v.push_back(e.op(0));
                v.push_back(e.op(0));
        } else {
-               for (int i=0; i<e.nops(); i++) {
+               for (unsigned i=0; i<e.nops(); i++) {
                        ex f = e.op(i);
                        if (is_ex_exactly_of_type(f, power) && f.op(1).is_equal(_ex2())) {
                                v.push_back(f.op(0));
@@ -604,7 +613,7 @@ ex simplify_indexed_product(const ex & e, exvector & free_indices, exvector & du
                        } else if (is_ex_exactly_of_type(f, ncmul)) {
                                // Noncommutative factor found, split it as well
                                non_commutative = true; // everything becomes noncommutative, ncmul will sort out the commutative factors later
-                               for (int j=0; j<f.nops(); j++)
+                               for (unsigned j=0; j<f.nops(); j++)
                                        v.push_back(f.op(j));
                        } else
                                v.push_back(f);
@@ -645,12 +654,13 @@ try_again:
                        // Check whether the two factors share dummy indices
                        exvector free, dummy;
                        find_free_and_dummy(un, free, dummy);
-                       if (dummy.size() == 0)
+                       unsigned num_dummies = dummy.size();
+                       if (num_dummies == 0)
                                continue;
 
                        // At least one dummy index, is it a defined scalar product?
                        bool contracted = false;
-                       if (free.size() == 0) {
+                       if (free.empty()) {
                                if (sp.is_defined(*it1, *it2)) {
                                        *it1 = sp.evaluate(*it1, *it2);
                                        *it2 = _ex1();
@@ -658,29 +668,6 @@ try_again:
                                }
                        }
 
-                       // Contraction of symmetric with antisymmetric object is zero
-                       if (dummy.size() > 1
-                        && ex_to<symmetry>(ex_to<indexed>(*it1).symtree).has_symmetry()
-                        && ex_to<symmetry>(ex_to<indexed>(*it2).symtree).has_symmetry()) {
-
-                               // Check all pairs of dummy indices
-                               for (unsigned idx1=0; idx1<dummy.size()-1; idx1++) {
-                                       for (unsigned idx2=idx1+1; idx2<dummy.size(); idx2++) {
-
-                                               // Try and swap the index pair and check whether the
-                                               // relative sign changed
-                                               lst subs_lst(dummy[idx1].op(0), dummy[idx2].op(0)), repl_lst(dummy[idx2].op(0), dummy[idx1].op(0));
-                                               ex swapped1 = it1->subs(subs_lst, repl_lst);
-                                               ex swapped2 = it2->subs(subs_lst, repl_lst);
-                                               if (it1->is_equal(swapped1) && it2->is_equal(-swapped2)
-                                                || it1->is_equal(-swapped1) && it2->is_equal(swapped2)) {
-                                                       free_indices.clear();
-                                                       return _ex0();
-                                               }
-                                       }
-                               }
-                       }
-
                        // Try to contract the first one with the second one
                        contracted = it1->op(0).bp->contract_with(it1, it2, v);
                        if (!contracted) {
@@ -739,6 +726,19 @@ contraction_done:
        else
                r = e;
 
+       // The result should be symmetric with respect to exchange of dummy
+       // indices, so if the symmetrization vanishes, the whole expression is
+       // zero. This detects things like eps.i.j.k * p.j * p.k = 0.
+       if (local_dummy_indices.size() >= 2) {
+               lst dummy_syms;
+               for (int i=0; i<local_dummy_indices.size(); i++)
+                       dummy_syms.append(local_dummy_indices[i].op(0));
+               if (r.symmetrize(dummy_syms).is_zero()) {
+                       free_indices.clear();
+                       return _ex0();
+               }
+       }
+
        // Dummy index renaming
        r = rename_dummy_indices(r, dummy_indices, local_dummy_indices);
 
@@ -890,10 +890,12 @@ ex scalar_products::evaluate(const ex & v1, const ex & v2) const
 void scalar_products::debugprint(void) const
 {
        std::cerr << "map size=" << spm.size() << std::endl;
-       for (spmap::const_iterator cit=spm.begin(); cit!=spm.end(); ++cit) {
-               const spmapkey & k = cit->first;
+       spmap::const_iterator i = spm.begin(), end = spm.end();
+       while (i != end) {
+               const spmapkey & k = i->first;
                std::cerr << "item key=(" << k.first << "," << k.second;
-               std::cerr << "), value=" << cit->second << std::endl;
+               std::cerr << "), value=" << i->second << std::endl;
+               ++i;
        }
 }