diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 34adee7a5..294dd9261 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.11.2","generation_timestamp":"2024-12-14T07:32:59","documenter_version":"1.8.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.11.2","generation_timestamp":"2024-12-14T07:33:24","documenter_version":"1.8.0"}} \ No newline at end of file diff --git a/dev/assets/Manifest.toml b/dev/assets/Manifest.toml index 5bf8d0974..8e66885ec 100644 --- a/dev/assets/Manifest.toml +++ b/dev/assets/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.11.2" manifest_format = "2.0" -project_hash = "62e94160f004c178d7079bbbecfc0c5e22a4efb8" +project_hash = "5cf93092d8875aad77d5c4b828047eeecba05f92" [[deps.ADTypes]] git-tree-sha1 = "72af59f5b8f09faee36b4ec48e014a79210f2f4f" diff --git a/dev/assets/Project.toml b/dev/assets/Project.toml index f2ee628b9..c218e3a04 100644 --- a/dev/assets/Project.toml +++ b/dev/assets/Project.toml @@ -15,7 +15,7 @@ BenchmarkTools = "1.3" Documenter = "1" Groebner = "0.8.2" Latexify = "0.15, 0.16" -Nemo = "0.46, 0.47" +Nemo = "0.46, 0.47, 0.48" OrdinaryDiffEq = "6.31" Plots = "1.36" StaticArrays = "1.5" diff --git a/dev/comparison/index.html b/dev/comparison/index.html index c41d1beba..3a8e0dc04 100644 --- a/dev/comparison/index.html +++ b/dev/comparison/index.html @@ -1,2 +1,2 @@ -Comparison Against SymPy · Symbolics.jl

Comparison of Julia's Symbolics.jl vs SymPy for Symbolic Computation

Symbolics.jl is a symbolic modeling language for Julia, built in Julia. Its goal is very different from Sympy: it was made to support symbolic-numerics, the combination of symbolic computing with numerical methods to allow for extreme performance computing that would not be possible without modifying the model. Because of this, Symbolics.jl excels in many areas due to purposeful design decisions:

  • Performance: Symbolics.jl is built in Julia, whereas SymPy was built in Python. Thus, the performance bar for Symbolics.jl is much higher. Symbolics.jl started because SymPy was far too slow and SymEngine was far too inflexible for the projects they were doing. Performance is key to Symbolics.jl. If you find any performance issues, please file an issue.
  • build_function: lambdify is “fine” for some people, but if you're building a super fast MPI-enabled Julia/C/Fortran simulation code, having a function that hits the Python interpreter is less than optimal. By default, build_function builds fast JIT-compiled functions due to being in Julia. However, it has support for things like static arrays, non-allocating functions via mutation, fast functions on sparse matrices and arrays of arrays, etc.: all core details of doing high performance computing.
  • Parallelism: Symbolics.jl has pervasive parallelism. The symbolic simplification via SymbolicUtils.jl has built-in parallelism, Symbolics.jl builds functions that parallelize across threads. Symbolics.jl is compatible with GPU libraries like CUDA.jl.
  • Extensible: Symbolics.jl and its underlying tools are written in pure Julia. Want to add new or better simplification rules? Add some Julia code! Need to add new derivatives? Add some Julia code! You get the picture. Breaking down these barriers makes it easier for the user to tailor the program to their needs and accelerates the development of the library.
  • Deep integration with the Julia ecosystem: Symbolics.jl's integration with neural networks is not the only thing that's deep. Symbolics.jl is built with the same philosophy as other SciML packages, eschewing “monorepos” for a distributed development approach that ties together the work of many developers. The differentiation parts utilize tools from automatic differentiation libraries, all linear algebra functionality comes from tracing Julia Base itself, symbolic rewriting (simplification and substitution) comes from SymbolicUtils.jl, parallelism comes from Julia Base libraries, Dagger.jl, etc. SciML Tools like DataDrivenDiffEq.jl can reconstruct symbolic expressions from neural networks and data, while NeuralPDE.jl can automatically solve partial differential equations from symbolic descriptions using physics-informed neural networks. The list keeps going. All told, by design Symbolics.jl's development moves fast because it's effectively using the work of hundreds of Julia developers, allowing it to grow fast.
  • While Symbolics.jl has many features missing from SymPy, it does not superset SymPy's functionality. For a list of missing features, see this issue.
+Comparison Against SymPy · Symbolics.jl

Comparison of Julia's Symbolics.jl vs SymPy for Symbolic Computation

Symbolics.jl is a symbolic modeling language for Julia, built in Julia. Its goal is very different from Sympy: it was made to support symbolic-numerics, the combination of symbolic computing with numerical methods to allow for extreme performance computing that would not be possible without modifying the model. Because of this, Symbolics.jl excels in many areas due to purposeful design decisions:

  • Performance: Symbolics.jl is built in Julia, whereas SymPy was built in Python. Thus, the performance bar for Symbolics.jl is much higher. Symbolics.jl started because SymPy was far too slow and SymEngine was far too inflexible for the projects they were doing. Performance is key to Symbolics.jl. If you find any performance issues, please file an issue.
  • build_function: lambdify is “fine” for some people, but if you're building a super fast MPI-enabled Julia/C/Fortran simulation code, having a function that hits the Python interpreter is less than optimal. By default, build_function builds fast JIT-compiled functions due to being in Julia. However, it has support for things like static arrays, non-allocating functions via mutation, fast functions on sparse matrices and arrays of arrays, etc.: all core details of doing high performance computing.
  • Parallelism: Symbolics.jl has pervasive parallelism. The symbolic simplification via SymbolicUtils.jl has built-in parallelism, Symbolics.jl builds functions that parallelize across threads. Symbolics.jl is compatible with GPU libraries like CUDA.jl.
  • Extensible: Symbolics.jl and its underlying tools are written in pure Julia. Want to add new or better simplification rules? Add some Julia code! Need to add new derivatives? Add some Julia code! You get the picture. Breaking down these barriers makes it easier for the user to tailor the program to their needs and accelerates the development of the library.
  • Deep integration with the Julia ecosystem: Symbolics.jl's integration with neural networks is not the only thing that's deep. Symbolics.jl is built with the same philosophy as other SciML packages, eschewing “monorepos” for a distributed development approach that ties together the work of many developers. The differentiation parts utilize tools from automatic differentiation libraries, all linear algebra functionality comes from tracing Julia Base itself, symbolic rewriting (simplification and substitution) comes from SymbolicUtils.jl, parallelism comes from Julia Base libraries, Dagger.jl, etc. SciML Tools like DataDrivenDiffEq.jl can reconstruct symbolic expressions from neural networks and data, while NeuralPDE.jl can automatically solve partial differential equations from symbolic descriptions using physics-informed neural networks. The list keeps going. All told, by design Symbolics.jl's development moves fast because it's effectively using the work of hundreds of Julia developers, allowing it to grow fast.
  • While Symbolics.jl has many features missing from SymPy, it does not superset SymPy's functionality. For a list of missing features, see this issue.
diff --git a/dev/getting_started/index.html b/dev/getting_started/index.html index 026dfd2b4..b58605b48 100644 --- a/dev/getting_started/index.html +++ b/dev/getting_started/index.html @@ -233,9 +233,9 @@ out = sparse(rows, cols, zeros(length(cols)), size(sj)...) # pre-allocate, and correct structure myf = eval(last(f_expr)) myf(out, rand(N)) # note that out matches the sparsity structure of sj -out
20×10 SparseArrays.SparseMatrixCSC{Float64, Int64} with 25 stored entries:
-⎡⠂⠔⠠⠅⠀⎤
-⎢⠄⠀⠀⠀⡀⎥
-⎢⠘⠘⡀⡀⠈⎥
-⎢⠄⠂⢁⠀⠀⎥
-⎣⢁⠐⠄⠁⠐⎦
+out
20×10 SparseArrays.SparseMatrixCSC{Float64, Int64} with 26 stored entries:
+⎡⠁⡀⠀⠀⠰⎤
+⎢⠀⢤⠠⠐⠀⎥
+⎢⠀⡁⠑⢀⠀⎥
+⎢⠀⠨⠐⠀⠃⎥
+⎣⠀⢀⠖⡠⠂⎦
diff --git a/dev/index.html b/dev/index.html index fd0ce50f5..ddacae650 100644 --- a/dev/index.html +++ b/dev/index.html @@ -404,4 +404,4 @@ [8e850b90] libblastrampoline_jll v5.11.0+0 [8e850ede] nghttp2_jll v1.59.0+0 [3f19e933] p7zip_jll v17.4.0+2 -Info Packages marked with ⌅ have new versions available but compatibility constraints restrict them from upgrading. To see why use `status --outdated -m`

You can also download the manifest file and the project file.

+Info Packages marked with ⌅ have new versions available but compatibility constraints restrict them from upgrading. To see why use `status --outdated -m`

You can also download the manifest file and the project file.

diff --git a/dev/manual/arrays/index.html b/dev/manual/arrays/index.html index c8720e05c..1a78ea211 100644 --- a/dev/manual/arrays/index.html +++ b/dev/manual/arrays/index.html @@ -64,4 +64,4 @@ A_{2,1} A_{3,1} + A_{2,2} A_{3,2} + A_{2,3} A_{3,3} \end{equation} \]

@syms i::Int j::Int
-Symbolics.scalarize(AAt[i,j])

In general, any scalar expression which is derived from array expressions can be scalarized.

#sum(A[:,1]) + sum(A[2,:])#latexify not working
Symbolics.scalarize(sum(A[:,1]) + sum(A[2,:]))
+Symbolics.scalarize(AAt[i,j])

In general, any scalar expression which is derived from array expressions can be scalarized.

