1 
2 #include "algorithms/einsteinify.hh"
3 
4 using namespace cadabra;
5 
einsteinify(const Kernel & k,Ex & e,Ex & m)6 einsteinify::einsteinify(const Kernel& k, Ex& e, Ex& m)
7 	: Algorithm(k, e), metric(m)
8 	{
9 	}
10 
can_apply(iterator it)11 bool einsteinify::can_apply(iterator it)
12 	{
13 	if(*it->name=="\\prod") return true;
14 	return false;
15 	}
16 
apply(iterator & it)17 Algorithm::result_t einsteinify::apply(iterator& it)
18 	{
19 	result_t res=result_t::l_no_action;
20 
21 	bool insert_metric=false;
22 	if(metric.begin()!=metric.end())
23 		if(*metric.begin()->name!="")
24 			insert_metric=true;
25 
26 	index_map_t ind_free, ind_dummy;
27 	classify_indices(it, ind_free, ind_dummy);
28 	index_map_t::iterator dit=ind_free.begin();
29 	index_map_t::iterator prev=ind_free.end();
30 	dit=ind_dummy.begin();
31 	prev=dit;
32 	++dit;
33 	while(dit!=ind_dummy.end()) {
34 		if(tree_exact_equal(&kernel.properties, (*dit).first, (*prev).first)) {
35 			if(insert_metric) { // put indices down and insert an inverse metric
36 				(*dit).second->fl.parent_rel=str_node::p_sub;
37 				(*prev).second->fl.parent_rel=str_node::p_sub;
38 				iterator invmet=tr.append_child(it,str_node(metric.begin()->name));
39 
40 				// get a new dummy index
41 				const Indices *dums=kernel.properties.get<Indices>(dit->second, true);
42 				assert(dums);
43 				Ex dum=get_dummy(dums, it);
44 
45 				// relink the indices
46 				iterator tmpit=tr.append_child(invmet, (*prev).second);
47 				tmpit->fl.bracket=str_node::b_none;
48 				tmpit->fl.parent_rel=str_node::p_super;
49 				tmpit=tr.append_child(invmet, dum.begin());
50 				tmpit->fl.bracket=str_node::b_none;
51 				tmpit->fl.parent_rel=str_node::p_super;
52 				tr.replace_index((*dit).second,dum.begin())->fl.parent_rel=str_node::p_sub;
53 
54 				res=result_t::l_applied;
55 				}
56 			else {   // raise one index
57 				if((*dit).second->fl.parent_rel==(*prev).second->fl.parent_rel) {
58 					if((*dit).second->fl.parent_rel==str_node::p_super)
59 						(*prev).second->fl.parent_rel=str_node::p_sub;
60 					else
61 						(*prev).second->fl.parent_rel=str_node::p_super;
62 					}
63 
64 				res=result_t::l_applied;
65 				}
66 			}
67 		prev=dit;
68 		++dit;
69 		}
70 	return res;
71 	}
72 
73