1 
2 #include "Functional.hh"
3 #include "Cleanup.hh"
4 #include "Permutations.hh"
5 #include "MultiIndex.hh"
6 //#include "SympyCdb.hh"
7 #include "algorithms/evaluate.hh"
8 #include "algorithms/simplify.hh"
9 #include "algorithms/substitute.hh"
10 #include "properties/EpsilonTensor.hh"
11 #include "properties/PartialDerivative.hh"
12 #include "properties/Coordinate.hh"
13 #include "properties/Depends.hh"
14 #include "properties/Accent.hh"
15 #include <functional>
16 
17 // #define DEBUG 1
18 
19 using namespace cadabra;
20 
evaluate(const Kernel & k,Ex & tr,const Ex & c,bool rhs,bool simplify)21 evaluate::evaluate(const Kernel& k, Ex& tr, const Ex& c, bool rhs, bool simplify)
22 	: Algorithm(k, tr), components(c), only_rhs(rhs), call_sympy(simplify)
23 	{
24 	}
25 
can_apply(iterator it)26 bool evaluate::can_apply(iterator it)
27 	{
28 	return tr.is_head(it); // only act at top level, we descend ourselves
29 	}
30 
is_scalar_function(iterator it) const31 bool evaluate::is_scalar_function(iterator it) const
32 	{
33 	if(*it->name=="\\pow" || *it->name=="\\exp" || *it->name=="\\sin" || *it->name=="\\cos" ) return true;
34 	return false;
35 	}
36 
apply(iterator & it)37 Algorithm::result_t evaluate::apply(iterator& it)
38 	{
39 	result_t res=result_t::l_no_action;
40 
41 	// The first pass is top-down.
42 
43 
44 	// The second pass is bottom-up. The general logic of the routines
45 	// this calls is that, instead of looping over all possible index
46 	// value sets, we look straight at the substitution rules, and
47 	// check that these are required for some index values (this is
48 	// where symmetry arguments should come in as well).
49 	//
50 	// The logic in Compare.cc helps us by matching component A_{t r}
51 	// in the rule to an abstract tensor A_{m n} in the expression, storing
52 	// the index name -> index value map.
53 
54 	it = cadabra::do_subtree(tr, it, [&](Ex::iterator walk) -> Ex::iterator {
55 #ifdef DEBUG
56 		std::cerr << "evaluate at " << walk << std::endl;
57 #endif
58 
59 		if(*(walk->name)=="\\components") walk = handle_components(walk);
60 		// FIXME: currently \pow is the only function for which we go straight up without
61 		// evaluating. For this reason, its children do not get wrapped in a \components node
62 		// in handle_factor. This needs to be extended to other function as well.
63 		else if(is_scalar_function(walk))
64 			{
65 			unwrap_scalar_in_components_node(walk);   // this is a scalar
66 			return walk;
67 			}
68 		else if(is_component(walk)) return walk;
69 		else if(*(walk->name)=="\\sum")   walk = handle_sum(walk);
70 		else if(*(walk->name)=="\\prod" || *(walk->name)=="\\wedge" || *(walk->name)=="\\frac")
71 			walk = handle_prod(walk);
72 		else
73 			{
74 			const PartialDerivative *pd = kernel.properties.get<PartialDerivative>(walk);
75 			if(pd) walk = handle_derivative(walk);
76 			else {
77 				const EpsilonTensor *eps = kernel.properties.get<EpsilonTensor>(walk);
78 				if(eps) {
79 					walk = handle_epsilon(walk);
80 					}
81 				else if(*walk->name!="\\equals" && walk->is_index()==false) {
82 					if(! (only_rhs && tr.is_head(walk)==false && ( *(tr.parent(walk)->name)=="\\equals" || *(tr.parent(walk)->name)=="\\arrow" ) && tr.index(walk)==0) ) {
83 						index_map_t empty;
84 						sibling_iterator tmp(walk);
85 #ifdef DEBUG
86 						std::cerr << "handling factor" << std::endl;
87 						std::cerr << *walk->name << std::endl;
88 #endif
89 						walk = handle_factor(tmp, empty);
90 						// std::cerr << "handling factor done" << std::endl;
91 						}
92 					}
93 				}
94 			}
95 		return walk;
96 		}
97 	                        );
98 
99 	// Final cleanup, e.g. to reduce scalar expressions to proper
100 	// scalars instead of 'components' nodes.
101 
102 	cleanup_dispatch_deep(kernel, tr);
103 
104 	return res;
105 	}
106 
is_component(iterator it) const107 bool evaluate::is_component(iterator it) const
108 	{
109 	// FIXME: The fact that this is called in the main loop above
110 	// prevents any evaluation of tensorial expressions which appear
111 	// inside components. Such things could in principle appear if, in
112 	// an existing components node, a scalar was replaced with an
113 	// object built from a tensor.
114 
115 	while(true) {
116 		if(*it->name=="\\components") {
117 			return true;
118 			}
119 		if(tr.is_head(it)==false)
120 			it=tr.parent(it);
121 		else
122 			break;
123 		}
124 	return false;
125 	}
126 
handle_components(iterator it)127 Ex::iterator evaluate::handle_components(iterator it)
128 	{
129 	// This just cleans up component nodes. At the moment this means
130 	// taking care of handling dummy pairs.
131 
132 	index_map_t ind_free, ind_dummy;
133 	classify_indices(it, ind_free, ind_dummy);
134 	if(ind_dummy.size()==0) return it;
135 
136 	// Wrap in a product, use handle_prod to sort out summation.
137 	it = tr.wrap(it, str_node("\\prod"));
138 	it = handle_prod(it);
139 	return it;
140 	}
141 
handle_sum(iterator it)142 Ex::iterator evaluate::handle_sum(iterator it)
143 	{
144 	// std::cerr << "handle sum" << Ex(it) << std::endl;
145 
146 	// pre-scan: remove zero nodes from evaluate having processed
147 	// nodes at lower level, and ensure child nodes are \component
148 	// nodes.
149 	sibling_iterator sib=tr.begin(it);
150 	while(sib!=tr.end(it)) {
151 		sibling_iterator nxt=sib;
152 		++nxt;
153 
154 		if(*sib->multiplier==0) { // zero terms can be removed
155 			tr.erase(sib);
156 			}
157 		else if(is_component(sib)==false) {
158 			index_map_t empty;
159 			handle_factor(sib, empty);
160 			}
161 
162 		sib=nxt;
163 		}
164 	if(tr.number_of_children(it)==0) {
165 		node_zero(it);
166 		return it;
167 		}
168 
169 	index_map_t full_ind_free, full_ind_dummy;
170 
171 	// First find the values that all indices will need to take. We do not loop over
172 	// them, but we need them in order to figure out which patterns in the rule can
173 	// match to patterns in the expression.
174 
175 	classify_indices(it, full_ind_free, full_ind_dummy);
176 	for(auto i: full_ind_free) {
177 		// std::cerr << "finding prop for " << Ex(i.second) << std::endl;
178 		const Indices *prop = kernel.properties.get<Indices>(i.second);
179 		if(prop==0) {
180 			const Coordinate *crd = kernel.properties.get<Coordinate>(i.second, true);
181 			if(crd==0)
182 				throw ArgumentException("evaluate: Index "+*(i.second->name)
183 				                        +" does not have an Indices property.");
184 			}
185 
186 		if(prop!=0 && prop->values.size()==0)
187 			throw ArgumentException("evaluate: Do not know values of index "+*(i.second->name)+".");
188 		}
189 
190 	// Iterate over all terms in the sum. These should be of two types: \component nodes,
191 	// which we do not need to touch anymore, and nodes which have still not been
192 	// evaluated. We send them all to handle_factor, which will return immediately on the
193 	// first node type, and convert the second type to the first.
194 
195 	sib=tr.begin(it);
196 	while(sib!=tr.end(it)) {
197 		sibling_iterator nxt=sib;
198 		++nxt;
199 		if(sib->is_zero())
200 			sib=tr.erase(sib);
201 		else {
202 			handle_factor(sib, full_ind_free);
203 			sib=nxt;
204 			}
205 		}
206 
207 	// Now all terms in the sum (which has its top node at 'it') are
208 	// \component nodes. We need to merge these together into a single
209 	// node.
210 
211 	auto sib1=tr.begin(it);
212 	//	merge_component_children(sib1);
213 	auto sib2=sib1;
214 	++sib2;
215 	while(sib2!=tr.end(it)) {
216 #ifdef DEBUG
217 		std::cerr << "merging components " << Ex(sib1) << " and " << Ex(sib2) << std::endl;
218 #endif
219 		merge_components(sib1, sib2);
220 		sib2=tr.erase(sib2);
221 		}
222 	cleanup_components(sib1);
223 
224 	it=tr.flatten_and_erase(it);
225 
226 	return it;
227 	}
228 
handle_factor(sibling_iterator sib,const index_map_t & full_ind_free)229 Ex::iterator evaluate::handle_factor(sibling_iterator sib, const index_map_t& full_ind_free)
230 	{
231 #ifdef DEBUG
232 	std::cerr << "handle_factor " << Ex(sib) << std::endl;
233 #endif
234 	if(*sib->name=="\\components") return sib;
235 
236 	// If this factor is an accent at the top level, descent further.
237 	const Accent *acc = kernel.properties.get<Accent>(sib);
238 	if(acc) {
239 		auto deeper=tr.begin(sib);
240 		handle_factor(deeper, full_ind_free);
241 		// Put the accent on each of the components.
242 		sibling_iterator cl = tr.end(deeper);
243 		--cl;
244 		cadabra::do_list(tr, cl, [&](Ex::iterator c) {
245 			auto towrap = tr.child(c, 1);
246 			tr.wrap(towrap, *sib);
247 			return true;
248 			});
249 		//tr.print_recursive_treeform(std::cerr, sib);
250 		// Move the component node up, outside the accent.
251 		sib=tr.flatten(sib);
252 		sib=tr.erase(sib);
253 		//tr.print_recursive_treeform(std::cerr, sib);
254 		return sib;
255 		}
256 
257 	// We need to know for all indices whether they are free or dummy,
258 	// in particular to handle internal contractions correctly.
259 	index_map_t ind_free, ind_dummy;
260 	classify_indices(sib, ind_free, ind_dummy);
261 
262 	// Pure scalar nodes need to be wrapped in a \component node to make life
263 	// easier for the rest of the algorithm.
264 	if(ind_free.size()==0 && ind_dummy.size()==0) {
265 		if(!tr.is_head(sib) && *tr.parent(sib)->name!="\\pow") {
266 			sib=wrap_scalar_in_components_node(sib);
267 #ifdef DEBUG
268 			std::cerr << "wrapped scalar" << std::endl;
269 #endif
270 			}
271 		return sib;
272 		}
273 	// If the indices are all Coordinates, this is a scalar, not a tensor.
274 	// It then needs simple wrapping just like a 'proper' scalar handed above.
275 	if(ind_dummy.size()==0 && ind_free.size()!=0) {
276 		bool all_coordinates=true;
277 		for(auto& ind: ind_free) {
278 			const Coordinate *crd = kernel.properties.get<Coordinate>(ind.second, true);
279 			if(!crd) {
280 				all_coordinates=false;
281 				break;
282 				}
283 			}
284 		if(all_coordinates) {
285 			if(!tr.is_head(sib) && *tr.parent(sib)->name!="\\pow") {
286 				sib=wrap_scalar_in_components_node(sib);
287 #ifdef DEBUG
288 				std::cerr << "wrapped scalar with component derivatives" << std::endl;
289 #endif
290 				}
291 			return sib;
292 			}
293 		}
294 
295 	// Attempt to apply each component substitution rule on this term.
296 	Ex repl("\\components");
297 	for(auto& ind: ind_free)
298 		repl.append_child(repl.begin(), ind.second);
299 	// If there are no free indices, add an empty first child anyway,
300 	// otherwise we need special cases in various other places.
301 	auto vl = repl.append_child(repl.begin(), str_node("\\comma"));
302 	bool has_acted=false;
303 	cadabra::do_list(components, components.begin(), [&](Ex::iterator c) {
304 		Ex rule(c);
305 		Ex obj(sib);
306 		//			std::cerr << "attempting rule " << rule << " on " << obj << std::endl;
307 		// rule is a single rule, we walk the list.
308 		substitute subs(kernel, obj, rule);
309 		subs.comparator.set_value_matches_index(true);
310 		iterator oit=obj.begin();
311 		if(subs.can_apply(oit)) {
312 			has_acted=true;
313 			// std::cerr << "can apply" << std::endl;
314 			auto el = repl.append_child(vl, str_node("\\equals"));
315 			auto il = repl.append_child(el, str_node("\\comma"));
316 			auto fi = full_ind_free.begin();
317 			// FIXME: need to do something sensible with indices on the lhs
318 			// of rules which are not coordinates. You can have A_{m n} as expression,
319 			// A_{0 0} -> r, A_{i j} -> \delta_{i j} as rule, but at the moment the
320 			// second rule does not do the right thing.
321 
322 			// Store all free indices (not the dummies!) in the component node.
323 			// If we have been passed an empty list of free indices (because the parent
324 			// node is not a sum node), simply add all free index values in turn.
325 			if(fi==full_ind_free.end()) {
326 				//					for(auto& r: subs.comparator.index_value_map) {
327 				//						repl.append_child(il, r.second.begin())->fl.parent_rel=str_node::p_none;
328 				//						}
329 
330 				fi=ind_free.begin();
331 				while(fi!=ind_free.end()) {
332 					for(auto& r: subs.comparator.index_value_map) {
333 						if(fi->first == r.first) {
334 							// std::cerr << "adding " << r.second.begin() << std::endl;
335 							repl.append_child(il, r.second.begin())->fl.parent_rel=str_node::p_none;
336 							break;
337 							}
338 						}
339 					auto fiold(fi);
340 					while(fi!=ind_free.end() && fiold->first==fi->first)
341 						++fi;
342 					}
343 				}
344 			else {
345 				while(fi!=full_ind_free.end()) {
346 					for(auto& r: subs.comparator.index_value_map) {
347 						if(fi->first == r.first) {
348 							repl.append_child(il, r.second.begin())->fl.parent_rel=str_node::p_none;
349 							break;
350 							}
351 						}
352 					auto fiold(fi);
353 					while(fi!=full_ind_free.end() && fiold->first==fi->first)
354 						++fi;
355 					}
356 				}
357 			subs.apply(oit);
358 			repl.append_child(el, obj.begin());
359 
360 			return true; // Cannot yet abort the do_list loop.
361 			}
362 		else {
363 			// TRACE: There is no rule which matches this factor. This means that
364 			// we want to keep all components?
365 			}
366 		return true;
367 		});
368 	if(!has_acted) {
369 		// There was not a single rule which matched for this tensor. That's means
370 		// that the user wants to keep the entire tensor (all components).
371 #ifdef DEBUG
372 		std::cerr << "No single rule matched " << Ex(sib) << std::endl;
373 #endif
374 		sib=dense_factor(sib, ind_free, ind_dummy);
375 		}
376 	else {
377 		merge_component_children(repl.begin());
378 
379 #ifdef DEBUG
380 		std::cerr << "result now " << repl << std::endl;
381 #endif
382 		sib = tr.move_ontop(iterator(sib), repl.begin());
383 		}
384 
385 	return sib;
386 	}
387 
dense_factor(iterator it,const index_map_t & ind_free,const index_map_t & ind_dummy)388 Ex::iterator evaluate::dense_factor(iterator it, const index_map_t& ind_free, const index_map_t& ind_dummy)
389 	{
390 	if(ind_dummy.size()!=0)
391 		throw RuntimeException("Cannot yet evaluate this expression.");
392 
393 	// For each index we need to iterate over all possible values, and generate a
394 	// components node for it. This should be done 'on the fly' eventually, the way
395 	// python treats 'map', but that will require wrapping all access to
396 	// '\components' in a separate class.
397 
398 	index_position_map_t ind_pos_free;
399 	fill_index_position_map(it, ind_free, ind_pos_free);
400 
401 	Ex comp("\\components");
402 
403 	auto fi = ind_free.begin();
404 	//std::cerr << "dense factor with indices: ";
405 	MultiIndex<Ex> mi;
406 	while(fi!=ind_free.end()) {
407 		comp.append_child(comp.begin(), fi->first.begin());
408 		// Look up which values this index takes.
409 		auto *id = kernel.properties.get<Indices>(fi->second);
410 		std::vector<Ex> values;
411 		if(!id || id->values.size()==0) {
412 			// No index property known, or not known which values the index
413 			// takes, so keep this index unexpanded.
414 			auto val=Ex(fi->second);
415 			val.begin()->fl.parent_rel=str_node::parent_rel_t::p_none;
416 			values.push_back(val);
417 			}
418 		else {
419 			for(const auto& ex: id->values)
420 				values.push_back(ex);
421 			}
422 
423 		mi.values.push_back(values);
424 		++fi;
425 		}
426 
427 	auto comma=comp.append_child(comp.begin(), str_node("\\comma"));
428 
429 	// For each set of index values...
430 	for(mi.start(); !mi.end(); ++mi) {
431 		auto ivs  = comp.append_child(comma, str_node("\\equals"));
432 		auto ivsc = comp.append_child(ivs, str_node("\\comma"));
433 		// ... add the values of the indices.
434 		for(std::size_t i=0; i<mi.values.size(); ++i) {
435 			comp.append_child(ivsc, mi[i].begin());
436 			}
437 		// ... then set the value of the tensor component.
438 		auto repfac = comp.append_child(ivs, it);
439 		fi = ind_free.begin();
440 		size_t i=0;
441 		while(fi!=ind_free.end()) {
442 			auto il = begin_index(repfac);
443 			auto num = ind_pos_free[fi->second];
444 			il += num;
445 			auto ii = iterator(il);
446 			auto parent_rel = il->fl.parent_rel;
447 			comp.replace(ii, mi[i].begin())->fl.parent_rel=parent_rel;
448 			++fi;
449 			++i;
450 			}
451 		}
452 
453 #ifdef DEBUG
454 	std::cerr << Ex(it) << std::endl;
455 #endif
456 
457 	it=tr.move_ontop(it, comp.begin());
458 
459 	return it;
460 	}
461 
merge_component_children(iterator it)462 void evaluate::merge_component_children(iterator it)
463 	{
464 	// Scan the entries of a single \components node for those
465 	// which carry the same index value for the free indices.
466 	// Such things can arise from e.g. A_{m} A_{m n} and the
467 	// rule { A_{r}=3, A_{t}=5, A_{r t}=1, A_{t t}=2 }, which
468 	// leads to two entries for the free index n=t.
469 
470 	//	if(*it->name!="\\components")
471 	//		std::cerr << "*** " << *it->name << std::endl;
472 	assert(*it->name=="\\components");
473 
474 	auto comma=tr.end(it);
475 	--comma;
476 
477 	//	if(*comma->name!="\\comma")
478 	//		std::cerr << "*** " << *comma->name << std::endl;
479 	assert(*comma->name=="\\comma");
480 
481 	auto cv1=tr.begin(comma);  // equals node
482 	while(cv1!=tr.end(comma)) {
483 		auto iv1=tr.begin(cv1); // index values \comma
484 		auto cv2=cv1;
485 		++cv2;
486 		while(cv2!=tr.end(comma)) {
487 			auto iv2=tr.begin(cv2); // index values \comma
488 			if(tr.equal_subtree(iv1, iv2)) {
489 				// std::cerr << "merging " << Ex(iv1) << std::endl;
490 				Ex::sibling_iterator tv1=iv1; // tensor component value
491 				++tv1;
492 				Ex::sibling_iterator tv2=iv2;
493 				++tv2;
494 				// std::cerr << "need to merge" << std::endl;
495 				if(*tv1->name!="\\sum")
496 					tv1=tr.wrap(tv1, str_node("\\sum"));
497 				tr.append_child(tv1, tv2);
498 				cv2=tr.erase(cv2);
499 				}
500 			else ++cv2;
501 			}
502 		++cv1;
503 		}
504 	}
505 
merge_components(iterator it1,iterator it2)506 void evaluate::merge_components(iterator it1, iterator it2)
507 	{
508 	// Merge two component nodes which come from two terms in a sum (so that
509 	// we can be assured that the free indices match; they just may not be
510 	// in the same order).
511 
512 #ifdef DEBUG
513 	std::cerr << "merge_components on " << Ex(it1) << " and " << Ex(it2) << std::endl;
514 #endif
515 
516 	assert(*it1->name=="\\components");
517 	assert(*it2->name=="\\components");
518 	sibling_iterator sib1=tr.end(it1);
519 	--sib1;
520 	sibling_iterator sib2=tr.end(it2);
521 	--sib2;
522 	assert(*sib1->name=="\\comma");
523 	assert(*sib2->name=="\\comma");
524 
525 	// We cannot directly compare the lhs of the equals nodes of it1
526 	// with the lhs of the equals node of it2, because the index order
527 	// on the two components nodes may be different. We first have to
528 	// ensure that the orders are the same (but only, of course) if we
529 	// have anything to permutate in the first place.
530 
531 	if(*tr.begin(it1)->name!="\\comma") {
532 		// Look at all indices on the two components nodes. Find
533 		// the permutation that takes the indices on it2 and brings
534 		// them in the order as they are on it1.
535 		Perm perm;
536 		perm.find(tr.begin(it2), sib2, tr.begin(it1), sib1);
537 
538 		// For each \equals node in the it2 comma node, permute
539 		// the values so they agree with the index order on it1.
540 		cadabra::do_list(tr, sib2, [&](Ex::iterator nd) {
541 			// nd is an \equals node.
542 			assert(*nd->name=="\\equals");
543 			auto comma = tr.begin(nd);
544 			assert(*comma->name=="\\comma");
545 			perm.apply(tr.begin(comma), tr.end(comma));
546 			return true;
547 			});
548 
549 #ifdef DEBUG
550 		std::cerr << "permutations done" << std::endl;
551 #endif
552 		}
553 
554 	// Now all index orders match and we can simply compare index value sets.
555 
556 	cadabra::do_list(tr, sib2, [&](Ex::iterator it2) {
557 		assert(*it2->name=="\\equals");
558 
559 		auto lhs2 = tr.begin(it2);
560 		auto found = cadabra::find_in_list(tr, sib1, [&](Ex::iterator it1) {
561 
562 			auto lhs1 = tr.begin(it1);
563 			//std::cerr << "comparing " << *lhs1->name << " with " << *lhs2->name << std::endl;
564 			if(tr.equal_subtree(lhs1, lhs2)) {
565 				auto sum1=lhs1;
566 				++sum1;
567 				auto sum2=lhs2;
568 				++sum2;
569 				if(*sum1->name!="\\sum")
570 					sum1=tr.wrap(sum1, str_node("\\sum"));
571 				tr.append_child(sum1, sum2);
572 				return iterator(sum1);
573 				}
574 
575 			return tr.end();
576 			});
577 		if(found==tr.end()) {
578 			tr.append_child(iterator(sib1), it2);
579 			}
580 		return true;
581 		});
582 
583 
584 	if(call_sympy)
585 		simplify_components(it1);
586 	}
587 
cleanup_components(iterator it)588 void evaluate::cleanup_components(iterator it)
589 	{
590 	sibling_iterator sib=tr.end(it);
591 	--sib;
592 
593 	cadabra::do_list(tr, sib, [&](Ex::iterator nd) {
594 		auto iv=tr.begin(nd);
595 		++iv;
596 		iterator p=iv;
597 		cleanup_dispatch(kernel, tr, p);
598 		return true;
599 		});
600 	}
601 
handle_derivative(iterator it)602 Ex::iterator evaluate::handle_derivative(iterator it)
603 	{
604 #ifdef DEBUG
605 	std::cerr << "handle_derivative " << Ex(it) << std::endl;
606 #endif
607 
608 	// In order to figure out which components to keep, we need to do two things:
609 	// expand into components the argument of the derivative, and then
610 	// figure out the dependence of that argument on the various coordinates.
611 	// There may be other orders (for e.g. situations where we want to keep entire
612 	// components unevaluated), but that's for later when we have practical use cases.
613 
614 	sibling_iterator sib=tr.begin(it);
615 	while(sib!=tr.end(it)) {
616 		if(sib->is_index()==false) {
617 			if(is_component(sib)==false) {
618 				index_map_t empty;
619 				// This really shouldn't be necessary; the way in which the
620 				// top level 'apply' works, it should have rewritten the argument
621 				// of the derivative into a \components node already.
622 				sib=handle_factor(sib, empty);
623 				}
624 			break;
625 			}
626 		++sib;
627 		}
628 	assert(sib!=tr.end(it));
629 
630 	// std::cerr << "after handle\n" << Ex(it) << std::endl;
631 
632 	index_map_t ind_free, ind_dummy;
633 	classify_indices(it, ind_free, ind_dummy);
634 
635 	// Flag an error if a partial derivative has an upper index which
636 	// is not position=free: this would require converting the index
637 	// with a metric, and that should be done by the user using
638 	// rewrite_indices.
639 	//
640 	// Also flag an error if there is more than one index type (we do
641 	// not handle those cases yet).
642 
643 	auto fu = tr.begin(it);
644 	const Indices *unique_indices=0;
645 	while(fu!=tr.end(it)) {
646 		if(fu->is_index()) {
647 			const Indices *ind = kernel.properties.get<Indices>(fu);
648 			if(ind!=unique_indices) {
649 				if(unique_indices==0)
650 					unique_indices=ind;
651 				else
652 					throw RuntimeException("All indices on a single derivative need to be of the same type.");
653 				}
654 
655 			if(fu->fl.parent_rel==str_node::p_super) {
656 				if(ind && ind->position_type!=Indices::free)
657 					throw RuntimeException("All indices on derivatives need to be lowered first.");
658 				}
659 			}
660 		++fu;
661 		}
662 
663 	// Figure out the positions of the index values in the components
664 	// node inside the derivative which correspond to values of dummy
665 	// indices (these necessarily have the other dummy on the
666 	// derivative itself).
667 	std::vector<std::pair<size_t, size_t>> dummy_positions;
668 
669 	decltype(ind_dummy.begin()) dumit[2];
670 	dumit[0] = ind_dummy.begin();
671 	while(dumit[0]!=ind_dummy.end()) {
672 		dumit[1]=dumit[0];
673 		++dumit[1];
674 		assert(dumit[1]!=ind_dummy.end());
675 
676 		bool     on_component[2];
677 		iterator parents[2];
678 		for(int i=0; i<2; ++i) {
679 			parents[i]=tr.parent(dumit[i]->second);
680 			on_component[i]=*parents[i]->name=="\\components";
681 			}
682 
683 		if(on_component[0]==false && on_component[1]==true)
684 			dummy_positions.push_back(std::make_pair(tr.index(dumit[0]->second), tr.index(dumit[1]->second)));
685 		else if(on_component[1]==false && on_component[0]==true)
686 			dummy_positions.push_back(std::make_pair(tr.index(dumit[1]->second), tr.index(dumit[0]->second)));
687 
688 		++dumit[0];
689 		++dumit[0];
690 		}
691 
692 	// Walk all the index value sets of the \components node inside the
693 	// \partial node.  For each, determine the dependencies, and
694 	// generate one element for each dependence.
695 
696 	sibling_iterator ivalues = tr.end(sib);
697 	--ivalues;
698 
699 	size_t ni=number_of_direct_indices(it);
700 
701 	cadabra::do_list(tr, ivalues, [&](Ex::iterator iv) {
702 #ifdef DEBUG
703 		std::cerr << "====" << std::endl;
704 		std::cerr << Ex(iv) << std::endl;
705 #endif
706 		// For each internal dummy set, keep track of the
707 		// position in the permutation array where we generate
708 		// its value.
709 		std::map<Ex, int, tree_exact_less_for_indexmap_obj> d2p;
710 
711 		Ex_comparator comp(kernel.properties);
712 
713 		sibling_iterator rhs = tr.begin(iv);
714 		++rhs;
715 		auto deps=dependencies(rhs);
716 
717 		if(deps.size()==0) {
718 			pm->message("No dependencies for " + *rhs->name);
719 			tr.erase(iv);
720 			return true;
721 			}
722 
723 		// If one of the dependencies is '\partial{#}', replace this will all the
724 		// index values that can appear in the derivative.
725 		auto dit = deps.begin();
726 		while(dit!=deps.end()) {
727 			comp.clear();
728 			if(*(dit->begin()->name)=="\\partial") { // FIXME: do a proper full-tree comparison with '\partial{#}'.
729 //			if(comp.equal_subtree("\partial{#}", *dit, Ex_comparator::useprops_t::never, true)==Ex_comparator::match_t::subtree_match) {
730 				deps.erase(dit);
731 				for(const auto& ival: unique_indices->values)
732 					deps.insert(ival);
733 				break;
734 				}
735 			++dit;
736 			}
737 
738 		// If the argument does not depend on anything, all derivatives
739 		// would produce zero. Remove this \equals node from the tree.
740 		if(deps.size()==0) {
741 			pm->message("No relevant dependencies for " + *rhs->name);
742 			tr.erase(iv);
743 			return true;
744 			}
745 
746 		// All indices on \partial can take any of the values of the
747 		// dependencies, EXCEPT when the index is a dummy index OR
748 		// when the index on the partial is a Coordinate. And of course
749 		// we should check that the indices can actually take the
750 		// values of the dependencies.
751 		//
752 		// In the 1st exceptional case, we firstly need to ensure
753 		// that both indices in the dummy pair take the same value
754 		// (this is done with d2p). Secondly, we need to ensure that
755 		// if the second index sits on the argument, we only use the
756 		// value of that index as given in the 'iv' list.
757 		//
758 		// In the 2nd exceptional case, we just need to determine if
759 		// the particular derivative does not annihilate the argument.
760 
761 		// Need all combinations of values, with repetition (multiple
762 		// pick) allowed.
763 
764 		combin::combinations<Ex> cb;
765 		for(auto& obj: deps) {
766 #ifdef DEBUG
767 			std::cerr << "dep " << obj << std::endl;
768 #endif
769 			if(unique_indices) {
770 //				std::cerr << "checking that deps are in values" << std::endl;
771 				for(const auto& allowed: unique_indices->values) {
772 					comp.clear();
773 					if(comp.equal_subtree(allowed.begin(), obj.begin(), Ex_comparator::useprops_t::never, true)<=Ex_comparator::match_t::subtree_match) {
774 						cb.original.push_back(obj);
775 						break;
776 						}
777 					}
778 				}
779 			else
780 				cb.original.push_back(obj);
781 			}
782 
783 		if(cb.original.size()==0) {
784 			// We may have had dependencies, but none of the index values can take those
785 			// values. So all is zero.
786 			tr.erase(iv);
787 			return true;
788 			}
789 
790 		cb.multiple_pick=true;
791 		cb.block_length=1;
792 		for(size_t n=0; n<ni; ++n) {
793 			// If this child is a coordinate, take it out of the combinatorics
794 			// of summing over index values (it's a single value).
795 			if(kernel.properties.get<Coordinate>(tr.child(it, n), true)!=0)
796 				continue;
797 
798 			Ex iname(tr.child(it,n)); // FIXME: does not handle Accented objects
799 			if(ind_dummy.find(iname)!=ind_dummy.end()) {
800 				// If this dummy has one leg on the argument of the derivative,
801 				// take it out of the combinatorics, because its value will
802 				// be fixed.
803 				bool out=false;
804 				for(auto& d: dummy_positions)
805 					if(d.first==n) {
806 						out=true;
807 						break;
808 						}
809 				if(out) continue;
810 
811 				if(d2p.find(iname)!=d2p.end())
812 					continue;
813 				else {
814 					d2p[iname]=cb.sublengths.size();
815 					}
816 				}
817 			cb.sublengths.push_back(1);
818 			}
819 		if(cb.sublengths.size()>0) // only if not all indices are fixed
820 			cb.permute();
821 
822 #ifdef DEBUG
823 		std::cerr << cb.size() << " permutations of indices" << std::endl;
824 #endif
825 
826 		// Note: indices on partial may be dummies, in which case the
827 		// values cannot be arbitrary. This is a self-contraction,
828 		// but cannot be caught by handle_factor because derivatives
829 		// do not get handled by patterns directly, they get
830 		// constructed by looking at dependencies.
831 
832 		// For each index value set we constructed for the indices on the
833 		// derivative, create an entry in the \components node.
834 
835 		for(unsigned int i=0; i<cb.size() || cb.size()==0; ++i) {
836 			// 'i' runs over all index combinations.
837 #ifdef DEBUG
838 			std::cerr << "Index combination " << i << std::endl;
839 #endif
840 			Ex eqcopy(iv);
841 			auto lhs=eqcopy.begin(eqcopy.begin());
842 			assert(*lhs->name=="\\comma");
843 
844 			if(cb.size()>0) {
845 #ifdef DEBUG
846 				std::cerr << "Copying values of derivative indices" << std::endl;
847 #endif
848 				// Setup the index values; simply copy from the cb array, but only
849 				// if the indices are not internal dummy.
850 				for(size_t j=0; j<cb[i].size(); ++j) {
851 					auto fd = ind_dummy.find(Ex(tr.child(it, j)));
852 					if(fd==ind_dummy.end()) {
853 						eqcopy.append_child(iterator(lhs), cb[i][j].begin() );
854 						}
855 					}
856 				}
857 			auto rhs=lhs;
858 			++rhs;
859 			multiplier_t mult=*rhs->multiplier;
860 			one(rhs->multiplier);
861 
862 			// Wrap a '\\partial' node around the component value, and add the
863 			// same index values as above to this node.
864 			rhs=eqcopy.wrap(rhs, str_node("\\partial"));
865 			multiply(rhs->multiplier, mult);
866 			multiply(rhs->multiplier, *it->multiplier);
867 			//				auto pch=tr.begin(it);
868 			//				iterator arg=tr.begin(rhs);
869 			for(size_t j=0, cb_j=0; j<ni; ++j) {
870 #ifdef DEBUG
871 				std::cerr << j << " : ";
872 #endif
873 				bool done=false;
874 				for(auto& d: dummy_positions) {
875 					if(d.first==j) {
876 						// This index is forced to a value because it is a dummy of which the partner
877 						// is fixed by the argument on which the derivative acts.
878 #ifdef DEBUG
879 						std::cerr << "fixed" << std::endl;
880 #endif
881 						eqcopy.insert_subtree(rhs.begin(), tr.child(lhs,d.second))->fl.parent_rel=str_node::p_sub;
882 						done=true;
883 						break;
884 						}
885 					}
886 				// std::cerr << "testing index " << j << " of \n" << Ex(it) << std::endl;
887 				if(kernel.properties.get<Coordinate>(tr.child(it, j), true)!=0) {
888 					// std::cerr << "Coordinate, so need straight copy" << std::endl;
889 					eqcopy.insert_subtree(rhs.begin(), tr.child(it,j))->fl.parent_rel=str_node::p_sub;
890 					done=true;
891 					}
892 				if(!done) {
893 					// If we get here, the index value was not fixed because it is part of an
894 					// already fixed dummy pair. And it was not fixed because the index was a
895 					// Coordinate.
896 					size_t fromj=cb_j;
897 					Ex iname(tr.child(it,j));
898 					auto fi = d2p.find(iname);
899 					if(fi!=d2p.end()) {
900 						fromj = (*fi).second;
901 						if(fromj == cb_j)
902 							++cb_j;
903 						}
904 					else {
905 						++cb_j;
906 						}
907 					// std::cerr << "cb: " << i << ", " << fromj << std::endl;
908 					eqcopy.insert_subtree(rhs.begin(), cb[i][fromj].begin() )->fl.parent_rel=str_node::p_sub;
909 					}
910 				}
911 			// std::cerr << "----" << std::endl;
912 
913 			// For all dummy pairs which have one index on the
914 			// \components node inside the derivative, we need to
915 			// remove the corresponding value from the components
916 			// node.
917 			std::vector<sibling_iterator> sibs_to_erase;
918 			for(auto di: dummy_positions) {
919 				sibs_to_erase.push_back(tr.child(lhs, di.second));
920 				}
921 			for(auto se: sibs_to_erase)
922 				tr.erase(se);
923 
924 			// Now move this replacement expression into the tree.
925 
926 			// std::cerr << "Replacement now " << std::endl;
927 			// std::cerr << eqcopy << std::endl;
928 			tr.move_before(tr.begin(ivalues), eqcopy.begin());
929 
930 			if(cb.size()==0) break;
931 			}
932 
933 		// Erase the original \equals entry (we generated a full replacement above).
934 		tr.erase(iv);
935 		return true;
936 		});
937 
938 #ifdef DEBUG
939 	std::cerr << tr.number_of_children(ivalues) << " nonzero components in this derivative" << std::endl;
940 #endif
941 	if(tr.number_of_children(ivalues)==0) {
942 		// All components of the derivative evaluated to zero because
943 		// there were no dependencies. Replace this derivative node with
944 		// a zero and return;
945 		node_zero(it);
946 		return it;
947 		}
948 
949 	one(it->multiplier);
950 
951 #ifdef DEBUG
952 	std::cerr << "now " << Ex(it) << std::endl;
953 #endif
954 
955 
956 	// Now move the free (but not the internal dummy or Coordinate!)
957 	//	partial indices to the components node, and then unwrap the
958 	//	partial node.
959 
960 	auto pch=tr.begin(it);
961 	for(size_t n=0; n<ni; ++n) {
962 		sibling_iterator nxt=pch;
963 		++nxt;
964 		if(ind_dummy.find(Ex(pch))!=ind_dummy.end()) {
965 			tr.erase(pch);
966 			}
967 		else if(kernel.properties.get<Coordinate>(pch, true)!=0) {
968 			tr.erase(pch);
969 			}
970 		else
971 			tr.move_before(ivalues, pch);
972 		pch=nxt;
973 		}
974 
975 
976 	// Remove indices from the components node which came from the
977 	// argument and which are dummy.
978 	it=tr.flatten_and_erase(it);
979 	auto se = tr.begin(it);
980 	while(se!=tr.end(it)) {
981 		if(ind_dummy.find(Ex(se))!=ind_dummy.end())
982 			se = tr.erase(se);
983 		else
984 			++se;
985 		}
986 
987 #ifdef DEBUG
988 	std::cerr << "after index move " << Ex(it) << std::endl;
989 #endif
990 
991 	merge_component_children(it);
992 
993 #ifdef DEBUG
994 	std::cerr << "after merge " << Ex(it) << std::endl;
995 #endif
996 
997 	if(call_sympy)
998 		simplify_components(it);
999 	// std::cerr << "then " << Ex(it) << std::endl;
1000 
1001 	return it;
1002 	}
1003 
handle_epsilon(iterator it)1004 Ex::iterator evaluate::handle_epsilon(iterator it)
1005 	{
1006 	Ex rep("\\components");
1007 	// attach indices to components
1008 	// figure out the index value ranges
1009 	// generate permutations of 'r1 ... rn' and signs
1010 	// fill components
1011 	auto sib=tr.begin(it);
1012 	while(sib!=tr.end(it)) {
1013 		rep.append_child(rep.begin(), (iterator)sib);
1014 		++sib;
1015 		}
1016 	auto cvals = rep.append_child(rep.begin(), str_node("\\comma"));
1017 
1018 	sib=tr.begin(it);
1019 	const Indices *ind = kernel.properties.get<Indices>(sib);
1020 	if(ind==0)
1021 		throw ArgumentException("No Indices property known for indices in EpsilonTensor.");
1022 
1023 	combin::combinations<Ex> cb;
1024 	for(auto& val: ind->values)
1025 		cb.original.push_back(val);
1026 	cb.multiple_pick=false;
1027 	cb.block_length=1;
1028 	cb.set_unit_sublengths();
1029 	cb.permute();
1030 
1031 	for(unsigned int i=0; i<cb.size(); ++i) {
1032 		auto equals = rep.append_child(cvals, str_node("\\equals"));
1033 		auto vcomma = rep.append_child(equals, str_node("\\comma"));
1034 		for(unsigned int j=0; j<cb.original.size(); ++j) {
1035 			//			std::cerr << *(cb[i][j].begin()->multiplier) << " ";
1036 			rep.append_child(vcomma, cb[i][j].begin());
1037 			}
1038 		auto one = rep.append_child(equals, str_node("1"));
1039 		multiply(one->multiplier, cb.ordersign(i));
1040 		//		std::cerr << std::endl;
1041 		}
1042 
1043 	it=tr.move_ontop(it, rep.begin());
1044 	return it;
1045 	}
1046 
simplify_components(iterator it)1047 void evaluate::simplify_components(iterator it)
1048 	{
1049 	assert(*it->name=="\\components");
1050 
1051 	// Simplify the components of the now single \component node by
1052 	// calling the scalar backend.  We feed it the components
1053 	// individually.
1054 	sibling_iterator lst = tr.end(it);
1055 	--lst;
1056 
1057 	cadabra::simplify simp(kernel, tr);
1058 	simp.set_progress_monitor(pm);
1059 
1060 	cadabra::do_list(tr, lst, [&](Ex::iterator eqs) {
1061 		assert(*eqs->name=="\\equals");
1062 		auto rhs1 = tr.begin(eqs);
1063 		++rhs1;
1064 		iterator nd=rhs1;
1065 		if(pm) pm->group("scalar_backend");
1066 		// std::cerr << "simplify at " << Ex(nd) << std::endl;
1067 		simp.apply_generic(nd, false, false, 0);
1068 		if(pm) pm->group();
1069 
1070 		if(nd->is_zero()) {
1071 			// std::cerr << "component zero " << nd.node << std::endl;
1072 			tr.erase(eqs);
1073 			}
1074 		else {
1075 			// std::cerr << "component non-zero " << nd.node << std::endl;
1076 			}
1077 		return true;
1078 		});
1079 
1080 	// Note: the 'erase' in the loop above may have left us with a
1081 	// \components node with an empty list of component values. However,
1082 	// since all logic expects to find a \component node, we do NOT yet
1083 	// replace this with a scalar zero here.
1084 	}
1085 
dependencies(iterator it)1086 std::set<Ex, tree_exact_less_obj> evaluate::dependencies(iterator it)
1087 	{
1088 	tree_exact_less_obj comp(&kernel.properties);
1089 	std::set<Ex, tree_exact_less_obj> ret(comp);
1090 
1091 	// Is this node a coordinate itself? If so, add it.
1092 	const Coordinate *cd = kernel.properties.get<Coordinate>(it, true);
1093 	if(cd) {
1094 		Ex cpy(it);
1095 		cpy.begin()->fl.bracket=str_node::b_none;
1096 		cpy.begin()->fl.parent_rel=str_node::p_none;
1097 		one(cpy.begin()->multiplier);
1098 		ret.insert(cpy);
1099 		}
1100 
1101 	// Determine explicit dependence on Coordinates, that is, collect
1102 	// parent_rel=p_none arguments, and add them directly if they
1103 	// carry a Coordinate property, or run the algorithm recursively
1104 	// if not (to catch e.g. exp(F(r)) depending on 'r'.
1105 
1106 	cadabra::do_subtree(tr, it, [&](Ex::iterator nd) -> Ex::iterator {
1107 		if(nd==it) return nd; // skip node itself, leads to indefinite recursion
1108 		if(nd->fl.parent_rel==str_node::p_none)
1109 			{
1110 			const Coordinate *cd = kernel.properties.get<Coordinate>(nd, true);
1111 			if(cd) {
1112 				Ex cpy(nd);
1113 				cpy.begin()->fl.bracket=str_node::b_none;
1114 				cpy.begin()->fl.parent_rel=str_node::p_none;
1115 				one(cpy.begin()->multiplier);
1116 				ret.insert(cpy);
1117 				}
1118 			else {
1119 				auto arg_deps=dependencies(nd);
1120 				if(arg_deps.size()>0)
1121 					for(const auto& new_dep: arg_deps)
1122 						ret.insert(new_dep);
1123 				}
1124 			}
1125 		return nd;
1126 		});
1127 
1128 	// Determine implicit dependence via Depends.
1129 #ifdef DEBUG
1130 	std::cerr << "deps for " << Ex(it) << std::endl;
1131 #endif
1132 
1133 	const DependsBase *dep = kernel.properties.get<DependsBase>(it, true);
1134 	if(dep) {
1135 #ifdef DEBUG
1136 		std::cerr << "implicit deps" << std::endl;
1137 #endif
1138 		Ex deps(dep->dependencies(kernel, it));
1139 		cadabra::do_list(deps, deps.begin(), [&](Ex::iterator nd) {
1140 			Ex cpy(nd);
1141 			cpy.begin()->fl.bracket=str_node::b_none;
1142 			cpy.begin()->fl.parent_rel=str_node::p_none;
1143 			ret.insert(cpy);
1144 			return true;
1145 			});
1146 #ifdef DEBUG
1147 		for(auto& e: ret)
1148 			std::cerr << e << std::endl;
1149 #endif
1150 		}
1151 
1152 	return ret;
1153 	}
1154 
wrap_scalar_in_components_node(iterator sib)1155 Algorithm::iterator evaluate::wrap_scalar_in_components_node(iterator sib)
1156 	{
1157 	// FIXME: would be good if we could write this in a more readable form.
1158 	auto eq=tr.wrap(sib, str_node("\\equals"));
1159 	tr.prepend_child(eq, str_node("\\comma"));
1160 	eq=tr.wrap(eq, str_node("\\comma"));
1161 	sib=tr.wrap(eq, str_node("\\components"));
1162 	return sib;
1163 	}
1164 
unwrap_scalar_in_components_node(iterator it)1165 void evaluate::unwrap_scalar_in_components_node(iterator it)
1166 	{
1167 	// To apply to a scalar function: remove all scalars wrapped in
1168 	// components nodes and make them normal scalars again.
1169 	auto sib=tr.begin(it);
1170 	while(sib!=tr.end(it)) {
1171 		if(*sib->name=="\\components") {
1172 			iterator tmp=sib;
1173 			::cleanup_components(kernel, tr, tmp);
1174 			}
1175 		++sib;
1176 		}
1177 	}
1178 
handle_prod(iterator it)1179 Ex::iterator evaluate::handle_prod(iterator it)
1180 	{
1181 	// std::cerr << "handle_prod " << Ex(it) << std::endl;
1182 
1183 	std::string prod_name=*it->name;
1184 
1185 	// All factors are either \component nodes, pure scalar nodes, or nodes which still need replacing.
1186 	// The handle_factor function takes care of the latter two.
1187 
1188 	sibling_iterator sib=tr.begin(it);
1189 	while(sib!=tr.end(it)) {
1190 		sibling_iterator nxt=sib;
1191 		++nxt;
1192 
1193 		if(*sib->multiplier==0) { // zero factors make the entire product zero.
1194 			node_zero(it);
1195 			return it;
1196 			}
1197 
1198 		if(is_component(sib)==false) {
1199 			index_map_t empty;
1200 			handle_factor(sib, empty);
1201 			}
1202 
1203 		sib=nxt;
1204 		}
1205 
1206 	// TRACE: If a factor has not had a rule match, it will be left
1207 	// un-evaluated here. So you get
1208 	//  X^{a} \component_{a}( 0=3, 2=-5 )
1209 	// and then we fail lower down. What we could do is let
1210 	// handle_factor write out such unevaluated expressions to
1211 	// component ones. That's somewhat wasteful though.
1212 
1213 #ifdef DEBUG
1214 	std::cerr << "every factor a \\components:\n" << Ex(it) << std::endl;
1215 #endif
1216 
1217 	// Now every factor in the product is a \component node.  The thing
1218 	// is effectively a large sparse tensor product. We need to do the
1219 	// sums over the dummy indices, turning this into a single
1220 	// \component node.
1221 
1222 	index_map_t ind_free, ind_dummy;
1223 	classify_indices(it, ind_free, ind_dummy);
1224 
1225 	auto di = ind_dummy.begin();
1226 	// Since no factor can be a sum anymore, dummy indices always occur in pairs,
1227 	// there is no need to account for anything more tricky. Every pair leads
1228 	// to a sum.
1229 	while(di!=ind_dummy.end()) {
1230 		auto di2=di;
1231 		++di2;
1232 		int num1 = tr.index(di->second);
1233 		int num2 = tr.index(di2->second);
1234 		// std::cerr << *(di->first.begin()->name)
1235 		// << " is index " << num1 << " in first and index " << num2 << " in second node " << std::endl;
1236 
1237 		// three cases:
1238 		//    two factors, single index in common. Merge is simple.
1239 		//    two factors, more than one index in common. After merging this turns into:
1240 		//    single factor, self-contraction
1241 
1242 		auto cit1 = tr.parent(di->second);
1243 		auto cit2 = tr.parent(di2->second);
1244 
1245 		// Are the components objects cit1, cit2 on which these indices sit the same one?
1246 		if(cit1 != cit2) {
1247 			// Walk through all components of the first tensor, and for each check whether
1248 			// any of the components of the second tensor matches the value for this dummy
1249 			// index.
1250 			sibling_iterator sib1=tr.end(cit1);
1251 			--sib1;
1252 			sibling_iterator sib2=tr.end(cit2);
1253 			--sib2;
1254 
1255 			// Move all indices of the second tensor to be indices of the first.
1256 			sibling_iterator mv=tr.begin(cit2);
1257 			while(mv!=sib2) {
1258 				sibling_iterator nxt=mv;
1259 				++nxt;
1260 				tr.move_before(sib1, mv);
1261 				mv=nxt;
1262 				}
1263 
1264 			cadabra::do_list(tr, sib1, [&](Ex::iterator it1) {
1265 				if(*it1->name!="\\equals")
1266 					std::cerr << *it->name << std::endl;
1267 				assert(*it1->name=="\\equals");
1268 				auto lhs1 = tr.begin(it1);
1269 				auto ivalue1 = tr.begin(lhs1);
1270 				ivalue1 += num1;
1271 				cadabra::do_list(tr, sib2, [&](Ex::iterator it2) {
1272 					assert(*it2->name=="\\equals");
1273 					auto lhs2 = tr.begin(it2);
1274 					auto ivalue2 = tr.begin(lhs2);
1275 					ivalue2 += num2;
1276 
1277 					// Compare the two index values in the two tensors, only continue if
1278 					// these are the same.
1279 					// std::cerr << "comparing value " << *ivalue1->name << " with " << *ivalue2->name << std::endl;
1280 					// std::cerr << "                " << &(*ivalue1) << " vs " << &(*ivalue2) << std::endl;
1281 					if(tr.equal_subtree(ivalue1,ivalue2)) {
1282 						// Create new merged index value set.
1283 						Ex ivs("\\equals");
1284 						auto ivs_lhs = tr.append_child(ivs.begin(), str_node("\\comma"));
1285 						auto ivs_rhs = tr.append_child(ivs.begin(), str_node(prod_name));
1286 						auto ci = tr.begin(lhs1);
1287 						int n=0;
1288 						while(ci!=tr.end(lhs1)) {
1289 							if(n!=num1)
1290 								ivs.append_child(ivs_lhs, iterator(ci));
1291 							++ci;
1292 							++n;
1293 							}
1294 						ci = ivs.begin(lhs2);
1295 						n=0;
1296 						while(ci!=ivs.end(lhs2)) {
1297 							if(n!=num2)
1298 								ivs.append_child(ivs_lhs, iterator(ci));
1299 							++ci;
1300 							++n;
1301 							}
1302 						auto rhs1=lhs1;
1303 						++rhs1;
1304 						ivs.append_child(ivs_rhs, iterator(rhs1));
1305 						auto rhs2=lhs2;
1306 						++rhs2;
1307 						ivs.append_child(ivs_rhs, iterator(rhs2));
1308 						//std::cerr << "ivs_rhs = " << Ex(ivs_rhs) << std::endl;
1309 						cleanup_dispatch_deep(kernel, ivs);
1310 						// Insert this new index value set before sib1, so that it will not get used
1311 						// inside the outer loop.
1312 						tr.move_before(it1, ivs.begin());
1313 						}
1314 					return true;
1315 					});
1316 				// This index value set can now be erased as all
1317 				// possible combinations have been considered.
1318 				tr.erase(it1);
1319 				return true;
1320 				});
1321 			// Remove the dummy indices from the index set of tensor 1.
1322 			tr.erase(di->second);
1323 			tr.erase(di2->second);
1324 			// Tensor 2 can now be removed from the product as well, as all information is now
1325 			// part of tensor 1.
1326 			tr.erase(cit2);
1327 			}
1328 
1329 		else {
1330 			// Components objects cit1 and cit2 are actually the same. We just need to
1331 			// do a single loop now, going over all index value sets and keeping those
1332 			// for which the num1-th and num2-th value are identical.
1333 
1334 			sibling_iterator sib1=tr.end(cit1);
1335 			--sib1;
1336 
1337 			cadabra::do_list(tr, sib1, [&](Ex::iterator it1) {
1338 				assert(*it1->name=="\\equals");
1339 				auto lhs = tr.begin(it1);
1340 				auto ivalue1 = tr.begin(lhs);
1341 				auto ivalue2 = ivalue1;
1342 				ivalue1 += num1;
1343 				ivalue2 += num2;
1344 				if(tr.equal_subtree(ivalue1,ivalue2)) {
1345 					tr.erase(ivalue1);
1346 					tr.erase(ivalue2);
1347 					}
1348 				else {
1349 					tr.erase(it1);
1350 					}
1351 				return true;
1352 				}
1353 			                );
1354 			tr.erase(di->second);
1355 			tr.erase(di2->second);
1356 			}
1357 
1358 		++di;
1359 		++di;
1360 		}
1361 
1362 	// TRACE: are we still ok here? Looks ok: one component node
1363 	// with no indices.
1364 	// std::cerr << "Before doing outer product:\n" << Ex(it) << std::endl;
1365 
1366 	// At this stage we have one or more components nodes in the product,
1367 	// and we have collected all possible index value combinations.
1368 	// We need to do an outer multiplication, merging all index names into
1369 	// one, and computing tensor component values for all possible index values.
1370 
1371 	int n=tr.number_of_children(it);
1372 	// std::cerr << "outer product:\n" << Ex(it) << std::endl;
1373 	if(n>1) {
1374 		//std::cerr << "merging" << std::endl;
1375 		auto first=tr.begin(it); // component node
1376 		auto other=first;
1377 		++other;
1378 		auto fi=tr.end(first);
1379 		--fi;
1380 		// Add the free indices of 'other' to 'first'.
1381 		while(other!=tr.end(it)) {
1382 			auto oi=tr.begin(other);
1383 			while(oi!=tr.end(other)) {
1384 				if(oi->is_index()==false)
1385 					break;
1386 				tr.insert_subtree(fi, oi);
1387 				++oi;
1388 				}
1389 			++other;
1390 			}
1391 
1392 		// Now do an outer combination of all possible indexvalue/componentvalue
1393 		// in the various component nodes.
1394 		auto comma1=tr.end(first);
1395 		--comma1;
1396 		other=first;
1397 		++other;
1398 		while(other!=tr.end(it)) {
1399 			Ex newcomma("\\comma"); // List of index value combinations and associated component values
1400 			auto comma2=tr.end(other);
1401 			--comma2;
1402 			assert(*comma1->name=="\\comma");
1403 			assert(*comma2->name=="\\comma");
1404 			auto eq1=tr.begin(comma1);    // The \equals node
1405 			while(eq1!=tr.end(comma1)) {
1406 				auto eq2=tr.begin(comma2);
1407 				while(eq2!=tr.end(comma2)) {
1408 					// Collect all index values.
1409 					auto neq = newcomma.append_child(newcomma.begin(), str_node("\\equals"));
1410 					auto ncm = newcomma.append_child(neq, str_node("\\comma")); // List of index values
1411 					auto iv=tr.begin(tr.begin(eq1));
1412 					while(iv!=tr.end(tr.begin(eq1))) {
1413 						newcomma.append_child(ncm, iterator(iv));
1414 						++iv;
1415 						}
1416 					iv=tr.begin(tr.begin(eq2));
1417 					while(iv!=tr.end(tr.begin(eq2))) {
1418 						newcomma.append_child(ncm, iterator(iv));
1419 						++iv;
1420 						}
1421 					// Multiply component values.
1422 					Ex prod(*it->name);
1423 					iv=tr.end(eq1);
1424 					--iv;
1425 					prod.append_child(prod.begin(), iterator(iv));
1426 					iv=tr.end(eq2);
1427 					--iv;
1428 					prod.append_child(prod.begin(), iterator(iv));
1429 					cleanup_dispatch_deep(kernel, prod);
1430 					newcomma.append_child(neq, prod.begin());
1431 					++eq2;
1432 					}
1433 				++eq1;
1434 				}
1435 			// Now replace the original comma1 node with newcomma, and re-iterate if there
1436 			// are further factors in the tensor product.
1437 			comma1 = tr.move_ontop(iterator(comma1), newcomma.begin());
1438 			other=tr.erase(other);
1439 			}
1440 		//		std::cerr << Ex(it) << std::endl;
1441 		}
1442 
1443 	// At this stage, there should be only one factor in the product, which
1444 	// should be a \components node. We do a cleanup, after which it should be
1445 	// at the 'it' node.
1446 
1447 	assert(*it->name=="\\prod" || *it->name=="\\wedge" || *it->name=="\\frac");
1448 	assert(tr.number_of_children(it)==1);
1449 	assert(*tr.begin(it)->name=="\\components");
1450 	tr.begin(it)->fl.bracket=it->fl.bracket;
1451 	tr.begin(it)->fl.parent_rel=it->fl.parent_rel;
1452 	tr.begin(it)->multiplier=it->multiplier;
1453 	tr.flatten(it);
1454 	it=tr.erase(it);
1455 	push_down_multiplier(kernel, tr, it);
1456 
1457 	//	iterator pr=tr.end();
1458 	//	if(tr.is_head(it)==false) {
1459 	//		pr=tr.parent(it);
1460 	//		std::cerr << "Tracing just before merge:\n " << Ex(pr) << std::endl;
1461 	//		}
1462 
1463 	merge_component_children(it);
1464 
1465 	//	if(pr!=tr.end())
1466 	//		std::cerr << "after component merge:\n " << Ex(pr) << std::endl;
1467 
1468 	//	cleanup_dispatch(kernel, tr, it);
1469 	//	if(pr!=tr.end())
1470 	//		std::cerr << "And afterwards:\n " << Ex(pr) << std::endl;
1471 
1472 	if(*it->name!="\\components") {
1473 		// The result is a scalar. Because we are expected to return
1474 		// a \components node, we wrap this scalar again.
1475 		// std::cerr << "wrapping scalar" << std::endl;
1476 		it=wrap_scalar_in_components_node(it);
1477 		// std::cerr << Ex(it) << std::endl;
1478 		}
1479 
1480 	//	else {
1481 	//		// We may have duplicate index value entries; merge them.
1482 	//		merge_component_children(it);
1483 	//		}
1484 
1485 	// Use sympy to simplify components.
1486 	if(call_sympy)
1487 		simplify_components(it);
1488 	//std::cerr << "simplified:\n" << Ex(it) << std::endl;
1489 
1490 	return it;
1491 	}
1492