From a77d34c5fdb7aa99bc9c0a81400d9821e8bbe0e6 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Wed, 31 Jul 2024 20:27:11 +0000 Subject: [PATCH] build based on 77949c9 --- dev/.documenter-siteinfo.json | 2 +- dev/assets/Manifest.toml | 6 +- dev/comparison/index.html | 2 +- dev/examples/perturbation/index.html | 2 +- dev/getting_started/index.html | 12 +- dev/index.html | 8 +- dev/manual/arrays/index.html | 2 +- dev/manual/build_function/index.html | 10 +- dev/manual/derivatives/index.html | 22 +- dev/manual/expression_manipulation/index.html | 16 +- dev/manual/faq/index.html | 2 +- dev/manual/functions/index.html | 6 +- dev/manual/groebner/index.html | 2 +- dev/manual/io/index.html | 2 +- dev/manual/limits/index.html | 2 +- dev/manual/parsing/index.html | 2 +- dev/manual/sparsity_detection/index.html | 12 +- dev/manual/types/index.html | 2 +- dev/manual/variables/index.html | 10 +- dev/objects.inv | Bin 2662 -> 2662 bytes .../{0a04ca86.svg => c919a105.svg} | 26414 ++++++++-------- dev/tutorials/auto_parallel/index.html | 4 +- dev/tutorials/converting_to_C/index.html | 4 +- 23 files changed, 13272 insertions(+), 13272 deletions(-) rename dev/tutorials/auto_parallel/{0a04ca86.svg => c919a105.svg} (58%) diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 56ea88140..a52e6e964 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.4","generation_timestamp":"2024-07-31T16:35:39","documenter_version":"1.5.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.4","generation_timestamp":"2024-07-31T20:27:04","documenter_version":"1.5.0"}} \ No newline at end of file diff --git a/dev/assets/Manifest.toml b/dev/assets/Manifest.toml index 0eb9d2a1c..c2d2cab0c 100644 --- a/dev/assets/Manifest.toml +++ b/dev/assets/Manifest.toml @@ -1517,9 +1517,9 @@ version = "0.6.43" [[deps.SciMLBase]] deps = ["ADTypes", "Accessors", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "Expronicon", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "SciMLStructures", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] -git-tree-sha1 = "b316ed5e5e71a6414b0c0e0c9f334afcc701ebf8" +git-tree-sha1 = "7f0e208db50f5fee2386b6d8dc9608d580059331" uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" -version = "2.48.0" +version = "2.48.1" [deps.SciMLBase.extensions] SciMLBaseChainRulesCoreExt = "ChainRulesCore" @@ -1765,7 +1765,7 @@ version = "2.1.2" deps = ["ADTypes", "ArrayInterface", "Bijections", "CommonWorldInvalidations", "ConstructionBase", "DataStructures", "DiffRules", "Distributions", "DocStringExtensions", "DomainSets", "DynamicPolynomials", "ForwardDiff", "IfElse", "LaTeXStrings", "LambertW", "Latexify", "Libdl", "LinearAlgebra", "LogExpFunctions", "MacroTools", "Markdown", "NaNMath", "PrecompileTools", "RecipesBase", "Reexport", "Requires", "RuntimeGeneratedFunctions", "SciMLBase", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArraysCore", "SymbolicIndexingInterface", "SymbolicLimits", "SymbolicUtils", "TermInterface"] path = "/home/runner/work/Symbolics.jl/Symbolics.jl" uuid = "0c5d862f-8b57-4792-8d23-62f2024744c7" -version = "5.35.0" +version = "5.35.1" [deps.Symbolics.extensions] SymbolicsGroebnerExt = "Groebner" diff --git a/dev/comparison/index.html b/dev/comparison/index.html index dcfdaa79d..f359abffb 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/examples/perturbation/index.html b/dev/examples/perturbation/index.html index db0a4946d..1c16fd363 100644 --- a/dev/examples/perturbation/index.html +++ b/dev/examples/perturbation/index.html @@ -83,4 +83,4 @@ - (𝜀 + 4*𝜀^2 + 10*𝜀^3)*𝑀^3/6 + (𝜀 + 16*𝜀^2 + 91*𝜀^3)*𝑀^5/120

Comparing the formula to the one for 𝐸 in the Wikipedia article on the Kepler's equation:

\[ E = \frac{1}{1-\epsilon}M -\frac{\epsilon}{(1-\epsilon)^4} \frac{M^3}{3!} + \frac{(9\epsilon^2 - + \epsilon)}{(1-\epsilon)^7}\frac{M^5}{5!}\cdots\]

The first deviation is in the coefficient of $\epsilon^3 M^5$.

+ + \epsilon)}{(1-\epsilon)^7}\frac{M^5}{5!}\cdots\]

