Common Operations¶
What common operations are supported?¶
Just normal mappers:
- Evaluation
- Turning expressions into 'human-readable' strings
- Performing substitution
- Taking derivatives
- Finding variables on which an expression depends
- Code Generation
Also:
- Parsing (i.e. turning a string into an expression)
Finding Independent Variables¶
In [3]:
from pymbolic.mapper.dependency import DependencyMapper
depmap = DependencyMapper()
depmap(expr)
Out[3]:
{Variable('x'), Variable('y')}
In [ ]:
##
Code generation¶
In [4]:
from pymbolic.mapper.c_code import CCodeMapper
ccm = CCodeMapper()
x = parse("x")
ccm((x+4)**17)
Out[4]:
'pow(x + 4, 17)'
(We're using parse
here just to give us a Variable("x")
object.)
Common subexpressions¶
Often, some parts of an expression occur multiple times in a bigger expression.
In [5]:
u = (x+4)**3
h = parse("h")
expr = u + 2*u*h + 4*u*h**2
ccm(expr)
Out[5]:
'pow(x + 4, 3) + 4 * pow(x + 4, 3) * h * h + 2 * pow(x + 4, 3) * h'
Obviously, that doesn't lead to great code. In particular, the redundancy is carried through to the code side.
There is a mechanism to prevent this redundancy. Individual parts of an expression can be tagged as "common subexpressions".
In [6]:
from pymbolic.primitives import CommonSubexpression as CSE
u = CSE((x+4)**3)
h = parse("h")
expr = u + 2*u*h + 4*u*h**2
result = ccm(expr)
for name, value in ccm.cse_name_list:
print(name, "=", value)
print(result)
_cse0 = pow(x + 4, 3) _cse0 + 4 * _cse0 * h * h + 2 * _cse0 * h
(These names can be customized, in case you're wondering.)