Skip to content

Commit df9daeb

Browse files
committed
Merge branch 'fix/evaluate_with_partial'
2 parents fa0aced + 6d05b37 commit df9daeb

File tree

7 files changed

+102
-41
lines changed

7 files changed

+102
-41
lines changed

core/DisplayTeX.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -430,8 +430,8 @@ void DisplayTeX::print_fraclike(std::ostream& str, Ex::iterator it)
430430
if(mult * (*it->multiplier)!=1) {
431431
print_multiplier(str, it, mult);
432432
}
433-
434-
dispatch(str, num);
433+
if(num->is_rational()==false || (mult * (*it->multiplier))==1)
434+
dispatch(str, num);
435435
str << "}{";
436436
dispatch(str, den);
437437
str << "}";

core/DisplayTerminal.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,8 @@ void DisplayTerminal::print_fraclike(std::ostream& str, Ex::iterator it)
352352
// if(needs_brackets(num))
353353
// str << "(";
354354

355-
dispatch(str, num);
355+
if(num->is_rational()==false || (*it->multiplier)==1)
356+
dispatch(str, num);
356357

357358
// if(needs_brackets(num))
358359
// str << ")";

core/Permutations.hh

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ class Perm {
2424
std::vector<int> perm;
2525

2626
/// Find the permutation that takes [start1, end1> to [start2, end2>.
27+
/// This will be available in 'perm' afterwards.
2728
template<class iterator>
2829
void find(iterator start1, iterator end1, iterator start2, iterator end2);
2930

30-
/// Apply the permutation on the range.
31+
/// Apply the permutation 'perm' on the given range.
3132
template<class iterator>
3233
void apply(iterator start1, iterator end1);
3334

@@ -81,7 +82,11 @@ void Perm::apply(iterator start, iterator end)
8182
}
8283

8384
// std::cerr << orig.size() << ", " << perm.size() << std::endl;
84-
assert(orig.size()==perm.size());
85+
if(orig.size()!=perm.size()) {
86+
std::cerr << "Perm::apply: orig.size()=" << orig.size() << ", "
87+
<< "perm.size()=" << perm.size() << std::endl;
88+
assert(orig.size()==perm.size());
89+
}
8590