#sum(A[:,1]) + sum(A[2,:])#latexify not working
Symbolics.scalarize(sum(A[:,1]) + sum(A[2,:]))
diff --git a/dev/manual/build_function/index.html b/dev/manual/build_function/index.html index a9b2c3724..7a2f44b27 100644 --- a/dev/manual/build_function/index.html +++ b/dev/manual/build_function/index.html @@ -3,7 +3,7 @@ expression = Val{true}, target = JuliaTarget(), parallel=nothing, - kwargs...)

Arguments:

Keyword Arguments:

Note that not all build targets support the full compilation interface. Check the individual target documentation for details.

source

Target-Specific Definitions

Symbolics._build_functionMethod
_build_function(target::JuliaTarget, rhss::AbstractArray, args...;
+               kwargs...)

Arguments:

  • ex: The Num to compile
  • args: The arguments of the function
  • expression: Whether to generate code or whether to generate the compiled form. By default, expression = Val{true}, which means that the code for the function is returned. If Val{false}, then the returned value is compiled.

Keyword Arguments:

  • target: The output target of the compilation process. Possible options are:
    • JuliaTarget: Generates a Julia function
    • CTarget: Generates a C function
    • StanTarget: Generates a function for compiling with the Stan probabilistic programming language
    • MATLABTarget: Generates an anonymous function for use in MATLAB and Octave environments
  • parallel: The kind of parallelism to use in the generated function. Defaults to SerialForm(), i.e. no parallelism, if ex is a single expression or an array containing <= 1500 non-zero expressions. If ex is an array of > 1500 non-zero expressions, then ShardedForm(80, 4) is used. See below for more on ShardedForm. Note that the parallel forms are not exported and thus need to be chosen like Symbolics.SerialForm(). The choices are:
    • SerialForm(): Serial execution.
    • ShardedForm(cutoff, ncalls): splits the output function into sub-functions which contain at most cutoff number of output rhss. These sub-functions are called by the top-level function that buildfunction returns. This helps in reducing the compile time of the generated function.
    • MultithreadedForm(): Multithreaded execution with a static split, evenly splitting the number of expressions per thread.
  • fname: Used by some targets for the name of the function in the target space.

Note that not all build targets support the full compilation interface. Check the individual target documentation for details.

source

Target-Specific Definitions

Symbolics._build_functionMethod
_build_function(target::JuliaTarget, rhss::AbstractArray, args...;
                    conv=toexpr,
                    expression = Val{true},
                    expression_module = @__MODULE__(),
@@ -26,14 +26,14 @@
                          convert_oop = true, force_SA = false,
                          skipzeros = outputidxs===nothing,
                          fillzeros = skipzeros && !(typeof(rhss)<:SparseMatrixCSC),
-                         parallel=SerialForm(), kwargs...)

Generates a Julia function which can then be utilized for further evaluations. If expression=Val{false}, the return is a Julia function which utilizes RuntimeGeneratedFunctions.jl to be free of world-age issues.

If the rhss is a scalar, the generated function is a function with a scalar output. Otherwise, if it's an AbstractArray, the output is two functions, one for out-of-place AbstractArray output and a second which is a mutating function. The outputted functions match the given argument order, i.e., f(u,p,args...) for the out-of-place and scalar functions and f!(du,u,p,args..) for the in-place version.

Special Keyword Arguments:

  • parallel: The kind of parallelism to use in the generated function. Defaults to SerialForm(), i.e. no parallelism. Note that the parallel forms are not exported and thus need to be chosen like Symbolics.SerialForm(). The choices are:
    • SerialForm(): Serial execution.
    • ShardedForm(cutoff, ncalls): splits the output function into sub-functions which contain at most cutoff number of output rhss. These sub-functions are called by the top-level function that buildfunction returns.
    • MultithreadedForm(): Multithreaded execution with a static split, evenly splitting the number of expressions per thread.
  • conv: The conversion function of symbolic types to Expr. By default, this uses the toexpr function.
  • checkbounds: For whether to enable bounds checking inside the generated function. Defaults to false, meaning that @inbounds is applied.
  • linenumbers: Determines whether the generated function expression retains the line numbers. Defaults to true.
  • convert_oop: Determines whether the OOP version should try to convert the output to match the type of the first input. This is useful for cases like LabelledArrays or other array types that carry extra information. Defaults to true.
  • force_SA: Forces the output of the OOP version to be a StaticArray. Defaults to false, and outputs a static array when the first argument is a static array.
  • skipzeros: Whether to skip filling zeros in the in-place version if the filling function is 0.
  • fillzeros: Whether to perform fill(out,0) before the calculations to ensure safety with skipzeros.
source
Symbolics._build_functionMethod

Build function target: CTarget

function _build_function(target::CTarget, eqs::Array{<:Equation}, args...;
+                         parallel=SerialForm(), kwargs...)

Generates a Julia function which can then be utilized for further evaluations. If expression=Val{false}, the return is a Julia function which utilizes RuntimeGeneratedFunctions.jl to be free of world-age issues.

If the rhss is a scalar, the generated function is a function with a scalar output. Otherwise, if it's an AbstractArray, the output is two functions, one for out-of-place AbstractArray output and a second which is a mutating function. The outputted functions match the given argument order, i.e., f(u,p,args...) for the out-of-place and scalar functions and f!(du,u,p,args..) for the in-place version.

Special Keyword Arguments:

  • parallel: The kind of parallelism to use in the generated function. Defaults to SerialForm(), i.e. no parallelism. Note that the parallel forms are not exported and thus need to be chosen like Symbolics.SerialForm(). The choices are:
    • SerialForm(): Serial execution.
    • ShardedForm(cutoff, ncalls): splits the output function into sub-functions which contain at most cutoff number of output rhss. These sub-functions are called by the top-level function that buildfunction returns.
    • MultithreadedForm(): Multithreaded execution with a static split, evenly splitting the number of expressions per thread.
  • conv: The conversion function of symbolic types to Expr. By default, this uses the toexpr function.
  • checkbounds: For whether to enable bounds checking inside the generated function. Defaults to false, meaning that @inbounds is applied.
  • linenumbers: Determines whether the generated function expression retains the line numbers. Defaults to true.
  • convert_oop: Determines whether the OOP version should try to convert the output to match the type of the first input. This is useful for cases like LabelledArrays or other array types that carry extra information. Defaults to true.
  • force_SA: Forces the output of the OOP version to be a StaticArray. Defaults to false, and outputs a static array when the first argument is a static array.
  • skipzeros: Whether to skip filling zeros in the in-place version if the filling function is 0.
  • fillzeros: Whether to perform fill(out,0) before the calculations to ensure safety with skipzeros.
source
Symbolics._build_functionMethod

Build function target: CTarget

function _build_function(target::CTarget, eqs::Array{<:Equation}, args...;
                          conv = toexpr, expression = Val{true},
                          fname = :diffeqf,
                          lhsname=:du,rhsnames=[Symbol("RHS$i") for i in 1:length(args)],
-                         libpath=tempname(),compiler=:gcc)

This builds an in-place C function. Only works on arrays of equations. If expression == Val{false}, then this builds a function in C, compiles it, and returns a lambda to that compiled function. These special keyword arguments control the compilation:

  • libpath: the path to store the binary. Defaults to a temporary path.
  • compiler: which C compiler to use. Defaults to :gcc, which is currently the only available option.
source
Symbolics._build_functionMethod

Build function target: StanTarget

function _build_function(target::StanTarget, eqs::Array{<:Equation}, vs, ps, iv;
+                         libpath=tempname(),compiler=:gcc)

This builds an in-place C function. Only works on arrays of equations. If expression == Val{false}, then this builds a function in C, compiles it, and returns a lambda to that compiled function. These special keyword arguments control the compilation:

  • libpath: the path to store the binary. Defaults to a temporary path.
  • compiler: which C compiler to use. Defaults to :gcc, which is currently the only available option.
source
Symbolics._build_functionMethod

Build function target: StanTarget

function _build_function(target::StanTarget, eqs::Array{<:Equation}, vs, ps, iv;
                          conv = toexpr, expression = Val{true},
                          fname = :diffeqf, lhsname=:internal_var___du,
-                         rhsnames=[:internal_var___u,:internal_var___p,:internal_var___t])

This builds an in-place Stan function compatible with the Stan differential equation solvers. Unlike other build targets, this one requires (vs, ps, iv) as the function arguments. Only allowed on arrays of equations.

source
Symbolics._build_functionMethod

Build function target: MATLABTarget

function _build_function(target::MATLABTarget, eqs::Array{<:Equation}, args...;
+                         rhsnames=[:internal_var___u,:internal_var___p,:internal_var___t])

This builds an in-place Stan function compatible with the Stan differential equation solvers. Unlike other build targets, this one requires (vs, ps, iv) as the function arguments. Only allowed on arrays of equations.

source
Symbolics._build_functionMethod

Build function target: MATLABTarget

function _build_function(target::MATLABTarget, eqs::Array{<:Equation}, args...;
                          conv = toexpr, expression = Val{true},
                          lhsname=:internal_var___du,
-                         rhsnames=[:internal_var___u,:internal_var___p,:internal_var___t])

This builds an out of place anonymous function @(t,rhsnames[1]) to be used in MATLAB. Compatible with the MATLAB differential equation solvers. Only allowed on expressions, and arrays of expressions.

source

Limitations

build_function

+ rhsnames=[:internal_var___u,:internal_var___p,:internal_var___t])

This builds an out of place anonymous function @(t,rhsnames[1]) to be used in MATLAB. Compatible with the MATLAB differential equation solvers. Only allowed on expressions, and arrays of expressions.

source

Limitations

build_function

