Skip to content

Commit df95b16

Browse files
committed
Merge branch 'cbehan-trace_op'
2 parents 97aed2a + fa480cf commit df95b16

File tree

15 files changed

+316
-24
lines changed

15 files changed

+316
-24
lines changed

core/Algorithm.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
3434
#include "properties/Indices.hh"
3535
#include "properties/Coordinate.hh"
3636
#include "properties/Symbol.hh"
37+
#include "properties/Trace.hh"
3738
#include "properties/DependsBase.hh"
3839

3940
#include <sstream>
@@ -319,7 +320,8 @@ void Algorithm::propagate_zeroes(post_order_iterator& it, const iterator& topnod
319320
return;
320321

321322
const Derivative *der=kernel.properties.get<Derivative>(walk);
322-
if(*walk->name=="\\prod" || der) {
323+
const Trace *trace=kernel.properties.get<Trace>(walk);
324+
if(*walk->name=="\\prod" || der || trace) {
323325
if(der && it->is_index()) return;
324326
walk->multiplier=rat_set.insert(0).first;
325327
it=walk;

core/Compare.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,23 @@ namespace cadabra {
11581158
return sign;
11591159
}
11601160

1161+
int Ex_comparator::can_swap_components(Ex::iterator one, Ex::iterator two, match_t subtree_comparison)
1162+
{
1163+
int tmp;
1164+
auto impi=properties.get_with_pattern<ImplicitIndex>(one, tmp);
1165+
if(impi.first) {
1166+
if(impi.first->explicit_form.size()>0) {
1167+
one=impi.first->explicit_form.begin();
1168+
}
1169+
}
1170+
impi=properties.get_with_pattern<ImplicitIndex>(two, tmp);
1171+
if(impi.first) {
1172+
if(impi.first->explicit_form.size()>0) {
1173+
two=impi.first->explicit_form.begin();
1174+
}
1175+
}
1176+
return can_swap(one, two, subtree_comparison, true);
1177+
}
11611178

11621179
// Determine the sign required to move the last factor in 'factors' to
11631180
// the right of the first. If moving left, do not count signs from

core/Compare.hh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,14 @@ namespace cadabra {
313313
int can_swap(Ex::iterator one, Ex::iterator two, match_t subtree_comparison,
314314
bool ignore_implicit_indices=false);
315315

316+
/// Wrapper for can_swap which is meant for objects that have implicit
317+
/// indices. This checks whether a single component of A commutes or
318+
/// anticommutes with a single component of B, saying nothing about
319+
/// whether A and B commute under matrix multiplication.
320+
321+
int can_swap_components(Ex::iterator one, Ex::iterator two,
322+
match_t subtree_comparison);
323+
316324
/// Determine whether object 'one' and 'two' can be moved next
317325
/// to each other by moving either one or the other: if fix_one==true
318326
/// the first node is kept fixed, otherwise the second node is kept fixed.

core/Props.hh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ namespace cadabra {
503503
if(ret1) { // property of the right type found for object 1
504504
property_map_t::const_iterator walk2=pit2.first;
505505
while(walk2!=pit2.second) {
506-
if((*walk2).second.first->match(*this, it2, ignore_parent_rel)) { // match for object 1 found
506+
if((*walk2).second.first->match(*this, it2, ignore_parent_rel)) { // match for object 2 found
507507
ret2=dynamic_cast<const T *>((*walk2).second.second);
508508
if(ret2) { // property of the right type found for object 2
509509
if(ret1==ret2 && walk1!=walk2) { // accept if properties are the same and patterns are not

core/algorithms/canonicalise.cc

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "Functional.hh"
55
#include "algorithms/canonicalise.hh"
66
#include "modules/xperm_new.h"
7+
#include "properties/Trace.hh"
78
#include "properties/Traceless.hh"
89
#include "properties/Diagonal.hh"
910
#include "properties/Derivative.hh"
@@ -50,18 +51,53 @@ bool canonicalise::remove_traceless_traces(iterator& it)
5051
while(facit!=tr.end(it)) {
5152
const Traceless *trl=kernel.properties.get_composite<Traceless>(facit);
5253
if(trl) {
54+
unsigned int ihits=0;
5355
tree_exact_less_mod_prel_obj comp(&kernel.properties);
5456
std::set<Ex, tree_exact_less_mod_prel_obj> countmap(comp);
5557
index_iterator indit=begin_index(facit);
5658
while(indit!=end_index(facit)) {
59+
bool incremented_now=false;
60+
auto ind=kernel.properties.get<Indices>(indit, true);
61+
if(ind) {
62+
// The indexs need to be in the set for which the object is
63+
// traceless (if specified, otherwise accept all).
64+
if(ind->set_name==trl->index_set_name || trl->index_set_name=="") {
65+
incremented_now=true;
66+
++ihits;
67+
}
68+
}
69+
else incremented_now=true;
70+
// Having no name is treated as having the right name
5771
if(countmap.find(Ex(indit))==countmap.end()) {
5872
countmap.insert(Ex(indit));
59-
++indit;
6073
}
61-
else {
74+
else if(incremented_now) {
6275
zero(it->multiplier);
6376
return true;
6477
}
78+
++indit;
79+
}
80+
iterator parent=it;
81+
if (tr.number_of_children(it)==1 && !tr.is_head(it)) parent=tr.parent(it);
82+
const Trace *trace=kernel.properties.get<Trace>(parent);
83+
if(trace) {
84+
int tmp;
85+
auto impi=kernel.properties.get_with_pattern<ImplicitIndex>(facit, tmp);
86+
if(impi.first->explicit_form.size()>0) {
87+
// Does the explicit form have two more indices of the right type?
88+
Ex::iterator eform=impi.first->explicit_form.begin();
89+
unsigned int ehits=0;
90+
indit=begin_index(eform);
91+
while(indit!=end_index(eform)) {
92+
auto ind=kernel.properties.get<Indices>(indit, true);
93+
if(ind->set_name==trl->index_set_name && ind->set_name==trace->index_set_name) ++ehits;
94+
if(ehits - ihits > 1) {
95+
zero(it->multiplier);
96+
return true;
97+
}
98+
++indit;
99+
}
100+
}
65101
}
66102
}
67103
++facit;

core/algorithms/combine.cc

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
using namespace cadabra;
77

8-
combine::combine(const Kernel& k, Ex& e)
9-
: Algorithm(k, e)
8+
combine::combine(const Kernel& k, Ex& e, Ex& t)
9+
: Algorithm(k, e), trace_op(t)
1010
{
1111
}
1212

@@ -36,7 +36,7 @@ Algorithm::result_t combine::apply(iterator& it)
3636

3737
while(ind_dummy.begin()!=ind_dummy.end()) {
3838
bool found=false;
39-
index_map_t::iterator start=ind_dummy.begin();
39+
index_map_t::iterator start=ind_dummy.begin(), backup;
4040
while(!found && start!=ind_dummy.end()) {
4141
iterator parent=tr.parent(start->second);
4242
sibling_iterator ch=tr.begin(parent), last_part;
@@ -46,11 +46,17 @@ Algorithm::result_t combine::apply(iterator& it)
4646
++ch;
4747
}
4848
if(last_part==start->second) {
49-
// We are on a rightmost contracted index
50-
found=true;
49+
++last_part;
50+
if(last_part==tr.end(parent)) {
51+
// Dummy index with nothing to the right is preferred
52+
found=true;
53+
}
54+
else backup=start;
5155
}
52-
else ++start;
56+
if(!found) ++start;
5357
}
58+
// As a backup, we use a dummy index with only non-dummies to the right
59+
if(!found) start=backup;
5460
bool paired=true;
5561
while(paired && start!=ind_dummy.end()) {
5662
iterator parent=tr.parent(start->second);
@@ -95,6 +101,7 @@ Algorithm::result_t combine::apply(iterator& it)
95101
}
96102
}
97103

104+
std::string trace_start="";
98105
std::vector<Ex::iterator>::iterator dums1=dummies.begin(), dums2;
99106
dums2=dums1;
100107
++dums2;
@@ -133,6 +140,38 @@ Algorithm::result_t combine::apply(iterator& it)
133140
iterator brackprod=tr.append_child(outerbrack, str_node("\\prod"));
134141
iterator parn1=tr.parent(*dums1);
135142
iterator parn2=tr.parent(*dums2);
143+
144+
// count how many sign changes stand between the two objects
145+
int sign=1;
146+
unsigned int hits=0;
147+
Ex_comparator compare(kernel.properties);
148+
sib=tr.begin(it);
149+
while(hits<2) {
150+
if(hits==1 && sib!=parn2) {
151+
// pass arguments manually as can_swap() does not check them
152+
bool isbrack=*(sib->name)=="\\indexbracket";
153+
if(isbrack && isbrack2) {
154+
auto es=compare.equal_subtree(tr.begin(parn2), tr.begin(sib));
155+
sign*=compare.can_swap_components(tr.begin(parn2), tr.begin(sib), es);
156+
}
157+
else if(isbrack && !isbrack2) {
158+
auto es=compare.equal_subtree(parn2, tr.begin(sib));
159+
sign*=compare.can_swap_components(parn2, tr.begin(sib), es);
160+
}
161+
else if(!isbrack && isbrack2) {
162+
auto es=compare.equal_subtree(tr.begin(parn2), sib);
163+
sign*=compare.can_swap_components(tr.begin(parn2), sib, es);
164+
}
165+
else {
166+
auto es=compare.equal_subtree(parn2, sib);
167+
sign*=compare.can_swap_components(parn2, sib, es);
168+
}
169+
}
170+
if(sib==parn1 || sib==parn2) ++hits;
171+
++sib;
172+
}
173+
if(sign==-1) flip_sign(brackprod->multiplier);
174+
136175
// remove the dummy index from these two objects, and move
137176
// other (dummy or not) indices to the outer indexbracket.
138177
sibling_iterator ind1=tr.begin(tr.parent(*dums1));
@@ -197,7 +236,22 @@ Algorithm::result_t combine::apply(iterator& it)
197236
if(consecutive) {
198237
++dums1;
199238
++dums2;
239+
if(dums2!=dummies.end() && trace_op.size()>0) {
240+
if(*(*dums2)->name==trace_start) {
241+
iterator parn=tr.parent(*dums2);
242+
iterator trace=tr.insert(parn, str_node(trace_op.begin()->name));
243+
sibling_iterator nxt=tr.begin(parn);
244+
++nxt;
245+
++dums1;
246+
++dums2;
247+
tr.reparent(trace, tr.begin(parn), nxt);
248+
multiply(trace->multiplier, *parn->multiplier);
249+
tr.erase(parn);
250+
trace_start="";
251+
}
252+
}
200253
}
254+
else trace_start=*(*dums1)->name;
201255
++dums1;
202256
++dums2;
203257
}

core/algorithms/combine.hh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@ namespace cadabra {
77

88
class combine : public Algorithm {
99
public:
10-
combine(const Kernel&, Ex&);
10+
combine(const Kernel&, Ex&, Ex&);
1111

1212
virtual bool can_apply(iterator) override;
1313
virtual result_t apply(iterator&) override;
1414

1515
private:
1616
typedef std::map<nset_t::iterator, iterator> indexlocmap_t;
1717

18+
Ex trace_op;
1819
indexlocmap_t iloc;
1920
};
2021

core/algorithms/sort_product.cc

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
#include "Cleanup.hh"
33
#include "algorithms/sort_product.hh"
4+
#include "properties/Trace.hh"
45

56
using namespace cadabra;
67

@@ -88,6 +89,61 @@ Algorithm::result_t sort_product::apply(iterator& st)
8889
}
8990
}
9091

92+
if(ret==result_t::l_no_action) {
93+
bool found=false;
94+
bool ascend=true;
95+
iterator parn=st;
96+
// It is fine to cycle when we have a sum of a sum inside a trace
97+
while(ascend && !tr.is_head(parn)) {
98+
parn=tr.parent(parn);
99+
const Trace *trace=kernel.properties.get<Trace>(parn);
100+
if(trace) {
101+
ascend=false;
102+
found=true;
103+
}
104+
else if(*parn->name=="\\indexbracket") {
105+
ascend=false;
106+
if(number_of_indices(parn)==2) {
107+
index_iterator first=begin_index(parn);
108+
index_iterator last=first;
109+
++last;
110+
if(*first->name==*last->name) found=true;
111+
}
112+
}
113+
else if(*parn->name!="\\sum") {
114+
ascend=false;
115+
}
116+
}
117+
if(found) {
118+
one=tr.begin(st);
119+
two=one;
120+
++two;
121+
while(two!=tr.end(st)) {
122+
compare.clear();
123+
auto es=compare.equal_subtree(one, two);
124+
if(compare.should_swap(one, es)) one=two;
125+
++two;
126+
}
127+
// We have found the element that should go at the front of the trace
128+
Ex::sibling_iterator front=one;
129+
while(tr.begin(st)!=front) {
130+
one=tr.begin(st);
131+
two=one;
132+
++two;
133+
while(two!=tr.end(st)) {
134+
compare.clear();
135+
auto es=compare.equal_subtree(one, two);
136+
int sign=compare.can_swap_components(one, two, es);
137+
if(sign==-1) flip_sign(st->multiplier);
138+
tr.swap(one);
139+
++two;
140+
++two;
141+
}
142+
}
143+
ret=result_t::l_applied;
144+
}
145+
}
146+
91147
if(cleanup)
92148
cleanup_dispatch(kernel, tr, st);
93149

core/algorithms/untrace.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,16 @@ Algorithm::result_t untrace::apply(iterator& trloc)
7575
}
7676

7777
if(move_out) {
78+
int sign=1;
79+
sibling_iterator st2=tr.begin(prodloc);
80+
Ex_comparator compare(kernel.properties);
81+
while(st2!=st) {
82+
auto es=compare.equal_subtree(st, st2);
83+
sign*=compare.can_swap_components(st, st2, es);
84+
++st2;
85+
}
7886
tr.move_before(trloc, st);
79-
//multiply(it->multiplier, sign);
87+
multiply(trloc->multiplier, sign);
8088
}
8189

8290
st=nxt;

core/properties/Traceless.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,11 @@ std::string Traceless::name() const
77
{
88
return "Traceless";
99
}
10+
11+
bool Traceless::parse(Kernel&, keyval_t& keyvals)
12+
{
13+
keyval_t::const_iterator kv=keyvals.find("indices");
14+
if(kv!=keyvals.end())
15+
index_set_name=*(kv->second->name);
16+
return true;
17+
}

0 commit comments

Comments
 (0)