# How to implement 'derivative' in ExpressionTreeWalker

I am trying to implement a method that requires traversing the expression tree. I have no problem with arithmetic functions, but I can't figure out how to deal with derivatives. Take this simple implementation for example:

sage: from sage.symbolic.expression_conversions import ExpressionTreeWalker
....: class ShowTree(ExpressionTreeWalker):
....:     def __init__(self, ring):
....:         self.ring = ring
....:     def arithmetic(self, ex, op):
....:         r = reduce(op, map(self, ex.operands()))
....:         print(['>>',ex, ex.operands(),op])
....:         return r
....:     def derivative(self, ex, op):
....:         r = operator(*map(self, ex.operands()))
....:         print(['d>>',ex, ex.operands(),op])
....:         return r


If you run it in the following:

var("a,b,x")
f = function('f')(x)
ShowTree(SR)(a*b+b*f(x).diff(x,2))


The following error occurs:

['>>', a*b, [a, b], <function mul_vararg at 0x34863e8c8>]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
....
<ipython-input-217-df4a3880d6a1> in derivative(self, ex, op)
8         return r
9     def derivative(self, ex, op):
---> 10         r = operator(*map(self, ex.operands()))
11         print(['d>>',ex, ex.operands(),op])
12         return r

TypeError: 'module' object is not callable


If that line is changed to:

    r = reduce(op,map(self, ex.operands()))


The result becomes:

(a, b, x)
['>>', a*b, [a, b], <function mul_vararg at 0x342dacbf8>]
['d>>', diff(f(x), x, x), [x], D[0, 0](f)]
['>>', b*diff(f(x), x, x), [b, diff(f(x), x, x)], <function mul_vararg at 0x342dacbf8>]
['>>', a*b + b*diff(f(x), x, x), [a*b, b*diff(f(x), x, x)], <function add_vararg at 0x342dacb70>]
a*b + b*x


That is the derivative operator is removed and substituted for the argument of the operator.

ExpressionTreeWalker is poorly documented at best, and I can't figure out what is expected as a return value from the derivative method (my first attempt comes from looking at the existing implementation). What am I missing?

edit retag close merge delete

Sort by ยป oldest newest most voted

What if you replace

r = operator(*map(self, ex.operands()))


with

r = op(*map(self, ex.operands()))


operator is a module, here you might want to refer to the op parameter of the method derivative.

more

Yes!! That works. Thanks!!

( 2020-09-28 21:31:22 +0200 )edit