Skip to content

Commit 3ba44d4

Browse files
committed
Added 'with_respect_to' argument to Derivative, and updated docs.
1 parent bbe8803 commit 3ba44d4

File tree

7 files changed

+232
-35
lines changed

7 files changed

+232
-35
lines changed

core/DisplaySympy.cc

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "DisplaySympy.hh"
55
#include "properties/Depends.hh"
66
#include "properties/Accent.hh"
7+
#include "properties/Derivative.hh"
78
#include <regex>
89

910
// #define DEBUG 1
@@ -201,6 +202,9 @@ void DisplaySympy::print_children(std::ostream& str, Ex::iterator it, int )
201202
// deplist is always a \comma node
202203
auto sib=tree.begin(deplist.begin());
203204
while(sib!=tree.end(deplist.begin())) {
205+
const Derivative *dep_is_derivative=kernel.properties.get<Derivative>(sib);
206+
if(dep_is_derivative)
207+
throw RuntimeException("Dependencies on derivatives are not yet handled in the SymPy bridge");
204208
dispatch(str, sib);
205209
++sib;
206210
if(sib!=tree.end(deplist.begin()))
@@ -522,6 +526,16 @@ void DisplaySympy::print_partial(std::ostream& str, Ex::iterator it)
522526
}
523527
++sib;
524528
}
529+
// write the implicit direction of the derivative, if any.
530+
const Derivative *derivative = kernel.properties.get<Derivative>(it);
531+
if(derivative) {
532+
if(derivative->with_respect_to.size()>0) {
533+
str << ", ";
534+
dispatch(str, derivative->with_respect_to.begin());
535+
}
536+
}
537+
538+
// write the explicit direction(s) of the derivative.
525539
sib=tree.begin(it);
526540
while(sib!=tree.end(it)) {
527541
if(sib->fl.parent_rel!=str_node::p_none) {
@@ -654,11 +668,55 @@ void DisplaySympy::import(Ex& ex)
654668

655669
args=nxt;
656670
}
671+
672+
// Strip subscripts which are the same as the 'with_respect_to' member of the
673+
// derivative (if any), as these are implicit in Cadabra. This is tricky, because
674+
// a multiple derivative with respect to this argument needs to be replaced
675+
// with a multiple nesting of the derivative operator itself, e.g.
676+
// \partial{\partial{r}} -> diff(diff(r(t),t),t) -> diff(r(t),t,t)
677+
678+
const Derivative *derivative = kernel.properties.get<Derivative>(it);
679+
if(derivative) {
680+
#ifdef DEBUG
681+
std::cerr << "is proper derivative" << std::endl;
682+
#endif
683+
if(derivative->with_respect_to.size()>0) {
684+
auto it_copy=it;
685+
args=ex.begin(it_copy);
686+
bool first=true;
687+
while(args!=ex.end(it_copy)) {
688+
#ifdef DEBUG
689+
std::cerr << "Comparing: " << args << std::endl
690+
<< "and " << derivative->with_respect_to.begin()
691+
<< std::endl;
692+
#endif
693+
694+
if(subtree_equal(0, args, derivative->with_respect_to.begin(), 0) ) {
695+
args=ex.erase(args);
696+
if(first) {
697+
first=false;
698+
}
699+
else {
700+
it=ex.wrap(it, str_node(it->name));
701+
}
702+
}
703+
else
704+
++args;
705+
}
706+
}
707+
}
708+
else {
709+
#ifdef DEBUG
710+
std::cerr << it << " is not a proper derivative" << std::endl;
711+
#endif
712+
713+
}
714+
657715
// ex.flatten(comma);
658716
// ex.erase(comma);
659717
// }
660718
}
661719

662720
return it;
663-
});
721+
});
664722
}

core/SympyCdb.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ pybind11::object sympy::SympyBridge::export_ex()
3131
output(str);
3232
pybind11::module sympy_parser = pybind11::module::import("sympy.parsing.sympy_parser");
3333
auto parse = sympy_parser.attr("parse_expr");
34+
#ifdef DEBUG
35+
std::cerr << str.str() << std::endl;
36+
#endif
3437
pybind11::object ret = parse(str.str());
3538

3639
return ret;

core/algorithms/unwrap.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,16 +143,22 @@ Algorithm::result_t unwrap::apply(iterator& it)
143143
#ifdef DEBUG
144144
std::cerr << *factor->name << " acted on by " << *old_it->name << "; depends" << std::endl;
145145
#endif
146+
auto derivative=kernel.properties.get<Derivative>(old_it);
146147
Ex deps=dep->dependencies(kernel, factor /* it */);
147148
sibling_iterator depobjs=deps.begin(deps.begin());
148149
while(depobjs!=deps.end(deps.begin())) {
149150
#ifdef DEBUG
150151
std::cerr << "?" << *old_it->name << " == " << *depobjs->name << std::endl;
151152
#endif
153+
// FIXME: need to compare more than the name
152154
if(old_it->name == depobjs->name) {
153155
move_out=false;
154156
break;
155157
}
158+
else if(derivative && derivative->with_respect_to.size()>0 && derivative->with_respect_to.begin()->name==depobjs->name) {
159+
move_out=false;
160+
break;
161+
}
156162
else {
157163
// compare all indices
158164
#ifdef DEBUG

core/properties/Derivative.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@
55

66
using namespace cadabra;
77

8+
bool Derivative::parse(Kernel&, std::shared_ptr<Ex>, keyval_t& keyvals)
9+
{
10+
keyval_t::const_iterator ki=keyvals.begin();
11+
while(ki!=keyvals.end()) {
12+
if(ki->first=="to") {
13+
with_respect_to=ki->second;
14+
}
15+
++ki;
16+
}
17+
return true;
18+
}
19+
820
unsigned int Derivative::size(const Properties& properties, Ex& tr, Ex::iterator it) const
921
{
1022
it=properties.head<Derivative>(it);

core/properties/Derivative.hh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ namespace cadabra {
2828
virtual unsigned int size(const Properties&, Ex&, Ex::iterator) const override;
2929
virtual tab_t get_tab(const Properties&, Ex&, Ex::iterator, unsigned int) const override;
3030
virtual multiplier_t value(const Kernel&, Ex::iterator, const std::string& forcedlabel) const override;
31+
virtual bool parse(Kernel&, std::shared_ptr<Ex>, keyval_t& keyvals) override;
32+
virtual std::string unnamed_argument() const override
33+
{
34+
return "to";
35+
};
36+
37+
Ex with_respect_to;
3138
};
3239

3340
}

0 commit comments

Comments
 (0)