diff --git a/dev/manual/derivatives/index.html b/dev/manual/derivatives/index.html index 98269aa2b..002799030 100644 --- a/dev/manual/derivatives/index.html +++ b/dev/manual/derivatives/index.html @@ -13,7 +13,7 @@ (D'~x(t)) ∘ (D'~y(t)) julia> D3 = Differential(x)^3 # 3rd order differential operator -(D'~x(t)) ∘ (D'~x(t)) ∘ (D'~x(t))source
Symbolics.expand_derivativesFunction
expand_derivatives(O; ...)
+(D'~x(t)) ∘ (D'~x(t)) ∘ (D'~x(t))
source
Symbolics.expand_derivativesFunction
expand_derivatives(O; ...)
 expand_derivatives(O, simplify; occurrences)
 

Expands derivatives within a symbolic expression O.

This function recursively traverses a symbolic expression, applying the chain rule and other derivative rules to expand any derivatives it encounters.

Arguments

  • O::Symbolic: The symbolic expression to expand.
  • simplify::Bool=false: Whether to simplify the resulting expression using SymbolicUtils.simplify.
  • occurrences=nothing: Information about the occurrences of the independent variable in the argument of the derivative. This is used internally for optimization purposes.

Examples

julia> @variables x y z k;
 
@@ -24,15 +24,15 @@
 (::Differential) (generic function with 2 methods)
 
 julia> dfx=expand_derivatives(Dx(f))
-(k*((2abs(x - y)) / y - 2z)*IfElse.ifelse(signbit(x - y), -1, 1)) / y
source
Missing docstring.

Missing docstring for is_derivative. Check Documenter's build log for details.

Note

For symbolic differentiation, all registered functions in the symbolic expression need a registered derivative. For more information, see the function registration page.

High-Level Differentiation Functions

The following functions are not exported and thus must be accessed in a namespaced way, i.e. Symbolics.jacobian.

Symbolics.derivativeFunction
derivative(O, var; simplify)
-

A helper function for computing the derivative of the expression O with respect to var.

source
Symbolics.jacobianFunction
jacobian(ops, vars; simplify, scalarize)
-

A helper function for computing the Jacobian of an array of expressions with respect to an array of variable expressions.

source
Symbolics.sparsejacobianFunction
sparsejacobian(ops, vars; simplify)
-

A helper function for computing the sparse Jacobian of an array of expressions with respect to an array of variable expressions.

source
Symbolics.sparsejacobian_valsFunction
sparsejacobian_vals(ops, vars, I, J; simplify)
-

A helper function for computing the values of the sparse Jacobian of an array of expressions with respect to an array of variable expressions given the sparsity structure.

source
Symbolics.gradientFunction
gradient(O, vars; simplify)
-

A helper function for computing the gradient of the expression O with respect to an array of variable expressions.

source
Symbolics.hessianFunction
hessian(O, vars; simplify)
-

A helper function for computing the Hessian of the expression O with respect to an array of variable expressions.

source
Symbolics.sparsehessianFunction
sparsehessian(op, vars; simplify, full)
-

A helper function for computing the sparse Hessian of an expression with respect to an array of variable expressions.

source
Symbolics.sparsehessian_valsFunction
sparsehessian_vals(op, vars, I, J; simplify)
-

A helper function for computing the values of the sparse Hessian of an expression with respect to an array of variable expressions given the sparsity structure.

source

Adding Analytical Derivatives

There are many derivatives pre-defined by DiffRules.jl. For example,

using Symbolics
+(k*((2abs(x - y)) / y - 2z)*IfElse.ifelse(signbit(x - y), -1, 1)) / y
source
Missing docstring.

Missing docstring for is_derivative. Check Documenter's build log for details.

Note

For symbolic differentiation, all registered functions in the symbolic expression need a registered derivative. For more information, see the function registration page.

High-Level Differentiation Functions

The following functions are not exported and thus must be accessed in a namespaced way, i.e. Symbolics.jacobian.

Symbolics.derivativeFunction
derivative(O, var; simplify)
+

A helper function for computing the derivative of the expression O with respect to var.

source
Symbolics.jacobianFunction
jacobian(ops, vars; simplify, scalarize)
+

A helper function for computing the Jacobian of an array of expressions with respect to an array of variable expressions.

source
Symbolics.sparsejacobianFunction
sparsejacobian(ops, vars; simplify)
+

A helper function for computing the sparse Jacobian of an array of expressions with respect to an array of variable expressions.

source
Symbolics.sparsejacobian_valsFunction
sparsejacobian_vals(ops, vars, I, J; simplify)
+

A helper function for computing the values of the sparse Jacobian of an array of expressions with respect to an array of variable expressions given the sparsity structure.

source
Symbolics.gradientFunction
gradient(O, vars; simplify)
+

A helper function for computing the gradient of the expression O with respect to an array of variable expressions.

source
Symbolics.hessianFunction
hessian(O, vars; simplify)
+

A helper function for computing the Hessian of the expression O with respect to an array of variable expressions.

source
Symbolics.sparsehessianFunction
sparsehessian(op, vars; simplify, full)
+

A helper function for computing the sparse Hessian of an expression with respect to an array of variable expressions.

source
Symbolics.sparsehessian_valsFunction
sparsehessian_vals(op, vars, I, J; simplify)
+

A helper function for computing the values of the sparse Hessian of an expression with respect to an array of variable expressions given the sparsity structure.

source

Adding Analytical Derivatives

There are many derivatives pre-defined by DiffRules.jl. For example,

using Symbolics
 @variables x y z
 f(x,y,z) = x^2 + sin(x+y) - z
f (generic function with 1 method)

f automatically has the derivatives defined via the tracing mechanism. It will do this by directly building the internals of your function and differentiating that.

However, often you may want to define your own derivatives so that way automatic Jacobian etc. calculations can utilize this information. This can allow for more succinct versions of the derivatives to be calculated to scale to larger systems. You can define derivatives for your function via the dispatch:

# `N` arguments are accepted by the relevant method of `my_function`
-Symbolics.derivative(::typeof(my_function), args::NTuple{N,Any}, ::Val{i})

where i means that it's the derivative with respect to the ith argument. args is the array of arguments, so, for example, if your function is f(x,t), then args = [x,t]. You should return an Term for the derivative of your function.

For example, sin(t)'s derivative (by t) is given by the following:

Symbolics.derivative(::typeof(sin), args::NTuple{1,Any}, ::Val{1}) = cos(args[1])
+Symbolics.derivative(::typeof(my_function), args::NTuple{N,Any}, ::Val{i})

where i means that it's the derivative with respect to the ith argument. args is the array of arguments, so, for example, if your function is f(x,t), then args = [x,t]. You should return an Term for the derivative of your function.

For example, sin(t)'s derivative (by t) is given by the following:

Symbolics.derivative(::typeof(sin), args::NTuple{1,Any}, ::Val{1}) = cos(args[1])
diff --git a/dev/manual/expression_manipulation/index.html b/dev/manual/expression_manipulation/index.html index 93fa6f5a4..d306c1e03 100644 --- a/dev/manual/expression_manipulation/index.html +++ b/dev/manual/expression_manipulation/index.html @@ -8,7 +8,7 @@ julia> ex = x + y + sin(z) (x + y) + sin(z(t)) julia> substitute(ex, Dict([x => z, sin(z) => z^2])) -(z(t) + y) + (z(t) ^ 2)source
SymbolicUtils.simplifyFunction
simplify(x; expand=false,
+(z(t) + y) + (z(t) ^ 2)
source
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

Documentation for rewriter can be found here, using the @rule macro or the @acrule macro from SymbolicUtils.jl.

Additional Manipulation Functions

Other additional manipulation functions are given below.

Symbolics.get_variablesFunction
get_variables(e, varlist = nothing; sort::Bool = false)

Return a vector of variables appearing in e, optionally restricting to variables in varlist.

Note that the returned variables are not wrapped in the Num type.

Examples

julia> @variables t x y z(t);
@@ -22,7 +22,7 @@
 julia> Symbolics.get_variables(x - y; sort = true)
 2-element Vector{SymbolicUtils.BasicSymbolic}:
  x
- y
source
Symbolics.tosymbolFunction
tosymbol(x::Union{Num,Symbolic}; states=nothing, escape=true) -> Symbol

Convert 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)
+ y
source
Symbolics.tosymbolFunction
tosymbol(x::Union{Num,Symbolic}; states=nothing, escape=true) -> Symbol

Convert 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)
@@ -31,13 +31,13 @@
 Symbol("z(t)")
 
 julia> Symbolics.tosymbol(z; escape=false)
-:z
source
Symbolics.diff2termFunction
diff2term(x, x_metadata::Dict{Datatype, Any}) -> Symbolic

Convert a differential variable to a Term. Note that it only takes a Term not a Num. Any upstream metadata can be passed via x_metadata

julia> @variables x t u(x, t) z(t)[1:2]; Dt = Differential(t); Dx = Differential(x);
+:z
source
Symbolics.diff2termFunction
diff2term(x, x_metadata::Dict{Datatype, Any}) -> Symbolic

Convert a differential variable to a Term. Note that it only takes a Term not a Num. Any upstream metadata can be passed via x_metadata

julia> @variables x t u(x, t) z(t)[1:2]; Dt = Differential(t); Dx = Differential(x);
 
 julia> Symbolics.diff2term(Symbolics.value(Dx(Dt(u))))
 uˍtx(x, t)
 
 julia> Symbolics.diff2term(Symbolics.value(Dt(z[1])))
-var"z(t)[1]ˍt"
source
Symbolics.degreeFunction
degree(p, sym=nothing)

Extract the degree of p with respect to sym.

Examples

julia> @variables x;
+var"z(t)[1]ˍt"
source
Symbolics.degreeFunction
degree(p, sym=nothing)

Extract the degree of p with respect to sym.

Examples

julia> @variables x;
 
 julia> Symbolics.degree(x^0)
 0
@@ -46,7 +46,7 @@
 1
 
 julia> Symbolics.degree(x^2)
-2
source
Symbolics.coeffFunction
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;
+2
source
Symbolics.coeffFunction
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
@@ -58,9 +58,9 @@
 1
 
 julia> Symbolics.coeff(2*x*y + y, x*y)
-2
source
Missing docstring.

Missing docstring for Symbolics.replace. Check Documenter's build log for details.

Base.occursinFunction
occursin(needle::Symbolic, haystack::Symbolic)

