通过 SymPy 对多元函数进行微分并在某一点进行评估
Differentiation of a multivariate function via SymPy and evaluation at a point
我想使用 SymPy 求多变量函数的导数,然后 a) 要打印的符号结果,然后 b) 要打印的点处的导数结果。我正在使用以下代码
import math as m
import numpy
import scipy
#define constants
lambdasq = 0.09
Ca = 3
qOsq = 2
def f1(a,b,NN,ktsq,x):
return NN*x**(-a)*ktsq**b*m.exp(m.sqrt(16*Ca/9*m.log(1/x)*m.log((m.log(ktsq/lambdasq))/m.log(qOsq/lambdasq))))
from sympy import *
x = symbols('x')
def f2(NN,a,b,x,ktsq):
return -x*diff(m.log(f1),x)
这会运行,但我找不到一种方法来打印符号结果,当我尝试在某个点进行评估时,比如添加 print(f2(0.3,0.1,-0.2,0.1,3))
我得到一个错误
TypeError: must be real number, not function
当我用它的符号表示替换 f1
时,我得到的是错误
ValueError:
Can't calculate 1st derivative wrt 0.100000000000000.
所以我可以将我的问题总结如下
a) 如何在我调用 diff(m.log(f1),x)
时打印出符号导数及其值(即不必用其实际表示替换 f1
)
b) 如果我必须在微分中使用符号表示(即使用 diff(m.log(NN*x**(-a)*ktsq**b*m.exp(m.sqrt(16*Ca/9*m.log(1/x)*m.log((m.log(ktsq\
/lambdasq))/m.log(qOsq/lambdasq))))),x)
那么如何打印出符号导数及其在某个点的值?
Python 的新手,所以希望有一个相对简单的修复。
谢谢!
首先,math
函数是数字的,它们不能使用 SymPy 的符号。使用您已经使用 from sympy import *
:
导入的 SymPy 中的相应函数(exp、log、sqrt)
def f1(a, b, NN, ktsq, x):
return NN*x**(-a)*ktsq**b*exp(sqrt(16*Ca/9*log(1/x)*log((log(ktsq/lambdasq))/log(qOsq/lambdasq))))
其次,在 f2 中您试图区分 f1
。但是 f1 是一个可调用的 Python 函数,而不是 SymPy 表达式。需要传入一些参数,得到一个SymPy表达式,然后可以求微分。
def f2(NN, a, b, x0, ktsq):
return (-x*diff(log(f1(a, b, NN, ktsq, x)), x)).subs(x, x0)
这里,除了值 x0 之外的数字参数被传递给 f1,导致包含 x 的 SymPy 表达式。那是要区别对待的事情。之后用数值x0代入x。
print(f2(0.3,0.1,-0.2,0.1,3)) # 0.366748952743614
要点是 SymPy 区分 表达式 ,而不是 函数 。 SymPy中没有f'
的概念,只有f'(x)
.
我发布这个答案是因为这个线程在搜索 'simpy multivariate differentiation' 时在我的搜索引擎上排名第一,可能会对某人有所帮助。
示例 1
import sympy as sp
def f(u):
return (u[0]**2 + u[1]**10 + u[2] - 4)**2
u = sp.IndexedBase('u')
print(sp.diff(f(u), u[0]))
产出
4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0]
这是 f(u) 对 u[0]
的导数
示例 2
如果我们想要整个雅可比矩阵,我们可以这样做:
for i in range(3):
print(sp.diff(f(u), u[i]))
输出
4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0]
20*(u[0]**2 + u[1]**10 + u[2] - 4)*u[1]**9
2*u[0]**2 + 2*u[1]**10 + 2*u[2] - 8
我们可以定义一个临时函数并复制粘贴这些行
def temp(u):
return np.array([
4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0],
20*(u[0]**2 + u[1]**10 + u[2] - 4)*u[1]**9,
2*u[0]**2 + 2*u[1]**10 + 2*u[2] - 8,
])
temp([1., 1., 1.])
这输出 array([ -4., -20., -2.])
并验证
from autograd import grad
gradient = grad(f)
gradient([1., 1., 1.])
这输出:[array(-4.), array(-20.), array(-2.)]
注意:这只是一个简单的展示如何在 sympy 中进行多元导数。我希望我可以帮助别人
我想使用 SymPy 求多变量函数的导数,然后 a) 要打印的符号结果,然后 b) 要打印的点处的导数结果。我正在使用以下代码
import math as m
import numpy
import scipy
#define constants
lambdasq = 0.09
Ca = 3
qOsq = 2
def f1(a,b,NN,ktsq,x):
return NN*x**(-a)*ktsq**b*m.exp(m.sqrt(16*Ca/9*m.log(1/x)*m.log((m.log(ktsq/lambdasq))/m.log(qOsq/lambdasq))))
from sympy import *
x = symbols('x')
def f2(NN,a,b,x,ktsq):
return -x*diff(m.log(f1),x)
这会运行,但我找不到一种方法来打印符号结果,当我尝试在某个点进行评估时,比如添加 print(f2(0.3,0.1,-0.2,0.1,3))
我得到一个错误
TypeError: must be real number, not function
当我用它的符号表示替换 f1
时,我得到的是错误
ValueError:
Can't calculate 1st derivative wrt 0.100000000000000.
所以我可以将我的问题总结如下
a) 如何在我调用 diff(m.log(f1),x)
时打印出符号导数及其值(即不必用其实际表示替换 f1
)
b) 如果我必须在微分中使用符号表示(即使用 diff(m.log(NN*x**(-a)*ktsq**b*m.exp(m.sqrt(16*Ca/9*m.log(1/x)*m.log((m.log(ktsq\
/lambdasq))/m.log(qOsq/lambdasq))))),x)
那么如何打印出符号导数及其在某个点的值?
Python 的新手,所以希望有一个相对简单的修复。 谢谢!
首先,math
函数是数字的,它们不能使用 SymPy 的符号。使用您已经使用 from sympy import *
:
def f1(a, b, NN, ktsq, x):
return NN*x**(-a)*ktsq**b*exp(sqrt(16*Ca/9*log(1/x)*log((log(ktsq/lambdasq))/log(qOsq/lambdasq))))
其次,在 f2 中您试图区分 f1
。但是 f1 是一个可调用的 Python 函数,而不是 SymPy 表达式。需要传入一些参数,得到一个SymPy表达式,然后可以求微分。
def f2(NN, a, b, x0, ktsq):
return (-x*diff(log(f1(a, b, NN, ktsq, x)), x)).subs(x, x0)
这里,除了值 x0 之外的数字参数被传递给 f1,导致包含 x 的 SymPy 表达式。那是要区别对待的事情。之后用数值x0代入x。
print(f2(0.3,0.1,-0.2,0.1,3)) # 0.366748952743614
要点是 SymPy 区分 表达式 ,而不是 函数 。 SymPy中没有f'
的概念,只有f'(x)
.
我发布这个答案是因为这个线程在搜索 'simpy multivariate differentiation' 时在我的搜索引擎上排名第一,可能会对某人有所帮助。
示例 1
import sympy as sp
def f(u):
return (u[0]**2 + u[1]**10 + u[2] - 4)**2
u = sp.IndexedBase('u')
print(sp.diff(f(u), u[0]))
产出
4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0]
这是 f(u) 对 u[0]
的导数示例 2
如果我们想要整个雅可比矩阵,我们可以这样做:
for i in range(3):
print(sp.diff(f(u), u[i]))
输出
4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0]
20*(u[0]**2 + u[1]**10 + u[2] - 4)*u[1]**9
2*u[0]**2 + 2*u[1]**10 + 2*u[2] - 8
我们可以定义一个临时函数并复制粘贴这些行
def temp(u):
return np.array([
4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0],
20*(u[0]**2 + u[1]**10 + u[2] - 4)*u[1]**9,
2*u[0]**2 + 2*u[1]**10 + 2*u[2] - 8,
])
temp([1., 1., 1.])
这输出 array([ -4., -20., -2.])
并验证
from autograd import grad
gradient = grad(f)
gradient([1., 1., 1.])
这输出:[array(-4.), array(-20.), array(-2.)]
注意:这只是一个简单的展示如何在 sympy 中进行多元导数。我希望我可以帮助别人