Skip to content

Commit b323ebb

Browse files
committed
Checking WIP
1 parent 7c35964 commit b323ebb

File tree

8 files changed

+189
-26
lines changed

8 files changed

+189
-26
lines changed

core/Algorithm.cc

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -837,15 +837,24 @@ bool Algorithm::is_nonprod_factor_in_prod(iterator it)
837837
bool Algorithm::prod_wrap_single_term(iterator& it)
838838
{
839839
if(is_single_term(it)) {
840-
force_prod_wrap(it);
840+
force_node_wrap(it, "\\prod");
841841
return true;
842842
}
843843
else return false;
844844
}
845845

846-
void Algorithm::force_prod_wrap(iterator& it)
846+
bool Algorithm::sum_wrap_single_term(iterator& it)
847847
{
848-
iterator prodnode=tr.insert(it, str_node("\\prod"));
848+
if(is_single_term(it)) {
849+
force_node_wrap(it, "\\sum");
850+
return true;
851+
}
852+
else return false;
853+
}
854+
855+
void Algorithm::force_node_wrap(iterator& it, std::string nm)
856+
{
857+
iterator prodnode=tr.insert(it, str_node(nm));
849858
sibling_iterator fr=it, to=it;
850859
++to;
851860
tr.reparent(prodnode, fr, to);
@@ -871,6 +880,21 @@ bool Algorithm::prod_unwrap_single_term(iterator& it)
871880
return false;
872881
}
873882

