Espresso ducumentation and thanks for all the fish
Espresso.jl Documentation
Expression parsing and rewriting
Expression matching
matchex
 match expression by pattern, extract matching elements. Elements of expression are matched to placeholders  symbols in pattern that start with '_' or any symbols passed in phs
parameter.
matchex(:(_x^2), :(u^2))
# Nullable(Dict{Symbol,Any}(:_x=>:u))
matchex(:(x^n), :(u^2); phs=Set([:x, :n]))
# Nullable(Dict{Symbol,Any}(:x=>:u,:n=>2))
See also matchingex
. See also findex
.
Expression substitution
subs
 substitute elements of in expression according to substitution table:
ex = :(x ^ n)
subs(ex, x=2)
# :(2 ^ n)
Expression rewriting
rewrite
 rewrite an expression matching it to a pattern and replacing corresponding placeholders in substitution expression.
ex = :(u ^ v)
pat = :(_x ^ _n)
subex = :(_n * _x ^ (_n  1))
rewrite(ex, pat, subex)
# :(v * u ^ (v  1))
See also tryrewrite
.
Expression simplification
simplify
 simplify numeric expression if possible.
simplify(:(2  1))
# 1
simplify(:(1 * (2x^1)))
# :(2x)
Einstein indexing notation
Espresso.jl also supports expressions in Einstein indexing notation and is mostly compatible with Einsum.jl. The most important functions are:
to_einstein
 convert vectorized expression to Einstein notation.
to_einstein(:(W*x + b); W=rand(3,4), x=rand(4), b=rand(3))
# quote
# tmp1[i] = W[i,k] * x[k]
# tmp2[i] = tmp1[i] + b[i]
# end
Here W=rand(3,4)
, x=rand(4)
and b=rand(3)
are example values  anything that has the same type and dimensions as real expected values.
from_einstein
 convert an expression in Einstein notation to vectorized form if possible.
from_einstein(:(W[i,k] * x[k] + b[i]))
# quote
# tmp1 = W * x
# tmp2 = tmp1 + b
# end
ExGraph
On lowlevel many functions of Espresso.jl use ExGraph
 expression graph, represented as a topologically sorted list of primitive expression. Example:
g = ExGraph(:(W*x + b); W=rand(3,4), x=rand(4), b=rand(3))
# ExGraph
# ExNode{input}(W = W  <Array{Float64,2}>)
# ExNode{input}(x = x  <Array{Float64,1}>)
# ExNode{input}(b = b  <Array{Float64,1}>)
# ExNode{call}(tmp1 = W * x  nothing)
# ExNode{call}(tmp2 = tmp1 + b  nothing)
The main advantage of using such representation is that each node represents exactly one simple enough expression such as assignment or function call. For example, to_einstein
and from_einstein
both use ExGraph
to find rule for transforming between two notations.
Functions
#
Espresso.matchex
— Method.
Match expression ex
to a pattern pat
, return nullable dictionary of matched symbols or rpatpressions. Example:
ex = :(u ^ v)
pat = :(_x ^ _n)
matchex(pat, ex)
# ==> Nullable(Dict{Symbol,Any}(:_n=>:v,:_x=>:u))
NOTE: two symbols match if they are equal or symbol in pattern is a placeholder. Placeholder is any symbol that starts with ''. It's also possible to pass list of placeholder names (not necessarily starting wiht '') via phs
parameter:
ex = :(u ^ v)
pat = :(x ^ n)
matchex(pat, ex; phs=Set([:x, :n]))
# ==> Nullable(Dict{Symbol,Any}(:n=>:v,:x=>:u))
Several elements may be matched using ...
expression, e.g.:
ex = :(A[i, j, k])
pat = :(x[I...])
matchex(pat, ex; phs=Set([:x, :I]))
# ==> Nullable(Dict(:x=>:A, :I=>[:i,:j,:k]))
Optional parameters:
 phs::Set{Symbol} = DEFAULT_PHS[1] A set of placeholder symbols

allow_ex::Boolean = true Allow matchinng of symbol pattern to an expression. Example:
matchex(:(_x + 1), :(a*b + 1); allow_ex=true) # ==> matches matchex(:(_x + 1), :(a*b + 1); allow_ex=false) # ==> doesn't match
* exact::Boolean = false Allow matching of the same expression to different keysmatchex(:(_x + _y), :(a + a); exact=false) # ==> matches matchex(:(_x = _y), :(a + a); exact=true) # ==> doesn't match