6

I have a rather large symbolic function that is evaluated for different values of a parameter in a loop. In each iteration, after finding the expression of the function, partial derivatives are derived. Something like this:

from sympy import diff, symbols,exp

def lagrange_eqs(a):
    x,y,z= symbols('x y z')
    FUNC=x**2-2*x*y**2+z+a*exp(z)
    d_lgrng_1=diff(FUNC,x)
    d_lgrng_2=diff(FUNC,y)
    d_lgrng_3=diff(FUNC,z)
    return [d_lgrng_1,d_lgrng_2,d_lgrng_3]

Next, I need to convert the output of this function to a Python function so that I can use fsolve to find x, y, z values for which derivatives are zero. The function must take x,y,z as a list.

Now here is my problem: how do I convert the output of the above function to a Python function which could be passed on to a solver. Such a function should look like this (for a=3):

def lagrange_eqs_solve(X): 
    x,y,z=X
    return [2*x - 2*y**2, -4*x*y, 3*exp(z) + 1]

I simply copied the output of the first function to build the second one. Is there a way I could code it? (Matlab has a built-in function for this, called matlabFunction)

AGandom
  • 295
  • 1
  • 3
  • 8

1 Answers1

9

You want lambdify.

f = lambdify(((x, y, z),), lagrange_eqs(a))

will give you a Python function f that you can evaluate like f((1, 2, 3)) (for x=1, y=2, z=3). I have made the arguments in a tuple so that it will work with scipy's fsolve.

You can set the modules flag to lambdify to determine where the exp function will come from. For instance, to use numpy, use lambdify((x, y, z), lagrange_eqs(a), modules="numpy"). To use the standard library math library, use modules="math". By default, numpy is used if it is installed, otherwise math is used.

asmeurer
  • 75,821
  • 22
  • 150
  • 217
  • Also, if multiple values of `a` are used, you would probably want to make that an argument to the lambdified function as well, so that you only have to create it once. – asmeurer Dec 10 '15 at 21:24
  • Thanks @asmeurer. `lambdify` does convert the output to a function, but it cannot be passed on to `fsolve`, because we need a function with one argument (a list of variables). When I try `fsolve(f,(0,0,0))` or `fsolve(f,[0,0,0])`, it throws `TypeError: () missing 2 required positional arguments: '_Dummy_17' and '_Dummy_18''`. – AGandom Dec 11 '15 at 00:12
  • Use `lambdify(((x, y, z),), lagrange_eqs(a))`. – asmeurer Dec 11 '15 at 03:44
  • in the answer, please add the missing comma in `f = lambdify(((x, y, z),), lagrange_eqs(a))`. I am not able to edit it. – AGandom Dec 11 '15 at 07:44