Defining Custom Node Types¶
Mathematical expressions are only the first step. Most of the time, in mathematical software, the interesting aspects are special "things" that are strung together by expressions.
So it would be helpful to be able to define our own expression types:
In [2]:
import pymbolic.primitives as p
x = p.Variable("x")
In [3]:
class DerivativeOperator(p.Expression):
def __init__(self, operand):
self.operand = operand
def __getinitargs__(self):
return (self.operand,)
mapper_method = "map_derivative_operator"
__getinitargs__
tells pymbolic
what the arguments of the constructor were. This is used for printing and comparisons.
In [4]:
u = x/DerivativeOperator((x + 23)**0.5)
u
Out[4]:
Quotient(Variable('x'), DerivativeOperator(Power(Sum((Variable('x'), 23)), 0.5)))
We can then also define custom mappers (let's call ours DerivDoubler
) that operate on these node types:
In [5]:
from pymbolic.mapper import IdentityMapper
In [6]:
class DerivDoubler(IdentityMapper):
def map_derivative_operator(self, expr):
return 2*DerivativeOperator(self.rec(expr.operand))
Now apply it:
In [7]:
dd = DerivDoubler()
dd(u)
Out[7]:
Quotient(Variable('x'), Product((2, DerivativeOperator(Power(Sum((Variable('x'), 23)), 0.5)))))
In [ ]: