pythonscipysympyscipy-optimize

solve Sympy functions in Scipy (optimize.root)


I'm trying to find the roots with the root function in Scipy for functions/variables created in Sympy.

sympy:

AllEquations = [x1 - 5, y1 - 5, z1 - 5, ((x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2)**0.5 - 150, y2 - 100, z2, ((x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2)**0.5 - 150]

AllVariables = [x1, y1, z1, x2, y2, z2]

Below works in Scipy, but is done manually:

def equation(p):
    x1, y1, z1, x2, y2, z2 = p
    return x1 - 5, y1 - 5, z1 - 5, ((x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2)**0.5 - 150, y2 - 100, z2, ((x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2)**0.5 - 150

initial_guess = [5,5,5,100,100,0]

from scipy.optimize import root
sol = root(equation, initial_guess, method = 'lm")

>>>sol.x
array([ 5.00000000e+00,  5.00000000e+00,  5.00000000e+00,  1.20974135e+02,
1.00000000e+02, -2.00332805e-25])

Question is now, how can I automate this? The equation function above is static and should be made dynamically as the number of parameters and functions will change continuously.


Solution

  • This can be done using sympy's lambdify function to turn the equation into a Python function that can be evaluated numerically.

    import sympy as smp
    from scipy.optimize import root
    
    x1, x2, y1, y2, z1, z2 = smp.symbols("x1 x2 y1 y2 z1 z2")
    variables = [x1, x2, y1, y2, z1, z2]
    
    equations = [x1 - 5,
                 y1 - 5,
                 z1 - 5,
                 ((x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2)**0.5 - 150,
                 y2 - 100,
                 z2,    
        ]
    
    # this list will contain all the functions you want to find the roots of
    equations_lamb = [smp.lambdify(variables, eq) for eq in equations]
    
    def combined_function(x, function_list):
        # evaluates the provided list of functions
        res = []
        for function in function_list:
            res.append(function(*x))
        return res
    
    initial_guess = [0]*len(variables)
    sol = root(combined_function, initial_guess, args=(equations_lamb,))
    print(sol)