8691
for(unsigned int i=0; i<orig.size(); ++i) {
8792
*start=orig[perm[i]];

core/SympyCdb.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
using namespace cadabra;
1313

14-
#define DEBUG
14+
//#define DEBUG
1515

1616
Ex::iterator sympy::apply(const Kernel& kernel, Ex& ex, Ex::iterator& it, const std::vector<std::string>& wrap, const std::string& args,
1717
const std::string& method)

core/algorithms/evaluate.cc

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -364,18 +364,24 @@ void evaluate::merge_components(iterator it1, iterator it2)
364364
// we can be assured that the free indices match; they just may not be
365365
// in the same order).
366366

367+
#ifdef DEBUG
368+
std::cerr << "merge_components on " << Ex(it1) << " and " << Ex(it2) << std::endl;
369+
#endif
370+
367371
assert(*it1->name=="\\components");
368372
assert(*it2->name=="\\components");
369373
sibling_iterator sib1=tr.end(it1);
370374
--sib1;
371375
sibling_iterator sib2=tr.end(it2);
372376
--sib2;
377+
assert(*sib1->name=="\\comma");
378+
assert(*sib2->name=="\\comma");
373379

374-
// We cannot directly compare the lhs of this equals node with the lhs
375-
// of the equals node of the other components node, because the index
376-
// order on the two components nodes may be different. We first
377-
// have to ensure that the orders are the same (but only, of course)
378-
// if we have anything to permutate in the first place.
380+
// We cannot directly compare the lhs of the equals nodes of it1
381+
// with the lhs of the equals node of it2, because the index order
382+
// on the two components nodes may be different. We first have to
383+
// ensure that the orders are the same (but only, of course) if we
384+
// have anything to permutate in the first place.
379385

380386
if(*tr.begin(it1)->name!="\\comma") {
381387
// Look at all indices on the two components nodes. Find
@@ -384,14 +390,20 @@ void evaluate::merge_components(iterator it1, iterator it2)
384390
Perm perm;
385391
perm.find(tr.begin(it2), sib2, tr.begin(it1), sib1);
386392

387-
//perm.apply(tr.begin(it2), sib2);
388-
//std::cerr << "after permutation " << Ex(tr) << std::endl;
389-
393+
// For each \equals node in the it2 comma node, permute
394+
// the values so they agree with the index order on it1.
390395
cadabra::do_list(tr, sib2, [&](Ex::iterator nd) {
391-
auto lhs2 = tr.begin(nd);
392-
perm.apply(tr.begin(lhs2), tr.end(lhs2));
396+
// nd is an \equals node.
397+
assert(*nd->name=="\\equals");
398+
auto comma = tr.begin(nd);
399+
assert(*comma->name=="\\comma");
400+
perm.apply(tr.begin(comma), tr.end(comma));
393401
return true;
394402
});
403+
404+
#ifdef DEBUG
405+
std::cerr << "permutations done" << std::endl;
406+
#endif
395407
}
396408

397409
// Now all index orders match and we can simply compare index value sets.
@@ -527,8 +539,10 @@ Ex::iterator evaluate::handle_derivative(iterator it)
527539
size_t ni=number_of_direct_indices(it);
528540

529541
cadabra::do_list(tr, ivalues, [&](Ex::iterator iv) {
530-
// std::cerr << "====" << std::endl;
531-
// std::cerr << Ex(iv) << std::endl;
542+
#ifdef DEBUG
543+
std::cerr << "====" << std::endl;
544+
std::cerr << Ex(iv) << std::endl;
545+
#endif
532546
// For each internal dummy set, keep track of the
533547
// position in the permutation array where we generate
534548
// its value.
@@ -539,9 +553,11 @@ Ex::iterator evaluate::handle_derivative(iterator it)
539553
auto deps=dependencies(rhs);
540554

541555
// If the argument does not depend on anything, all derivatives
542-
// would produce zero.
543-
if(deps.size()==0)
556+
// would produce zero. Remove this \equals node from the tree.
557+
if(deps.size()==0) {
558+
tr.erase(iv);
544559
return true;
560+
}
545561

546562
// All indices on \partial can take any of the values of the
547563
// dependencies, EXCEPT when the index is a dummy index. In
@@ -556,7 +572,9 @@ Ex::iterator evaluate::handle_derivative(iterator it)
556572

557573
combin::combinations<Ex> cb;
558574
for(auto& obj: deps) {
559-
// std::cerr << "dep " << obj << std::endl;
575+
#ifdef DEBUG
576+
std::cerr << "dep " << obj << std::endl;
577+
#endif
560578
cb.original.push_back(obj);
561579
}
562580
cb.multiple_pick=true;
@@ -596,18 +614,24 @@ Ex::iterator evaluate::handle_derivative(iterator it)
596614
// derivative, create an entry in the \components node.
597615

598616
for(unsigned int i=0; i<cb.size() || cb.size()==0; ++i) {
599-
// std::cerr << "Index combination " << i << std::endl;
617+
#ifdef DEBUG
618+
std::cerr << "Index combination " << i << std::endl;
619+
#endif
600620
Ex eqcopy(iv);
601621
auto lhs=eqcopy.begin(eqcopy.begin());
602622
assert(*lhs->name=="\\comma");
603623

604624
if(cb.size()>0) {
625+
#ifdef DEBUG
626+
std::cerr << "Copying values of derivative indices" << std::endl;
627+
#endif
605628
// Setup the index values; simply copy from the cb array, but only
606629
// if the indices are not internal dummy.
607630
for(size_t j=0; j<cb[i].size(); ++j) {
608631
auto fd = ind_dummy.find(Ex(tr.child(it, j)));
609-
if(fd==ind_dummy.end())
632+
if(fd==ind_dummy.end()) {
610633
eqcopy.append_child(iterator(lhs), cb[i][j].begin() );
634+
}
611635
}
612636
}
613637
auto rhs=lhs;
@@ -672,14 +696,16 @@ Ex::iterator evaluate::handle_derivative(iterator it)
672696

673697
if(cb.size()==0) break;
674698
}
699+
700+
// Erase the original \equals entry (we generated a full replacement above).
675701
tr.erase(iv);
676702
return true;
677703
});
678704

679705
one(it->multiplier);
680706
// std::cerr << "now " << Ex(it) << std::endl;
681707

682-
708+
683709
// Now move the free (but not the internal dummy!) partial indices
684710
// to the components node, and then unwrap the partial node.
685711

@@ -707,11 +733,15 @@ Ex::iterator evaluate::handle_derivative(iterator it)
707733
++se;
708734
}
709735

710-
// std::cerr << "after index move " << Ex(it) << std::endl;
736+
#ifdef DEBUG
737+
std::cerr << "after index move " << Ex(it) << std::endl;
738+
#endif
711739

712740
merge_component_children(it);
713741

714-
// std::cerr << "after merge " << Ex(it) << std::endl;
742+
#ifdef DEBUG
743+
std::cerr << "after merge " << Ex(it) << std::endl;
744+
#endif
715745

716746
simplify_components(it);
717747
// std::cerr << "then " << Ex(it) << std::endl;

