Search code examples
pythonsympycomplex-numberspolynomial-mathequation-solving

How To Find Complex Roots of A Multivariate Polynomial Equation System (Python)


Consider following equation system:

1623.66790917 * x ** 2 + 468.829686367 * x * y + 252.762128419 * y ** 2 + -1027209.42116 * x + -301192.975791 * y + 188804356.212 = 0

11154.1759415 * x ** 2 + 31741.0229155 * x * y + 32933.5622632 * y ** 2 + -16226174.4037 * x + -26323622.7497 * y + 6038609721.67 = 0

As you see there are two pairs of complex solutions to the system. I tried sympy but it was not a success. I want to know how to figure it out in Python. BTW I don't have a nice initial guess to use numeric methods.


Solution

  • You can solve those equations numerically using mpmath's findroot(). As far as I know there isn't a way to tell findroot() to find multiple roots, but we can get around that restriction: first, find a solution pair (xa, ya), then divide the equations by (x - xa)*(y - ya). You do have to supply an initial approximate solution, but I managed to find something that worked in only a few tries.

    from mpmath import mp
    
    mp.dps = 30
    prec = 20
    
    f_1 = lambda x, y: 1623.66790917 * x ** 2 + 468.829686367 * x * y + 252.762128419 * y ** 2 + -1027209.42116 * x + -301192.975791 * y + 188804356.212
    
    f_2 = lambda x, y: 11154.1759415 * x ** 2 + 31741.0229155 * x * y + 32933.5622632 * y ** 2 + -16226174.4037 * x + -26323622.7497 * y + 6038609721.67
    
    def solve(f1, f2, initxy):
        return mp.findroot([f1, f2], initxy, solver='muller')
    
    def show(x, y):
        print 'x=', mp.nstr(x, prec)
        print 'y=', mp.nstr(y, prec)
        print mp.nstr(f_1(x, y), prec)
        print mp.nstr(f_2(x, y), prec)
        print
    
    f1a = f_1
    f2a = f_2
    xa, ya = solve(f1a, f2a, (240+40j, 265-85j))
    show(xa, ya)
    
    f1b  = lambda x, y: f1a(x, y) / ((x - xa) * (y - ya))
    f2b  = lambda x, y: f2a(x, y) / ((x - xa) * (y - ya))
    xb, yb = solve(f1b, f2b, (290+20j, 270+30j))
    show(xb, yb)
    

    output

    x= (246.82064795986653023 + 42.076841530787279711j)
    y= (261.83565021239842638 - 81.555049135736951496j)
    (0.0 + 3.3087224502121106995e-24j)
    (0.0 + 0.0j)
    
    x= (289.31873055121622967 + 20.548128321524345062j)
    y= (272.23440694481666637 + 29.381152413744722108j)
    (0.0 + 3.3087224502121106995e-24j)
    (0.0 + 0.0j)