From af1449de4a6c87e48689804755eee782caccb569 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Mon, 25 Nov 2024 17:27:42 +0000 Subject: [PATCH] build based on 1af55d4 --- dev/.documenter-siteinfo.json | 2 +- dev/api/index.html | 14 +++++++------- dev/index.html | 2 +- dev/manual/codegen/index.html | 6 +++--- dev/manual/interface/index.html | 2 +- dev/manual/representation/index.html | 2 +- dev/manual/rewrite/index.html | 2 +- dev/upgrade/index.html | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 9cccaae2..414ce470 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-11-18T18:21:51","documenter_version":"1.8.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-11-25T17:27:36","documenter_version":"1.8.0"}} \ No newline at end of file diff --git a/dev/api/index.html b/dev/api/index.html index 7c2b37c0..72330c82 100644 --- a/dev/api/index.html +++ b/dev/api/index.html @@ -1,6 +1,6 @@ -API Reference · SymbolicUtils.jl

API Reference

Symbols and Terms

SymbolicUtils.@symsMacro
@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.

source
Missing docstring.

Missing docstring for SymbolicUtils.Sym. Check Documenter's build log for details.

SymbolicUtils.issymFunction
issym(x)

Returns true if x is a Sym. If true, nameof must be defined on x and must return a Symbol.

source
SymbolicUtils.symtypeFunction
symtype(x)
-

Returns the numeric 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.

source
Missing 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_symtypeFunction
promote_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.@symsMacro
@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.

source
Missing docstring.

Missing docstring for SymbolicUtils.Sym. Check Documenter's build log for details.

SymbolicUtils.issymFunction
issym(x)

Returns true if x is a Sym. If true, nameof must be defined on x and must return a Symbol.

source
SymbolicUtils.symtypeFunction
symtype(x)
+

Returns the numeric 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.

source
Missing 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_symtypeFunction
promote_symtype(f, Ts...)

The result of applying f to arguments of symtype Ts...

julia> promote_symtype(+, Real, Real)
 Real
 
 julia> promote_symtype(+, Complex, Real)
@@ -10,7 +10,7 @@
 (f(::Number)::Complex,)
 
 julia> promote_symtype(f, Number)
-Complex

When constructing Terms without an explicit symtype, promote_symtype is used to figure out the symtype of the Term.

source
promote_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.

source

Rewriters

SymbolicUtils.@ruleMacro
@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 Terms without an explicit symtype, promote_symtype is used to figure out the symtype of the Term.

source
promote_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.

source

Rewriters

SymbolicUtils.@ruleMacro
@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)
@@ -56,13 +56,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.

source
SymbolicUtils.RewritersModule

A 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 false
  • If(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).
source

Simplify

