JuliaSymbolics / Symbolics.jl

Symbolic programming for the next generation of numerical software
https://docs.sciml.ai/Symbolics/stable/
Other
1.37k stars 154 forks source link

Groebner requirement error even though Groebner is loaded. #1370

Open 1-Bart-1 opened 2 days ago

1-Bart-1 commented 2 days ago

https://discourse.julialang.org/t/getting-the-symbolic-solution-of-system-of-equations-using-modelingtoolkit/122786/3

solve_multivar using Groebner is broken

using Symbolics
using Groebner

@variables Vpack R1 RisoP RisoN R2 R3 
@variables Vadc_off Vadc_on

# RisoN || (R2+R3)
A = 1/(1/RisoN + 1/(R2+R3))
# RisoP || R1
B = 1/(1/RisoP + 1/R1)
# R3 / (R2+R3)
Vadc_ratio = R3/(R2+R3)

Vchassis_off = Vpack * (A / (RisoP + A))
Vchassis_on = Vpack * (A / (A+B))

eq1 = Vadc_off ~ Vchassis_off * Vadc_ratio
eq2 = Vadc_on  ~ Vchassis_on * Vadc_ratio

symbolic_solve([eq1, eq2], (RisoP, RisoN))
[ Info: Assuming (R2*RisoN + R2*RisoP + R3*RisoN + R3*RisoP + RisoN*RisoP) != 0
[ Info: Assuming (R1*R2*RisoN + R1*R2*RisoP + R1*R3*RisoN + R1*R3*RisoP + R1*RisoN*RisoP + R2*RisoN*RisoP + R3*RisoN*RisoP) != 0
ERROR: LoadError: "Groebner bases engine is required. Execute `using Groebner` to enable this functionality."
Stacktrace:
 [1] solve_multivar(eqs::Vector{Num}, vars::Tuple{Num, Num}; dropmultiplicity::Bool, warns::Bool)
   @ Symbolics ~/.julia/packages/Symbolics/GYV9b/src/solver/main.jl:326
 [2] symbolic_solve(expr::Vector{Equation}, x::Tuple{Num, Num}; dropmultiplicity::Bool, warns::Bool)
   @ Symbolics ~/.julia/packages/Symbolics/GYV9b/src/solver/main.jl:204
 [3] symbolic_solve(expr::Vector{Equation}, x::Tuple{Num, Num})
   @ Symbolics ~/.julia/packages/Symbolics/GYV9b/src/solver/main.jl:145
 [4] top-level scope
   @ ~/Code/Tethers.jl/mwes/mwe06.jl:20
 [5] include(fname::String)
   @ Base.MainInclude ./client.jl:494
 [6] top-level scope
   @ REPL[1]:1

[0c5d862f] Symbolics v6.21.0

sumiya11 commented 2 days ago

I guess there is a bug in handling tuples, since the following "works":

julia> symbolic_solve([eq1, eq2], [RisoP, RisoN])

"works" in quotation because it fails later with the familiar monomial ordering error:

julia> symbolic_solve([eq1, eq2], [RisoP, RisoN])
[ Info: Assuming (R2*RisoN + R2*RisoP + R3*RisoN + R3*RisoP + RisoN*RisoP) != 0
[ Info: Assuming (R1*R2*RisoN + R1*R2*RisoP + R1*R3*RisoN + R1*R3*RisoP + R1*RisoN*RisoP + R2*RisoN*RisoP + R3*RisoN*RisoP) != 0
ERROR: DomainError with Invalid monomial ordering.:

Stacktrace:
  [1] map_variables(vars::Vector{Num}, varmap::Dict{DynamicPolynomials.Variable{…}, Int64})
    @ Groebner ~/Groebner.jl/src/monomials/orderings.jl:347
  [2] ordering_transform(ord::Lex{false, Num}, varmap::Dict{DynamicPolynomials.Variable{…}, Int64})
    @ Groebner ~/Groebner.jl/src/monomials/orderings.jl:355
  [3] io_convert_polynomials_to_ir(polynomials::Vector{DynamicPolynomials.Polynomial{…}}, options::Groebner.KeywordArguments)
    @ GroebnerDynamicPolynomialsExt ~/Groebner.jl/ext/GroebnerDynamicPolynomialsExt.jl:32
  [4] groebner0(polynomials::Vector{DynamicPolynomials.Polynomial{…}}, options::Groebner.KeywordArguments)
    @ Groebner ~/Groebner.jl/src/groebner/groebner.jl:9
  [5] #groebner#214
    @ ~/Groebner.jl/src/interface.jl:110 [inlined]
  [6] groebner_basis(polynomials::Vector{Num}; ordering::Lex{false, Num}, kwargs::@Kwargs{})
    @ SymbolicsGroebnerExt ~/.julia/packages/Symbolics/8MbnV/ext/SymbolicsGroebnerExt.jl:45
  [7] solve_zerodim(eqs::Vector{Num}, vars::Vector{Num}; dropmultiplicity::Bool, warns::Bool)
    @ SymbolicsGroebnerExt ~/.julia/packages/Symbolics/8MbnV/ext/SymbolicsGroebnerExt.jl:209
  [8] solve_zerodim
    @ ~/.julia/packages/Symbolics/8MbnV/ext/SymbolicsGroebnerExt.jl:174 [inlined]
  [9] solve_multivar(eqs::Vector{Num}, vars::Vector{Num}; dropmultiplicity::Bool, warns::Bool)
    @ SymbolicsGroebnerExt ~/.julia/packages/Symbolics/8MbnV/ext/SymbolicsGroebnerExt.jl:311
 [10] solve_multivar
    @ ~/.julia/packages/Symbolics/8MbnV/ext/SymbolicsGroebnerExt.jl:310 [inlined]
 [11] symbolic_solve(expr::Vector{Equation}, x::Vector{Num}; dropmultiplicity::Bool, warns::Bool)
    @ Symbolics ~/.julia/packages/Symbolics/8MbnV/src/solver/main.jl:204
 [12] symbolic_solve(expr::Vector{Equation}, x::Vector{Num})
    @ Symbolics ~/.julia/packages/Symbolics/8MbnV/src/solver/main.jl:145
 [13] top-level scope
    @ REPL[15]:1
Some type information was truncated. Use `show(err)` to see complete types.

Seems we really ought to revisit Symbolics.groebner_basis 😅

sumiya11 commented 2 days ago

The issue is that pvar2sym, sym2term may not contain all actually present variables:

https://github.com/JuliaSymbolics/Symbolics.jl/blob/c31c3fda5a4cba3393c35df88181c32f0170439b/ext/SymbolicsGroebnerExt.jl#L37

and I turn to hacky shenanigans to alleviate that (https://github.com/JuliaSymbolics/Symbolics.jl/pull/1324).

EDIT: @n0rbed maybe the solver has some internal function to convert to DP.jl polynomials and maintain a map of vartiables that we can use instead of symbol_to_poly ?

n0rbed commented 2 days ago

Im afraid we'll still need the Symbolic version of the polys. we go back and forth a lot between both types. If you have the time, can you try running solve_zerodim or a portion of it on a DP? if no Symbolic equation is needed then this is good yes

sumiya11 commented 2 days ago

If you have the time, can you try running solve_zerodim or a portion of it on a DP?

Recall that we call symbolic_solve on univariate expressions in solve_zerodim. Whence I think translating to DP.jl in solve_zerodim is challenging.

sumiya11 commented 2 days ago

It seems in the long run the solver would benefit from robust functions

symbolics_to_dp(expr :: Num) -> poly :: DP.Polynomial

dp_to_symbolics(poly :: DP.Polynomial) -> expr :: Num

that

  1. handle special cases gracefully: complex variables, time-dependent variables, float coefficients, etc.
  2. optionally return the variable map: Dict{Num, DP.Polynomial}

We use PolyForm and it currently does not do 2. in a conveniet way (or at least I did not manage to make it always work).