Determine whether the second argument contains the first argument. Note that this function doesn't handle associativity, commutativity, or distributivity.

source
Symbolics.filterchildrenFunction

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
+2
source
Missing docstring.

Missing docstring for Symbolics.replace. Check Documenter's build log for details.

Base.occursinFunction
occursin(needle::Symbolic, haystack::Symbolic)

Determine whether the second argument contains the first argument. Note that this function doesn't handle associativity, commutativity, or distributivity.

source
Symbolics.filterchildrenFunction

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))]

source
Symbolics.fixpoint_subFunction
fixpoint_sub(expr, dict; operator = Nothing, maxiters = 10000)

Given a symbolic expression, equation or inequality expr perform the substitutions in dict recursively until the expression does not change. Substitutions that depend on one another will thus be recursively expanded. For example, fixpoint_sub(x, Dict(x => y, y => 3)) will return 3. The operator keyword can be specified to prevent substitution of expressions inside operators of the given type. The maxiters keyword is used to limit the number of times the substitution can occur to avoid infinite loops in cases where the substitutions in dict are circular (e.g. [x => y, y => x]).

See also: fast_substitute.

source
Symbolics.fast_substituteFunction
fast_substitute(expr, dict; operator = Nothing)

Given a symbolic expression, equation or inequality expr perform the substitutions in dict. This only performs the substitutions once. For example, fast_substitute(x, Dict(x => y, y => 3)) will return y. The operator keyword can be specified to prevent substitution of expressions inside operators of the given type.

See also: fixpoint_sub.

source
Symbolics.symbolic_to_floatFunction
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
+Symbolics.filterchildren(Symbolics.is_derivative, X + D(X) + D(X^2))

returns [Differential(t)(X(t)^2), Differential(t)(X(t))]

source
Symbolics.fixpoint_subFunction
fixpoint_sub(expr, dict; operator = Nothing, maxiters = 10000)

Given a symbolic expression, equation or inequality expr perform the substitutions in dict recursively until the expression does not change. Substitutions that depend on one another will thus be recursively expanded. For example, fixpoint_sub(x, Dict(x => y, y => 3)) will return 3. The operator keyword can be specified to prevent substitution of expressions inside operators of the given type. The maxiters keyword is used to limit the number of times the substitution can occur to avoid infinite loops in cases where the substitutions in dict are circular (e.g. [x => y, y => x]).

See also: fast_substitute.

source
Symbolics.fast_substituteFunction
fast_substitute(expr, dict; operator = Nothing)

Given a symbolic expression, equation or inequality expr perform the substitutions in dict. This only performs the substitutions once. For example, fast_substitute(x, Dict(x => y, y => 3)) will return y. The operator keyword can be specified to prevent substitution of expressions inside operators of the given type.

See also: fixpoint_sub.

source
Symbolics.symbolic_to_floatFunction
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.175823272122517
source
+symbolic_to_float((1//2)*√(279//4)) # 4.175823272122517source diff --git a/dev/manual/faq/index.html b/dev/manual/faq/index.html index cc9506fe6..0ad31ba95 100644 --- a/dev/manual/faq/index.html +++ b/dev/manual/faq/index.html @@ -30,4 +30,4 @@ b = only(@variables($a))

\[ \begin{equation} c \end{equation} - \]

In this example, @variables($a) created a variable named c, and set this variable to b.

+ \]

In this example, @variables($a) created a variable named c, and set this variable to b.

diff --git a/dev/manual/functions/index.html b/dev/manual/functions/index.html index a3e6961e5..32a6626cb 100644 --- a/dev/manual/functions/index.html +++ b/dev/manual/functions/index.html @@ -41,19 +41,19 @@ \]

Note that at this time array derivatives cannot be defined.

Registration API

Symbolics.@register_symbolicMacro
@register_symbolic(expr, define_promotion = true, Ts = [Real])

Overload appropriate methods so that Symbolics can stop tracing into the registered function. If define_promotion is true, then a promotion method in the form of

SymbolicUtils.promote_symtype(::typeof(f_registered), args...) = Real # or the annotated return type

is defined for the register function. Note that when defining multiple register overloads for one function, all the rest of the registers must set define_promotion to false except for the first one, to avoid method overwriting.

Examples

@register_symbolic foo(x, y)
 @register_symbolic foo(x, y::Bool) false # do not overload a duplicate promotion rule
 @register_symbolic goo(x, y::Int) # `y` is not overloaded to take symbolic objects
-@register_symbolic hoo(x, y)::Int # `hoo` returns `Int`

See @register_array_symbolic to register functions which return arrays.

source
Symbolics.@register_array_symbolicMacro
@register_array_symbolic(expr, define_promotion = true)

Example:

# Let's say vandermonde takes an n-vector and returns an n x n matrix
+@register_symbolic hoo(x, y)::Int # `hoo` returns `Int`

See @register_array_symbolic to register functions which return arrays.

source
Symbolics.@register_array_symbolicMacro
@register_array_symbolic(expr, define_promotion = true)

Example:

# Let's say vandermonde takes an n-vector and returns an n x n matrix
 @register_array_symbolic vandermonde(x::AbstractVector) begin
     size=(length(x), length(x))
     eltype=eltype(x) # optional, will default to the promoted eltypes of x
 end

You can also register calls on callable structs:

@register_array_symbolic (c::Conv)(x::AbstractMatrix) begin
     size=size(x) .- size(c.kernel) .+ 1
     eltype=promote_type(eltype(x), eltype(c))
-end

If define_promotion = true then a promotion method in the form of

SymbolicUtils.promote_symtype(::typeof(f_registered), args...) = # inferred or annotated return type

is defined for the register function. Note that when defining multiple register overloads for one function, all the rest of the registers must set define_promotion to false except for the first one, to avoid method overwriting.

source

Direct Registration API (Advanced, Experimental)

Warn

This is a lower level API which is not as stable as the macro APIs.

In some circumstances you may need to use the direct API in order to define registration on functions or types without using the macro. This is done by directly defining dispatches on symbolic objects.

A good example of this is DataInterpolations.jl's interpolations object. On an interpolation by a symbolic variable, we generate the symbolic function (the term) for the interpolation function. This looks like:

using DataInterpolations, Symbolics, SymbolicUtils
+end

If define_promotion = true then a promotion method in the form of

SymbolicUtils.promote_symtype(::typeof(f_registered), args...) = # inferred or annotated return type

is defined for the register function. Note that when defining multiple register overloads for one function, all the rest of the registers must set define_promotion to false except for the first one, to avoid method overwriting.

source

Direct Registration API (Advanced, Experimental)

Warn

This is a lower level API which is not as stable as the macro APIs.

In some circumstances you may need to use the direct API in order to define registration on functions or types without using the macro. This is done by directly defining dispatches on symbolic objects.

A good example of this is DataInterpolations.jl's interpolations object. On an interpolation by a symbolic variable, we generate the symbolic function (the term) for the interpolation function. This looks like:

using DataInterpolations, Symbolics, SymbolicUtils
 (interp::AbstractInterpolation)(t::Num) = SymbolicUtils.term(interp, unwrap(t))

In order for this to work, it is required that we define the symtype for the symbolic type inference. This is done via:

SymbolicUtils.promote_symtype(t::AbstractInterpolation, args...) = Real

Additionally a symbolic name is required:

Base.nameof(interp::AbstractInterpolation) = :Interpolation

The derivative is defined similarly to the macro case:

function Symbolics.derivative(interp::AbstractInterpolation, args::NTuple{1, Any}, ::Val{1})
     Symbolics.unwrap(derivative(interp, Symbolics.wrap(args[1])))
-end

Inverse function registration

Symbolics.jl allows defining and querying the inverses of functions.

Symbolics.inverseFunction
inverse(f)

Given a single-input single-output function f, return its inverse g. This requires that f is bijective. If inverse is defined for a function, left_inverse and right_inverse should return inverse(f). inverse(g) should also be defined to return f.

See also: left_inverse, right_inverse, @register_inverse.

source
Symbolics.left_inverseFunction
left_inverse(f)

Given a single-input single-output function f, return its left inverse g. This requires that f is injective. If left_inverse is defined for a function, right_inverse and inverse must not be defined and should error. right_inverse(g) should also be defined to return f.

See also: inverse, right_inverse, @register_inverse.

source
Symbolics.right_inverseFunction
right_inverse(f)

Given a single-input single-output function f, return its right inverse g. This requires that f is surjective. If right_inverse is defined for a function, left_inverse and inverse must not be defined and should error. left_inverse(g) should also be defined to return f.

See also inverse, left_inverse, @register_inverse.

source
Symbolics.@register_inverseMacro
@register_inverse f g
+end

Inverse function registration

Symbolics.jl allows defining and querying the inverses of functions.

Symbolics.inverseFunction
inverse(f)

Given a single-input single-output function f, return its inverse g. This requires that f is bijective. If inverse is defined for a function, left_inverse and right_inverse should return inverse(f). inverse(g) should also be defined to return f.

See also: left_inverse, right_inverse, @register_inverse.

source
Symbolics.left_inverseFunction
left_inverse(f)

Given a single-input single-output function f, return its left inverse g. This requires that f is injective. If left_inverse is defined for a function, right_inverse and inverse must not be defined and should error. right_inverse(g) should also be defined to return f.

See also: inverse, right_inverse, @register_inverse.

source
Symbolics.right_inverseFunction
right_inverse(f)

Given a single-input single-output function f, return its right inverse g. This requires that f is surjective. If right_inverse is defined for a function, left_inverse and inverse must not be defined and should error. left_inverse(g) should also be defined to return f.

See also inverse, left_inverse, @register_inverse.

source
Symbolics.@register_inverseMacro
@register_inverse f g
 @register_inverse f g left
-@register_inverse f g right

