(Некоторая функция) не определена с помощью SymPy Lambdify

Итак, я пишу сценарий, оценивающий серию Тейлор. Однако я хочу, чтобы он оценивался для всех типов функций. Я попробовал, например, использовать функцию acot(x).

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

Вышеупомянутое выполняется без исключения (кроме случаев, когда я, например, использую acsch, и он не запускается).

Но затем, когда он достигает этой строки:

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

Я получил:

NameError: name 'acot' is not defined

Я попытался заменить numpy на sympy в вызове lambdify, но это, похоже, оценивается символически. Это происходит с некоторыми (более редкими функциями), но не с другими. Спасибо!

Мой импорт следующий:

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

person rb612    schedule 24.07.2017    source источник


Ответы (2)


У меня были подобные проблемы и раньше, и я их решил.

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

выглядит нормально. Я привожу один мой старый код, который отлично работает, вы можете просто сравнить.

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()
person MishaVacic    schedule 24.07.2017

Основная проблема здесь в том, что функция lambdify использует аргумент modules для определения доступных модулей для предоставленной функции. Кажется, acot недоступен в пространстве имен numpy.

Давайте сведем это к чему-то простому:

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))

Это вызывает NameError, поскольку acot не определен в пространстве имен numpy. Обратите внимание на аргумент модулей. Если мы расширим доступные модули до sympy, мы больше не получим NameError:

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

Если у вас возникли проблемы с нечетными функциями, вы также можете добавить отдельные функции в параметр lambdify modules в виде словаря пар func_name: function:

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

Что касается построения графика с использованием matplotlib, для меня работает векторизация уравнения, а затем построение графика:

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()
person Andrew Guy    schedule 24.07.2017
comment
Это хорошо, спасибо. За исключением того, что это будет оценивать символически. Например, acot(4) будет просто acot(4), а не числовая оценка, необходимая для построения значений из линейного пространства. - person rb612; 24.07.2017
comment
@ rb612, да, acot(4) вычисляет символически. Но func_lambda(4) оценивает численно. Я добавлю дополнительные детали, чтобы график заработал. - person Andrew Guy; 24.07.2017
comment
Спасибо за ваш ответ, но когда я пытаюсь его оценить, я получаю оценку acot(4) при печати вывода func_lambda(4). Но если я принудительно использую float (вместо этого использую 4.0), он вычисляется численно. Это нормально? - person rb612; 25.07.2017
comment
Простите, вы правы. Не уверен, что делал раньше. Тем не менее, преобразование в число с плавающей запятой довольно просто (float(func_lambda(4))), если это необходимо. Даже без явного преобразования в float построение графика с помощью matplotlib по-прежнему работает хорошо (т.е. пробовал с x1 = [1,2,3,4]). - person Andrew Guy; 25.07.2017