对包含 UndefinedFunction 的导数的 sympy 表达式进行lambdify [英] lambdify a sympy expression that contains a Derivative of UndefinedFunction
问题描述
我有几个未定义函数的表达式,其中一些包含该函数的相应(未定义)导数.函数及其导数都仅作为数值数据存在.我想从我的表达式中创建函数,然后使用相应的数值数据调用该函数以数值计算表达式.不幸的是,我遇到了 Lambdify 的问题.
I have several expressions of an undefined function some of which contain the corresponding (undefined) derivatives of that function. Both the function and its derivatives exist only as numerical data. I want to make functions out of my expressions and then call that function with the corresponding numerical data to numerically compute the expression. Unfortunately I have run into a problem with lambdify.
考虑以下简化示例:
import sympy
import numpy
# define a parameter and an unknown function on said parameter
t = sympy.Symbol('t')
s = sympy.Function('s')(t)
# a "normal" expression
a = t*s**2
print(a)
#OUT: t*s(t)**2
# an expression which contains a derivative
b = a.diff(t)
print(b)
#OUT: 2*t*s(t)*Derivative(s(t), t) + s(t)**2
# generate an arbitrary numerical input
# for demo purposes lets assume that s(t):=sin(t)
t0 = 0
s0 = numpy.sin(t0)
sd0 = numpy.cos(t0)
# labdify a
fa = sympy.lambdify([t, s], a)
va = fa(t0, s0)
print (va)
#OUT: 0
# try to lambdify b
fb = sympy.lambdify([t, s, s.diff(t)], b) # this fails with syntax error
vb = fb(t0, s0, sd0)
print (vb)
错误信息:
File "<string>", line 1
lambda _Dummy_142,_Dummy_143,Derivative(s(t), t): (2*_Dummy_142*_Dummy_143*Derivative(_Dummy_143, _Dummy_142) + _Dummy_143**2)
^
SyntaxError: invalid syntax
显然 Derivative 对象没有正确解析,我该如何解决?
Apparently the Derivative object is not resolved correctly, how can I work around that?
作为 Lambdify 的替代方案,我也愿意使用基于 theano 或 cython 的解决方案,但我在使用相应的打印机时遇到了类似的问题.
As an alternative to lambdify I'm also open to using theano or cython based solutions, but I have encountered similar problems with the corresponding printers.
感谢任何帮助.
推荐答案
据我所知,问题源于 lambdify 函数中不正确/不幸的虚拟化过程.在将参数和表达式传递给lambdifying 之前,我已经编写了自己的dummification 函数.
As far as I can tell, the problem originates from an incorrect/unfortunate dummification process within the lambdify function. I have written my own dummification function that I apply to the parameters as well as the expression before passing them to lambdifying.
def dummify_undefined_functions(expr):
mapping = {}
# replace all Derivative terms
for der in expr.atoms(sympy.Derivative):
f_name = der.expr.func.__name__
var_names = [var.name for var in der.variables]
name = "d%s_d%s" % (f_name, 'd'.join(var_names))
mapping[der] = sympy.Symbol(name)
# replace undefined functions
from sympy.core.function import AppliedUndef
for f in expr.atoms(AppliedUndef):
f_name = f.func.__name__
mapping[f] = sympy.Symbol(f_name)
return expr.subs(mapping)
像这样使用:
params = [dummify_undefined_functions(x) for x in [t, s, s.diff(t)]]
expr = dummify_undefined_functions(b)
fb = sympy.lambdify(params, expr)
显然这有点脆弱:
- 没有防止名称冲突
- 也许不是最好的名称方案:df_dxdy for
Derivative(f(x,y), x, y)
- 假设所有导数都具有以下形式:
Derivative(s(t), t, ...)
其中s(t)
是UndefinedFunction
和t
>符号
.如果 Derivative 的任何参数是更复杂的表达式,我不知道会发生什么.我有点认为/希望(自动)简化过程将任何更复杂的导数减少为由基本"导数组成的表达式.但我当然不防备. - 基本上未经测试(除了我的特定用例)
- no guard against name-collisions
- perhaps not the best possible name-scheme: df_dxdy for
Derivative(f(x,y), x, y)
- it is assumed that all derivatives are of the form:
Derivative(s(t), t, ...)
withs(t)
being anUndefinedFunction
andt
aSymbol
. I have no idea what will happen if any argument to Derivative is a more complex expression. I kind of think/hope that the (automatic) simplification process will reduce any more complex derivative into an expression consisting of 'basic' derivatives. But I certainly do not guard against it. - largely untested (except for my specific use-cases)
除此之外,它工作得很好.
Other than that it works quite well.
这篇关于对包含 UndefinedFunction 的导数的 sympy 表达式进行lambdify的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!