# 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 [2]:

    from pymbolic import parse
    from pymbolic.mapper.evaluator import EvaluationMapper

    expr = parse("(x**2 + y**2)**0.5")
    expr

Out[2]:

    Power(Sum((Power(Variable('x'), 2), Power(Variable('y'), 2))), 0.5)

In [3]:

    print(expr)

    (x**2 + y**2)**0.5

In [4]:

    evm = EvaluationMapper({"x": 17, "y": 3})

    print(evm(expr))

    17.26267650163207

This is just a normal mapper, so its behavior can be overridden as described before.

## Finding Independent Variables¶

In [5]:

    from pymbolic.mapper.dependency import DependencyMapper

    depmap = DependencyMapper()
    depmap(expr)

Out[5]:

    {Variable('x'), Variable('y')}

## Code generation¶

In [6]:

    from pymbolic.mapper.c_code import CCodeMapper

    ccm = CCodeMapper()
    x = parse("x")
    ccm((x+4)**17)

Out[6]:

    '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 [20]:

    u = (x+4)**3

    h = parse("h")

    expr = u + 2*u*h + 4*u*h**2
    ccm(expr)

Out[20]:

    '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 [21]:

    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.)