#include "algorithms/rename_dummies.hh" #include "properties/Indices.hh" #include "Exceptions.hh" using namespace cadabra; rename_dummies::rename_dummies(const Kernel& k, Ex& tr, std::string d1, std::string d2) : Algorithm(k, tr), dset1(d1), dset2(d2) { } bool rename_dummies::can_apply(iterator st) { // std::cerr << "---" << std::endl << Ex(st); if(*st->name=="\\equals") { // special case: rename all free indices on lhs and rhs. // FIXME: add flag to class to disable this when called as rename_dummies. return true; } if(*st->name!="\\prod") // && *st->name!="\\sum") if(!is_single_term(st)) return false; // if(*st->name=="\\prod" && tr.is_head(st)==false && *(tr.parent(st)->name)=="\\sum") return false; return true; } Algorithm::result_t rename_dummies::apply(iterator& st) { result_t res=result_t::l_no_action; // if(*st->name=="\\equals") { // // } // std::cerr << Ex(st); prod_wrap_single_term(st); // std::cerr << Ex(st); // First do a normal classify_indices both downwards and upwards. // index_map_t ind_free, ind_dummy, ind_free_up, ind_dummy_up; classify_indices(st, ind_free, ind_dummy); classify_indices_up(st, ind_free_up, ind_dummy_up); // print_classify_indices(std::cerr, st); // Run through all indices once more, in order. If an index // occurs in the ind_dummy set, and there is no entry in repmap, // find the index type and get a new dummy. If the index already // occurs in repmap, reuse the new dummy stored there. // typedef std::map repmap_t; repmap_t repmap; index_map_t added_dummies; // If a target set is provided, move any dummies from this set in ind_dummy // to added_dummies to prevent them from being reused if (dset2 != "") { for (const auto& idx : ind_dummy) { const Indices* idxset = kernel.properties.get(idx.second, true); if (idxset->set_name == dset2) added_dummies.insert(idx); } } // Store all indices in a map sorted by the name of the parent. // FIXME: this is not sufficient, you really need to determine which // are common factors in all terms in a sum, and then collect those // to the front of the renaming queue. std::multimap parent_sorted_indices; auto ii = begin_index(st); while(ii!=end_index(st)) { parent_sorted_indices.insert(std::make_pair(tr.parent(iterator(ii))->name, ii)); ++ii; } // If target set is specified, find a handle to the Indices property // with this name. const Indices *ind2=0; if(dset2!="") { auto f2=kernel.properties.pats.begin(); while(f2!=kernel.properties.pats.end()) { ind2 = dynamic_cast(f2->first); if(ind2) { if(ind2->set_name==dset2) break; else ind2=0; } ++f2; } if(ind2==0) throw ConsistencyException("No index set with name `"+dset2+"' known."); } auto iim=parent_sorted_indices.begin(); while(iim!=parent_sorted_indices.end()) { ii = iim->second; if(ind_dummy.find(Ex(ii))!=ind_dummy.end()) { // std::cerr << Ex(ii) << " is dummy " << std::endl; repmap_t::iterator rmi=repmap.find(Ex(ii)); if(rmi==repmap.end()) { Ex other_parent_rel(ii); if(other_parent_rel.begin()->fl.parent_rel==str_node::p_super) other_parent_rel.begin()->fl.parent_rel=str_node::p_sub; else other_parent_rel.begin()->fl.parent_rel=str_node::p_super; rmi=repmap.find(other_parent_rel); } if(rmi==repmap.end()) { const Indices *dums=kernel.properties.get(ii, true); if(!dums) throw ConsistencyException("No index set for index "+*ii->name+" known."); // only rename dummies from dset1. if(dset1=="" || dums->set_name==dset1) { if(dset2!="") dums=ind2; // replace with dummies from set 2 Ex relabel=get_dummy(dums, &ind_free, &ind_free_up, &ind_dummy_up, &added_dummies); repmap.insert(repmap_t::value_type(Ex(ii),relabel)); added_dummies.insert(index_map_t::value_type(relabel, ii)); if(subtree_compare(&kernel.properties, ii, relabel.begin())!=0) { res=result_t::l_applied; tr.replace_index(ii, relabel.begin(), true); } } } else { // std::cerr << "already encountered => " << rmi->second << std::endl; // index_iterator tmp(ii); // ++tmp; tr.replace_index(ii, (*rmi).second.begin(), true); // ii=tmp; } } ++iim; } // Now rename free indices. // if(*st->name=="\\equals") { // auto fit = ind_free.begin(); // while(fit!=ind_free.end()) { // std::cerr << "renaming " << fit->first << std::endl; // Ex relabel=get_dummy(dums, &ind_free, &ind_free_up, &ind_dummy_up, &added_dummies); // ++fit; // } // std::cerr << "----" << std::endl; // } // std::cerr << Ex(st); prod_unwrap_single_term(st); // std::cerr << Ex(st); return res; }