Recursive utility functions
SymbolicUtils.jl provides several utility functions to perform common operations that require recursing over the expression tree.
Missing docstring for SymbolicUtils.substitute. Check Documenter's build log for details.
SymbolicUtils.Substituter — Type
Substituter{Fold, #= ... =# }A functor which acts as the workhorse for substitute. Passing fold = Val(true) corresponds to Substituter{true, #= ... =# } (and similarly for Val(false)). To define substitution rules for custom types that wrap/contain BasicSymbolic, define methods for this functor. For example,
struct Equation
lhs::BasicSymbolic{SymReal}
rhs::BasicSymbolic{SymReal}
end
function (subst::Substituter)(eq::Equation)
return Equation(subst(eq.lhs), subst(eq.rhs))
endInstead of repeatedly calling substitute with the same rules, it is usually more efficient to build a Substituter and reuse it.
Substituter is also allowed to cache intermediate results as necessary. When constructing Substituter with an AbstractDict, it will alias the provided mapping. Mutating the map such that the identity of the substitution rules changes invalidates the substituter. It can be reused by clearing the cache using SymbolicUtils.clear_cache!.
The caching is only available when the SymbolicUtils.vartype of the expressions is inferrable from the substitution rules, or explicitly specified. As long as either the keys or values of the substitution rules are all BasicSymbolic{T} (for some T) the automatic inference will work. To allow the inference to work for your custom wrapper type, implement SymbolicUtils.infer_vartype. For example:
struct Num <: Real
inner::BasicSymbolic{SymReal}
end
SymbolicUtils.infer_vartype(::Type{Num}) = SymRealAlternatively, the vartype can be provided as the third positional argument to the Substituter constructor.
Extended help
The following is internal details of Substituter and should not be relied on as public API.
Fields
dict::AbstractDict: TheAbstractDictof substitution rules.
filter::Any: The filter function to eliminate trees that do not need substitution.
cache::Any: Cache of intermediate results.
SymbolicUtils.clear_cache! — Function
clear_cache!(fn) -> Any
Clear the cache for SymbolicUtils.@cached function fn. This is task specific. Also resets the stats.
clear_cache!(subst::SymbolicUtils.Substituter) -> Any
Clear the cached values associated with subst. See the documentation of SymbolicUtils.Substituter for more details.
SymbolicUtils.default_substitute_filter — Function
default_substitute_filter(
ex::SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{T}
) -> Bool
The default filter function used by substitute to determine whether to substitute within an expression. Returns false for expressions that are Terms with an Operator as the operation (preventing substitution within operator calls), and true otherwise.
Arguments
ex::BasicSymbolic{T}: The expression to check.
Returns
Bool:falseif the expression should not be substituted into,trueotherwise.
Missing docstring for SymbolicUtils.evaluate. Check Documenter's build log for details.
SymbolicUtils.query — Function
query(
predicate,
expr::SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{T} where T;
recurse,
default
) -> Any
Recursively search an expression tree to determine if any subexpression satisfies a given predicate. This function traverses the expression tree and returns true if the predicate returns true for any node in the tree.
Arguments
predicate::F: A function that takes an expression and returns aBool.expr::BasicSymbolic: The expression to search.
Keyword Arguments
recurse::G=iscall: A function determining whether to recurse into a subexpression.default::Bool=false: The default value to return if the expression is not a call or recursion is prevented.
Returns
Bool:trueif any subexpression satisfies the predicate,falseotherwise.
Missing docstring for SymbolicUtils.search_variables. Check Documenter's build log for details.
SymbolicUtils.search_variables! — Function
search_variables!(
buffer,
expr::SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{T} where T;
is_atomic,
recurse
)
Find all variables used in expr and add them to buffer. A variable is identified by the predicate is_atomic. The predicate recurse determines whether to search further inside expr if it is not a variable. Note that recurse must at least return false if iscall returns false.
Wrappers for BasicSymbolic should implement this function by unwrapping.
See also: default_is_atomic.
SymbolicUtils.default_is_atomic — Function
default_is_atomic(
ex::SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{T}
) -> Bool
The default is_atomic predicate for search_variables!. ex is considered atomic if one of the following conditions is true:
- It is a
Symand not an internal index variable for an arrayop - It is a
Term, the operation is aBasicSymbolicand the operation represents a dependent variable according tois_function_symbolic. - It is a
Term, the operation isgetindexand the variable being indexed is atomic.
SymbolicUtils.scalarize — Function
scalarize(
x::SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{T}
) -> Any
scalarize(
x::SymbolicUtils.BasicSymbolicImpl.var"typeof(BasicSymbolicImpl)"{T},
::Val{toplevel}
) -> Any
Convert a symbolic expression with array operations into a fully scalarized form. This function expands array operations into element-wise operations, converting symbolic array expressions into arrays of scalar symbolic expressions.
For ArrayOp expressions, this function reduces eliminated indices and substitutes concrete values for output indices to generate scalar expressions for each array element.
Arguments
x::BasicSymbolic{T}: The symbolic expression to scalarize.::Val{toplevel}=Val{false}(): Whether to evaluate constant expressions at the top level. Whentrue, constant subexpressions are evaluated; whenfalse, they are recursively scalarized.
Returns
- The scalarized expression. For array-shaped expressions, returns an array of scalar expressions. For scalar expressions, returns the expression unchanged or with recursively scalarized subexpressions.
SymbolicUtils.scalarization_function — Function
scalarization_function(
_
) -> typeof(SymbolicUtils._scalarize_add)
Given a function f, return a function that will scalarize an expression with f as the head. The returned function is passed f, the expression with f as the head, and Val(true) or Val(false) indicating whether to recursively scalarize or not.
This function provides a dispatch mechanism for customizing scalarization behavior based on the operation type. Different operations may require different scalarization strategies (e.g., array operations, determinants, indexing operations).
Arguments
f: The function/operation to get a scalarization function for.
Returns
- A function that takes
(f, x::BasicSymbolic{T}, ::Val{toplevel})and returns the scalarized form ofx.