883+
bool Algorithm::sum_unwrap_single_term(iterator& it)
884+
{
885+
if((*it->name)=="\\sum") {
886+
if(tr.number_of_children(it)==1) {
887+
multiply(tr.begin(it)->multiplier, *it->multiplier);
888+
tr.begin(it)->fl.bracket=it->fl.bracket;
889+
tr.begin(it)->multiplier=it->multiplier;
890+
tr.flatten(it);
891+
it=tr.erase(it);
892+
return true;
893+
}
894+
}
895+
return false;
896+
}
897+
874898
bool Algorithm::separated_by_derivative(iterator i1, iterator i2, iterator check_dependence) const
875899
{
876900
iterator lca = tr.lowest_common_ancestor(i1, i2);

core/Algorithm.hh

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,14 @@ class Algorithm : public IndexClassifier {
177177
bool is_nonprod_factor_in_prod(iterator);
178178
bool prod_wrap_single_term(iterator&);
179179
bool prod_unwrap_single_term(iterator&);
180-
181-
/// Wrap a term in a product, irrespective of its parent (it usually makes
182-
/// more sense to call the safer prod_wrap_single_term above).
183-
void force_prod_wrap(iterator&);
180+
bool sum_wrap_single_term(iterator&);
181+
bool sum_unwrap_single_term(iterator&);
182+
183+
/// Wrap a term in a product or sum in a node with indicated
184+
/// name, irrespective of its parent (it usually makes more
185+
/// sense to call the safer prod_wrap_single_term or
186+
/// sum_wrap_single_term above).
187+
void force_node_wrap(iterator&, std::string);
184188

185189
/// Figure out whether two objects (commonly indices) are separated by a derivative
186190
/// operator, as in \f[ \partial_{a}{A_{b}} C^{b} \f].

core/IndexClassifier.cc

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,6 @@ void IndexClassifier::fill_map(index_map_t& mp, Ex::sibling_iterator st, Ex::sib
5151
}
5252
}
5353

54-
// Determine those indices in 'two' which have a name which is identical to
55-
// an index name occurring in 'one'. Store these indices of 'two' in target.
56-
// If 'move_out' is true, instead move both the indices in 'one' and 'two'
57-
// (i.e. move instead of copy, and also store the 'one' index).
58-
//
59-
// One exception: numerical, coordinate and symbol indices are always kept in 'one'.
60-
//
6154
void IndexClassifier::determine_intersection(index_map_t& one, index_map_t& two, index_map_t& target, bool move_out) const
6255
{
6356
index_map_t::iterator it1=one.begin();

core/IndexClassifier.hh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,16 @@ class IndexClassifier {
3535
void fill_index_position_map(Ex::iterator, const index_map_t&, index_position_map_t&) const;
3636
void fill_map(index_map_t&, Ex::sibling_iterator, Ex::sibling_iterator) const;
3737
void print_classify_indices(std::ostream&, Ex::iterator) const;
38+
39+
/// Determine those indices in 'two' which have a name which is identical to
40+
/// an index name occurring in 'one'. Store these indices of 'two' in target.
41+
/// If 'move_out' is true, instead move both the indices in 'one' and 'two'
42+
/// (i.e. move instead of copy, and also store the 'one' index).
43+
/// One exception: numerical, coordinate and symbol indices are always kept in 'one'.
44+
3845
void determine_intersection(index_map_t& one, index_map_t& two, index_map_t& target,
39-
bool move_out=false) const;
46+
bool move_out=false) const;
47+
4048
void classify_add_index(Ex::iterator it, index_map_t& ind_free, index_map_t& ind_dummy) const;
4149
void classify_indices_up(Ex::iterator, index_map_t& ind_free, index_map_t& ind_dummy) const;
4250
void classify_indices(Ex::iterator, index_map_t& ind_free, index_map_t& ind_dummy) const;

core/Props.hh

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ class Properties {
262262
template<class T> const T* get_composite(Ex::iterator, Ex::iterator, bool ignore_parent_rel=false) const;
263263
template<class T> const T* get_composite(Ex::iterator, Ex::iterator, int&, int&, bool ignore_parent_rel=false) const;
264264

265+
template<class T>
266+
std::pair<const T*, const pattern *> get_with_pattern(Ex::iterator, int& serialnum, bool doserial=true, bool ignore_parent_rel=false) const;
267+
265268
// Get the outermost node which has the given property attached, i.e. go down through
266269
// all (if any) nodes which have just inherited the property.
267270
template<class T> Ex::iterator head(Ex::iterator, bool ignore_parent_rel=false) const;
@@ -302,7 +305,16 @@ const T* Properties::get_composite(Ex::iterator it, bool ignore_parent_rel) cons
302305
template<class T>
303306
const T* Properties::get_composite(Ex::iterator it, int& serialnum, bool doserial, bool ignore_parent_rel) const
304307
{
305-
const T* ret=0;
308+
auto ret = get_with_pattern<T>(it, serialnum, doserial, ignore_parent_rel);
309+
return ret.first;
310+
}
311+
312+
template<class T>
313+
std::pair<const T*, const pattern *> Properties::get_with_pattern(Ex::iterator it, int& serialnum, bool doserial, bool ignore_parent_rel) const
314+
{
315+
std::pair<const T*, const pattern *> ret;
316+
ret.first=0;
317+
ret.second=0;
306318
bool inherits=false;
307319

308320
//std::cerr << *it->name_only() << std::endl;
@@ -318,9 +330,10 @@ const T* Properties::get_composite(Ex::iterator it, int& serialnum, bool doseria
318330
while(walk!=pit.second) {
319331
if(wildcards==(*walk).second.first->children_wildcard()) {
320332
// First check property type; a dynamic cast is much faster than a pattern match.
321-
ret=dynamic_cast<const T *>((*walk).second.second);
322-
if(ret) {
333+
ret.first=dynamic_cast<const T *>((*walk).second.second);
334+
if(ret.first) {
323335
if((*walk).second.first->match(*this, it, ignore_parent_rel)) {
336+
ret.second=(*walk).second.first;
324337
if(doserial) {
325338
std::pair<pattern_map_t::const_iterator, pattern_map_t::const_iterator>
326339
pm=pats.equal_range((*walk).second.second);
@@ -335,15 +348,15 @@ const T* Properties::get_composite(Ex::iterator it, int& serialnum, bool doseria
335348
break;
336349
}
337350
}
338-
ret=0;
351+
ret.first=0;
339352
if(dynamic_cast<const PropertyInherit *>((*walk).second.second))
340353
inherits=true;
341354
else if(dynamic_cast<const Inherit<T> *>((*walk).second.second))
342355
inherits=true;
343356
}
344357
++walk;
345358
}
346-
if(!wildcards && !ret) {
359+
if(!wildcards && !ret.first) {
347360
// std::cerr << "not yet found, switching to wildcards" << std::endl;
348361
wildcards=true;
349362
}
@@ -354,12 +367,12 @@ const T* Properties::get_composite(Ex::iterator it, int& serialnum, bool doseria
354367
}
355368

356369
// If no property was found, figure out whether a property is inherited from a child node.
357-
if(!ret && inherits) {
370+
if(!ret.first && inherits) {
358371
// std::cout << "no match but perhaps inheritance?" << std::endl;
359372
Ex::sibling_iterator sib=it.begin();
360373
while(sib!=it.end()) {
361-
const T* tmp=get_composite<T>((Ex::iterator)(sib), serialnum, doserial);
362-
if(tmp) {
374+
std::pair<const T*, const pattern *> tmp=get_with_pattern<T>((Ex::iterator)(sib), serialnum, doserial);
375+
if(tmp.first) {
363376
ret=tmp;
364377
break;
365378
}

core/algorithms/explicit_indices.cc

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

22
#include "explicit_indices.hh"
33

4+
#include "algorithms/substitute.hh"
45
#include "properties/ImplicitIndex.hh"
56

67
using namespace cadabra;
@@ -17,13 +18,117 @@ bool explicit_indices::can_apply(iterator st)
1718
// All this because when we generate free indices, we need to
1819
// ensure that all terms and all sides of an equals node use the
1920
// same index names.
21+
22+
if(*st->name=="\\equals") return false; // switch
23+
if(*st->name=="\\sum") return true;
24+
if(is_termlike(st)) {
25+
if(tr.is_head(st)) return true;
26+
if(*tr.parent(st)->name=="\\sum") return false;
27+
return true;
28+
}
2029

2130
return false;
2231
}
2332

24-
Algorithm::result_t explicit_indices::apply(iterator& prod)
33+
Algorithm::result_t explicit_indices::apply(iterator& it)
2534
{
35+
result_t res=result_t::l_no_action;
36+
37+
// Ensure that we are always working on a sum, even
38+
// if there is only one term.
39+
if(is_termlike(it))
40+
force_node_wrap(it, "\\sum");
41+
42+
// Classify all free and dummy indices already present. Any new
43+
// indices cannot be taken from these.
44+
index_map_t ind_free_sum, ind_dummy_sum;
45+
classify_indices(it, ind_free_sum, ind_dummy_sum);
46+
for(auto& k: ind_free_sum)
47+
std::cerr << k.first << std::endl;
48+
for(auto& k: ind_dummy_sum)
49+
std::cerr << k.first << std::endl;
50+
51+
sibling_iterator term=tr.begin(it);
52+
while(term!=tr.end(it)) {
53+
iterator tmp=term;
54+
prod_wrap_single_term(tmp);
55+
term=tmp;
56+
57+
// For each index set, keep track of the last used index in
58+
// building the explicit index line.
59+
std::map<const Indices *, Ex::iterator> index_lines;
60+
61+
sibling_iterator factor=tr.begin(term);
62+
while(factor!=tr.end(term)) {
63+
int tmp;
64+
auto ii = kernel.properties.get_with_pattern<ImplicitIndex>(factor, tmp);
65+
if(ii.first) {
66+
// Determine indices on this factor. Use a copy because we
67+
// need this object later.
68+
Ex orig(factor);
69+
index_map_t factor_ind_free, factor_ind_dummy;
70+
classify_indices(orig.begin(), factor_ind_free, factor_ind_dummy);
71+
72+
// Substitute explcit replacement and rename the indices
73+
// already present on the implicit factor.
74+
Ex replacement("\\arrow");
75+
replacement.append_child(replacement.begin(), ii.second->obj.begin());
76+
replacement.append_child(replacement.begin(), ii.first->explicit_form.begin());
77+
substitute subs(kernel, tr, replacement);
78+
iterator factor_tmp=factor;
79+
if(subs.can_apply(factor_tmp))
80+
subs.apply(factor_tmp);
81+
else
82+
throw InternalError("Internal inconsistency encountered, aborting.");
83+
factor=factor_tmp;
84+
85+
// Determine indices on the replacement.
86+
index_map_t repl_ind_free, repl_ind_dummy;
87+
classify_indices(factor, repl_ind_free, repl_ind_dummy);
88+
89+
// Which indices have been added?
90+
index_map_t ind_same;
91+
IndexClassifier ic(kernel);
92+
ic.determine_intersection(factor_ind_free, repl_ind_free, ind_same, true);
93+
94+
// Go through indices in order of appearance, determine if they have
95+
// been added, and rename. Note: indices do not appear in order in the
96+
// index maps above.
97+
auto iit=index_iterator::begin(kernel.properties, factor);
98+
while(iit!=index_iterator::end(kernel.properties, factor)) {
99+
auto search=repl_ind_free.begin();
100+
bool found=false;
101+
while(search!=repl_ind_free.end()) {
102+
if(search->second == (iterator)iit) {
103+
found=true;
104+
break;
105+
}
106+
++search;
107+
}
108+
if(found) {
109+
// This index was added.
110+
// Get a new free index.
111+
112+
auto ip = kernel.properties.get<Indices>(search->second);
113+
if(!ip)
114+
throw InternalError("Do not have Indices property for all implicit indices.");
115+
116+
std::cerr << "getting dummy index" << std::endl;
117+
auto di = ic.get_dummy(ip, &ind_free_sum, &ind_dummy_sum);
118+
std::cerr << di << std::endl;
119+
tr.replace(search->second, di.begin());
120+
}
121+
122+
++iit;
123+
}
124+
}
125+
++factor;
126+
}
26127

128+
tmp=term;
129+
prod_unwrap_single_term(tmp);
130+
++term;
131+
}
27132

28-
return result_t::l_applied;
133+
return res;
29134
}

core/algorithms/rewrite_indices.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Algorithm::result_t rewrite_indices::apply(iterator& it)
4343

4444
result_t res=result_t::l_no_action;
4545

46-
if(is_derivative_argument) force_prod_wrap(it);
46+
if(is_derivative_argument) force_node_wrap(it, "\\prod");
4747
else prod_wrap_single_term(it);
4848

4949
index_map_t ind_free, ind_dummy;

tests/explicit_implicit.cdb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
{m,n,p}::Indices(spacetime, position=fixed);
3+
{a,b,c,d}::Indices(spinor, position=fixed);
4+
\sigma^{p}::ImplicitIndex(\sigma^{p a}_{b});
5+
\psi::ImplicitIndex(\psi_{a});
6+
\chi::ImplicitIndex(\chi_{a});
7+
\bpsi::ImplicitIndex(\bpsi^{a});
8+
\bchi::ImplicitIndex(\bchi^{a});
9+
10+
11+
ex:= \psi \sigma^{m} \sigma^{n} \chi \lambda^{a} + \lambda_{b} \chi^{b} T^{m n}\chi^{a};
12+
explicit_indices(_);
13+
14+
ex:= \psi \sigma^{m} \chi + \chi \sigma^{m} \chi;
15+
explicit_indices(_);
16+

0 commit comments

Comments
 (0)