我有一个损失函数L(u1,...,un),形式为
L(u) = Integral( (I**2 + J**2) * h, (t,c,d) ) //h=h(t), I=I(t,u)
其中
I = Integral( f, (x,a,b) ) // f=f(x,t,u)
J = Integral( g, (x,a,b) ) // g=g(x,t,u)
我想用L
在数值上最小化scipy
,因此我需要lambdify
表达式。
但是,此时lambdify
本身并不支持翻译积分。通过一些技巧,可以使它与单个参数积分一起使用,请参见Lambdify A Parametric Integral。但是,我看不出如何将提议的解决方案扩展到这种一般情况。
以下原则上可行的一个想法是:
采用定义L
的计算图。从叶子开始,递归地将每个符号运算替换为表示为lambda
函数的相应数值运算。但是,这将导致大量的lambda函数嵌套,我怀疑这会对性能产生非常不利的影响。
理想情况下,我们希望获得与手工制作相同的结果:
L = lambda u: quad(lambda t: (quad(lambda x: f,a,b)[0]**2
+ quad(lambda x: g,a,b)[0]**2)*h, c, d)[0]
MWE:(使用旧线程中的代码)
from sympy import *
from scipy.integrate import quad
import numpy as np
def integral_as_quad(function, limits):
x, a, b = limits
param = tuple(function.free_symbols - {x})
f = sp.lambdify((x, *param), function, modules=['numpy'])
return quad(f, a, b, args=param)[0]
x,a,b,t = sp.symbols('x a b t')
f = (x/t-a)**2
g = (x/t-b)**2
h = exp(-t)
I = Integral( f**2,(x,0,1))
J = Integral( g**2,(x,0,1))
K = Integral( (I**2 + J**2)*h,(t,1,+oo))
F = lambdify( (a,b), K, modules=['sympy',{"Integral": integral_as_quad}])
L = lambda a,b: quad(lambda t: (quad(lambda x: (x/t-a)**2,0,1)[0]**2
+ quad(lambda x: (x/t-b)**2,0,1)[0]**2)*np.exp(-t), 1, np.inf)[0]
display(F(1,1))
display(type(F(1,1)))
display(L(1,1))