# coding: utf-8 # # 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) # ## Evaluation # In[1]: from pymbolic import parse from pymbolic.mapper.evaluator import EvaluationMapper expr = parse("(x**2 + y**2)**0.5") expr # In[3]: print(expr) # In[2]: evm = EvaluationMapper({"x": 17, "y": 3}) print(evm(expr)) # This is just a normal mapper, so its behavior can be overridden as described before. # ## Finding Independent Variables # In[3]: from pymbolic.mapper.dependency import DependencyMapper depmap = DependencyMapper() depmap(expr) # ## Code generation # In[4]: from pymbolic.mapper.c_code import CCodeMapper ccm = CCodeMapper() x = parse("x") ccm((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) # 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) # (These names can be customized, in case you're wondering.)