1

I'm trying to solve a system with three nonlinear equations in Python 3.8. I'm using the function sympy.nonlinsolve(). However, I received the error message "convergence to root failed; try n < 15 or maxsteps > 50".

This is my code:

import sympy as sp

x_1 = 0.0
z_1 = 1.0
x_2 = 15.81
z_2 = 0.99
x_3 = 23.8
z_3 = 0.98

r, x_m, z_m = sp.symbols('r, x_m, z_m', real=True)
Eq_1 = sp.Eq((x_1 - x_m) ** 2 + (z_1 - z_m) ** 2 - r ** 2, 0)
Eq_2 = sp.Eq((x_2 - x_m) ** 2 + (z_2 - z_m) ** 2 - r ** 2, 0)
Eq_3 = sp.Eq((x_3 - x_m) ** 2 + (z_3 - z_m) ** 2 - r ** 2, 0)
ans = sp.nonlinsolve([Eq_1, Eq_2, Eq_3], [r, x_m, z_m])

I would welcome every help. Thanks in advance.

  • Does this answer your question? [Python Sympy module NoConvergence: convergence to root failed; try n < 15 or maxsteps > 50](https://stackoverflow.com/questions/52319939/python-sympy-module-noconvergence-convergence-to-root-failed-try-n-15-or-max) – Josh Friedlander Oct 20 '21 at 14:01
  • Hey @JoshFriedlander, thanks for your answer. Your advice is good to solve one equation. But I need to solve a system of three equations. – Digital_Citizen Oct 20 '21 at 14:18

2 Answers2

0

I get an answer from solve:

In [56]: sp.solve([Eq_1, Eq_2, Eq_3], [r, x_m, z_m])
Out[56]: 
[(-5.71609538434502e+18, -4.80343980343979e+15, -5.71609336609336e+18), (-19222.9235141152, -4.2537
0843989772, -19221.9230434783), (19222.9235141152, -4.25370843989772, -19221.9230434783), (5.716095
38434502e+18, -4.80343980343979e+15, -5.71609336609336e+18)]

I'm not sure why nonlinsolve works but from the large numbers in the answer I guess that this isn't well conditioned.

If you use exact rational numbers then you can get the same solution from both solve and nonlinsolve:

In [59]: import sympy as sp
    ...: 
    ...: x_1 = 0
    ...: z_1 = 1
    ...: x_2 = sp.Rational('15.81')
    ...: z_2 = sp.Rational('0.99')
    ...: x_3 = sp.Rational('23.8')
    ...: z_3 = sp.Rational('0.98')
    ...: 
    ...: r, x_m, z_m = sp.symbols('r, x_m, z_m', real=True)
    ...: Eq_1 = sp.Eq((x_1 - x_m) ** 2 + (z_1 - z_m) ** 2 - r ** 2, 0)
    ...: Eq_2 = sp.Eq((x_2 - x_m) ** 2 + (z_2 - z_m) ** 2 - r ** 2, 0)
    ...: Eq_3 = sp.Eq((x_3 - x_m) ** 2 + (z_3 - z_m) ** 2 - r ** 2, 0)
    ...: ans = sp.solve([Eq_1, Eq_2, Eq_3], [r, x_m, z_m])

In [60]: ans
Out[60]: 
⎡⎛-√564927076558939081   -8316   -44210423 ⎞  ⎛√564927076558939081  -8316   -44210423 ⎞⎤
⎢⎜─────────────────────, ──────, ──────────⎟, ⎜───────────────────, ──────, ──────────⎟⎥
⎣⎝        39100           1955      2300   ⎠  ⎝       39100          1955      2300   ⎠⎦
Oscar Benjamin
  • 12,649
  • 1
  • 12
  • 14
0

This is another of those cases where it is good to emphasize the A of CAS and let it help you as you work through the problem by hand:

_ solve first equation for r**2

>>> from sympy import solve
>>> r2 = solve(Eq_1, r**2)

_ substitute into the other two equations and expand them

>>> eqs = [i.subs(r**2, r2[0]).expand() for i in (Eq_2, Eq_3)]

_ see what you've get

>>> eqs
[Eq(-31.62*x_m + 0.02*z_m + 249.9362, 0), Eq(-47.6*x_m + 0.04*z_m + 566.4004, 0)]

_ That's two linear equations. Solve with solve -- nonlinsolve is not needed

>>> xz = solve(eqs); xz
{x_m: -4.25370843989770, z_m: -19221.9230434783}

_ substitute into r2 and set equal to r**2 and solve for r

>>> ris = solve(Eq(r**2, r2[0].subs(xz))); ris
[-19222.9235141152, 19222.9235141152]

_ collect the solutions

soln = []
>>> for i in ris:
...     xz[r] = i
...     soln.append(xz)
... 
>>> soln
[{x_m: -4.25370843989770, z_m: -19221.9230434783, r: -19222.9235141152}, 
 {x_m: -4.25370843989770, z_m: -19221.9230434783, r: 19222.9235141152}]

[print out has been edited for viewing pleasure]

When solving nonlinear systems, try reduce the number of systems that you have to deal with. Eliminate linear variables for sure -- other (r**2 in this case) if possible -- before trying to solve the nonlinear parts.

The very large numbers obtained when solving all 3 at once might be a reflection of the ill-posed nature of the system ("not well conditioned" as Oscar noted. Perhaps the problem was designed to teach that point.

smichr
  • 16,948
  • 2
  • 27
  • 34