solve
Inspired by this ask.sagemath.org
question.
This question was about the names of the symbolic variables created by Maxima’s solve
to denote arbitrary constants. Exploring the example used in this questions revealed a non-trivial problem with sympy’s solve
.
Solve the system :
$$
\begin{align*}
# Set up sympy (brutal version)
import sympy
from sympy import *
init_session()
init_printing(pretty_print=False)
# System to solve
a1, a2, b1, b2 = symbols('a1 a2 b1 b2')
Unk = [a1, a2, b1, b2]
eq1 = a1 * a2**2 - a2 * a1**3
eq2 = 2*a1*a2*b2 + b2*a2**2 - 3*a2*a1**2*b1 - a1*b2
eq3 = a2**3 - a2**2*a1**2
eq4 = 3*a2**2*b2 - 2*a2*a1**2*b2 - 2*a2**2*b1
Sys = [eq1, eq2, eq3, eq4]
IPython console for SymPy 1.9 (Python 3.9.9-64-bit) (ground types: gmpy)
These commands were executed:
>>> from __future__ import division
>>> from sympy import *
>>> x, y, z, t = symbols('x y z t')
>>> k, m, n = symbols('k m n', integer=True)
>>> f, g, h = symbols('f g h', cls=Function)
>>> init_printing()
Documentation can be found at https://docs.sympy.org/1.9/
Sol = solve(Sys, Unk)
DSol = [dict(zip(Unk, u)) for u in Sol]
DSol
[{a1: 0, a2: 0, b1: b1, b2: b2}, {a1: 0, a2: 0, b1: b1, b2: b2}, {a1: 0, a2: 0, b1: b1, b2: b2}, {a1: 0, a2: 0, b1: b2/2, b2: b2}, {a1: a1, a2: 0, b1: b1, b2: 0}, {a1: -sqrt(a2), a2: a2, b1: 0, b2: 0}, {a1: -2**(5/6)*sqrt(48*2**(1/3) + 624/(1499 + 3*sqrt(303)*I)**(1/3) + 3*2**(2/3)*(1499 + 3*sqrt(303)*I)**(1/3))/6, a2: 16/3 + 104*2**(2/3)/(3*(1499 + 3*sqrt(303)*I)**(1/3)) + 2**(1/3)*(1499 + 3*sqrt(303)*I)**(1/3)/3, b1: b2/2, b2: b2}, {a1: -sqrt(6)*sqrt(32 - 2**(1/3)*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3) - 416*2**(2/3)/((1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)))/6, a2: 2**(2/3)*(-208/3 + (1 + sqrt(3)*I)*(32 + (-1 - sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)/((1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)), b1: b2/2, b2: b2}, {a1: -sqrt(6)*sqrt(32 - 416*2**(2/3)/((1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) - 2**(1/3)*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3))/6, a2: 2**(2/3)*(-208/3 + (1 - sqrt(3)*I)*(32 + (-1 + sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)/((1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)), b1: b2/2, b2: b2}]
Something went sideways: the six first solutions are okay,but the last three use expressions, some of them being polynomials in b2
.
Attempt to check them formally :
Chk=[[u.subs(s) for u in Sys] for s in DSol]
Chk
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [-2**(5/6)*(16/3 + 104*2**(2/3)/(3*(1499 + 3*sqrt(303)*I)**(1/3)) + 2**(1/3)*(1499 + 3*sqrt(303)*I)**(1/3)/3)**2*sqrt(48*2**(1/3) + 624/(1499 + 3*sqrt(303)*I)**(1/3) + 3*2**(2/3)*(1499 + 3*sqrt(303)*I)**(1/3))/6 + sqrt(2)*(16/3 + 104*2**(2/3)/(3*(1499 + 3*sqrt(303)*I)**(1/3)) + 2**(1/3)*(1499 + 3*sqrt(303)*I)**(1/3)/3)*(48*2**(1/3) + 624/(1499 + 3*sqrt(303)*I)**(1/3) + 3*2**(2/3)*(1499 + 3*sqrt(303)*I)**(1/3))**(3/2)/54, -2**(2/3)*b2*(16/3 + 104*2**(2/3)/(3*(1499 + 3*sqrt(303)*I)**(1/3)) + 2**(1/3)*(1499 + 3*sqrt(303)*I)**(1/3)/3)*(48*2**(1/3) + 624/(1499 + 3*sqrt(303)*I)**(1/3) + 3*2**(2/3)*(1499 + 3*sqrt(303)*I)**(1/3))/12 - 2**(5/6)*b2*(16/3 + 104*2**(2/3)/(3*(1499 + 3*sqrt(303)*I)**(1/3)) + 2**(1/3)*(1499 + 3*sqrt(303)*I)**(1/3)/3)*sqrt(48*2**(1/3) + 624/(1499 + 3*sqrt(303)*I)**(1/3) + 3*2**(2/3)*(1499 + 3*sqrt(303)*I)**(1/3))/3 + b2*(16/3 + 104*2**(2/3)/(3*(1499 + 3*sqrt(303)*I)**(1/3)) + 2**(1/3)*(1499 + 3*sqrt(303)*I)**(1/3)/3)**2 + 2**(5/6)*b2*sqrt(48*2**(1/3) + 624/(1499 + 3*sqrt(303)*I)**(1/3) + 3*2**(2/3)*(1499 + 3*sqrt(303)*I)**(1/3))/6, -2**(2/3)*(16/3 + 104*2**(2/3)/(3*(1499 + 3*sqrt(303)*I)**(1/3)) + 2**(1/3)*(1499 + 3*sqrt(303)*I)**(1/3)/3)**2*(48*2**(1/3) + 624/(1499 + 3*sqrt(303)*I)**(1/3) + 3*2**(2/3)*(1499 + 3*sqrt(303)*I)**(1/3))/18 + (16/3 + 104*2**(2/3)/(3*(1499 + 3*sqrt(303)*I)**(1/3)) + 2**(1/3)*(1499 + 3*sqrt(303)*I)**(1/3)/3)**3, -2**(2/3)*b2*(16/3 + 104*2**(2/3)/(3*(1499 + 3*sqrt(303)*I)**(1/3)) + 2**(1/3)*(1499 + 3*sqrt(303)*I)**(1/3)/3)*(48*2**(1/3) + 624/(1499 + 3*sqrt(303)*I)**(1/3) + 3*2**(2/3)*(1499 + 3*sqrt(303)*I)**(1/3))/9 + 2*b2*(16/3 + 104*2**(2/3)/(3*(1499 + 3*sqrt(303)*I)**(1/3)) + 2**(1/3)*(1499 + 3*sqrt(303)*I)**(1/3)/3)**2], [2**(1/6)*sqrt(3)*(-208/3 + (1 + sqrt(3)*I)*(32 + (-1 - sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)*(32 - 2**(1/3)*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3) - 416*2**(2/3)/((1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)))**(3/2)/(18*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) - 2**(5/6)*sqrt(3)*(-208/3 + (1 + sqrt(3)*I)*(32 + (-1 - sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)**2*sqrt(32 - 2**(1/3)*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3) - 416*2**(2/3)/((1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)))/(3*(1 + sqrt(3)*I)**2*(1499 + 3*sqrt(303)*I)**(2/3)), -2*2**(1/6)*sqrt(3)*b2*(-208/3 + (1 + sqrt(3)*I)*(32 + (-1 - sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)*sqrt(32 - 2**(1/3)*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3) - 416*2**(2/3)/((1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)))/(3*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) - 3*2**(2/3)*b2*(-208/3 + (1 + sqrt(3)*I)*(32 + (-1 - sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)*(16/3 - 2**(1/3)*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)/6 - 208*2**(2/3)/(3*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)))/(2*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) + sqrt(6)*b2*sqrt(32 - 2**(1/3)*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3) - 416*2**(2/3)/((1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)))/6 + 2*2**(1/3)*b2*(-208/3 + (1 + sqrt(3)*I)*(32 + (-1 - sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)**2/((1 + sqrt(3)*I)**2*(1499 + 3*sqrt(303)*I)**(2/3)), -2*2**(1/3)*(-208/3 + (1 + sqrt(3)*I)*(32 + (-1 - sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)**2*(16/3 - 2**(1/3)*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)/6 - 208*2**(2/3)/(3*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)))/((1 + sqrt(3)*I)**2*(1499 + 3*sqrt(303)*I)**(2/3)) + 4*(-208/3 + (1 + sqrt(3)*I)*(32 + (-1 - sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)**3/((1 + sqrt(3)*I)**3*(1499 + 3*sqrt(303)*I)), -2*2**(2/3)*b2*(-208/3 + (1 + sqrt(3)*I)*(32 + (-1 - sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)*(16/3 - 2**(1/3)*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)/6 - 208*2**(2/3)/(3*(1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)))/((1 + sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) + 4*2**(1/3)*b2*(-208/3 + (1 + sqrt(3)*I)*(32 + (-1 - sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)**2/((1 + sqrt(3)*I)**2*(1499 + 3*sqrt(303)*I)**(2/3))], [-2**(5/6)*sqrt(3)*(-208/3 + (1 - sqrt(3)*I)*(32 + (-1 + sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)**2*sqrt(32 - 416*2**(2/3)/((1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) - 2**(1/3)*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3))/(3*(1 - sqrt(3)*I)**2*(1499 + 3*sqrt(303)*I)**(2/3)) + 2**(1/6)*sqrt(3)*(-208/3 + (1 - sqrt(3)*I)*(32 + (-1 + sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)*(32 - 416*2**(2/3)/((1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) - 2**(1/3)*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3))**(3/2)/(18*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)), sqrt(6)*b2*sqrt(32 - 416*2**(2/3)/((1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) - 2**(1/3)*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3))/6 + 2*2**(1/3)*b2*(-208/3 + (1 - sqrt(3)*I)*(32 + (-1 + sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)**2/((1 - sqrt(3)*I)**2*(1499 + 3*sqrt(303)*I)**(2/3)) - 3*2**(2/3)*b2*(-208/3 + (1 - sqrt(3)*I)*(32 + (-1 + sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)*(16/3 - 208*2**(2/3)/(3*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) - 2**(1/3)*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)/6)/(2*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) - 2*2**(1/6)*sqrt(3)*b2*(-208/3 + (1 - sqrt(3)*I)*(32 + (-1 + sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)*sqrt(32 - 416*2**(2/3)/((1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) - 2**(1/3)*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3))/(3*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)), 4*(-208/3 + (1 - sqrt(3)*I)*(32 + (-1 + sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)**3/((1 - sqrt(3)*I)**3*(1499 + 3*sqrt(303)*I)) - 2*2**(1/3)*(-208/3 + (1 - sqrt(3)*I)*(32 + (-1 + sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)**2*(16/3 - 208*2**(2/3)/(3*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) - 2**(1/3)*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)/6)/((1 - sqrt(3)*I)**2*(1499 + 3*sqrt(303)*I)**(2/3)), -2*2**(2/3)*b2*(-208/3 + (1 - sqrt(3)*I)*(32 + (-1 + sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)*(16/3 - 208*2**(2/3)/(3*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) - 2**(1/3)*(1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)/6)/((1 - sqrt(3)*I)*(1499 + 3*sqrt(303)*I)**(1/3)) + 4*2**(1/3)*b2*(-208/3 + (1 - sqrt(3)*I)*(32 + (-1 + sqrt(3)*I)*(2998 + 6*sqrt(303)*I)**(1/3))*(2998 + 6*sqrt(303)*I)**(1/3)/12)**2/((1 - sqrt(3)*I)**2*(1499 + 3*sqrt(303)*I)**(2/3))]]
Some of these expressions are polynomial in b2
whose coefficients of not-null dregree are nort obviously null.
A bit of hit-and-miss trials leads to this attempt at numerical check :
def chz(x):
r = x.factor().is_zero
if r is None: return x.coeff(b2).n()
return r
[[chz(u) for u in v] for v in Chk]
[[True, True, True, True],
[True, True, True, True],
[True, True, True, True],
[True, True, True, True],
[True, True, True, True],
[True, True, True, True],
[True, -223.427427555427 + 0.e-25*I, True, True],
[True, -0.388012232966408 - 5.25038392589403e-29*I, True, True],
[True, -0.e-137 + 1.12445821450677e-139*I, True, True]]
Solution #8 may be exactr, but #6 and #7 cannot.
eq1
and eq3
give us solutions for a1
and a2
:
S13=solve([eq3, eq1], [a2, a1], dict=True) ; S13
[{a1: -sqrt(a2)}, {a1: sqrt(a2)}, {a2: 0}]
which we prefer to rewrite as :
S13 = [{a2:a1**2}, {a2:0}]; S13
[{a2: a1**2}, {a2: 0}]
Substituting these values in eq4
gives us :
E4 = [eq4.subs(s) for s in S13] ; E4
[-2*a1**4*b1 + a1**4*b2, 0]
The second solution tells us that S13[1]
is also,a solution to [eq1, eq3, eq4]
.
S134=S13[1:] ; S134
[{a2: 0}]
Substituting S13[0] in
eq4and solving for the variables of the resulting polynomial augments the set
S134of solutions of
[eq1, eq3`, eq4]’ :
V4=E4[0].free_symbols
S4=[solve(E4[0], v, dict=True) for v in V4] ; S4
for S in S4:
for s in S:
S0={u:S13[0][u].subs(s) for u in S13[0].keys()}
S134 += [S0.copy()|s]
S134
[{a2: 0}, {a2: a1**2, b1: b2/2}, {a1: 0, a2: 0}, {a2: a1**2, b2: 2*b1}]
Again, we prefer to rewrite it in a simpler (and shorter) fashion :
S134=[{a2:0}, {a2:a1**2, b2:2*b1}] ; S134
[{a2: 0}, {a2: a1**2, b2: 2*b1}]
Substituting in eq3
gives :
[eq2.subs(s) for s in S134]
[-a1*b2, -a1**4*b1 + 4*a1**3*b1 - 2*a1*b1]
Solving these equations for their free symbols a,d merging with the previous partial solutions gives us the solutions of the full system :
S1234=[]
for S in S134:
# print("S=",S)
E=eq2.subs(S)
# print("E=",E)
S1=[solve(E, v, dict=True) for v in E.free_symbols]
# print("S1=",S1)
for s in flatten(S1):
# print("s=",s)
S0={u:S[u].subs(s) if "subs" in dir(S[u]) else S[u] for u in S.keys()}
S1234+=[S0.copy()|s]
S1234
[{a1: 0, a2: 0}, {a2: 0, b2: 0}, {a2: a1**2, b1: 0, b2: 0}, {a1: 0, a2: 0, b2: 2*b1}, {a1: 4/3 + (-1/2 - sqrt(3)*I/2)*(37/27 + sqrt(303)*I/9)**(1/3) + 16/(9*(-1/2 - sqrt(3)*I/2)*(37/27 + sqrt(303)*I/9)**(1/3)), a2: (4/3 + (-1/2 - sqrt(3)*I/2)*(37/27 + sqrt(303)*I/9)**(1/3) + 16/(9*(-1/2 - sqrt(3)*I/2)*(37/27 + sqrt(303)*I/9)**(1/3)))**2, b2: 2*b1}, {a1: 4/3 + 16/(9*(-1/2 + sqrt(3)*I/2)*(37/27 + sqrt(303)*I/9)**(1/3)) + (-1/2 + sqrt(3)*I/2)*(37/27 + sqrt(303)*I/9)**(1/3), a2: (4/3 + 16/(9*(-1/2 + sqrt(3)*I/2)*(37/27 + sqrt(303)*I/9)**(1/3)) + (-1/2 + sqrt(3)*I/2)*(37/27 + sqrt(303)*I/9)**(1/3))**2, b2: 2*b1}, {a1: 4/3 + 16/(9*(37/27 + sqrt(303)*I/9)**(1/3)) + (37/27 + sqrt(303)*I/9)**(1/3), a2: (4/3 + 16/(9*(37/27 + sqrt(303)*I/9)**(1/3)) + (37/27 + sqrt(303)*I/9)**(1/3))**2, b2: 2*b1}]
Again, some solutions, substituted in eq2
, give first-degree monomials in b1
whose oefficient cannot be shownt to be null byis_zero
:
[[e.subs(s).is_zero for e in Sys] for s in S1234]
[[True, True, True, True],
[True, True, True, True],
[True, True, True, True],
[True, True, True, True],
[True, None, True, True],
[True, None, True, True],
[True, None, True, True]]
But, this time, the numerical check points to a probably null result :
[Sys[1].subs(S1234[u]).coeff(b1).n() for u in range(3,6)]
[0, 0.e-125 + 0.e-127*I, 0.e-125 - 0.e-127*I]
It’s a bit more involved than that; see the parallel discussion of the same problem in this post on Sagemath support list.