1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
#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<Ex, Ex, tree_exact_less_for_indexmap_obj> 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<Indices>(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<nset_t::iterator, index_iterator, nset_it_less> 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<const Indices *>(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<Indices>(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;
}
|