The first deviation is in the coefficient of $\epsilon^3 M^5$.

diff --git a/dev/getting_started/index.html b/dev/getting_started/index.html index 789c75ba0..f2b19bc88 100644 --- a/dev/getting_started/index.html +++ b/dev/getting_started/index.html @@ -220,9 +220,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 18 stored entries:
-⎡⠀⠀⠀⠐⠀⎤
-⎢⣠⠁⠀⠀⠀⎥
-⎢⠠⠤⠆⠀⠠⎥
-⎢⢀⠀⠀⠀⠀⎥
-⎣⠒⠂⠐⢂⠀⎦
+out
20×10 SparseArrays.SparseMatrixCSC{Float64, Int64} with 19 stored entries:
+⎡⠍⠀⠀⠠⠢⎤
+⎢⠈⠀⢈⠀⠁⎥
+⎢⠀⠂⠋⠀⠐⎥
+⎢⡀⠀⠐⠠⠀⎥
+⎣⠀⠀⠀⠠⠀⎦
diff --git a/dev/index.html b/dev/index.html index 9bbfcfa51..86955298c 100644 --- a/dev/index.html +++ b/dev/index.html @@ -13,7 +13,7 @@ [91a5bcdd] Plots v1.40.5 [90137ffa] StaticArrays v1.9.7 ⌅ [d1185830] SymbolicUtils v2.1.2 - [0c5d862f] Symbolics v5.35.0 `~/work/Symbolics.jl/Symbolics.jl` + [0c5d862f] Symbolics v5.35.1 `~/work/Symbolics.jl/Symbolics.jl` Info Packages marked with ⌅ have new versions available but compatibility constraints restrict them from upgrading. To see why use `status --outdated`
and using this machine and Julia version.
Julia Version 1.10.4
 Commit 48d4fd48430 (2024-06-04 10:41 UTC)
 Build Info:
@@ -170,7 +170,7 @@
   [7e49a35a] RuntimeGeneratedFunctions v0.5.13
   [94e857df] SIMDTypes v0.1.0
   [476501e8] SLEEFPirates v0.6.43
-  [0bca4576] SciMLBase v2.48.0
+  [0bca4576] SciMLBase v2.48.1
   [c0aeaf25] SciMLOperators v0.3.8
   [53ae85a6] SciMLStructures v1.4.1
   [6c6a2e73] Scratch v1.2.1
@@ -196,7 +196,7 @@
   [2efcf032] SymbolicIndexingInterface v0.3.27
 ⌃ [19f23fe9] SymbolicLimits v0.2.1
 ⌅ [d1185830] SymbolicUtils v2.1.2
-  [0c5d862f] Symbolics v5.35.0 `~/work/Symbolics.jl/Symbolics.jl`
+  [0c5d862f] Symbolics v5.35.1 `~/work/Symbolics.jl/Symbolics.jl`
   [3783bdb8] TableTraits v1.0.1
   [bd369af6] Tables v1.12.0
   [62fd8b95] TensorCore v0.1.1
@@ -351,4 +351,4 @@
   [8e850b90] libblastrampoline_jll v5.8.0+1
   [8e850ede] nghttp2_jll v1.52.0+1
   [3f19e933] p7zip_jll v17.4.0+2
-Info Packages marked with ⌃ and ⌅ have new versions available. Those with ⌃ may be upgradable, but those with ⌅ are restricted by compatibility constraints from upgrading. To see why use `status --outdated -m`

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

+Info Packages marked with ⌃ and ⌅ have new versions available. Those with ⌃ may be upgradable, but those with ⌅ are restricted by compatibility constraints 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 4788f8905..633b4112b 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 e7a96377c..2a89c0f9b 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 f348c3f88..79d640267 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 a3d5d58be..7f2fcc1a7 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(O) -> Vector{BasicSymbolic}

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

Examples

julia> @variables t x y z(t)
@@ -25,7 +25,7 @@
 3-element Vector{Any}:
  x
  y