Mark f and g as inverses of each other. By default, assume that f and g are bijective. Also defines left_inverse and right_inverse to call inverse. If the third argument is left, assume that f is injective and g is its left inverse. If the third argument is right, assume that f is surjective and g is its right inverse.

source

Symbolics.jl implements inverses for standard trigonometric and logarithmic functions, as well as their variants from NaNMath. It also implements inverses of ComposedFunctions.

+@register_inverse f g right

Mark f and g as inverses of each other. By default, assume that f and g are bijective. Also defines left_inverse and right_inverse to call inverse. If the third argument is left, assume that f is injective and g is its left inverse. If the third argument is right, assume that f is surjective and g is its right inverse.

source
Symbolics.has_inverseFunction
has_inverse(_) -> Bool
+

Check if the provided function has an inverse defined via inverse. Uses hasmethod to perform the check.

source
Symbolics.has_left_inverseFunction
has_left_inverse(_) -> Bool
+

Check if the provided function has a left inverse defined via left_inverse Uses hasmethod to perform the check.

source
Symbolics.has_right_inverseFunction
has_right_inverse(_) -> Bool
+

Check if the provided function has a left inverse defined via left_inverse Uses hasmethod to perform the check.

source

Symbolics.jl implements inverses for standard trigonometric and logarithmic functions, as well as their variants from NaNMath. It also implements inverses of ComposedFunctions.

diff --git a/dev/manual/groebner/index.html b/dev/manual/groebner/index.html index e8640fb0f..2ef672f79 100644 --- a/dev/manual/groebner/index.html +++ b/dev/manual/groebner/index.html @@ -1,2 +1,2 @@ -Groebner bases · Symbolics.jl

Groebner bases

Groebner bases use the implementation of the F4 algorithm from Groebner.jl package as its backend. We refer to the documentation of Groebner.jl, which lists some implementations details and possible use-cases of Groebner bases.

Symbolics.groebner_basisFunction
groebner_basis(polynomials)

Computes a Groebner basis of the ideal generated by the given polynomials.

This function requires a Groebner bases backend (such as Groebner.jl) to be loaded.

source
+Groebner bases · Symbolics.jl

Groebner bases

Groebner bases use the implementation of the F4 algorithm from Groebner.jl package as its backend. We refer to the documentation of Groebner.jl, which lists some implementations details and possible use-cases of Groebner bases.

Symbolics.groebner_basisFunction
groebner_basis(polynomials)

Computes a Groebner basis of the ideal generated by the given polynomials.

This function requires a Groebner bases backend (such as Groebner.jl) to be loaded.

source
diff --git a/dev/manual/io/index.html b/dev/manual/io/index.html index 4fc0c4d2b..a3df39f0d 100644 --- a/dev/manual/io/index.html +++ b/dev/manual/io/index.html @@ -6,4 +6,4 @@ end ex1, ex2 = build_function(f(u),u) write("function.jl", string(ex2))
898

Now we can do something like:

g = include("function.jl")
#1 (generic function with 1 method)

and that will load the function back in. Note that this can be done to save the transformation results of Symbolics.jl so that they can be stored and used in a precompiled Julia package.

Latexification

Symbolics.jl's expressions support Latexify.jl, and thus

using Latexify
-latexify(ex)

will produce LaTeX output from Symbolics models and expressions. This works on basics like Term all the way to higher primitives like ODESystem and ReactionSystem.

+latexify(ex)

will produce LaTeX output from Symbolics models and expressions. This works on basics like Term all the way to higher primitives like ODESystem and ReactionSystem.

diff --git a/dev/manual/limits/index.html b/dev/manual/limits/index.html index b00e56fed..fa11c1181 100644 --- a/dev/manual/limits/index.html +++ b/dev/manual/limits/index.html @@ -1,2 +1,2 @@ -Symbolic Limits · Symbolics.jl

Symbolic Limits

Experimental symbolic limit support is provided by the limit function, documented below. See SymbolicLimits.jl for more information and implementation details.

Symbolics.limitFunction
limit(expr, var, h[, side::Symbol])

Compute the limit of expr as var approaches h.

side indicates the direction from which var approaches h. It may be one of :left, :right, or :both. If side is :both and the two sides do not align, an error is thrown. Side defaults to :both for finite h, :left for h = Inf, and :right for h = -Inf.

expr must be composed of log, exp, constants, and the rational operators +, -, *, and /. This limitation may eventually be relaxed.

Warning

Because symbolic limit computation is undecidable, this function necessarily employs heuristics and may occasionally return wrong answers. Nevertheless, please report wrong answers as issues as we aim to have heuristics that produce correct answers in all practical cases.

source
+Symbolic Limits · Symbolics.jl

Symbolic Limits

Experimental symbolic limit support is provided by the limit function, documented below. See SymbolicLimits.jl for more information and implementation details.

Symbolics.limitFunction
limit(expr, var, h[, side::Symbol])

Compute the limit of expr as var approaches h.

side indicates the direction from which var approaches h. It may be one of :left, :right, or :both. If side is :both and the two sides do not align, an error is thrown. Side defaults to :both for finite h, :left for h = Inf, and :right for h = -Inf.

expr must be composed of log, exp, constants, and the rational operators +, -, *, and /. This limitation may eventually be relaxed.

Warning

Because symbolic limit computation is undecidable, this function necessarily employs heuristics and may occasionally return wrong answers. Nevertheless, please report wrong answers as issues as we aim to have heuristics that produce correct answers in all practical cases.

source
diff --git a/dev/manual/parsing/index.html b/dev/manual/parsing/index.html index dc2577a23..cf5543b59 100644 --- a/dev/manual/parsing/index.html +++ b/dev/manual/parsing/index.html @@ -15,4 +15,4 @@ z ~ 2] all(isequal.(eqs,ex)) # true

Limitations

Symbolic-ness Tied to Environment Definitions

The parsing to a symbolic expression has to be able to recognize the difference between functions, numbers, and globals defined within one's Julia environment and those that are to be made symbolic. The way this functionality handles this problem is that it does not define anything as symbolic that is already defined in the chosen mod module. For example, f(x,y) will have f as non-symbolic if the function f (named f) is defined in mod, i.e. if isdefined(mod,:f) is true. When the symbol is defined, it will be replaced by its value. Notably, this means that the parsing behavior changes depending on the environment that it is applied.

For example:

parse_expr_to_symbolic(:(x - y),@__MODULE__) # x - y
 x = 2.0
-parse_expr_to_symbolic(:(x - y),@__MODULE__) # 2.0 - y

This is required to detect that standard functions like - are functions instead of symbolic symbols. For safety, one should create anonymous modules or other sub-environments to ensure no stray variables are defined.

Metadata is Blank

Because all the variables defined by the expressions are not defined with the standard @variables, there is no metadata that is or can be associated with any of the generated variables. Instead, they all have blank metadata, but are defined in the Real domain. Thus, the variables which come out of this parsing may not evaluate as equal to a symbolic variable defined elsewhere.

source
Missing docstring.

Missing docstring for @parse_expr_to_symbolic. Check Documenter's build log for details.

+parse_expr_to_symbolic(:(x - y),@__MODULE__) # 2.0 - y

This is required to detect that standard functions like - are functions instead of symbolic symbols. For safety, one should create anonymous modules or other sub-environments to ensure no stray variables are defined.

Metadata is Blank

Because all the variables defined by the expressions are not defined with the standard @variables, there is no metadata that is or can be associated with any of the generated variables. Instead, they all have blank metadata, but are defined in the Real domain. Thus, the variables which come out of this parsing may not evaluate as equal to a symbolic variable defined elsewhere.

source
Missing docstring.

Missing docstring for @parse_expr_to_symbolic. Check Documenter's build log for details.

diff --git a/dev/manual/solver/index.html b/dev/manual/solver/index.html index 0a47a6ed1..d48689c71 100644 --- a/dev/manual/solver/index.html +++ b/dev/manual/solver/index.html @@ -65,7 +65,7 @@ julia> Symbolics.symbolic_to_float.(roots) 1-element Vector{Complex{BigFloat}}: - -4.512941594732059759689023145584186058252768936052415430071569066192919491762214 + 3.428598090438030380369414618548038962770087500755160535832807433942464545729382imsource

One other symbolic solver is symbolic_linear_solve which is limited compared to symbolic_solve as it only solves linear equations.

Symbolics.symbolic_linear_solveFunction
symbolic_linear_solve(eq, var; simplify, check) -> Any
+ -4.512941594732059759689023145584186058252768936052415430071569066192919491762214 + 3.428598090438030380369414618548038962770087500755160535832807433942464545729382im
source

One other symbolic solver is symbolic_linear_solve which is limited compared to symbolic_solve as it only solves linear equations.

Symbolics.symbolic_linear_solveFunction
symbolic_linear_solve(eq, var; simplify, check) -> Any
 

Solve equation(s) eqs for a set of variables vars.

Assumes length(eqs) == length(vars)

Currently only works if all equations are linear. check if the expr is linear w.r.t vars.

Examples

julia> @variables x y
 2-element Vector{Num}:
  x
@@ -77,7 +77,7 @@
 julia> Symbolics.symbolic_linear_solve([x + y ~ 0, x - y ~ 2], [x, y])
 2-element Vector{Float64}:
   1.0
- -1.0
source

symbolic_solve only supports symbolic, i.e. non-floating point computations, and thus prefers equations where the coefficients are integer, rational, or symbolic. Floating point coefficients are transformed into rational values and BigInt values are used internally with a potential performance loss, and thus it is recommended that this functionality is only used with floating point values if necessary. In contrast, symbolic_linear_solve directly handles floating point values using standard factorizations.

More technical details and examples

Technical details