SymbolicUtils.simplifyFunction
simplify(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.

source
SymbolicUtils.RewritersModule

A 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 false
  • If(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).
source

Simplify

SymbolicUtils.simplifyFunction
simplify(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.

source
SymbolicUtils.expandFunction
expand(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.

source
SymbolicUtils.substituteFunction
substitute(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.

source
SymbolicUtils.expandFunction
expand(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.

source
SymbolicUtils.substituteFunction
substitute(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)
source

Utilities

Utilities

SymbolicUtils.@timerewriteMacro
@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)
 
@@ -82,4 +82,4 @@
    ...
    ...
  ────────────────────────────────────────────────────────────────────────────────────────────────
-(a ^ 26) * (b ^ 30) * (c ^ 16) * (d ^ 28)
source
+(a ^ 26) * (b ^ 30) * (c ^ 16) * (d ^ 28)
source
diff --git a/dev/index.html b/dev/index.html index 2398408c..e1ce76d4 100644 --- a/dev/index.html +++ b/dev/index.html @@ -14,4 +14,4 @@ expr1 + expr2

SymbolicUtils automatically simplifies

2w + 3w - 3z + α

and reorders

(z + w)*(α + β)

expressions of type Symbolic{<:Number} (which includes Sym{Real}) when they are created. It also does constant elimination (including rational numbers)

5 + 2w - 3z + α - (β + 5//3) + 3w - 2 + 3//2 * β

It's worth remembering that the expression may be transformed with respect to the input when it's created.

Function-like symbols

Symbols can be defined to behave like functions. Both the input and output types for the function can be specified. Any application to that function will only admit either values of those types or symbols of the same symtype.

using SymbolicUtils
 @syms f(x) g(x::Real, y::Real)::Real
 
-f(z) + g(1, α) + sin(w)

This does not work since z is a Number, not a Real.

g(1, z)

This works because g "returns" a Real.

g(2//5, g(1, β))

Expression interface

Symbolic expressions are of type Term{T}, Add{T}, Mul{T}, Pow{T} or Div{T} and denote some function call where one or more arguments are themselves such expressions or Syms. See more about the representation here.

All the expression types support the TermInterface.jl interface. Please refer to the package for the complete reference of the interface.

Term rewriting

SymbolicUtils contains a rule-based rewriting language for easy pattern matching and rewriting of expression. There is also a combinator library to combine rules to chain, branch and loop over rules.

Simplification

By default +, * and ^ operations apply the most basic simplification upon construction of the expression.

The rules with which the canonical form of Symbolic{<:Number} terms are constructed are the next (where x isa Symbolic and c isa Number)

Here is an example of this

2 * (w+w+α+β + sin(z)^2 + cos(z)^2 - 1)

The simplify function applies a built-in set of rules to rewrite expressions in order to simplify it.

simplify(2 * (w+w+α+β + sin(z)^2 + cos(z)^2 - 1))

The rules in the default simplify applies simple constant elimination and trigonometric identities.

If you read the previous section on the rules DSL, you should be able to read and understand the rules that are used by simplify.

Code generation

Experimental feature

It is common to want to generate executable code from symbolic expressions and blocks of them. We are working on experimental support for turning Symbolic expressions into executable functions with specific focus on array input and output and performance which is critical to the Differential Equations ecosystem which is making heavy use of this package.

See Code generation for more about this.

Learn more

If you have a package that you would like to utilize rule-based rewriting in, look at the suggestions in the Interfacing section to find out how you can do that without any fundamental changes to your package. Look at the API documentation for docstrings about specific functions or macros.

Head over to the github repository to ask questions and report problems! Join the Zulip stream to chat!

+f(z) + g(1, α) + sin(w)

This does not work since z is a Number, not a Real.

g(1, z)

This works because g "returns" a Real.

g(2//5, g(1, β))

Expression interface

Symbolic expressions are of type Term{T}, Add{T}, Mul{T}, Pow{T} or Div{T} and denote some function call where one or more arguments are themselves such expressions or Syms. See more about the representation here.

All the expression types support the TermInterface.jl interface. Please refer to the package for the complete reference of the interface.

Term rewriting

SymbolicUtils contains a rule-based rewriting language for easy pattern matching and rewriting of expression. There is also a combinator library to combine rules to chain, branch and loop over rules.

Simplification

By default +, * and ^ operations apply the most basic simplification upon construction of the expression.

The rules with which the canonical form of Symbolic{<:Number} terms are constructed are the next (where x isa Symbolic and c isa Number)

Here is an example of this

2 * (w+w+α+β + sin(z)^2 + cos(z)^2 - 1)

The simplify function applies a built-in set of rules to rewrite expressions in order to simplify it.

simplify(2 * (w+w+α+β + sin(z)^2 + cos(z)^2 - 1))

The rules in the default simplify applies simple constant elimination and trigonometric identities.

If you read the previous section on the rules DSL, you should be able to read and understand the rules that are used by simplify.

Code generation

Experimental feature

It is common to want to generate executable code from symbolic expressions and blocks of them. We are working on experimental support for turning Symbolic expressions into executable functions with specific focus on array input and output and performance which is critical to the Differential Equations ecosystem which is making heavy use of this package.

See Code generation for more about this.

Learn more

If you have a package that you would like to utilize rule-based rewriting in, look at the suggestions in the Interfacing section to find out how you can do that without any fundamental changes to your package. Look at the API documentation for docstrings about specific functions or macros.

Head over to the github repository to ask questions and report problems! Join the Zulip stream to chat!

diff --git a/dev/manual/codegen/index.html b/dev/manual/codegen/index.html index 827d94d4..f371c747 100644 --- a/dev/manual/codegen/index.html +++ b/dev/manual/codegen/index.html @@ -11,7 +11,7 @@ args: Array{Any}((3,)) 1: + (function of type typeof(+)) 2: Symbol a - 3: Symbol b

Note that the function is an actual function object.

For more complex expressions, see other code-related combinators,

Namely Assignment, Let, Func, SetArray, MakeArray, MakeSparseArray and MakeTuple.

To make your own type convertible to Expr using toexpr define toexpr(x, st) and forward the state st in internal calls to toexpr. st is state used to know when to leave something like y(t) as it is or when to make it var"y(t)". E.g. when y(t) is itself the argument of a function rather than y.

source

Code Combinators

These are all exported when you do using SymbolicUtils.Code

SymbolicUtils.Code.AssignmentType
Assignment(lhs, rhs)

An assignment expression. Shorthand lhs ← rhs (\leftarrow)

source
SymbolicUtils.Code.LetType
Let(assignments, body[, let_block])

A Let block.

  • assignments is a vector of Assignments
  • body is the body of the let block
  • let_block boolean (default=true) – do not create a let block if false.
source
SymbolicUtils.Code.FuncType
Func(args, kwargs, body[, pre])

A function.

  • args is a vector of expressions
  • kwargs is a vector of Assignments
  • body is the body of the function
  • pre a vector of expressions to be prepended to the function body, for example, it could be [Expr(:meta, :inline), Expr(:meta, :propagate_inbounds)] to create an @inline @propagate_inbounds function definition.

Special features in args:

  • args can contain DestructuredArgs
  • call expressions

For example,


+    3: Symbol b

Note that the function is an actual function object.

For more complex expressions, see other code-related combinators,

Namely Assignment, Let, Func, SetArray, MakeArray, MakeSparseArray and MakeTuple.

To make your own type convertible to Expr using toexpr define toexpr(x, st) and forward the state st in internal calls to toexpr. st is state used to know when to leave something like y(t) as it is or when to make it var"y(t)". E.g. when y(t) is itself the argument of a function rather than y.

source

Code Combinators

These are all exported when you do using SymbolicUtils.Code

SymbolicUtils.Code.AssignmentType
Assignment(lhs, rhs)

An assignment expression. Shorthand lhs ← rhs (\leftarrow)

source
SymbolicUtils.Code.LetType
Let(assignments, body[, let_block])

A Let block.

  • assignments is a vector of Assignments
  • body is the body of the let block
  • let_block boolean (default=true) – do not create a let block if false.
source
SymbolicUtils.Code.FuncType
Func(args, kwargs, body[, pre])

A function.

  • args is a vector of expressions
  • kwargs is a vector of Assignments
  • body is the body of the function
  • pre a vector of expressions to be prepended to the function body, for example, it could be [Expr(:meta, :inline), Expr(:meta, :propagate_inbounds)] to create an @inline @propagate_inbounds function definition.

Special features in args:

  • args can contain DestructuredArgs
  • call expressions

For example,


 julia> @syms a b c t f(d) x(t) y(t) z(t)
 (a, b, c, t, f(::Number)::Number, x(::Number)::Number, y(::Number)::Number, z(::Number)::Number)
 
@@ -28,9 +28,9 @@
 #10 (generic function with 1 method)
 
 julia> executable(1, 2.0, [2,3.0], x->string(x); var"z(t)" = sqrt(42))
-"11.98074069840786"
source
SymbolicUtils.Code.SpawnFetchType
SpawnFetch{ParallelType}(funcs [, args], reduce)

Run every expression in funcs in its own task, the expression should be a Func object and is passed to Threads.Task(f). If Func takes arguments, then the arguments must be passed in as args–a vector of vector of arguments to each function in funcs. We don't use @spawn in order to support RuntimeGeneratedFunctions which disallow closures, instead we interpolate these functions or closures as smaller RuntimeGeneratedFunctions.

reduce function is used to combine the results of executing exprs. A SpawnFetch expression returns the reduced result.

Use Symbolics.MultithreadedForm ParallelType from the Symbolics.jl package to get the RuntimeGeneratedFunction version SpawnFetch.

ParallelType can be used to define more parallelism types SymbolicUtils supports Multithreaded type. Which spawns threaded tasks.

source
SymbolicUtils.Code.SetArrayType
SetArray(inbounds, arr, elems)

An expression representing setting of elements of arr.

By default, every element of elems is copied over to arr,

but if elems contains AtIndex(i, val) objects, then arr[i] = val is performed in its place.

inbounds is a boolean flag, true surrounds the resulting expression in an @inbounds.

source
SymbolicUtils.Code.MakeArrayType
MakeArray(elems, similarto, [output_eltype=nothing])

An expression which constructs an array.

  • elems is the output array
  • similarto can either be a type, or some symbol that is an array whose type needs to be emulated. If similarto is a StaticArrays.SArray, then the output array is also created as an SArray, similarly, an Array will result in an Array, and a LabelledArrays.SLArray will result in a labelled static array.
  • output_eltype: if set, then forces the element type of the output array to be this. by default, the output type is inferred automatically.

You can define:

@inline function create_array(A::Type{<:MyArray},a
+"11.98074069840786"
source
SymbolicUtils.Code.SpawnFetchType
SpawnFetch{ParallelType}(funcs [, args], reduce)

Run every expression in funcs in its own task, the expression should be a Func object and is passed to Threads.Task(f). If Func takes arguments, then the arguments must be passed in as args–a vector of vector of arguments to each function in funcs. We don't use @spawn in order to support RuntimeGeneratedFunctions which disallow closures, instead we interpolate these functions or closures as smaller RuntimeGeneratedFunctions.

reduce function is used to combine the results of executing exprs. A SpawnFetch expression returns the reduced result.

Use Symbolics.MultithreadedForm ParallelType from the Symbolics.jl package to get the RuntimeGeneratedFunction version SpawnFetch.

ParallelType can be used to define more parallelism types SymbolicUtils supports Multithreaded type. Which spawns threaded tasks.

source
SymbolicUtils.Code.SetArrayType
SetArray(inbounds, arr, elems)

An expression representing setting of elements of arr.

By default, every element of elems is copied over to arr,

but if elems contains AtIndex(i, val) objects, then arr[i] = val is performed in its place.

inbounds is a boolean flag, true surrounds the resulting expression in an @inbounds.

source
SymbolicUtils.Code.MakeArrayType
MakeArray(elems, similarto, [output_eltype=nothing])

An expression which constructs an array.

  • elems is the output array
  • similarto can either be a type, or some symbol that is an array whose type needs to be emulated. If similarto is a StaticArrays.SArray, then the output array is also created as an SArray, similarly, an Array will result in an Array, and a LabelledArrays.SLArray will result in a labelled static array.
  • output_eltype: if set, then forces the element type of the output array to be this. by default, the output type is inferred automatically.

You can define:

@inline function create_array(A::Type{<:MyArray},a
                               ::Nothing, d::Val{dims}, elems...) where dims
 
 # and
 
-@inline function create_array(::Type{<:MyArray}, T, ::Val{dims}, elems...) where dims

which creates an array of size dims using the elements elems and eltype T, to allow MakeArray to create arrays similarto MyArrays.

source
SymbolicUtils.Code.MakeSparseArrayType
MakeSpaseArray(array)

An expression which creates a SparseMatrixCSC or a SparseVector.

The generated expression contains the sparsity information of array,

it only creates the nzval field at run time.

source
SymbolicUtils.Code.MakeTupleType
MakeTuple(tup)

Make a Tuple from a tuple of expressions.

source
SymbolicUtils.Code.LiteralExprType
LiteralExpr(ex)

Literally ex, an Expr. toexpr on LiteralExpr recursively calls toexpr on any interpolated symbolic expressions.

source
+@inline function create_array(::Type{<:MyArray}, T, ::Val{dims}, elems...) where dims

which creates an array of size dims using the elements elems and eltype T, to allow MakeArray to create arrays similarto MyArrays.

source
SymbolicUtils.Code.MakeSparseArrayType
MakeSpaseArray(array)

An expression which creates a SparseMatrixCSC or a SparseVector.

The generated expression contains the sparsity information of array,

it only creates the nzval field at run time.

source
SymbolicUtils.Code.MakeTupleType
MakeTuple(tup)

Make a Tuple from a tuple of expressions.

source
SymbolicUtils.Code.LiteralExprType
LiteralExpr(ex)

Literally ex, an Expr. toexpr on LiteralExpr recursively calls toexpr on any interpolated symbolic expressions.

source
diff --git a/dev/manual/interface/index.html b/dev/manual/interface/index.html index 8a7b1a77..d1fc80cd 100644 --- a/dev/manual/interface/index.html +++ b/dev/manual/interface/index.html @@ -1,2 +1,2 @@ -Interfacing with SymbolicUtils.jl · SymbolicUtils.jl

Interfacing with SymbolicUtils.jl

This section is for Julia package developers who may want to use the simplify and rule rewriting system on their own expression types.

Defining the interface

SymbolicUtils matchers can match any Julia object that implements an interface to traverse it as a tree. The interface in question, is defined in the TermInterface.jl package. Its purpose is to provide a shared interface between various symbolic programming Julia packages.

In particular, you should define methods from TermInterface.jl for an expression tree type T with symbol types S to work with SymbolicUtils.jl

You can read the documentation of TermInterface.jl on the Github repository.

+Interfacing with SymbolicUtils.jl · SymbolicUtils.jl

Interfacing with SymbolicUtils.jl

This section is for Julia package developers who may want to use the simplify and rule rewriting system on their own expression types.

Defining the interface

SymbolicUtils matchers can match any Julia object that implements an interface to traverse it as a tree. The interface in question, is defined in the TermInterface.jl package. Its purpose is to provide a shared interface between various symbolic programming Julia packages.

In particular, you should define methods from TermInterface.jl for an expression tree type T with symbol types S to work with SymbolicUtils.jl

You can read the documentation of TermInterface.jl on the Github repository.

diff --git a/dev/manual/representation/index.html b/dev/manual/representation/index.html index 1f71d32b..0655cbe3 100644 --- a/dev/manual/representation/index.html +++ b/dev/manual/representation/index.html @@ -23,4 +23,4 @@ (cos(x)^2 + sin(x)^2) / (cos(x)*sin(x)) julia> simplify(ans) -1 / (cos(x)*sin(x)) +1 / (cos(x)*sin(x)) diff --git a/dev/manual/rewrite/index.html b/dev/manual/rewrite/index.html index 7f9faaa4..21fdbacb 100644 --- a/dev/manual/rewrite/index.html +++ b/dev/manual/rewrite/index.html @@ -111,4 +111,4 @@ 1 + 2sin(x)*cos(x)

It restarts the chain after each successful application of a rule, so after sqexpand is hit it (re)starts again and successfully applies acpyid to resulting expression.

You can also use Fixpoint to apply the rules until there are no changes.

Fixpoint(cas)((cos(x) + sin(x))^2)
 
 # output
-1 + 2sin(x)*cos(x)
+1 + 2sin(x)*cos(x) diff --git a/dev/upgrade/index.html b/dev/upgrade/index.html index 0be72754..2c5ba29d 100644 --- a/dev/upgrade/index.html +++ b/dev/upgrade/index.html @@ -1,2 +1,2 @@ -Upgrade to SymbolicUtils v1 · SymbolicUtils.jl

Upgrade to SymbolicUtils v1

The version 1 of SymbolicUtils utilizes Unityper to speed up the compilation time. We introduce a new type BasicSymbolic <: Symbolic to represent all the previous types Sym, Term, Add, Mul, Pow and Div. Since BasicSymbolic is a concrete type, checking x isa Sym or x isa Pow no longer works. Instead, one should use issym(x) or ispow(x) to check the "type" of the expression. Also, note that if one does not need to work on a specific symbolic representation, issym(x) and isterm(x) should be replaced by x isa Symbolic && !istree(x) and istree(x) to be more generic. Furthermore, dispatching on Sym, Term, etc no longer works. Instead, a function that takes BasicSymbolic should check the type of the expression using a if statement to select the right code path.

Although we don't have Sym, Term, etc in the Julia type system anymore, we still provide convenient constructors for them. For example, Sym{Real}(:x) would still work. For constructor that takes a collection like Terms, we recommend directly construct Any element type constructors like Term(f, Any[x1, x2]) to reduce extra memory allocation and compile time.

+Upgrade to SymbolicUtils v1 · SymbolicUtils.jl

Upgrade to SymbolicUtils v1

The version 1 of SymbolicUtils utilizes Unityper to speed up the compilation time. We introduce a new type BasicSymbolic <: Symbolic to represent all the previous types Sym, Term, Add, Mul, Pow and Div. Since BasicSymbolic is a concrete type, checking x isa Sym or x isa Pow no longer works. Instead, one should use issym(x) or ispow(x) to check the "type" of the expression. Also, note that if one does not need to work on a specific symbolic representation, issym(x) and isterm(x) should be replaced by x isa Symbolic && !istree(x) and istree(x) to be more generic. Furthermore, dispatching on Sym, Term, etc no longer works. Instead, a function that takes BasicSymbolic should check the type of the expression using a if statement to select the right code path.

Although we don't have Sym, Term, etc in the Julia type system anymore, we still provide convenient constructors for them. For example, Sym{Real}(:x) would still work. For constructor that takes a collection like Terms, we recommend directly construct Any element type constructors like Term(f, Any[x1, x2]) to reduce extra memory allocation and compile time.