From e06bb02e8e2711a23e271c85b7b5942892bdf786 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 17 Aug 2024 06:15:21 -0400 Subject: [PATCH 1/9] Make SymbolicsPreallocationTools also depend on ForwardDiff Fixes potential circular dep? --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index e0b6f9ead..1be4830e9 100644 --- a/Project.toml +++ b/Project.toml @@ -50,7 +50,7 @@ SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6" SymbolicsForwardDiffExt = "ForwardDiff" SymbolicsGroebnerExt = "Groebner" SymbolicsLuxCoreExt = "LuxCore" -SymbolicsPreallocationToolsExt = "PreallocationTools" +SymbolicsPreallocationToolsExt = ["PreallocationTools", "ForwardDiff"] SymbolicsSymPyExt = "SymPy" [compat] From 33cbdfbd9b4ab6dd6c59c06a9ee5d7b31a3860cc Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 17 Aug 2024 06:15:40 -0400 Subject: [PATCH 2/9] Update SymbolicsPreallocationToolsExt.jl --- ext/SymbolicsPreallocationToolsExt.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/SymbolicsPreallocationToolsExt.jl b/ext/SymbolicsPreallocationToolsExt.jl index 5d2686c8c..f850c461b 100644 --- a/ext/SymbolicsPreallocationToolsExt.jl +++ b/ext/SymbolicsPreallocationToolsExt.jl @@ -2,7 +2,7 @@ module SymbolicsPreallocationToolsExt using PreallocationTools import PreallocationTools: _restructure, get_tmp -using Symbolics, PreallocationTools.ForwardDiff +using Symbolics, ForwardDiff function get_tmp(dc::DiffCache, u::Type{X}) where {T,N, X<: ForwardDiff.Dual{T, Num, N}} if length(dc.du) > length(dc.any_du) From 44146cec74fbd799fd67090132e15aed66ead421 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Sat, 17 Aug 2024 08:30:17 -0400 Subject: [PATCH 3/9] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 1be4830e9..eb59d14cd 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Symbolics" uuid = "0c5d862f-8b57-4792-8d23-62f2024744c7" authors = ["Shashi Gowda "] -version = "6.1.0" +version = "6.2.0" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" From 1d68f3fd8127b7b7885e27970d9acf134c1e039f Mon Sep 17 00:00:00 2001 From: Yassin Elbedwihy <58118886+n0rbed@users.noreply.github.com> Date: Sat, 17 Aug 2024 15:39:19 +0300 Subject: [PATCH 4/9] Update src/Symbolics.jl Co-authored-by: Christopher Rackauckas --- src/Symbolics.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symbolics.jl b/src/Symbolics.jl index 0362455b3..c5b36e1b3 100644 --- a/src/Symbolics.jl +++ b/src/Symbolics.jl @@ -153,7 +153,6 @@ include("plot_recipes.jl") include("semipoly.jl") -export lambertw include("parsing.jl") export parse_expr_to_symbolic From 9cad8100aa094ed5fd99cea53ba218cabc4e0abb Mon Sep 17 00:00:00 2001 From: Sasha Demin Date: Sat, 17 Aug 2024 15:01:07 +0200 Subject: [PATCH 5/9] docs: specify versions --- docs/Project.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index fe2a6cf59..958c0903d 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,19 +1,21 @@ [deps] BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Groebner = "0b43b601-686d-58a3-8a1c-6623616c7cd4" Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" +Nemo = "2edaba10-b0f1-5616-af89-8c11ac63239a" OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" SymbolicUtils = "d1185830-fcd6-423d-90d6-eec64667417b" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" -Groebner = "0b43b601-686d-58a3-8a1c-6623616c7cd4" -Nemo = "2edaba10-b0f1-5616-af89-8c11ac63239a" [compat] BenchmarkTools = "1.3" Documenter = "1" +Groebner = "0.7" Latexify = "0.15, 0.16" +Nemo = "0.46" OrdinaryDiffEq = "6.31" Plots = "1.36" StaticArrays = "1.5" From fcbadcccd500d68d9e45aebbaa7e00ba3c6b09b7 Mon Sep 17 00:00:00 2001 From: Sasha Demin Date: Sat, 17 Aug 2024 15:33:53 +0200 Subject: [PATCH 6/9] add feature list to solver docs --- docs/Project.toml | 2 +- docs/src/manual/solver.md | 27 ++++++++++++++++++++------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index 958c0903d..0719ffd01 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -15,7 +15,7 @@ BenchmarkTools = "1.3" Documenter = "1" Groebner = "0.7" Latexify = "0.15, 0.16" -Nemo = "0.46" +Nemo = "0.45, 0.46" OrdinaryDiffEq = "6.31" Plots = "1.36" StaticArrays = "1.5" diff --git a/docs/src/manual/solver.md b/docs/src/manual/solver.md index 7135cab6d..2f61c9af4 100644 --- a/docs/src/manual/solver.md +++ b/docs/src/manual/solver.md @@ -1,7 +1,8 @@ # Solver -The main `symbolic` solver for Symbolics.jl is `symbolic_solve`. Symbolic solving -means that it only uses analytical methods and manually solves equations for input variables. -It uses no numerical methods and only outputs exact solutions. + +The main symbolic solver for Symbolics.jl is `symbolic_solve`. Symbolic solving +means that it only uses symbolic (algebraic) methods and outputs exact solutions. + ```@docs Symbolics.symbolic_solve ``` @@ -19,17 +20,20 @@ that this functionality is only used with floating point values if necessary. In directly handles floating point values using standard factorizations. ### More technical details and examples + #### Technical details + The `symbolic_solve` function uses 4 hidden solvers in order to solve the user's input. Its base, `solve_univar`, uses analytic solutions up to polynomials of degree 4 and factoring as its method for solving univariate polynomials. The function's `solve_multipoly` uses GCD on the input polynomials then throws passes the result to `solve_univar`. The function's `solve_multivar` uses Groebner basis and a separating form in order to create linear equations in the -input variables and a single high degree equation in the separating variable. Each equation resulting from the basis is then passed -to `solve_univar`. We can see that essentially, `solve_univar` is the building block of `symbolic_solve`.if the input is not a valid polynomial and can not be solved by the algorithm above, `symbolic_solve` passes -it to `ia_solve`, which attempts solving by attraction and isolation [^1]. This only works when the input is a single expression +input variables and a single high degree equation in the separating variable [^1]. Each equation resulting from the basis is then passed +to `solve_univar`. We can see that essentially, `solve_univar` is the building block of `symbolic_solve`. If the input is not a valid polynomial and can not be solved by the algorithm above, `symbolic_solve` passes +it to `ia_solve`, which attempts solving by attraction and isolation [^2]. This only works when the input is a single expression and the user wants the answer in terms of a single variable. Say `log(x) - a == 0` gives us `[e^a]`. #### Nice examples + ```@example solver using Symbolics, Nemo; @variables x; @@ -49,6 +53,15 @@ eqs = [x^2 + y + z - 1, x + y^2 + z - 1, x + y + z^2 - 1] Symbolics.symbolic_solve(eqs, [x,y,z]) ``` +### Feature completeness + +- [x] Linear and polynomial equations +- [x] Systems of linear and polynomial equations +- [x] Some transcendental functions +- [ ] Systems of linear and polynomial equations with parameters +- [ ] Inequalities + # References -[^1]: [R. W. Hamming, Coding and Information Theory, ScienceDirect, 1980](https://www.sciencedirect.com/science/article/pii/S0747717189800070). +[^1] [Rouillier, F. Solving Zero-Dimensional Systems Through the Rational Univariate Representation. AAECC 9, 433–461 (1999).](https://doi.org/10.1007/s002000050114) +[^2]: [R. W. Hamming, Coding and Information Theory, ScienceDirect, 1980](https://www.sciencedirect.com/science/article/pii/S0747717189800070). From 734143cb8ebd4b041227681eee1432735f002076 Mon Sep 17 00:00:00 2001 From: Sasha Demin Date: Sat, 17 Aug 2024 15:35:00 +0200 Subject: [PATCH 7/9] specify Nemo version --- Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Project.toml b/Project.toml index 26598caa9..ad59649ca 100644 --- a/Project.toml +++ b/Project.toml @@ -78,6 +78,7 @@ LogExpFunctions = "0.3" LuxCore = "0.1.11" MacroTools = "0.5" NaNMath = "1" +Nemo = "0.45, 0.46" PreallocationTools = "0.4" PrecompileTools = "1" RecipesBase = "1.1" From 71ad8ecd10252620b0df40a14cd862d1cf99648e Mon Sep 17 00:00:00 2001 From: Sasha Demin Date: Sat, 17 Aug 2024 16:17:21 +0200 Subject: [PATCH 8/9] very small changes --- docs/src/manual/solver.md | 3 ++- src/solver/main.jl | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/src/manual/solver.md b/docs/src/manual/solver.md index 2f61c9af4..c0089366e 100644 --- a/docs/src/manual/solver.md +++ b/docs/src/manual/solver.md @@ -58,7 +58,8 @@ Symbolics.symbolic_solve(eqs, [x,y,z]) - [x] Linear and polynomial equations - [x] Systems of linear and polynomial equations - [x] Some transcendental functions -- [ ] Systems of linear and polynomial equations with parameters +- [x] Systems of linear equations with parameters (via `symbolic_linear_solve`) +- [ ] Systems of polynomial equations with parameters - [ ] Inequalities # References diff --git a/src/solver/main.jl b/src/solver/main.jl index d659987a8..88d9f627f 100644 --- a/src/solver/main.jl +++ b/src/solver/main.jl @@ -30,17 +30,19 @@ Currently, `symbolic_solve` supports ### `solve_univar` (uses factoring and analytic solutions up to degree 4) ```jldoctest +julia> @variables x a b; + julia> expr = expand((x + b)*(x^2 + 2x + 1)*(x^2 - a)) -a*b - a*x - 2a*b*x - 2a*(x^2) + b*(x^2) + x^3 - a*b*(x^2) - a*(x^3) + 2b*(x^3) + 2(x^4) + b*(x^4) + x^5 -julia> Symbolics.symbolic_solve(expr, x) +julia> symbolic_solve(expr, x) 4-element Vector{Any}: -1 -b (1//2)*√(4a) (-1//2)*√(4a) -julia> Symbolics.symbolic_solve(expr, x, dropmultiplicity=false) +julia> symbolic_solve(expr, x, dropmultiplicity=false) 5-element Vector{Any}: -1 -1 @@ -49,7 +51,7 @@ julia> Symbolics.symbolic_solve(expr, x, dropmultiplicity=false) (-1//2)*√(4a) ``` ```jldoctest -julia> Symbolics.symbolic_solve(x^2 + a*x + 6, x) +julia> symbolic_solve(x^2 + a*x + 6, x) 2-element Vector{SymbolicUtils.BasicSymbolic{Real}}: (1//2)*(-a + √(-24 + a^2)) (1//2)*(-a - √(-24 + a^2)) @@ -108,13 +110,11 @@ julia> symbolic_solve(a*x^b + c, x) ((-c)^(1 / b)) / (a^(1 / b)) ``` """ -function symbolic_solve(expr, x; dropmultiplicity=true, warns=true) - type_x = typeof(x) +function symbolic_solve(expr, x::T; dropmultiplicity=true, warns=true) where {T} expr_univar = false x_univar = false - - if (type_x == Num || type_x == SymbolicUtils.BasicSymbolic{Real}) + if (T == Num || T == SymbolicUtils.BasicSymbolic{Real}) x_univar = true @assert is_singleton(unwrap(x)) "Expected a variable, got $x" else From 01d1ef3cce4382c9689fbfe235a8674c12e8c28b Mon Sep 17 00:00:00 2001 From: Sasha Demin Date: Sat, 17 Aug 2024 16:19:10 +0200 Subject: [PATCH 9/9] export symbolic_linear_solve, solve_for --- src/Symbolics.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symbolics.jl b/src/Symbolics.jl index c5b36e1b3..cd191bd9b 100644 --- a/src/Symbolics.jl +++ b/src/Symbolics.jl @@ -133,6 +133,7 @@ using LogExpFunctions include("logexpfunctions-lib.jl") include("linear_algebra.jl") +export symbolic_linear_solve, solve_for include("groebner_basis.jl") export groebner_basis, is_groebner_basis