Search code examples
pythonsympyequation

System of equations not being solved after an hour of waiting


I was trying to solve a non-linear system that consists of two equations with 2 unknowns, I tried using Sympy module to complete the task. After trying to run the code below (on Atom and Google Collab notebook), nothing is happening and the process is never terminated (waited for over that 15min). What could be the problem? is my system to complicated? I tried to use fsolve from scipy and i was able to get one of the roots in no time

This is the code below

import sympy as sym

sym.init_printing()
x,y = sym.symbols('x,y')
dmin = 70 #minimum of the actuator
dmax = 140 #maximum of the actuator

l3 = 10
l4 = 10

Amin = 0.523599 #min angle in radians
Amax = 2.0944 #max angle in radians

cos1 = sym.cos(Amin - sym.atan(l4/x) - sym.atan(l3/y))
cos2 = sym.cos(Amax - sym.atan(l4/x) - sym.atan(l3/y))

a2 = x**2 + l4**2
b2 = y**2 + l3**2

f=sym.Eq(a2 + b2 - 2*sym.sqrt(a2)*sym.sqrt(b2)*cos1, dmin**2)
g=sym.Eq(a2 + b2 - 2*sym.sqrt(a2)*sym.sqrt(b2)*cos2, dmax**2)

print(sym.solve([f,g],(x,y)))

