API Reference
Symbols and Terms
SymbolicUtils.@syms
— Macro@syms <lhs_expr>[::T1] <lhs_expr>[::T2]...
For instance:
@syms foo::Real bar baz(x, y::Real)::Complex
Create one or more variables. <lhs_expr>
can be just a symbol in which case it will be the name of the variable, or a function call in which case a function-like variable which has the same name as the function being called. The Sym type, or in the case of a function-like Sym, the output type of calling the function can be set using the ::T
syntax.
Examples:
@syms foo bar::Real baz::Int
will create
variable foo
of symtype Number
(the default), bar
of symtype Real
and baz
of symtype Int
@syms f(x) g(y::Real, x)::Int h(a::Int, f(b))
creates 1-argf
2-argg
and 2 arg h
. The second argument to h
must be a one argument function-like variable. So, h(1, g)
will fail and h(1, f)
will work.
Missing docstring for SymbolicUtils.Sym
. Check Documenter's build log for details.
SymbolicUtils.symtype
— Functionsymtype(x)
Returns the symbolic type of x
. By default this is just typeof(x)
. Define this for your symbolic types if you want SymbolicUtils.simplify
to apply rules specific to numbers (such as commutativity of multiplication). Or such rules that may be implemented in the future.
Missing docstring for SymbolicUtils.Term
. Check Documenter's build log for details.
Missing docstring for SymbolicUtils.Add
. Check Documenter's build log for details.
Missing docstring for SymbolicUtils.Mul
. Check Documenter's build log for details.
Missing docstring for SymbolicUtils.Pow
. Check Documenter's build log for details.
SymbolicUtils.promote_symtype
— Functionpromote_symtype(f, Ts...)
The result of applying f
to arguments of symtype
Ts...
julia> promote_symtype(+, Real, Real)
+API Reference · SymbolicUtils.jl API Reference
Symbols and Terms
SymbolicUtils.@syms
— Macro@syms <lhs_expr>[::T1] <lhs_expr>[::T2]...
For instance:
@syms foo::Real bar baz(x, y::Real)::Complex
Create one or more variables. <lhs_expr>
can be just a symbol in which case it will be the name of the variable, or a function call in which case a function-like variable which has the same name as the function being called. The Sym type, or in the case of a function-like Sym, the output type of calling the function can be set using the ::T
syntax.
Examples:
@syms foo bar::Real baz::Int
will create
variable foo
of symtype Number
(the default), bar
of symtype Real
and baz
of symtype Int
@syms f(x) g(y::Real, x)::Int h(a::Int, f(b))
creates 1-arg f
2-arg g
and 2 arg h
. The second argument to h
must be a one argument function-like variable. So, h(1, g)
will fail and h(1, f)
will work.
sourceMissing docstring. Missing docstring for SymbolicUtils.Sym
. Check Documenter's build log for details.
SymbolicUtils.symtype
— Functionsymtype(x)
Returns the symbolic type of x
. By default this is just typeof(x)
. Define this for your symbolic types if you want SymbolicUtils.simplify
to apply rules specific to numbers (such as commutativity of multiplication). Or such rules that may be implemented in the future.
sourceMissing docstring. Missing docstring for SymbolicUtils.Term
. Check Documenter's build log for details.
Missing docstring. Missing docstring for SymbolicUtils.Add
. Check Documenter's build log for details.
Missing docstring. Missing docstring for SymbolicUtils.Mul
. Check Documenter's build log for details.
Missing docstring. Missing docstring for SymbolicUtils.Pow
. Check Documenter's build log for details.
SymbolicUtils.promote_symtype
— Functionpromote_symtype(f, Ts...)
The result of applying f
to arguments of symtype
Ts...
julia> promote_symtype(+, Real, Real)
Real
julia> promote_symtype(+, Complex, Real)
@@ -9,7 +9,7 @@
(f(::Number)::Complex,)
julia> promote_symtype(f, Number)
-Complex
When constructing Term
s without an explicit symtype, promote_symtype
is used to figure out the symtype of the Term.
sourcepromote_symtype(f::FnType{X,Y}, arg_symtypes...)
The output symtype of applying variable f
to arguments of symtype arg_symtypes...
. if the arguments are of the wrong type then this function will error.
sourceInterfacing
SymbolicUtils.istree
— Functionistree(x)
Returns true
if x
is a term. If true, operation
, arguments
must also be defined for x
appropriately.
sourceSymbolicUtils.operation
— Functionoperation(x)
If x
is a term as defined by istree(x)
, operation(x)
returns the head of the term if x
represents a function call, for example, the head is the function being called.
sourceSymbolicUtils.arguments
— Functionarguments(x)
Get the arguments of x
, must be defined if istree(x)
is true
.
sourceSymbolicUtils.similarterm
— Functionsimilarterm(x, head, args, symtype=nothing; metadata=nothing, exprhead=:call)
Returns a term that is in the same closure of types as typeof(x)
, with head
as the head and args
as the arguments, type
as the symtype and metadata
as the metadata. By default this will execute head(args...)
. x
parameter can also be a Type
. The exprhead
keyword argument is useful when manipulating Expr
s.
sourceRewriters
SymbolicUtils.@rule
— Macro@rule LHS => RHS
Creates a Rule
object. A rule object is callable, and takes an expression and rewrites it if it matches the LHS pattern to the RHS pattern, returns nothing
otherwise. The rule language is described below.
LHS can be any possibly nested function call expression where any of the arguments can optionally be a Slot (~x
) or a Segment (~~x
) (described below).
If an expression matches LHS entirely, then it is rewritten to the pattern in the RHS Segment (~x
) and slot variables (~~x
) on the RHS will substitute the result of the matches found for these variables in the LHS.
Slot:
A Slot variable is written as ~x
and matches a single expression. x
is the name of the variable. If a slot appears more than once in an LHS expression then expression matched at every such location must be equal (as shown by isequal
).
Example:
Simple rule to turn any sin
into cos
:
julia> @syms a b c
+Complex
When constructing Term
s without an explicit symtype, promote_symtype
is used to figure out the symtype of the Term.
sourcepromote_symtype(f::FnType{X,Y}, arg_symtypes...)
The output symtype of applying variable f
to arguments of symtype arg_symtypes...
. if the arguments are of the wrong type then this function will error.
sourceInterfacing
SymbolicUtils.istree
— Functionistree(x)
Returns true
if x
is a term. If true, operation
, arguments
must also be defined for x
appropriately.
sourceSymbolicUtils.operation
— Functionoperation(x)
If x
is a term as defined by istree(x)
, operation(x)
returns the head of the term if x
represents a function call, for example, the head is the function being called.
sourceSymbolicUtils.arguments
— Functionarguments(x)
Get the arguments of x
, must be defined if istree(x)
is true
.
sourceSymbolicUtils.similarterm
— Functionsimilarterm(x, head, args, symtype=nothing; metadata=nothing, exprhead=:call)
Returns a term that is in the same closure of types as typeof(x)
, with head
as the head and args
as the arguments, type
as the symtype and metadata
as the metadata. By default this will execute head(args...)
. x
parameter can also be a Type
. The exprhead
keyword argument is useful when manipulating Expr
s.
sourceRewriters
SymbolicUtils.@rule
— Macro@rule LHS => RHS
Creates a Rule
object. A rule object is callable, and takes an expression and rewrites it if it matches the LHS pattern to the RHS pattern, returns nothing
otherwise. The rule language is described below.
LHS can be any possibly nested function call expression where any of the arguments can optionally be a Slot (~x
) or a Segment (~~x
) (described below).
If an expression matches LHS entirely, then it is rewritten to the pattern in the RHS Segment (~x
) and slot variables (~~x
) on the RHS will substitute the result of the matches found for these variables in the LHS.
Slot:
A Slot variable is written as ~x
and matches a single expression. x
is the name of the variable. If a slot appears more than once in an LHS expression then expression matched at every such location must be equal (as shown by isequal
).
Example:
Simple rule to turn any sin
into cos
:
julia> @syms a b c
(a, b, c)
julia> r = @rule sin(~x) => cos(~x)
@@ -55,13 +55,13 @@
a
julia> r(b) === nothing
-true
Note that this is syntactic sugar and that it is the same as something like @rule ~x => f(~x) ? ~x : nothing
.
Context:
In predicates: Contextual predicates are functions wrapped in the Contextual
type. The function is called with 2 arguments: the expression and a context object passed during a call to the Rule object (maybe done by passing a context to simplify
or a RuleSet
object).
The function can use the inputs however it wants, and must return a boolean indicating whether the predicate holds or not.
In the consequent pattern: Use (@ctx)
to access the context object on the right hand side of an expression.
sourceSymbolicUtils.Rewriters
— ModuleA rewriter is any function which takes an expression and returns an expression or nothing
. If nothing
is returned that means there was no changes applicable to the input expression.
The Rewriters
module contains some types which create and transform rewriters.
Empty()
is a rewriter which always returns nothing
Chain(itr)
chain an iterator of rewriters into a single rewriter which applies each chained rewriter in the given order. If a rewriter returns nothing
this is treated as a no-change.RestartedChain(itr)
like Chain(itr)
but restarts from the first rewriter once on the first successful application of one of the chained rewriters.IfElse(cond, rw1, rw2)
runs the cond
function on the input, applies rw1
if cond returns true, rw2
if it returns falseIf(cond, rw)
is the same as IfElse(cond, rw, Empty())
Prewalk(rw; threaded=false, thread_cutoff=100)
returns a rewriter which does a pre-order traversal of a given expression and applies the rewriter rw
. Note that if rw
returns nothing
when a match is not found, then Prewalk(rw)
will also return nothing unless a match is found at every level of the walk. threaded=true
will use multi threading for traversal. thread_cutoff
is the minimum number of nodes in a subtree which should be walked in a threaded spawn.Postwalk(rw; threaded=false, thread_cutoff=100)
similarly does post-order traversal.Fixpoint(rw)
returns a rewriter which applies rw
repeatedly until there are no changes to be made.FixpointNoCycle
behaves like Fixpoint
but instead it applies rw
repeatedly only while it is returning new results.PassThrough(rw)
returns a rewriter which if rw(x)
returns nothing
will instead return x
otherwise will return rw(x)
.
sourceSimplify
SymbolicUtils.simplify
— Functionsimplify(x; expand=false,
+true
Note that this is syntactic sugar and that it is the same as something like @rule ~x => f(~x) ? ~x : nothing
.
Context:
In predicates: Contextual predicates are functions wrapped in the Contextual
type. The function is called with 2 arguments: the expression and a context object passed during a call to the Rule object (maybe done by passing a context to simplify
or a RuleSet
object).
The function can use the inputs however it wants, and must return a boolean indicating whether the predicate holds or not.
In the consequent pattern: Use (@ctx)
to access the context object on the right hand side of an expression.
sourceSymbolicUtils.Rewriters
— ModuleA rewriter is any function which takes an expression and returns an expression or nothing
. If nothing
is returned that means there was no changes applicable to the input expression.
The Rewriters
module contains some types which create and transform rewriters.
Empty()
is a rewriter which always returns nothing
Chain(itr)
chain an iterator of rewriters into a single rewriter which applies each chained rewriter in the given order. If a rewriter returns nothing
this is treated as a no-change.RestartedChain(itr)
like Chain(itr)
but restarts from the first rewriter once on the first successful application of one of the chained rewriters.IfElse(cond, rw1, rw2)
runs the cond
function on the input, applies rw1
if cond returns true, rw2
if it returns falseIf(cond, rw)
is the same as IfElse(cond, rw, Empty())
Prewalk(rw; threaded=false, thread_cutoff=100)
returns a rewriter which does a pre-order traversal of a given expression and applies the rewriter rw
. Note that if rw
returns nothing
when a match is not found, then Prewalk(rw)
will also return nothing unless a match is found at every level of the walk. threaded=true
will use multi threading for traversal. thread_cutoff
is the minimum number of nodes in a subtree which should be walked in a threaded spawn.Postwalk(rw; threaded=false, thread_cutoff=100)
similarly does post-order traversal.Fixpoint(rw)
returns a rewriter which applies rw
repeatedly until there are no changes to be made.FixpointNoCycle
behaves like Fixpoint
but instead it applies rw
repeatedly only while it is returning new results.PassThrough(rw)
returns a rewriter which if rw(x)
returns nothing
will instead return x
otherwise will return rw(x)
.
sourceSimplify
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.
sourceSymbolicUtils.expand
— Functionexpand(expr)
Expand expressions by distributing multiplication over addition, e.g., a*(b+c)
becomes ab+ac
.
expand
uses replace symbols and non-algebraic expressions by variables of type variable_type
to compute the distribution using a specialized sparse multivariate polynomials implementation. variable_type
can be any subtype of MultivariatePolynomials.AbstractVariable
.
sourceSymbolicUtils.substitute
— Functionsubstitute(expr, dict; fold=true)
substitute any subexpression that matches a key in dict
with the corresponding value. If fold=false
, expressions which can be evaluated won't be evaluated.
julia> substitute(1+sqrt(y), Dict(y => 2), fold=true)
+ 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.
sourceSymbolicUtils.expand
— Functionexpand(expr)
Expand expressions by distributing multiplication over addition, e.g., a*(b+c)
becomes ab+ac
.
expand
uses replace symbols and non-algebraic expressions by variables of type variable_type
to compute the distribution using a specialized sparse multivariate polynomials implementation. variable_type
can be any subtype of MultivariatePolynomials.AbstractVariable
.
sourceSymbolicUtils.substitute
— Functionsubstitute(expr, dict; fold=true)
substitute any subexpression that matches a key in dict
with the corresponding value. If fold=false
, expressions which can be evaluated won't be evaluated.
julia> substitute(1+sqrt(y), Dict(y => 2), fold=true)
2.414213562373095
julia> substitute(1+sqrt(y), Dict(y => 2), fold=false)
-1 + sqrt(2)
sourceUtilities
SymbolicUtils.@timerewrite
— Macro@timerewrite expr
If expr
calls simplify
or a RuleSet
object, track the amount of time it spent on applying each rule and pretty print the timing.
This uses TimerOutputs.jl.
Example:
+1 + sqrt(2)
sourceUtilities
SymbolicUtils.@timerewrite
— Macro@timerewrite expr
If expr
calls simplify
or a RuleSet
object, track the amount of time it spent on applying each rule and pretty print the timing.
This uses TimerOutputs.jl.
Example:
julia> expr = foldr(*, rand([a,b,c,d], 100))
(a ^ 26) * (b ^ 30) * (c ^ 16) * (d ^ 28)
@@ -81,4 +81,4 @@
...
...
────────────────────────────────────────────────────────────────────────────────────────────────
-(a ^ 26) * (b ^ 30) * (c ^ 16) * (d ^ 28)
sourceSettings
This document was generated with Documenter.jl version 1.4.1 on Saturday 25 May 2024. Using Julia version 1.10.3.
+(a ^ 26) * (b ^ 30) * (c ^ 16) * (d ^ 28)