使用 Sympy 返回自动导数
Returning automatic derivatives with Sympy
我正在尝试构建一个 class,其目标是 return 函数 f
的导数也作为函数。我已阅读有关 Sympy 的信息,并开始尝试使用此软件包。
主要问题
假设我有一个只有一个参数的简单函数,如下所示:
def f1p(x):
return x**2 + 5**x * 2*x + 1
现在,我有一种方法可以确保函数只有一个参数,然后计算导数(仅作为表达式):
from sympy import *
import inspect
def get_derivative(fun):
parameters=inspect.getargspec(f).args
if(len(parameters)>1):
raise ValueError('Function has more than one parameter.')
fdiff=fun(Symbol(parameters[0])).diff()
print(fdiff)
假设 fdiff
包含导数函数的主要表达式,那么,我要解决的问题是 returning 一个函数以对其求值,例如:
f_deriv=get_derivative(f1p) #f_deriv is a callable function
print(f_deriv(a)) #Prints derivative value of f1p in a
注意:我试过return eval/exec(diff)
但这是个坏主意,因为需要声明参数。我还尝试用以下方式包装表达式:
eval('def foo('+parameters[0]+'):\n\treturn '+diff)
这仍然不是一个好主意。
扩展主要问题
假设现在我们在基函数中使用(例如)对数,那么,我们这样实现它
import math
def f1p(x):
return x**2 + 5**x * 2*x + 1 + math.log(x)
当我将之前的函数应用于此时,出现以下错误:
TypeError: can't convert expression to float
这是因为 Sympy 无法理解 math.log(x)
。所以,我的问题是:
- 解决主要问题:有没有办法从
get_derivative
函数 return 一个可调用函数?
- 解决扩展问题:有什么方法可以将 sympy 表达式转换为 Python 可评估表达式?
提前致谢。
您可以使用 lambdify 到 return 可从您的 get_derivative
:
调用
import inspect
from sympy import symbols, diff
from sympy.utilities.lambdify import lambdify
def get_derivative(function):
if len(inspect.getfullargspec(function).args) > 1:
raise ValueError('Function has more than one parameter.')
x = symbols('x')
return lambdify(x, diff(f1p(x), x))
第一个 f1p
版本的检查结果:
def f1p(x):
return x**2 + 5**x * 2*x + 1
derivative = get_derivative(f1p)
derivative(1)
这将得到 28.094379124341003
。这是一个正确的结果。
现在,如果你想使用对数,那么你应该使用来自 sympy 的那个,而不是来自 math:
from sympy import log
def f1p(x):
return x**2 + 5**x * 2*x + 1 + log(x)
derivative = get_derivative(f1p)
derivative(1)
这将得到 29.094379124341003
。也正确。
我正在尝试构建一个 class,其目标是 return 函数 f
的导数也作为函数。我已阅读有关 Sympy 的信息,并开始尝试使用此软件包。
主要问题
假设我有一个只有一个参数的简单函数,如下所示:
def f1p(x):
return x**2 + 5**x * 2*x + 1
现在,我有一种方法可以确保函数只有一个参数,然后计算导数(仅作为表达式):
from sympy import *
import inspect
def get_derivative(fun):
parameters=inspect.getargspec(f).args
if(len(parameters)>1):
raise ValueError('Function has more than one parameter.')
fdiff=fun(Symbol(parameters[0])).diff()
print(fdiff)
假设 fdiff
包含导数函数的主要表达式,那么,我要解决的问题是 returning 一个函数以对其求值,例如:
f_deriv=get_derivative(f1p) #f_deriv is a callable function
print(f_deriv(a)) #Prints derivative value of f1p in a
注意:我试过return eval/exec(diff)
但这是个坏主意,因为需要声明参数。我还尝试用以下方式包装表达式:
eval('def foo('+parameters[0]+'):\n\treturn '+diff)
这仍然不是一个好主意。
扩展主要问题
假设现在我们在基函数中使用(例如)对数,那么,我们这样实现它
import math
def f1p(x):
return x**2 + 5**x * 2*x + 1 + math.log(x)
当我将之前的函数应用于此时,出现以下错误:
TypeError: can't convert expression to float
这是因为 Sympy 无法理解 math.log(x)
。所以,我的问题是:
- 解决主要问题:有没有办法从
get_derivative
函数 return 一个可调用函数? - 解决扩展问题:有什么方法可以将 sympy 表达式转换为 Python 可评估表达式?
提前致谢。
您可以使用 lambdify 到 return 可从您的 get_derivative
:
import inspect
from sympy import symbols, diff
from sympy.utilities.lambdify import lambdify
def get_derivative(function):
if len(inspect.getfullargspec(function).args) > 1:
raise ValueError('Function has more than one parameter.')
x = symbols('x')
return lambdify(x, diff(f1p(x), x))
第一个 f1p
版本的检查结果:
def f1p(x):
return x**2 + 5**x * 2*x + 1
derivative = get_derivative(f1p)
derivative(1)
这将得到 28.094379124341003
。这是一个正确的结果。
现在,如果你想使用对数,那么你应该使用来自 sympy 的那个,而不是来自 math:
from sympy import log
def f1p(x):
return x**2 + 5**x * 2*x + 1 + log(x)
derivative = get_derivative(f1p)
derivative(1)
这将得到 29.094379124341003
。也正确。