(Some function) is not defined with SymPy Lambdify

2020-07-17 04:45发布

问题:

So I'm writing a script that evaluates Taylor Series. However, I want it to evaluate for all types of functions. So I tried, for example, using the function acot(x).

x = sy.Symbol('x')
f = acot(x)
...
func = taylor(f,0,3)
taylor_lambda = sy.lambdify(x, func, 'numpy')

The above runs without an exception (except if I use acsch, for example, and it does not run).

But then when it reaches this line:

plt.plot(x1,taylor_lambda(x1),label='taylor approximation')

I get:

NameError: name 'acot' is not defined

I tried to replace numpy with sympy in the lambdify call but this seems to evaluate symbolically. This is happening with some (more rare functions) but not for others. Thank you!

My imports are as follows:

import sympy as sy
import numpy as np
from sympy.functions import *
from sympy import pi, E,acot
import matplotlib.pyplot as plt
import math

回答1:

I did have similar problems before and have managed to solve them.Your line

plt.plot(x1,taylor_lambda(x1),label='taylor approximation')

looks OK.I am giving one my older code that works fine,you can just compare.

from sympy.abc import x
from sympy import sin, series
from sympy.utilities.lambdify import lambdify

import numpy as np
import matplotlib.pyplot as plt


func = sin(x)/x
taylor = series(func, n=6).removeO()

evalfunc = lambdify(x, func, modules=['numpy'])
evaltaylor = lambdify(x, taylor, modules=['numpy'])

t = np.linspace(-7.5, 7.5 , 100)
plt.plot(t, evalfunc(t), 'b', label='sin(x)/x')
plt.plot(t, evaltaylor(t), 'r', label='Taylor')
plt.legend(loc='best')
plt.show()


回答2:

The main issue here is that the lambdify function uses the modules argument to define available modules for the supplied function. It seems acot is not available within the numpy namespace.

Lets reduce this down to something simple:

import sympy as sy
import numpy as np
from sympy.functions import *

x = sy.Symbol('x')
f = acot(x)
func_lambda = sy.lambdify(x, f, modules='numpy')
print(func_lambda(1))

This raises a NameError as acot is not defined in the numpy namespace. Note the modules argument. If we extend the available modules to sympy, we no longer get a NameError:

func_lambda = sy.lambdify(x, f, modules=['numpy', 'sympy'])
print(func_lambda(1))
# Prints pi/4

If you're having trouble with odd functions, you can also add individual functions to the lambdify modules parameter as a dictionary of func_name: function pairs:

func_lambda = sy.lambdify(x, f, modules=['numpy', {'acot':acot}])
print(func_lambda(1))
# Prints pi/4

As far as plotting using matplotlib, vectorizing the equation and then plotting works for me:

import matplotlib.pyplot as plt
vfunc = np.vectorize(func_lambda)
x1 = np.linspace(-10, 10 , 1000)
plt.plot(x1, vfunc(x1),label='acot')
plt.show()