The symbolic_solve function uses 4 hidden solvers in order to solve the user's input. Its base, solve_univar, uses analytic solutions up to polynomials of degree 4 and factoring as its method for solving univariate polynomials. The function's solve_multipoly uses GCD on the input polynomials then throws passes the result to solve_univar. The function's solve_multivar uses Groebner basis and a separating form in order to create linear equations in the input variables and a single high degree equation in the separating variable [1]. Each equation resulting from the basis is then passed to solve_univar. We can see that essentially, solve_univar is the building block of symbolic_solve. If the input is not a valid polynomial and can not be solved by the algorithm above, symbolic_solve passes it to ia_solve, which attempts solving by attraction and isolation [2]. This only works when the input is a single expression and the user wants the answer in terms of a single variable. Say log(x) - a == 0 gives us [e^a].

Symbolics.solve_univarFunction
solve_univar(expression, x; dropmultiplicity=true)

This solver uses analytic solutions up to degree 4 to solve univariate polynomials. It first handles the special case of the expression being of operation ^. E.g. math (x+2)^{20}. We solve this by removing the int 20, then solving the poly math x+2 on its own. If the parameter mult of the solver is set to true, we then repeat the found roots of math x+2 twenty times before returning the results to the user.

Step 2 is filtering the expression after handling this special case, and then factoring it using factor_use_nemo. We then solve all the factors outputted using the analytic methods implemented in the function get_roots and its children.

Arguments

  • expr: Single symbolics Num or SymbolicUtils.BasicSymbolic expression. This is equated to 0 and then solved. E.g. expr = x+2, we solve x+2 = 0

  • x: Single symbolics variable

  • dropmultiplicity (optional): Print repeated roots or not?

  • strict (optional): Bool that enables/disables strict assert if input expression is a univariate polynomial or not. If strict=true and expression is not a polynomial, solve_univar throws an assertion error.

Examples

source
Missing docstring.

Missing docstring for Symbolics.solve_multivar. Check Documenter's build log for details.

Symbolics.ia_solveFunction
ia_solve(lhs, var; kwargs...)

This function attempts to solve transcendental functions by first checking the "smart" number of occurrences in the input LHS. By smart here we mean that polynomials are counted as 1 occurrence. for example x^2 + 2x is 1 occurrence of x. So we abstract all occurrences of x's as polynomials. Say: log(x+1) + x^2 is seen as log(f(x)) + g(x) so there are 2 occurrences of x. If there is only 1 occurrence of x in an input expression, isolate is called.

Isolate reverses all operations applied on the occurrence of x until we have f(x) = some constant then we can solve this using our polynomial solvers.

If more than 1 occurrence of x is found, ia_solve attempts to attract the occurrences of x in order to reduce these occurrences to 1. For example, log(x+1) + log(x-1) can be converted to log(x^2 - 1) which now could be isolated using Isolate.

attract(lhs, var) currently uses 4 techniques for attraction.

  • Log addition: log(f(x)) + log(g(x)) => log(h(x))
  • Exponential simplification: a*b^(f(x)) + c*d^(g(x)) => f(x) * log(b) - g(x) * log(d) + log(-a/c). And now this is actually 1 occurrence of x since f(x) and g(x) are just multiplied by constants not wrapped in some operation.
  • Trig simplification: this bruteforces multiple trig identities and doesn't detect them before hand.
  • Polynomialization: as a last resort, attract attempts to polynomialize the expression. Say sin(x+2)^2 + sin(x+2) + 10 is converted to X^2 + X + 10, we then solve this using our polynomial solver, and afterwards, isolate sin(x+2) = the roots found by solve for X^2 + X + 10

After attraction, we check the number of occurrences again, and if its 1, we isolate, if not, we throw an error to tell the user that this is currently unsolvable by our covered techniques.

Arguments

  • lhs: a Num/SymbolicUtils.BasicSymbolic
  • var: variable to solve for.

Keyword arguments

  • warns = true: Whether to emit warnings for unsolvable expressions.
  • complex_roots = true: Whether to consider complex roots of x ^ n ~ y, where n is an integer.
  • periodic_roots = true: If true, isolate f(x) ~ y as x ~ finv(y) + n * period where is_periodic(f) == true, finv = left_inverse(f) and period = fundamental_period(f). n is a new anonymous symbolic variable.

Examples

julia> solve(a*x^b + c, x)
+ -1.0
source

symbolic_solve only supports symbolic, i.e. non-floating point computations, and thus prefers equations where the coefficients are integer, rational, or symbolic. Floating point coefficients are transformed into rational values and BigInt values are used internally with a potential performance loss, and thus it is recommended that this functionality is only used with floating point values if necessary. In contrast, symbolic_linear_solve directly handles floating point values using standard factorizations.

More technical details and examples

Technical details

The symbolic_solve function uses 4 hidden solvers in order to solve the user's input. Its base, solve_univar, uses analytic solutions up to polynomials of degree 4 and factoring as its method for solving univariate polynomials. The function's solve_multipoly uses GCD on the input polynomials then throws passes the result to solve_univar. The function's solve_multivar uses Groebner basis and a separating form in order to create linear equations in the input variables and a single high degree equation in the separating variable [1]. Each equation resulting from the basis is then passed to solve_univar. We can see that essentially, solve_univar is the building block of symbolic_solve. If the input is not a valid polynomial and can not be solved by the algorithm above, symbolic_solve passes it to ia_solve, which attempts solving by attraction and isolation [2]. This only works when the input is a single expression and the user wants the answer in terms of a single variable. Say log(x) - a == 0 gives us [e^a].

Symbolics.solve_univarFunction
solve_univar(expression, x; dropmultiplicity=true)

This solver uses analytic solutions up to degree 4 to solve univariate polynomials. It first handles the special case of the expression being of operation ^. E.g. math (x+2)^{20}. We solve this by removing the int 20, then solving the poly math x+2 on its own. If the parameter mult of the solver is set to true, we then repeat the found roots of math x+2 twenty times before returning the results to the user.

Step 2 is filtering the expression after handling this special case, and then factoring it using factor_use_nemo. We then solve all the factors outputted using the analytic methods implemented in the function get_roots and its children.

Arguments

  • expr: Single symbolics Num or SymbolicUtils.BasicSymbolic expression. This is equated to 0 and then solved. E.g. expr = x+2, we solve x+2 = 0

  • x: Single symbolics variable

  • dropmultiplicity (optional): Print repeated roots or not?

  • strict (optional): Bool that enables/disables strict assert if input expression is a univariate polynomial or not. If strict=true and expression is not a polynomial, solve_univar throws an assertion error.

Examples

source
Missing docstring.

Missing docstring for Symbolics.solve_multivar. Check Documenter's build log for details.

Symbolics.ia_solveFunction
ia_solve(lhs, var; kwargs...)

This function attempts to solve transcendental functions by first checking the "smart" number of occurrences in the input LHS. By smart here we mean that polynomials are counted as 1 occurrence. for example x^2 + 2x is 1 occurrence of x. So we abstract all occurrences of x's as polynomials. Say: log(x+1) + x^2 is seen as log(f(x)) + g(x) so there are 2 occurrences of x. If there is only 1 occurrence of x in an input expression, isolate is called.

Isolate reverses all operations applied on the occurrence of x until we have f(x) = some constant then we can solve this using our polynomial solvers.

If more than 1 occurrence of x is found, ia_solve attempts to attract the occurrences of x in order to reduce these occurrences to 1. For example, log(x+1) + log(x-1) can be converted to log(x^2 - 1) which now could be isolated using Isolate.

attract(lhs, var) currently uses 4 techniques for attraction.

  • Log addition: log(f(x)) + log(g(x)) => log(h(x))
  • Exponential simplification: a*b^(f(x)) + c*d^(g(x)) => f(x) * log(b) - g(x) * log(d) + log(-a/c). And now this is actually 1 occurrence of x since f(x) and g(x) are just multiplied by constants not wrapped in some operation.
  • Trig simplification: this bruteforces multiple trig identities and doesn't detect them before hand.
  • Polynomialization: as a last resort, attract attempts to polynomialize the expression. Say sin(x+2)^2 + sin(x+2) + 10 is converted to X^2 + X + 10, we then solve this using our polynomial solver, and afterwards, isolate sin(x+2) = the roots found by solve for X^2 + X + 10

After attraction, we check the number of occurrences again, and if its 1, we isolate, if not, we throw an error to tell the user that this is currently unsolvable by our covered techniques.

Arguments

  • lhs: a Num/SymbolicUtils.BasicSymbolic
  • var: variable to solve for.

Keyword arguments

  • warns = true: Whether to emit warnings for unsolvable expressions.
  • complex_roots = true: Whether to consider complex roots of x ^ n ~ y, where n is an integer.
  • periodic_roots = true: If true, isolate f(x) ~ y as x ~ finv(y) + n * period where is_periodic(f) == true, finv = left_inverse(f) and period = fundamental_period(f). n is a new anonymous symbolic variable.

Examples

julia> solve(a*x^b + c, x)
 ((-c)^(1 / b)) / (a^(1 / b))
julia> solve(2^(x+1) + 5^(x+3), x)
 1-element Vector{SymbolicUtils.BasicSymbolic{Real}}:
  (-log(2) + 3log(5) - log(complex(-1))) / (log(2) - log(5))
