diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index b6c872382..a1e32f1ce 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.4","generation_timestamp":"2024-06-25T09:16:24","documenter_version":"1.4.1"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.4","generation_timestamp":"2024-06-25T09:16:46","documenter_version":"1.4.1"}} \ No newline at end of file diff --git a/dev/api/index.html b/dev/api/index.html index 731925a33..760ea8e5b 100644 --- a/dev/api/index.html +++ b/dev/api/index.html @@ -1,5 +1,5 @@ -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.

Missing docstring.

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

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.

Missing docstring.

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

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)
@@ -9,7 +9,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)
@@ -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.

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)
 
@@ -81,4 +81,4 @@
    ...
    ...
  ────────────────────────────────────────────────────────────────────────────────────────────────
-(a ^ 26) * (b ^ 30) * (c ^ 16) * (d ^ 28)
source
+(a ^ 26) * (b ^ 30) * (c ^ 16) * (d ^ 28)
source
diff --git a/dev/manual/codegen/index.html b/dev/manual/codegen/index.html index 893596d53..d0a38aa8a 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/objects.inv b/dev/objects.inv index f78052f9d..6b54cbf2c 100644 Binary files a/dev/objects.inv and b/dev/objects.inv differ