Transformers
A transformer can be viewed as a function that, when called, transform an expression that it gets as an argument into another expression. It is similar to a computation graph. The reasons for transformers in Symbolica are twofold:
- Delayed execution
- High-performance execution
The delayed execution is explained in the pattern matching where the right-hand side should be transformed, but only after substitution of the wildcard.
High-performance execution in Symbolica can also be achieved even when running from Python. As is well known, Python generally does not achieve performance similar to Rust as it is not a compiled language. However, we can use transformers to build a program that is run entirely in Rust.
A simple example of a transformer is:
from symbolica import Transformer
= Transformer().expand() t
Transformer().expand()
is similar to lambda x: x.expand()
A transformer can be executed
by calling execute()
on it. For this, the input expression must be known. One way to give input is to call transform()
on an Expression
:
from symbolica import Transformer
= Expression.parse('(x+1)^2')
e e.transform().expand().execute()
Some functions take an unbound transformer as an input (with no expression set). An example is the map()
function uses for term streaming and the replace_all()
function.
Below is an example in Python that uses the repeat
transformer, which takes a list of transformers that it will repeat until there are no more changes between the input and output expression.
= Expression.symbol('x_')
x_ = Expression.symbol('f')
f = Expression.parse('f(100)')
e
= e.transform().repeat(
e
Transformer().expand(),- 1) + f(x_ - 2), x_.req_gt(1))
Transformer().replace_all(f(x_), f(x_ ).execute()
Transformers can be chained, so the program above can also be rewritten
from symbolica import Expression, Transformer
= Expression.symbol('x_')
x_ = Expression.symbol('f')
f = Expression.parse('f(100)')
e
= e.transform().repeat(
e - 1) + f(x_ - 2), x_.req_gt(1))
Transformer().expand().replace_all(f(x_), f(x_ ).execute()