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
The substitute and simplify functions are provided by SymbolicUtils and reexported by Symbolics. Documentation for rewriter can be found here, using the @rule macro or the @acrule macro from SymbolicUtils.jl.
Functionality Provided by SymPy.jl Integration
SymPy also includes solves as well, and the SymPy.jl extensions allow for automatically converting Symbolics expressions for use in its simplifier.
Symbolics.sympy_simplify — Function
sympy_simplify(expr)Simplifies a Symbolics expression using SymPy.
Arguments
expr: Symbolics expression.
Returns
Simplified Symbolics expression.
Example
@variables x
expr = x^2 + 2x^2
result = sympy_simplify(expr)Additional Manipulation Functions
Other additional manipulation functions are given below.
SymbolicUtils.substitute — Function
substitute(expr, s; fold=Val(false))Performs the substitution on expr according to rule(s) s. If fold=Val(true), expressions which can be fully evaluated will be evaluated to a number.
As of Symbolics.jl v7 (SymbolicUtils.jl v4), substitute does not recurse into the arguments of Differential expressions. For example, substitute(D(x), Dict(x => y)) returns D(x), not D(y). Use substitute_in_deriv or substitute_in_deriv_and_depvar to substitute inside Differential applications.
Examples
julia> using Symbolics
julia> @variables t x y z(t)
4-element Vector{Num}:
t
x
y
z(t)
julia> ex = x + y + sin(z)
sin(z(t)) + x + y
julia> substitute(ex, Dict([x => z, sin(z) => z^2]))
y + z(t) + z(t)^2
julia> substitute(sqrt(2x), Dict([x => 1]))
sqrt(2)
julia> substitute(sqrt(2x), Dict([x => 1]); fold=Val(true))
1.4142135623730951Symbolics.get_variables — Function
get_variables(e, varlist = nothing; kw...)Return a vector of variables appearing in e, optionally restricting to variables in varlist. Takes the same keyword arguments as SymbolicUtils.search_variables.
Note that the returned variables are not wrapped in the Num type.
Examples ≡≡≡≡≡≡≡≡
julia> @variables t x y z(t);
julia> Symbolics.get_variables(x + y + sin(z))
3-element Vector{SymbolicUtils.BasicSymbolic}:
x
y
z(t)
julia> Symbolics.get_variables(x - y)
2-element Vector{SymbolicUtils.BasicSymbolic}:
x
ySymbolics.tosymbol — Function
tosymbol(x::Union{Num,BasicSymbolic}; states=nothing, escape=true) -> SymbolConvert 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)
:zSymbolics.diff2term — Function
diff2term(x) -> BasicSymbolicConvert a differential variable to a Term. Note that it only takes a Term not a Num.
julia> using Symbolics
julia> vars = @variables x t u(x, t) z(t)[1:2]; length(vars)
4
julia> Dt = Differential(t)
Differential(t, 1)
julia> Dx = Differential(x)
Differential(x, 1)
julia> Symbolics.diff2term(Symbolics.value(Dx(Dt(u))))
uˍxt(x, t)
julia> Symbolics.diff2term(Symbolics.value(Dt(z[1])))
(zˍt(t))[1]Symbolics.degree — Function
degree(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)
2Symbolics.coeff — Function
coeff(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
julia> Symbolics.coeff(2*x*y + y, x*y)
2Symbolics.fixpoint_sub — Function
fixpoint_sub(
expr, dict, ::Type{OP} = Nothing;
maxiters = 1000,
warn_maxiters = true,
filterer = SymbolicUtils.default_substitute_filter,
fold = Val(false),
)Recursively apply the substitutions in dict until expr no longer changes. Substitutions that depend on one another are fully expanded. Circular substitutions stop after maxiters applications.
Arguments
expr: symbolic expression, equation, inequality, or array to transform.dict: substitution rules accepted bySymbolicUtils.Substituter.OP: operator type whose contents should not be substituted. The defaultNothingdoes not exclude an operator type.
Keywords
maxiters::Integer = 1000: maximum number of repeated substitutions.warn_maxiters::Bool = true: emit a warning when the iteration limit is reached.filterer = SymbolicUtils.default_substitute_filter: predicate controlling which expression nodes may be substituted.fold::Val = Val(false): whether to constant-fold while substituting.
Returns
The transformed value after reaching a fixpoint or the iteration limit.
Examples
julia> using Symbolics
julia> @variables x y;
julia> Symbolics.fixpoint_sub(x, Dict(x => y, y => 3))
3See also: FixpointSubstituter.
Symbolics.evaluate — Function
evaluate(eq::Equation, subs)
evaluate(ineq::Inequality, subs)Evaluate the equation eq or inequality ineq. subs is a dictionary of variable to numerical value substitutions. If both sides of the equation or inequality are numeric, then the result is a boolean.
Examples
julia> @variables x y
julia> eq = x ~ y
julia> evaluate(eq, Dict(x => 1, y => 1))
true
julia> ltr = x ≲ y
julia> evaluate(ltr, Dict(x => 1, y => 2))
true
julia> gtr = x ≳ y
julia> evaluate(gtr, Dict(x => 1, y => 2))
falseSymbolics.symbolic_to_float — Function
symbolic_to_float(x::Union{Num, BasicSymbolic})::Union{AbstractFloat, BasicSymbolic}If the symbolic value is exactly equal to a number, converts the symbolic value to a floating point number. Otherwise retains the symbolic value.
Examples
symbolic_to_float((1//2 * x)/x) # 0.5
symbolic_to_float((1/2 * x)/x) # 0.5
symbolic_to_float((1//2)*√(279//4)) # 4.175823272122517Symbolics.terms — Method
terms(x)Get the terms of the symbolic expression x.
Examples
julia> terms(-x + y - z)
3-element Vector{Num}:
-z
y
-xSymbolics.factors — Method
factors(x)Get the factors of the symbolic expression x.
Examples
julia> factors(2 * x * y)
3-element Vector{Num}:
2
y
xBase.numerator — Method
numerator(x)Return the numerator of the symbolic expression x.
Examples
julia> numerator(x/y)
xBase.denominator — Method
denominator(x)Return the denominator of the symbolic expression x.
Examples
julia> denominator(x/y)
yTermInterface.arguments — Function
arguments(x, op::Function)Get the arguments of the symbolic expression x with respect to the operation or function op.
Symbolics.hasnode — Function
hasnode(c, x)Returns true if any part of x fulfills 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
hasnode(x, log(x) + x + 1) # returns `true`.
hasnode(x, log(y) + y + 1) # returns `false`.@variables t X(t)
D = Differential(t)
hasnode(Symbolics.is_derivative, X + D(X) + D(X^2)) # returns `true`.Symbolics.filterchildren — Function
filterchildren(c, x)Returns all parts of x that fulfills 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.replacenode — Function
replacenode(expr::BasicSymbolic, rules...)Walk the expression and replacenode 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 replacenoded 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 replacenodements.
Set fixpoint = true to repeatedly apply rules until no change to the expression remains to be made.
Symbolics.gather_factor — Function
gather_factor(expr, sym)
gather_factor(expr, syms::AbstractArray)Collect the additive terms of expr by grouping them according to the powers of sym that they contain. Equivalent to SymPy's collect.
Operates directly on the dict-based representation of the Add / Mul IR nodes for efficiency.
For multiple symbols, collection is applied sequentially left-to-right.
Examples
julia> @variables a b x;
julia> gather_factor(a*b*x + a*b + b*x, x)
a*b + (b + a*b)*x
julia> gather_factor(a*b*x + a*b + b*x, b)
(a + x + a*x)*b
julia> gather_factor(x^2 + 2x + 1, x)
1 + 2x + x^2gather_factor(expr, syms::AbstractArray)Apply gather_factor sequentially for each element of syms.
Symbolics.FixpointSubstituter — Type
FixpointSubstituter{Fold, #= ... =# } <: SymbolicUtils.Substituter{Fold}A substituter which repeatedly substitutes an expression until a fixpoint is reached, or a maximum number of substitutions in case of circular rules. For example, the rules [x => y, y => x] will lead to hitting the maximum iterations. This follows the same caching rules as SymbolicUtils.Substituter.
See also: fixpoint_sub.
Symbolics.sympy_pythoncall_simplify — Function
sympy_pythoncall_simplify(expr)Simplifies symbolic expressions using SymPyPythonCall.
Arguments
expr: Symbolics expression to simplify.
Returns
Simplified Symbolics expression.
Example
@variables x
expr = (x^2 - 1)/(x - 1)
result = sympy_pythoncall_simplify(expr)