- z(t)
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)
+ z(t)
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)
@@ -34,13 +34,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.solve_forFunction
solve_for(eq, var; simplify, check) -> Any
+var"z(t)[1]ˍt"
source
Symbolics.solve_forFunction
solve_for(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
@@ -52,7 +52,7 @@
 julia> Symbolics.solve_for([x + y ~ 0, x - y ~ 2], [x, y])
 2-element Vector{Float64}:
   1.0
- -1.0
source
Symbolics.degreeFunction
degree(p, sym=nothing)

Extract the degree of p with respect to sym.

Examples

julia> @variables x;
+ -1.0
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
@@ -61,7 +61,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
@@ -70,7 +70,7 @@
 2
 
 julia> Symbolics.coeff(x^2 + y, x^2)
-1
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 fufills 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
+1
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 fufills 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)

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.

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

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.

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
diff --git a/dev/manual/faq/index.html b/dev/manual/faq/index.html index a49a6fba6..fc6f1e727 100644 --- a/dev/manual/faq/index.html +++ b/dev/manual/faq/index.html @@ -16,4 +16,4 @@ x in [x] catch e e -end
TypeError(:if, "", Bool, x == x)
x in Set([x])
true
any(isequal(x), [x])
true

If == is used instead, you will receive TypeError: non-boolean (Num) used in boolean context. What this error is telling you is that the symbolic x == y expression is being used where a Bool is required, such as if x == y, and since the symbolic expression is held lazily this will error because the appropriate branch cannot be selected (since x == y is unknown for arbitrary symbolic values!). This is why the check isequal(x,y) is required, since this is a non-lazy check of whether the symbol x is always equal to the symbol y, rather than an expression of whether x and y currently have the same value.

+end
TypeError(:if, "", Bool, x == x)
x in Set([x])
true
any(isequal(x), [x])
true

If == is used instead, you will receive TypeError: non-boolean (Num) used in boolean context. What this error is telling you is that the symbolic x == y expression is being used where a Bool is required, such as if x == y, and since the symbolic expression is held lazily this will error because the appropriate branch cannot be selected (since x == y is unknown for arbitrary symbolic values!). This is why the check isequal(x,y) is required, since this is a non-lazy check of whether the symbol x is always equal to the symbol y, rather than an expression of whether x and y currently have the same value.

diff --git a/dev/manual/functions/index.html b/dev/manual/functions/index.html index fae20b7b6..dea46c6e7 100644 --- a/dev/manual/functions/index.html +++ b/dev/manual/functions/index.html @@ -41,14 +41,14 @@ \]

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
+end diff --git a/dev/manual/groebner/index.html b/dev/manual/groebner/index.html index f1ef59c30..427450d16 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 921861267..bd4228d4d 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 672ebbf53..86d249536 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 e51eee990..de3f7462f 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/sparsity_detection/index.html b/dev/manual/sparsity_detection/index.html index e2661be63..019c0df52 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/types/index.html b/dev/manual/types/index.html index 9e70d15a1..5c53a5d0f 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 6acb50e67..1084d3d29 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 482 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} \mathrm{identity}\left( \pi \right) \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/objects.inv b/dev/objects.inv index 9b6334c84704a5c85c8f418a61d7dc05862d38de..ff5dba8165d1501a105d4534ef8647627ed6fff5 100644 GIT binary patch delta 12 TcmaDR@=RocE2H5?Hw7*LAf5yr delta 12 TcmaDR@=RocE2F_iHw7*LAejUl diff --git a/dev/tutorials/auto_parallel/0a04ca86.svg b/dev/tutorials/auto_parallel/c919a105.svg similarity index 58% rename from dev/tutorials/auto_parallel/0a04ca86.svg rename to dev/tutorials/auto_parallel/c919a105.svg index 0dc2af062..decac90ea 100644 --- a/dev/tutorials/auto_parallel/0a04ca86.svg +++ b/dev/tutorials/auto_parallel/c919a105.svg @@ -1,13222 +1,13222 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/tutorials/auto_parallel/index.html b/dev/tutorials/auto_parallel/index.html index 02c3d3bf1..91c8eecac 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 507609a48..f6ac61b8f 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_EX6pQju3Ur"), Cvoid, (Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Float64), du, u, p, t)
+          ccall(("diffeqf", "/tmp/jl_c7UJSxknAd"), 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