#include "algorithms/epsilon_to_delta.hh" #include "algorithms/reduce_delta.hh" #include "properties/EpsilonTensor.hh" #include "properties/Metric.hh" using namespace cadabra; epsilon_to_delta::epsilon_to_delta(const Kernel& k, Ex& tr, bool r) : Algorithm(k, tr), reduce(r) { } bool epsilon_to_delta::can_apply(iterator st) { if(*st->name!="\\prod") return false; epsilons.clear(); // Find the two epsilon tensors in the product. std::multimap emap; sibling_iterator it=tr.begin(st); while(it!=tr.end(st)) { const EpsilonTensor *eps=kernel.properties.get(it); if(eps) emap.insert(std::pair(get_index_set_name(begin_index(it)),it)); ++it; } signature=1; std::multimap::iterator eit=emap.begin(); while(epsilons.size()<2 && eit!=emap.end()) { if(emap.count(eit->first)>1) { epsilons.push_back(eit->second); ++eit; epsilons.push_back(eit->second); const EpsilonTensor *eps=kernel.properties.get(eit->second); if(eps->metric.begin()!=eps->metric.end()) { const Metric *met=kernel.properties.get(eps->metric.begin()); if(met) signature=met->signature; } if(eps->krdelta.begin()!=eps->krdelta.end()) repdelta=eps->krdelta; } ++eit; } if(epsilons.size()<2) return false; if(repdelta.begin()==repdelta.end()) return false; else repdelta.erase_children(repdelta.begin()); return true; } Algorithm::result_t epsilon_to_delta::apply(iterator& st) { Ex rep(repdelta); iterator delta=rep.begin(); // std::cerr << Ex(st) << std::endl; sibling_iterator eps1=tr.begin(epsilons[0]); sibling_iterator eps2=tr.begin(epsilons[1]); while(eps1!=tr.end(epsilons[0])) { rep.append_child(delta, *eps1); rep.append_child(delta, *eps2); ++eps1; ++eps2; } // std::cerr << "result: " << rep.begin() << std::endl; multiply(st->multiplier, *epsilons[0]->multiplier); multiply(st->multiplier, *epsilons[1]->multiplier); tr.erase(epsilons[0]); // std::cerr << tr.number_of_children(epsilons[1]) << std::endl; // std::cerr << " -> " << *st->multiplier << " * " << combin::fact(multiplier_t(tr.number_of_children(epsilons[1]))) << std::endl; multiply(st->multiplier, combin::fact(multiplier_t(tr.number_of_children(epsilons[1])))); // std::cerr << "A:" << *st->multiplier << std::endl; multiply(st->multiplier, signature); // std::cerr << "B:" << *st->multiplier << std::endl; iterator gend=tr.replace(epsilons[1], rep.begin()); // std::cerr << "B2:" << *st->multiplier << std::endl; if(reduce) { // std::cerr << "reducing" << std::endl; reduce_delta rg(kernel, tr); if(rg.can_apply(gend)) rg.apply(gend); if(*gend->multiplier==0) { zero(st->multiplier); return result_t::l_applied; } } if(*gend->multiplier!=1) { // std::cerr << "B3:" << *st->multiplier << std::endl; // std::cerr << "B3:" << *gend->multiplier << std::endl; multiply(tr.parent(gend)->multiplier, *gend->multiplier); one(gend->multiplier); // std::cerr << "C:" << *st->multiplier << std::endl; } if(tr.number_of_children(st)==1) { multiply(tr.begin(st)->multiplier, *st->multiplier); tr.flatten(st); st=tr.erase(st); } // std::cerr << Ex(st) << std::endl; return result_t::l_applied; }