import pymbolic.primitives as p
x = p.Variable("x")
u = (x+3)**5
u
Many options to walk this expression.
if isinstance
checksp.Sum.mapper_method
from pymbolic.mapper import WalkMapper
class MyMapper(WalkMapper):
def map_sum(self, expr):
print("sum", expr.children)
u = (x+3)**5
u
mymapper = MyMapper()
mymapper(u)
What if there is another sum nested inside our existing one?
u = (x+3)**5 + 5
u
mymapper(u)
What do you notice? Is something missing?
Improve implementation as MyMapper2
:
from pymbolic.mapper import WalkMapper
class MyMapper2(WalkMapper):
def map_sum(self, expr):
print("sum", expr.children)
for ch in expr.children:
self.rec(ch)
mymapper2 = MyMapper2()
mymapper2(u)
map_variable
? map_power
?This makes it easy to inherit a base behavior and then selectively change a few pieces.
For example: Could return a string.
from pymbolic.mapper import RecursiveMapper
class MyStringifier(RecursiveMapper):
def map_sum(self, expr):
return "+".join(self.rec(ch) for ch in expr.children)
def map_product(self, expr):
return "*".join(self.rec(ch) for ch in expr.children)
def map_variable(self, expr):
return expr.name
def map_constant(self, expr):
return str(expr)
u = (x * 5)+(x * 7)
mystrifier = MyStringifier()
mystrifier(u)
Mappers can also return another expression. IdentityMapper
is a base that returns an identical (deep) copy of an expression:
from pymbolic.mapper import IdentityMapper
idmap = IdentityMapper()
u2 = idmap(u)
print(u2 == u)
print(u2 is u)
IdentityMapper
can be used as a convenient base for term rewriting.
As a very simple example, let us
class MyIdentityMapper(IdentityMapper):
def map_variable(self, expr):
return p.Variable(expr.name + "'")
def map_product(self, expr):
return p.Sum(tuple(self.rec(ch) for ch in expr.children))
u = (x*3)*(x+17)**3
myidmap = MyIdentityMapper()
print(myidmap(u))