Skip to content

Commit e4f8fec

Browse files
committed
Fixes for explicit_indices, and a manual page.
1 parent 07c6bf6 commit e4f8fec

File tree

5 files changed

+281
-26
lines changed

5 files changed

+281
-26
lines changed

core/algorithms/explicit_indices.cc

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@ bool explicit_indices::can_apply(iterator st)
2323

2424
if(*st->name=="\\equals") return false; // switch
2525
auto trace = kernel.properties.get<Trace>(st);
26-
if(trace) return false;
27-
if(*st->name=="\\sum") return true;
28-
if(is_termlike(st)) {
26+
if(trace) return true;
27+
if(is_termlike(st) || *st->name=="\\sum") {
2928
if(tr.is_head(st)) return true;
3029
if(*tr.parent(st)->name=="\\sum") return false;
30+
auto ptrace = kernel.properties.get<Trace>(tr.parent(st));
31+
if(ptrace) return false;
32+
auto pderiv = kernel.properties.get<PartialDerivative>(tr.parent(st));
33+
if(pderiv) return false;
3134
return true;
3235
}
3336

@@ -38,9 +41,20 @@ Algorithm::result_t explicit_indices::apply(iterator& it)
3841
{
3942
result_t res=result_t::l_no_action;
4043

41-
std::cerr << "apply at " << it << std::endl;
44+
// std::cerr << "apply at " << it << std::endl;
4245

43-
// Ensure that we are always working on a sum, even
46+
auto trace = kernel.properties.get<Trace>(it);
47+
iterator parit=it;
48+
if(trace) {
49+
// Handle the argument, then at the end, close the index loop
50+
// and remove the trace operator.
51+
iterator arg=tr.begin(it);
52+
if(! (*arg->name=="\\sum" || is_termlike(arg)))
53+
return res;
54+
it=arg;
55+
}
56+
57+
// Ensure that we are always working on a sum, even
4458
// if there is only one term.
4559
if(is_termlike(it))
4660
force_node_wrap(it, "\\sum");
@@ -50,10 +64,13 @@ Algorithm::result_t explicit_indices::apply(iterator& it)
5064
ind_free_sum.clear();
5165
ind_dummy_sum.clear();
5266
classify_indices(it, ind_free_sum, ind_dummy_sum);
67+
// std::cerr << "free indices in this term:" << std::endl;
68+
// for(const auto& ind: ind_free_sum)
69+
// std::cerr << ind.second << std::endl;
5370

5471
sibling_iterator term=tr.begin(it);
5572
while(term!=tr.end(it)) {
56-
iterator nxt=term;
73+
sibling_iterator nxt=term;
5774
++nxt;
5875

5976
iterator tmp=term;
@@ -64,6 +81,8 @@ Algorithm::result_t explicit_indices::apply(iterator& it)
6481
// building the explicit index line.
6582
added_this_term.clear();
6683
index_lines.clear();
84+
first_index.clear();
85+
last_index.clear();
6786

6887
sibling_iterator factor=tr.begin(term);
6988
while(factor!=tr.end(term)) {
@@ -72,29 +91,40 @@ Algorithm::result_t explicit_indices::apply(iterator& it)
7291
sibling_iterator args=tr.begin(factor);
7392
while(args!=tr.end(factor)) {
7493
if(args->fl.parent_rel==str_node::p_none) {
75-
handle_factor(args);
94+
handle_factor(args, trace!=0);
7695
break;
7796
}
7897
++args;
7998
}
8099
}
81100
else {
82-
handle_factor(factor);
101+
handle_factor(factor, trace!=0);
83102
}
84103
++factor;
85104
}
105+
// If this term is a trace, make indices equal
106+
if(trace) {
107+
for(auto& li: last_index) {
108+
tr.replace_index(li.second, first_index[li.first], true);
109+
}
110+
}
111+
86112

87113
tmp=term;
88-
std::cerr << term << std::endl;
89114
prod_unwrap_single_term(tmp);
90115

91116
term=nxt;
92117
}
93118

119+
if(trace) {
120+
it=parit;
121+
it = tr.flatten_and_erase(it);
122+
}
123+
94124
return res;
95125
}
96126

97-
void explicit_indices::handle_factor(sibling_iterator& factor)
127+
void explicit_indices::handle_factor(sibling_iterator& factor, bool trace_it)
98128
{
99129
int tmp;
100130
auto ii = kernel.properties.get_with_pattern<ImplicitIndex>(factor, tmp);
@@ -163,6 +193,11 @@ void explicit_indices::handle_factor(sibling_iterator& factor)
163193
added_this_term.insert(index_map_t::value_type(di, loc));
164194
index_lines[ip]=loc;
165195
index_lines_factor[ip]=loc;
196+
last_index[ip]=loc;
197+
auto first = first_index.find(ip);
198+
if(first==first_index.end()) {
199+
first_index[ip]=loc;
200+
}
166201
}
167202
else {
168203
// Use the active line index, then unset the active line.
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
{
2+
"cells" :
3+
[
4+
{
5+
"cell_origin" : "client",
6+
"cell_type" : "latex",
7+
"cells" :
8+
[
9+
{
10+
"cell_origin" : "client",
11+
"cell_type" : "latex_view",
12+
"source" : "\\algorithm{explicit_indices}{Make indices explicit on an expression with implicit indices.}\n\nIn Cadabra you can write expressions which are understood to have indices suppressed, in order\nto get a cleaner notation. This is often used for vector/matrix notation, or when dealing\nwith spinors. In order to inform Cadabra about these implicit indices, you use the\n\\prop{ImplicitIndex} property (which is also necessary to prevent Cadabra from moving\nthese objects through each other when sorting products into canonical form). \nThe \\algo{explicit_indices} algorithm can then make these indices explicit, which can \nsometimes make them easier to work with, for example when doing substitutions."
13+
}
14+
],
15+
"hidden" : true,
16+
"source" : "\\algorithm{explicit_indices}{Make indices explicit on an expression with implicit indices.}\n\nIn Cadabra you can write expressions which are understood to have indices suppressed, in order\nto get a cleaner notation. This is often used for vector/matrix notation, or when dealing\nwith spinors. In order to inform Cadabra about these implicit indices, you use the\n\\prop{ImplicitIndex} property (which is also necessary to prevent Cadabra from moving\nthese objects through each other when sorting products into canonical form). \nThe \\algo{explicit_indices} algorithm can then make these indices explicit, which can \nsometimes make them easier to work with, for example when doing substitutions."
17+
},
18+
{
19+
"cell_origin" : "client",
20+
"cell_type" : "latex",
21+
"cells" :
22+
[
23+
{
24+
"cell_origin" : "client",
25+
"cell_type" : "latex_view",
26+
"source" : "In the following example we define two sets of indices, and several objects which are assumed\nto have implicit indices."
27+
}
28+
],
29+
"hidden" : true,
30+
"source" : "In the following example we define two sets of indices, and several objects which are assumed\nto have implicit indices."
31+
},
32+
{
33+
"cell_origin" : "client",
34+
"cell_type" : "input",
35+
"cells" :
36+
[
37+
{
38+
"cell_origin" : "server",
39+
"cell_type" : "latex_view",
40+
"source" : "\\begin{dmath*}{}\\text{Attached property Indices(position=fixed) to~}\\left[m,~\\discretionary{}{}{} n,~\\discretionary{}{}{} p\\right].\\end{dmath*}"
41+
},
42+
{
43+
"cell_origin" : "server",
44+
"cell_type" : "latex_view",
45+
"source" : "\\begin{dmath*}{}\\text{Attached property Indices(position=fixed) to~}\\left[a,~\\discretionary{}{}{} b,~\\discretionary{}{}{} c,~\\discretionary{}{}{} d,~\\discretionary{}{}{} e,~\\discretionary{}{}{} f,~\\discretionary{}{}{} g,~\\discretionary{}{}{} h\\right].\\end{dmath*}"
46+
},
47+
{
48+
"cell_origin" : "server",
49+
"cell_type" : "latex_view",
50+
"source" : "\\begin{dmath*}{}\\text{Attached property ImplicitIndex to~}\\sigma^{p}.\\end{dmath*}"
51+
},
52+
{
53+
"cell_origin" : "server",
54+
"cell_type" : "latex_view",
55+
"source" : "\\begin{dmath*}{}\\text{Attached property ImplicitIndex to~}\\psi.\\end{dmath*}"
56+
},
57+
{
58+
"cell_origin" : "server",
59+
"cell_type" : "latex_view",
60+
"source" : "\\begin{dmath*}{}\\text{Attached property ImplicitIndex to~}\\chi.\\end{dmath*}"
61+
}
62+
],
63+
"source" : "{m,n,p}::Indices(spacetime, position=fixed);\n{a,b,c,d,e,f,g,h}::Indices(spinor, position=fixed);\n\\sigma^{p}::ImplicitIndex(\\sigma^{p a}_{b});\n\\psi::ImplicitIndex(\\psi_{a});\n\\chi::ImplicitIndex(\\chi^{a});"
64+
},
65+
{
66+
"cell_origin" : "client",
67+
"cell_type" : "latex",
68+
"cells" :
69+
[
70+
{
71+
"cell_origin" : "client",
72+
"cell_type" : "latex_view",
73+
"source" : "The following is a valid expression for a spinor bilinear,"
74+
}
75+
],
76+
"hidden" : true,
77+
"source" : "The following is a valid expression for a spinor bilinear,"
78+
},
79+
{
80+
"cell_origin" : "client",
81+
"cell_type" : "input",
82+
"cells" :
83+
[
84+
{
85+
"cell_origin" : "server",
86+
"cell_type" : "latex_view",
87+
"cells" :
88+
[
89+
{
90+
"cell_origin" : "server",
91+
"cell_type" : "input_form",
92+
"source" : "\\psi \\sigma^{m} \\sigma^{n} \\chi"
93+
}
94+
],
95+
"source" : "\\begin{dmath*}{}\\psi \\sigma^{m} \\sigma^{n} \\chi\\end{dmath*}"
96+
}
97+
],
98+
"source" : "ex:= \\psi \\sigma^{m} \\sigma^{n} \\chi;"
99+
},
100+
{
101+
"cell_origin" : "client",
102+
"cell_type" : "latex",
103+
"cells" :
104+
[
105+
{
106+
"cell_origin" : "client",
107+
"cell_type" : "latex_view",
108+
"source" : "We can now make the indices explicit using"
109+
}
110+
],
111+
"hidden" : true,
112+
"source" : "We can now make the indices explicit using"
113+
},
114+
{
115+
"cell_origin" : "client",
116+
"cell_type" : "input",
117+
"cells" :
118+
[
119+
{
120+
"cell_origin" : "server",
121+
"cell_type" : "latex_view",
122+
"cells" :
123+
[
124+
{
125+
"cell_origin" : "server",
126+
"cell_type" : "input_form",
127+
"source" : "\\psi_{a} \\sigma^{m a}_{b} \\sigma^{n b}_{c} \\chi^{c}"
128+
}
129+
],
130+
"source" : "\\begin{dmath*}{}\\psi_{a} \\sigma^{m a}\\,_{b} \\sigma^{n b}\\,_{c} \\chi^{c}\\end{dmath*}"
131+
}
132+
],
133+
"source" : "explicit_indices(ex);"
134+
},
135+
{
136+
"cell_origin" : "client",
137+
"cell_type" : "latex",
138+
"cells" :
139+
[
140+
{
141+
"cell_origin" : "client",
142+
"cell_type" : "latex_view",
143+
"source" : "This also works when there are trace operators, as is illustrated in the following \nexample."
144+
}
145+
],
146+
"hidden" : true,
147+
"source" : "This also works when there are trace operators, as is illustrated in the following \nexample."
148+
},
149+
{
150+
"cell_origin" : "client",
151+
"cell_type" : "input",
152+
"cells" :
153+
[
154+
{
155+
"cell_origin" : "server",
156+
"cell_type" : "latex_view",
157+
"source" : "\\begin{dmath*}{}\\text{Attached property Trace to~}{\\rm Tr}\\left(\\#\\right).\\end{dmath*}"
158+
},
159+
{
160+
"cell_origin" : "server",
161+
"cell_type" : "latex_view",
162+
"cells" :
163+
[
164+
{
165+
"cell_origin" : "server",
166+
"cell_type" : "input_form",
167+
"source" : "Tr(\\sigma^{m} \\sigma^{n} + \\sigma^{n} \\sigma^{m})"
168+
}
169+
],
170+
"source" : "\\begin{dmath*}{}{\\rm Tr}\\left(\\sigma^{m} \\sigma^{n}+\\sigma^{n} \\sigma^{m}\\right)\\end{dmath*}"
171+
}
172+
],
173+
"source" : "Tr{#}::LaTeXForm(\"{\\rm Tr}\").\nTr{#}::Trace(indices=spinor);\nex:= Tr(\\sigma^{m} \\sigma^{n} + \\sigma^{n} \\sigma^{m});"
174+
},
175+
{
176+
"cell_origin" : "client",
177+
"cell_type" : "input",
178+
"cells" :
179+
[
180+
{
181+
"cell_origin" : "server",
182+
"cell_type" : "latex_view",
183+
"cells" :
184+
[
185+
{
186+
"cell_origin" : "server",
187+
"cell_type" : "input_form",
188+
"source" : "\\sigma^{m a}_{b} \\sigma^{n b}_{a} + \\sigma^{n a}_{b} \\sigma^{m b}_{a}"
189+
}
190+
],
191+
"source" : "\\begin{dmath*}{}\\sigma^{m a}\\,_{b} \\sigma^{n b}\\,_{a}+\\sigma^{n a}\\,_{b} \\sigma^{m b}\\,_{a}\\end{dmath*}"
192+
}
193+
],
194+
"source" : "explicit_indices(_);"
195+
},
196+
{
197+
"cell_origin" : "client",
198+
"cell_type" : "input",
199+
"source" : ""
200+
}
201+
],
202+
"description" : "Cadabra JSON notebook format",
203+
"version" : 1
204+
}

core/algorithms/explicit_indices.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ class explicit_indices : public Algorithm {
1515
private:
1616
index_map_t ind_free_sum, ind_dummy_sum;
1717
index_map_t added_this_term;
18-
std::map<const Indices *, Ex::iterator> index_lines; // for the current term
18+
std::map<const Indices *, Ex::iterator> index_lines, first_index, last_index; // for the current term
1919

20-
void handle_factor(sibling_iterator& factor);
20+
void handle_factor(sibling_iterator& factor, bool trace_it);
2121
};
2222

2323
}