doc/cadabra2_hep.tex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,9 +493,9 @@ \subsection{Bianchi, Ricci and Schouten identities}
493493
494494
\toprule
495495
\begin{cdbin}
496-
\tableau{#}::FilledTableau(dimension=10).
497-
\tableau{0,0}{1,1} \tableau{a,a}{b,b}:
498-
@lr_tensor!(%);
496+
\ftableau{#}::FilledTableau(dimension=10).
497+
ex:=\ftableau{0,0}{1,1} \ftableau{a,a}{b,b}:
498+
lr_tensor(_);
499499
\end{cdbin}
500500
\begin{cdbout}
501501
\ftableau{{0}{0}{a}{a},{1}{1}{b}{b}} + \ftableau{{0}{0}{a}{a},{1}{1}{b},{b}} + \ftableau{{0}{0}{a}{a},{1}{1},{b}{b}} + \ftableau{{0}{0}{a},{1}{1}{b},{a},{b}} + \ftableau{{0}{0}{a},{1}{1},{a}{b},{b}} + \ftableau{{0}{0},{1}{1},{a}{a},{b}{b}};

tests/components.cdb

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ def test22():
418418
test22()
419419

420420
def test23():
421+
__cdbkernel__=create_scope()
421422
{r,t}::Coordinate;
422423
{a,b,c}::Indices(values={r,t}, position=fixed);
423424
\partial{#}::PartialDerivative;
@@ -453,18 +454,42 @@ test23()
453454
# rl:= \partial_{r}{ A_{t} } = 1;
454455
# evaluate(ex, rl);
455456

456-
{\theta, \varphi}::Coordinate;
457-
{\alpha, \beta, \gamma, \delta, \rho, \sigma, \mu, \nu, \lambda}::Indices(values={\varphi, \theta}, position=fixed);
458-
\partial{#}::PartialDerivative;
459-
g_{\alpha\beta}::Metric.
460-
g^{\alpha\beta}::InverseMetric.
457+
def test24():
458+
__cdbkernel__=create_scope()
459+
{\theta, \varphi}::Coordinate;
460+
{\alpha, \beta, \gamma, \delta, \rho, \sigma, \mu, \nu, \lambda}::Indices(values={\varphi, \theta}, position=fixed);
461+
\partial{#}::PartialDerivative;
462+
g_{\alpha\beta}::Metric.
463+
g^{\alpha\beta}::InverseMetric.
464+
465+
sphe:={ g_{\theta\theta} = r**2,
466+
g_{\varphi\varphi} = r**2 \sin(\theta)**2 }.
467+
complete(sphe, $g^{\alpha\beta}$)
468+
469+
ch:= \Gamma^{\alpha}_{\mu\nu} = 1/2 g^{\alpha\beta} ( \partial_{\nu}{g_{\beta\mu}}
470+
+\partial_{\mu}{g_{\beta\nu}}
471+
-\partial_{\beta}{g_{\mu\nu}} );
461472

462-
sphe:={ g_{\theta\theta} = r**2,
463-
g_{\varphi\varphi} = r**2 \sin(\theta)**2 }.
464-
# complete(sphe, $g^{\alpha\beta}$);
473+
evaluate(ch, sphe, rhsonly=True)
465474

466-
#ch:= \Gamma^{\alpha}_{\mu\nu} = 1/2 g^{\alpha\beta} ( \partial_{\nu}{g_{\beta\mu}}
467-
# +\partial_{\mu}{g_{\beta\nu}}
468-
# -\partial_{\beta}{g_{\mu\nu}} );
475+
rm:= R^{\rho}_{\sigma\mu\nu} = +\partial_{\mu}{\Gamma^{\rho}_{\sigma\nu}}
476+
-\partial_{\nu}{\Gamma^{\rho}_{\sigma\mu}}
477+
+\Gamma^{\rho}_{\beta\mu} \Gamma^{\beta}_{\sigma\nu}
478+
-\Gamma^{\rho}_{\beta\nu} \Gamma^{\beta}_{\sigma\mu};
469479

470-
# evaluate(ch, sphe, rhsonly=True);
480+
substitute(rm, ch)
481+
evaluate(rm, sphe, rhsonly=True)
482+
483+
ricci:= R_{\sigma\nu} = R^{\rho}_{\sigma\rho\nu};
484+
substitute(ricci, rm)
485+
evaluate(ricci, sphe, rhsonly=True)
486+
487+
R:= R = R_{\sigma\nu} g^{\sigma\nu};
488+
substitute(R, ricci)
489+
evaluate(R, sphe, rhsonly=True)
490+
val = rhs(R)
491+
tst:= @(val) - 2/r**2;
492+
assert(tst==0)
493+
print("Test 24 passed")
494+
495+
test24()

0 commit comments

Comments
 (0)