julia> solve(log(x+1)+log(x-1), x)
@@ -91,7 +91,7 @@
 [ Info: var"##234" ϵ Ζ: e.g. 0, 1, 2...
 2-element Vector{SymbolicUtils.BasicSymbolic{Real}}:
  -2 + π*2var"##230" + asin((1//2)*(-1 + RootFinding.ssqrt(-39)))
- -2 + π*2var"##234" + asin((1//2)*(-1 - RootFinding.ssqrt(-39)))

All transcendental functions for which left_inverse is defined are supported. To enable ia_solve to handle custom transcendental functions, define an inverse or left inverse. If the function is periodic, is_periodic and fundamental_period must be defined. If the function imposes certain conditions on its input or output (for example, log requires that its input be positive) define ia_conditions!.

See also: left_inverse, inverse, is_periodic, fundamental_period, ia_conditions!.

References

source
Symbolics.ia_conditions!Function
ia_conditions!(f, lhs, rhs::Vector{Any}, conditions::Vector{Tuple})

If f is a left-invertible function, lhs and rhs[i] are univariate functions and f(lhs) ~ rhs[i] for all i in eachindex(rhss), push to conditions all the relevant conditions on lhs or rhs[i]. Each condition is of the form (sym, op) where sym is an expression involving lhs and/or rhs[i] and op is a binary relational operator. The condition op(sym, 0) is then required to be true for the equation f(lhs) ~ rhs[i] to be valid.

For example, if f = log, lhs = x and rhss = [y, z] then the condition x > 0 must be true. Thus, (lhs, >) is pushed to conditions. Similarly, if f = sqrt, rhs[i] >= 0 must be true for all i, and so (y, >=) and (z, >=) will be appended to conditions.

source
Symbolics.is_periodicFunction
is_periodic(f)

Return true if f is a single-input single-output periodic function. Return false by default. If is_periodic(f) == true, then fundamental_period(f) must also be defined.

See also: fundamental_period

source
Symbolics.fundamental_periodFunction
fundamental_period(f)

Return the fundamental period of periodic function f. Must only be called if is_periodic(f) == true.

see also: is_periodic

source

Nice examples

using Symbolics, Nemo;
+ -2 + π*2var"##234" + asin((1//2)*(-1 - RootFinding.ssqrt(-39)))

All transcendental functions for which left_inverse is defined are supported. To enable ia_solve to handle custom transcendental functions, define an inverse or left inverse. If the function is periodic, is_periodic and fundamental_period must be defined. If the function imposes certain conditions on its input or output (for example, log requires that its input be positive) define ia_conditions!.

See also: left_inverse, inverse, is_periodic, fundamental_period, ia_conditions!.

References

source
Symbolics.ia_conditions!Function
ia_conditions!(f, lhs, rhs::Vector{Any}, conditions::Vector{Tuple})

If f is a left-invertible function, lhs and rhs[i] are univariate functions and f(lhs) ~ rhs[i] for all i in eachindex(rhss), push to conditions all the relevant conditions on lhs or rhs[i]. Each condition is of the form (sym, op) where sym is an expression involving lhs and/or rhs[i] and op is a binary relational operator. The condition op(sym, 0) is then required to be true for the equation f(lhs) ~ rhs[i] to be valid.

For example, if f = log, lhs = x and rhss = [y, z] then the condition x > 0 must be true. Thus, (lhs, >) is pushed to conditions. Similarly, if f = sqrt, rhs[i] >= 0 must be true for all i, and so (y, >=) and (z, >=) will be appended to conditions.

source
Symbolics.is_periodicFunction
is_periodic(f)

Return true if f is a single-input single-output periodic function. Return false by default. If is_periodic(f) == true, then fundamental_period(f) must also be defined.

See also: fundamental_period

source
Symbolics.fundamental_periodFunction
fundamental_period(f)

Return the fundamental period of periodic function f. Must only be called if is_periodic(f) == true.

see also: is_periodic

source

Nice examples

using Symbolics, Nemo;
 @variables x;
 Symbolics.symbolic_solve(9^x + 3^x ~ 8, x)
2-element Vector{SymbolicUtils.BasicSymbolic{Real}}:
  slog(-(1//2) + (1//2)*√(33)) / slog(3)
@@ -117,4 +117,4 @@
 Out[2]= a \[Element] Reals && x > -a
 
 In[3]:= Solve[x^(x)  + 3 == 0, x]
-Out[3]= {{x -> (I \[Pi] + Log[3])/ProductLog[I \[Pi] + Log[3]]}}

References

+Out[3]= {{x -> (I \[Pi] + Log[3])/ProductLog[I \[Pi] + Log[3]]}}

References

diff --git a/dev/manual/sparsity_detection/index.html b/dev/manual/sparsity_detection/index.html index 6b8aa5360..193a21edf 100644 --- a/dev/manual/sparsity_detection/index.html +++ b/dev/manual/sparsity_detection/index.html @@ -17,7 +17,7 @@ 3×2 SparseArrays.SparseMatrixCSC{Bool, Int64} with 4 stored entries: 1 ⋅ ⋅ 1 - 1 1source
jacobian_sparsity(
+ 1  1
source
jacobian_sparsity(
     f!::Function,
     output::AbstractArray,
     input::AbstractArray,
@@ -36,7 +36,7 @@
 3×2 SparseArrays.SparseMatrixCSC{Bool, Int64} with 4 stored entries:
  ⋅  1
  1  ⋅
- 1  1
source
Symbolics.hessian_sparsityFunction
hessian_sparsity(
+ 1  1
source
Symbolics.hessian_sparsityFunction
hessian_sparsity(
     expr,
     vars::AbstractVector;
     full
@@ -50,7 +50,7 @@
 julia> Symbolics.hessian_sparsity(expr, vars)
 2×2 SparseArrays.SparseMatrixCSC{Bool, Int64} with 3 stored entries:
  1  1
- 1  ⋅
source
hessian_sparsity(
+ 1  ⋅
source
hessian_sparsity(
     f::Function,
     input::AbstractVector,
     args...;
@@ -66,6 +66,6 @@
 julia> Symbolics.hessian_sparsity(f, input)
 2×2 SparseArrays.SparseMatrixCSC{Bool, Int64} with 3 stored entries:
  ⋅  1
- 1  1
source

Structure Detection

Symbolics.islinearFunction
islinear(ex, u)
-

Check if an expression is linear with respect to a list of variable expressions.

source
Symbolics.isaffineFunction
isaffine(ex, u)
-

Check if an expression is affine with respect to a list of variable expressions.

source

ADTypes.jl interface

Symbolics.SymbolicsSparsityDetectorType
SymbolicsSparsityDetector <: ADTypes.AbstractSparsityDetector

Sparsity detection algorithm based on the Symbolics.jl tracing system.

This type makes Symbolics.jl compatible with the ADTypes.jl sparsity detection framework. The following functions are implemented:

Reference

Sparsity Programming: Automated Sparsity-Aware Optimizations in Differentiable Programming, Gowda et al. (2019)

source
+ 1 1source

Structure Detection

Symbolics.islinearFunction
islinear(ex, u)
+

Check if an expression is linear with respect to a list of variable expressions.

source
Symbolics.isaffineFunction
isaffine(ex, u)
+

Check if an expression is affine with respect to a list of variable expressions.

source

ADTypes.jl interface

Symbolics.SymbolicsSparsityDetectorType
SymbolicsSparsityDetector <: ADTypes.AbstractSparsityDetector

Sparsity detection algorithm based on the Symbolics.jl tracing system.

This type makes Symbolics.jl compatible with the ADTypes.jl sparsity detection framework. The following functions are implemented:

Reference

Sparsity Programming: Automated Sparsity-Aware Optimizations in Differentiable Programming, Gowda et al. (2019)

source
diff --git a/dev/manual/taylor/index.html b/dev/manual/taylor/index.html index 1515f0c45..0c6c3b617 100644 --- a/dev/manual/taylor/index.html +++ b/dev/manual/taylor/index.html @@ -9,7 +9,7 @@ y[0] + (-2 + x)*y[1] + ((-2 + x)^2)*y[2] + ((-2 + x)^3)*y[3] julia> series(z, x, 2, 0:3) -z[0] + (-2 + x)*z[1] + ((-2 + x)^2)*z[2] + ((-2 + x)^3)*z[3]source
Symbolics.taylorFunction
taylor(f, x, [x0=0,] n; rationalize=true)

Calculate the n-th order term(s) in the Taylor series of f around x = x0. If rationalize, float coefficients are approximated as rational numbers (this can produce unexpected results for irrational numbers, for example).

Examples

julia> @variables x
+z[0] + (-2 + x)*z[1] + ((-2 + x)^2)*z[2] + ((-2 + x)^3)*z[3]
source
Symbolics.taylorFunction
taylor(f, x, [x0=0,] n; rationalize=true)

Calculate the n-th order term(s) in the Taylor series of f around x = x0. If rationalize, float coefficients are approximated as rational numbers (this can produce unexpected results for irrational numbers, for example).

Examples

julia> @variables x
 1-element Vector{Num}:
  x
 
@@ -23,7 +23,7 @@
 1 + (1//2)*(-1 + x) - (1//8)*((-1 + x)^2) + (1//16)*((-1 + x)^3)
 
 julia> isequal(taylor(exp(im*x), x, 0:5), taylor(exp(im*x), x, 0:5))
-true
source
Symbolics.taylor_coeffFunction
taylor_coeff(f, x[, n]; rationalize=true)

Calculate the n-th order coefficient(s) in the Taylor series of f around x = 0.

Examples

julia> @variables x y
+true
source
Symbolics.taylor_coeffFunction
taylor_coeff(f, x[, n]; rationalize=true)

Calculate the n-th order coefficient(s) in the Taylor series of f around x = 0.

Examples

julia> @variables x y
 2-element Vector{Num}:
  x
  y
@@ -32,4 +32,4 @@
 3-element Vector{Num}:
  y[0]
  y[2]
- y[4]
source
+ y[4]source diff --git a/dev/manual/types/index.html b/dev/manual/types/index.html index c926f88ce..6eb93a954 100644 --- a/dev/manual/types/index.html +++ b/dev/manual/types/index.html @@ -5,4 +5,4 @@ z X[1:10,1:10] Z[1:10] - s
typeof(x)
Num
typeof(z)
Complex{Num}
typeof(X)
Symbolics.Arr{Num, 2}
typeof(Z)
Symbolics.Arr{Complex{Num}, 1}
typeof(s)
SymbolicUtils.BasicSymbolic{String}
+ s
typeof(x)
Num
typeof(z)
Complex{Num}
typeof(X)
Symbolics.Arr{Num, 2}
typeof(Z)
Symbolics.Arr{Complex{Num}, 1}
typeof(s)
SymbolicUtils.BasicSymbolic{String}
diff --git a/dev/manual/variables/index.html b/dev/manual/variables/index.html index 2de58e487..fcae3cdd5 100644 --- a/dev/manual/variables/index.html +++ b/dev/manual/variables/index.html @@ -28,15 +28,15 @@ (value_c(t))[1:3] julia> (t, a, b, c) -(t, :runtime_symbol_value, :value_b, :value_c)source
Symbolics.variableFunction
variable(name::Symbol, idx::Integer...; T=Real)

Create a variable with the given name along with subscripted indices with the symtype=T. When T=FnType, it creates a symbolic function.

julia> Symbolics.variable(:x, 4, 2, 0)
+(t, :runtime_symbol_value, :value_b, :value_c)
source
Symbolics.variableFunction
variable(name::Symbol, idx::Integer...; T=Real)

Create a variable with the given name along with subscripted indices with the symtype=T. When T=FnType, it creates a symbolic function.

julia> Symbolics.variable(:x, 4, 2, 0)
 x₄ˏ₂ˏ₀
 
 julia> Symbolics.variable(:x, 4, 2, 0, T=Symbolics.FnType)
-x₄ˏ₂ˏ₀⋆

Also see variables.

source
Symbolics.variablesFunction
variables(name::Symbol, indices...)

Create a multi-dimensional array of individual variables named with subscript notation. Use @variables instead to create symbolic array variables (as opposed to array of variables). See variable to create one variable with subscripts.

julia> Symbolics.variables(:x, 1:3, 3:6)
+x₄ˏ₂ˏ₀⋆

Also see variables.

source
Symbolics.variablesFunction
variables(name::Symbol, indices...)

Create a multi-dimensional array of individual variables named with subscript notation. Use @variables instead to create symbolic array variables (as opposed to array of variables). See variable to create one variable with subscripts.

julia> Symbolics.variables(:x, 1:3, 3:6)
 3×4 Matrix{Num}:
  x₁ˏ₃  x₁ˏ₄  x₁ˏ₅  x₁ˏ₆
  x₂ˏ₃  x₂ˏ₄  x₂ˏ₅  x₂ˏ₆
- x₃ˏ₃  x₃ˏ₄  x₃ˏ₅  x₃ˏ₆
source
Symbolics.EquationType
struct Equation

An equality relationship between two expressions.

Fields

  • lhs: The expression on the left-hand side of the equation.

  • rhs: The expression on the right-hand side of the equation.

source
Base.:~Method
~(lhs, rhs) -> Any
+ x₃ˏ₃  x₃ˏ₄  x₃ˏ₅  x₃ˏ₆
source
Symbolics.EquationType
struct Equation

An equality relationship between two expressions.

Fields

  • lhs: The expression on the left-hand side of the equation.

  • rhs: The expression on the right-hand side of the equation.

source
Base.:~Method
~(lhs, rhs) -> Any
 

Create an Equation out of two Num instances, or an Num and a Number.

Examples

julia> using Symbolics
 
 julia> @variables x y;
@@ -53,7 +53,7 @@
 (broadcast(~, A, B))[1:3,1:3]
 
 julia> A .~ 3x
-(broadcast(~, A, 3x))[1:3,1:3]
source

A note about functions restricted to Numbers

Sym and Term objects are NOT subtypes of Number. Symbolics provides a simple wrapper type called Num which is a subtype of Real. Num wraps either a Sym or a Term or any other object, defines the same set of operations as symbolic expressions and forwards those to the values it wraps. You can use Symbolics.value function to unwrap a Num.

By default, the @variables macros return Num-wrapped objects to allow calling functions which are restricted to Number or Real.

using Symbolics
+(broadcast(~, A, 3x))[1:3,1:3]
source

A note about functions restricted to Numbers

Sym and Term objects are NOT subtypes of Number. Symbolics provides a simple wrapper type called Num which is a subtype of Real. Num wraps either a Sym or a Term or any other object, defines the same set of operations as symbolic expressions and forwards those to the values it wraps. You can use Symbolics.value function to unwrap a Num.

By default, the @variables macros return Num-wrapped objects to allow calling functions which are restricted to Number or Real.

using Symbolics
 @variables t x y z(t);
 Symbolics.operation(Symbolics.value(x + y))
+ (generic function with 1053 methods)
Symbolics.operation(Symbolics.value(z))

\[ \begin{equation} z @@ -68,4 +68,4 @@ f(t)

\[ \begin{equation} 1 + t \left( \frac{2}{3} + \frac{4}{5} \pi \right) \end{equation} - \]

This will work for any floating-point input, as well as symbolic input.

Symbolic Control Flow

Control flow can be expressed in Symbolics.jl in the following ways:

Inspection Functions

Missing docstring.

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

Missing docstring.

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

Missing docstring.

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

+ \]

This will work for any floating-point input, as well as symbolic input.

Symbolic Control Flow

Control flow can be expressed in Symbolics.jl in the following ways:

Inspection Functions

Missing docstring.

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

Missing docstring.

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

Missing docstring.

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

diff --git a/dev/tutorials/auto_parallel/d6d2c0c2.svg b/dev/tutorials/auto_parallel/27d4b628.svg similarity index 57% rename from dev/tutorials/auto_parallel/d6d2c0c2.svg rename to dev/tutorials/auto_parallel/27d4b628.svg index 8b03af6b7..477626bdb 100644 --- a/dev/tutorials/auto_parallel/d6d2c0c2.svg +++ b/dev/tutorials/auto_parallel/27d4b628.svg @@ -1,13222 +1,13222 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tutorials/auto_parallel/index.html b/dev/tutorials/auto_parallel/index.html index d1da0b7d7..cf45464ca 100644 --- a/dev/tutorials/auto_parallel/index.html +++ b/dev/tutorials/auto_parallel/index.html @@ -59,7 +59,7 @@ \]

The output, here the in-place modified du, is a symbolic representation of each output of the function. We can then utilize this in the Symbolics functionality. For example, let's build a parallel version of f first:

fastf = eval(Symbolics.build_function(du,u,
             parallel=Symbolics.MultithreadedForm())[2])
#13 (generic function with 1 method)

Now let's compute the sparse Jacobian function and compile a fast multithreaded version:

jac = Symbolics.sparsejacobian(vec(du), vec(u))
 row,col,val = findnz(jac)
-scatter(row,col,legend=false,ms=1,c=:black)
Example block output
fjac = eval(Symbolics.build_function(jac,u,
+scatter(row,col,legend=false,ms=1,c=:black)
Example block output
fjac = eval(Symbolics.build_function(jac,u,
             parallel=Symbolics.MultithreadedForm())[2])
#15 (generic function with 1 method)

It takes awhile for this to generate, but the results will be worth it! Now let's set up the parabolic PDE to be solved by DifferentialEquations.jl. We will set up the vanilla version and the sparse multithreaded version:

using OrdinaryDiffEq
 u0 = zeros(N, N, 3)
 MyA = zeros(N, N);
@@ -139,4 +139,4 @@
  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0     0.0  0.0  0.0  0.0  0.0  0.0  0.0

Let's see the timing difference:

using BenchmarkTools
 #@btime solve(prob, TRBDF2()); # 33.073 s (895404 allocations: 23.87 GiB)
 #warning the following solve takes a long time to compile, but afterwards is very fast.
-#@btime solve(fastprob, TRBDF2()); # 209.670 ms (8208 allocations: 109.25 MiB)

Boom, an automatic 157x acceleration that grows as the size of the problem increases!

+#@btime solve(fastprob, TRBDF2()); # 209.670 ms (8208 allocations: 109.25 MiB)

Boom, an automatic 157x acceleration that grows as the size of the problem increases!

diff --git a/dev/tutorials/converting_to_C/index.html b/dev/tutorials/converting_to_C/index.html index 72a0e4c7e..91a002a6c 100644 --- a/dev/tutorials/converting_to_C/index.html +++ b/dev/tutorials/converting_to_C/index.html @@ -18,11 +18,11 @@ \end{equation} \]

and then we build the function:

build_function(du, u, p, t, target=Symbolics.CTarget())
"#include <math.h>\nvoid diffeqf(double* du, const double* RHS1, const double* RHS2, const double RHS3) {\n  du[0] = RHS2[0] * RHS1[0] + -1 * RHS2[1] * RHS1[0] * RHS1[1];\n  du[1] = -1 * RHS2[2] * RHS1[1] + RHS2[3] * RHS1[0] * RHS1[1];\n}\n"

If we want to compile this, we do expression=Val{false}:

f = build_function(du, u, p, t, target=Symbolics.CTarget(), expression=Val{false})
RuntimeGeneratedFunction(#=in Symbolics=#, #=using Symbolics=#, :((du, u, p, t)->begin
           #= /home/runner/work/Symbolics.jl/Symbolics.jl/src/build_function.jl:809 =#
-          ccall(("diffeqf", "/tmp/jl_zAbWPejeTg"), Cvoid, (Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Float64), du, u, p, t)
+          ccall(("diffeqf", "/tmp/jl_LgLkRW9wJ6"), Cvoid, (Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Float64), du, u, p, t)
       end))

now we check it computes the same thing:

du = rand(2); du2 = rand(2)
 u = rand(2)
 p = rand(4)
 t = rand()
 f(du, u, p, t)
 lotka_volterra!(du2, u, p, t)
-du == du2 # true!
true
+du == du2 # true!
true
diff --git a/dev/tutorials/perturbation/index.html b/dev/tutorials/perturbation/index.html index 8324af85e..69cf51cfe 100644 --- a/dev/tutorials/perturbation/index.html +++ b/dev/tutorials/perturbation/index.html @@ -112,4 +112,4 @@ \]

This looks very different from our first series E_pert. If they are the same, we should get $0$ if we subtract and expand both as multivariate Taylor series in $(e,M)$. Indeed:

taylor(taylor(E_pert′ - E_pert, e, 0:4), M, 0:4)

\[ \begin{equation} 0 \end{equation} - \]

+ \]