Solution

  • Your equations are like:

    In [160]: f
    Out[160]: 
                   __________    __________                                                 
     2    2       ╱  2          ╱  2           ⎛    ⎛10⎞       ⎛10⎞           ⎞             
    x  + y  - 2⋅╲╱  x  + 100 ⋅╲╱  y  + 100 ⋅cos⎜atan⎜──⎟ + atan⎜──⎟ - 0.523599⎟ + 200 = 4900
                                               ⎝    ⎝x ⎠       ⎝y ⎠           ⎠             
    
    In [161]: g
    Out[161]: 
                   __________    __________                                                
     2    2       ╱  2          ╱  2           ⎛    ⎛10⎞       ⎛10⎞         ⎞              
    x  + y  - 2⋅╲╱  x  + 100 ⋅╲╱  y  + 100 ⋅cos⎜atan⎜──⎟ + atan⎜──⎟ - 2.0944⎟ + 200 = 19600
                                               ⎝    ⎝x ⎠       ⎝y ⎠         ⎠  
    

    Usually a mix of algebraic and transcendental functions like this would not have any anlytic solution but in this case the cos can cancel with the atan to make purely algebraic equations:

    In [162]: expand_trig(f)
    Out[162]: 
                   __________    __________                                                                                                                                                     
     2    2       ╱  2          ╱  2        ⎛      0.866025291583566                 5.00000194337561                  5.00000194337561                   86.6025291583566        ⎞             
    x  + y  - 2⋅╲╱  x  + 100 ⋅╲╱  y  + 100 ⋅⎜───────────────────────────── + ─────────────────────────────── + ─────────────────────────────── - ─────────────────────────────────⎟ + 200 = 4900
                                            ⎜     _________      _________          _________      _________          _________      _________            _________      _________⎟             
                                            ⎜    ╱     100      ╱     100          ╱     100      ╱     100          ╱     100      ╱     100            ╱     100      ╱     100 ⎟             
                                            ⎜   ╱  1 + ─── ⋅   ╱  1 + ───    y⋅   ╱  1 + ─── ⋅   ╱  1 + ───    x⋅   ╱  1 + ─── ⋅   ╱  1 + ───    x⋅y⋅   ╱  1 + ─── ⋅   ╱  1 + ─── ⎟             
                                            ⎜  ╱         2    ╱         2        ╱         2    ╱         2        ╱         2    ╱         2          ╱         2    ╱         2 ⎟             
                                            ⎝╲╱         x   ╲╱         y       ╲╱         x   ╲╱         y       ╲╱         x   ╲╱         y         ╲╱         x   ╲╱         y  ⎠             
    
    In [163]: expand_trig(g)
    Out[163]: 
                   __________    __________                                                                                                                                                        
     2    2       ╱  2          ╱  2        ⎛        0.500004241445914                 8.6602295497065                   8.6602295497065                    50.0004241445914        ⎞              
    x  + y  - 2⋅╲╱  x  + 100 ⋅╲╱  y  + 100 ⋅⎜- ───────────────────────────── + ─────────────────────────────── + ─────────────────────────────── + ─────────────────────────────────⎟ + 200 = 19600
                                            ⎜       _________      _________          _________      _________          _________      _________            _________      _________⎟              
                                            ⎜      ╱     100      ╱     100          ╱     100      ╱     100          ╱     100      ╱     100            ╱     100      ╱     100 ⎟              
                                            ⎜     ╱  1 + ─── ⋅   ╱  1 + ───    y⋅   ╱  1 + ─── ⋅   ╱  1 + ───    x⋅   ╱  1 + ─── ⋅   ╱  1 + ───    x⋅y⋅   ╱  1 + ─── ⋅   ╱  1 + ─── ⎟              
                                            ⎜    ╱         2    ╱         2        ╱         2    ╱         2        ╱         2    ╱         2          ╱         2    ╱         2 ⎟              
                                            ⎝  ╲╱         x   ╲╱         y       ╲╱         x   ╲╱         y       ╲╱         x   ╲╱         y         ╲╱         x   ╲╱         y  ⎠              
    
    

    Using this we can massage the system into a pair of polynomials and then solve it with Groebner bases:

    In [181]: from sympy.solvers.solvers import unrad
    
    In [174]: eq1 = trigsimp(unrad(expand_trig(nsimplify(f)).rewrite(Add))[0]/(x*y)).factor().args[-1]
    
    In [175]: eq2 = trigsimp(unrad(expand_trig(nsimplify(g)).rewrite(Add))[0]/(x*y)).factor().args[-1]
    
    In [176]: gb = groebner([nsimplify(eq1.n()), nsimplify(eq2.n())], [x, y])
    
    In [177]: for p in gb: print(p.n(2))
    x - 2.9e-27*y**15 - 4.4e-25*y**14 + 2.8e-22*y**13 + 4.2e-20*y**12 - 1.2e-17*y**11 - 1.6e-15*y**10 + 2.7e-13*y**9 + 3.2e-11*y**8 - 3.6e-9*y**7 - 3.6e-7*y**6 + 2.7e-5*y**5 + 0.0021*y**4 - 0.099*y**3 - 6.2*y**2 + 1.3e+2*y + 6.5e+3
    y**16 + 1.4e+2*y**15 - 1.0e+5*y**14 - 1.3e+7*y**13 + 4.4e+9*y**12 + 4.7e+11*y**11 - 1.1e+14*y**10 - 9.0e+15*y**9 + 1.5e+18*y**8 + 9.3e+19*y**7 - 1.3e+22*y**6 - 5.1e+23*y**5 + 6.3e+25*y**4 + 1.3e+27*y**3 - 1.5e+29*y**2 - 1.2e+30*y + 1.3e+32
    
    In [178]: ry = [r.n() for r in real_roots(gb[-1])]
    
    In [179]: ry
    Out[179]: 
    [-112.210054906433, -94.6849042632114, -53.6834203472101, -49.4635109350851, 48.579017974275, 50.194835
    2176397, 82.5120279645666, 103.812504924146, 118.173390238157, 142.710285016351]
    
    In [180]: for yval in ry:
         ...:     print('y =', yval, ', x =', solve(gb[0].subs(y, yval), x)[0])
         ...: 
    y = -112.210054906433 , x = 48.5790179742034
    y = -94.6849042632114 , x = -53.6834203471953
    y = -53.6834203472101 , x = -94.6849042632093
    y = -49.4635109350851 , x = 103.812504924146
    y = 48.5790179742750 , x = -112.210054906433
    y = 50.1948352176397 , x = 118.173390238151
    y = 82.5120279645666 , x = 142.710285016423
    y = 103.812504924146 , x = -49.4635109348164
    y = 118.173390238157 , x = 50.1948352170293
    y = 142.710285016351 , x = 82.5120279639959
    

    Rewriting as polynomial introduces spurious solutions so only some of those are actually solutions of f and g.

    A simpler and faster way to compute these solutions if you have an initial guess for a particular solution that you want is just to use nsolve to solve the system numerically:

    In [194]: nsolve([f, g], [x, y], [118, 50])
    Out[194]: 
    ⎡118.173390238157⎤
    ⎢                ⎥
    ⎣50.1948352176396⎦