# Welcome to pymbolic!¶

Pymbolic is a simple and extensible package for precise manipulation of symbolic expressions in Python. It doesn’t try to compete with sympy as a computer algebra system. Pymbolic emphasizes providing an extensible expression tree and a flexible, extensible way to manipulate it.

## A taste of pymbolic¶

Follow along on a simple example. Let’s import pymbolic and create a symbol, x in this case.

>>> import pymbolic as pmbl

>>> x = pmbl.var("x")
>>> x
Variable('x')


Next, let’s create an expression using x:

>>> u = (x+1)**5
>>> u
Power(Sum((Variable('x'), 1)), 5)
>>> print(u)
(x + 1)**5


Note the two ways an expression can be printed, namely repr() and str(). pymbolic purposefully distinguishes the two.

pymbolic does not perform any manipulations on expressions you put in. It has a few of those built in, but that’s not really the point:

>>> print(pmbl.differentiate(u, 'x'))
5*(x + 1)**4


### Manipulating expressions¶

The point is for you to be able to easily write so-called mappers to manipulate expressions. Suppose we would like all sums replaced by products:

>>> from pymbolic.mapper import IdentityMapper
>>> class MyMapper(IdentityMapper):
...     def map_sum(self, expr):
...         return pmbl.primitives.Product(expr.children)
...
>>> print(u)
(x + 1)**5
>>> print(MyMapper()(u))
(x*1)**5


### Custom Objects¶

You can also easily define your own objects to use inside an expression:

>>> from pymbolic.primitives import Expression
>>> class FancyOperator(Expression):
...     def __init__(self, operand):
...         self.operand = operand
...
...     def __getinitargs__(self):
...         return (self.operand,)
...
...     mapper_method = "map_fancy_operator"
...
>>> u
Power(Sum((Variable('x'), 1)), 5)
>>> 17*FancyOperator(u)
Product((17, FancyOperator(Power(Sum((Variable('x'), 1)), 5))))


As a final example, we can now derive from MyMapper to multiply all FancyOperator instances by 2.

>>> class MyMapper2(MyMapper):
...     def map_fancy_operator(self, expr):
...         return 2*FancyOperator(self.rec(expr.operand))
...
>>> MyMapper2()(FancyOperator(u))
Product((2, FancyOperator(Power(Product((Variable('x'), 1)), 5))))