|
4 | 4 | #include "DisplaySympy.hh" |
5 | 5 | #include "properties/Depends.hh" |
6 | 6 | #include "properties/Accent.hh" |
| 7 | +#include "properties/Derivative.hh" |
7 | 8 | #include <regex> |
8 | 9 |
|
9 | 10 | // #define DEBUG 1 |
@@ -201,6 +202,9 @@ void DisplaySympy::print_children(std::ostream& str, Ex::iterator it, int ) |
201 | 202 | // deplist is always a \comma node |
202 | 203 | auto sib=tree.begin(deplist.begin()); |
203 | 204 | 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"); |
204 | 208 | dispatch(str, sib); |
205 | 209 | ++sib; |
206 | 210 | if(sib!=tree.end(deplist.begin())) |
@@ -522,6 +526,16 @@ void DisplaySympy::print_partial(std::ostream& str, Ex::iterator it) |
522 | 526 | } |
523 | 527 | ++sib; |
524 | 528 | } |
| 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. |
525 | 539 | sib=tree.begin(it); |
526 | 540 | while(sib!=tree.end(it)) { |
527 | 541 | if(sib->fl.parent_rel!=str_node::p_none) { |
@@ -654,11 +668,55 @@ void DisplaySympy::import(Ex& ex) |
654 | 668 |
|
655 | 669 | args=nxt; |
656 | 670 | } |
| 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 | + |
657 | 715 | // ex.flatten(comma); |
658 | 716 | // ex.erase(comma); |
659 | 717 | // } |
660 | 718 | } |
661 | 719 |
|
662 | 720 | return it; |
663 | | - }); |
| 721 | + }); |
664 | 722 | } |
0 commit comments