tests/explicit_implicit.cdb

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,35 @@ def test03():
5151

5252
test03()
5353

54-
# def test04():
55-
# __cdbkernel__=create_scope()
56-
# {m,n,p}::Indices(spacetime, position=fixed);
57-
# {a,b,c,d,e,f,g,h}::Indices(spinor, position=fixed);
58-
# \sigma^{p}::ImplicitIndex(\sigma^{p}_{a b});
59-
# \tau^{p}::ImplicitIndex(\tau^{p a b});
60-
# Tr{#}::Trace(indices=spinor);
61-
# ex:= Tr( \sigma^{m} \tau^{n} );
62-
# explicit_indices(_);
63-
# tst:= \sigma^{m}_{a b} \tau^{n b a} - @(ex);
64-
# assert(tst==0)
65-
# print("Test 04 passed")
66-
#
67-
# test04()
54+
def test04():
55+
__cdbkernel__=create_scope()
56+
{m,n,p}::Indices(spacetime, position=fixed);
57+
{a,b,c,d,e,f,g,h}::Indices(spinor, position=fixed);
58+
\sigma^{p}::ImplicitIndex(\sigma^{p}_{a b});
59+
\tau^{p}::ImplicitIndex(\tau^{p a b});
60+
Tr{#}::Trace(indices=spinor);
61+
ex:= Tr( \sigma^{m} \tau^{n} );
62+
explicit_indices(_);
63+
tst:= \sigma^{m}_{a b} \tau^{n b a} - @(ex);
64+
assert(tst==0)
65+
print("Test 04 passed")
66+
67+
test04()
68+
69+
def test05():
70+
__cdbkernel__=create_scope()
71+
{m,n,p}::Indices(spacetime, position=fixed);
72+
{a,b,c,d,e,f,g,h}::Indices(spinor, position=fixed);
73+
\sigma^{p}::ImplicitIndex(\sigma^{p}_{a b});
74+
\tau^{p}::ImplicitIndex(\tau^{p a b});
75+
Tr{#}::Trace(indices=spinor);
76+
ex:= Tr( \sigma^{m} \tau^{n} + \tau^{n} \sigma^{m} );
77+
explicit_indices(_);
78+
tst:= \sigma^{m}_{a b} \tau^{n b a} + \tau^{n a b} \sigma^{m}_{b a} - @(ex);
79+
assert(tst==0)
80+
print("Test 05 passed")
81+
82+
test05()
6883

6984
#ex:= \chi \psi \sigma^{n} \chi;
7085
#explicit_indices(_);

web2/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ set(ALGOS
6969
expand_delta
7070
expand_diracbar
7171
expand_power
72+
explicit_indices
7273
factor_in
7374
factor_out
7475
fierz

0 commit comments

Comments
 (0)