Expression Manipulation
Symbolics.jl provides functionality for easily manipulating expressions. Most of the functionality comes by the expression objects obeying the standard mathematical semantics. For example, if one has A
a matrix of symbolic expressions wrapped in Num
, then A^2
calculates the expressions for the squared matrix. It is thus encouraged to use standard Julia for performing many of the manipulation on the IR. For example, calculating the sparse form of the matrix via sparse(A)
is valid, legible, and easily understandable to all Julia programmers.
Functionality Inherited From SymbolicUtils.jl
SymbolicUtils.substitute
— Functionsubstitute(expr, s)
Performs the substitution on expr
according to rule(s) s
.
Examples
julia> @variables t x y z(t)
4-element Vector{Num}:
t
x
y
z(t)
julia> ex = x + y + sin(z)
(x + y) + sin(z(t))
julia> substitute(ex, Dict([x => z, sin(z) => z^2]))
(z(t) + y) + (z(t) ^ 2)
SymbolicUtils.simplify
— Functionsimplify(x; expand=false,
threaded=false,
thread_subtree_cutoff=100,
rewriter=nothing)
Simplify an expression (x
) by applying rewriter
until there are no changes. expand=true
applies expand
in the beginning of each fixpoint iteration.
By default, simplify will assume denominators are not zero and allow cancellation in fractions. Pass simplify_fractions=false
to prevent this.
Documentation for rewriter
can be found here, using the @rule
macro or the @acrule
macro from SymbolicUtils.jl.
Additional Manipulation Functions
Other additional manipulation functions are given below.
Symbolics.get_variables
— Functionget_variables(O) -> Vector{BasicSymbolic}
Returns the variables in the expression. Note that the returned variables are not wrapped in the Num
type.
Examples
julia> @variables t x y z(t)
4-element Vector{Num}:
t
x
y
z(t)
julia> ex = x + y + sin(z)
(x + y) + sin(z(t))
julia> Symbolics.get_variables(ex)
3-element Vector{Any}:
x
y
z(t)
Symbolics.tosymbol
— Functiontosymbol(x::Union{Num,Symbolic}; states=nothing, escape=true) -> Symbol
Convert x
to a symbol. states
are the states of a system, and escape
means if the target has escapes like val"y(t)"
. If escape
is false, then it will only output y
instead of y(t)
.
Examples
julia> @variables t z(t)
2-element Vector{Num}:
t
z(t)
julia> Symbolics.tosymbol(z)
Symbol("z(t)")
julia> Symbolics.tosymbol(z; escape=false)
:z
Symbolics.diff2term
— Functiondiff2term(x) -> Symbolic
Convert a differential variable to a Term
. Note that it only takes a Term
not a Num
.
julia> @variables x t u(x, t) z(t)[1:2]; Dt = Differential(t); Dx = Differential(x);
julia> Symbolics.diff2term(Symbolics.value(Dx(Dt(u))))
uˍtx(x, t)
julia> Symbolics.diff2term(Symbolics.value(Dt(z[1])))
var"z(t)[1]ˍt"
Symbolics.solve_for
— Functionsolve_for(eq, var; simplify, check) -> Any
Solve equation(s) eqs
for a set of variables vars
.
Assumes length(eqs) == length(vars)
Currently only works if all equations are linear. check
if the expr is linear w.r.t vars
.
Examples
julia> @variables x y
2-element Vector{Num}:
x
y
julia> Symbolics.solve_for(x + y ~ 0, x)
-y
julia> Symbolics.solve_for([x + y ~ 0, x - y ~ 2], [x, y])
2-element Vector{Float64}:
1.0
-1.0
Symbolics.degree
— Functiondegree(p, sym=nothing)
Extract the degree of p
with respect to sym
.
Examples
julia> @variables x;
julia> Symbolics.degree(x^0)
0
julia> Symbolics.degree(x)
1
julia> Symbolics.degree(x^2)
2
Symbolics.coeff
— Functioncoeff(p, sym=nothing)
Extract the coefficient of p
with respect to sym
. Note that p
might need to be expanded and/or simplified with expand
and/or simplify
.
Examples
julia> @variables a x y;
julia> Symbolics.coeff(2a, x)
0
julia> Symbolics.coeff(3x + 2y, y)
2
julia> Symbolics.coeff(x^2 + y, x^2)
1
Base.replace
— Functionreplace(expr::Symbolic, rules...)
Walk the expression and replace subexpressions according to rules
. rules
could be rules constructed with @rule
, a function, or a pair where the left hand side is matched with equality (using isequal
) and is replaced by the right hand side.
Rules will be applied left-to-right simultaneously, so only one pattern will be applied to any subexpression, and the patterns will only be applied to the input text, not the replacements.
Set fixpoint = true
to repeatedly apply rules until no change to the expression remains to be made.
Base.occursin
— Functionoccursin(c, x)
Returns true if any part of x
fufills the condition given in c. c can be a function or an expression. If it is a function, returns true if x is true for any part of x. If c is an expression, returns true if x contains c.
Examples:
@syms x y
Symbolics.occursin(x, log(x) + x + 1) # returns `true`.
Symbolics.occursin(x, log(y) + y + 1) # returns `false`.
@variables t X(t)
D = Differential(t)
Symbolics.occursin(Symbolics.is_derivative, X + D(X) + D(X^2)) # returns `true`.
occursin(needle::Symbolic, haystack::Symbolic)
Determine whether the second argument contains the first argument. Note that this function doesn't handle associativity, commutativity, or distributivity.
Symbolics.filterchildren
— Functionfilterchildren(c, x) Returns all parts of x
that fufills the condition given in c. c can be a function or an expression. If it is a function, returns everything for which the function is true
. If c is an expression, returns all expressions that matches it.
Examples:
@syms x
Symbolics.filterchildren(x, log(x) + x + 1)
returns [x, x]
@variables t X(t)
D = Differential(t)
Symbolics.filterchildren(Symbolics.is_derivative, X + D(X) + D(X^2))
returns [Differential(t)(X(t)^2), Differential(t)(X(t))]
Symbolics.fixpoint_sub
— Functionfixpoint_sub(expr, dict; operator = Nothing)
Given a symbolic expression, equation or inequality expr
perform the substitutions in dict
recursively until the expression does not change. Substitutions that depend on one another will thus be recursively expanded. For example, fixpoint_sub(x, Dict(x => y, y => 3))
will return 3
. The operator
keyword can be specified to prevent substitution of expressions inside operators of the given type.
See also: fast_substitute
.
Symbolics.fast_substitute
— Functionfast_substitute(expr, dict; operator = Nothing)
Given a symbolic expression, equation or inequality expr
perform the substitutions in dict
. This only performs the substitutions once. For example, fast_substitute(x, Dict(x => y, y => 3))
will return y
. The operator
keyword can be specified to prevent substitution of expressions inside operators of the given type.
See also: fixpoint_sub
.