首页 > 解决方案 > Lambdify 参数积分

问题描述

我有以下问题:我想要lambdify一个sympy包含参数积分的表达式,如Integral(tanh(a*x),(x,0,1)). 我尝试像这里一样进行手动实现。

我们想要的本质上是将积分转换为以下内容:

lambda theta: quad(lambda x: g(x,theta), a,b)[0]

在哪里

g = sp.lambdify((x,param), f, modules='numpy'))

考虑以下 MWE:

import sympy as sp
import numpy as np
from scipy.integrate import quad

def integral_as_quad(function, limits):
    x, a, b = limits
    param = function.free_symbols - {x}
    f = sp.lambdify( (x,*param), function, modules='numpy')
    return lambda y: quad(lambda x: f(x,y), a,b)[0]

a, x = sp.symbols('a,x')
I = sp.Integral(sp.tanh(a*x),(x,0,1))
K = integral_as_quad(sp.tanh(a*x),(x,0,1))
L = sp.lambdify(a, I, modules=['numpy', {'Integral':integral_as_quad}] )

然后调用例如K(1)返回正确的值。然而L(1)

AttributeError: 'Mul' object has no attribute 'tanh'

有谁知道如何解决这个问题?

注意:手动操作是不可取的,因为我处理的表达式要复杂得多,并且可能包含几个不同的积分。所以我真的需要让lambdify工作。

标签: python-3.xsympy

解决方案


我认为从integral_as_quad无法返回一个 lambda,因为这个 lambda 永远不会被调用,因为IntegralSymPy 中的对象是不可调用的。相反,参数元组可以quad通过其args参数传递给。我做的另一个改变是在外部lambdification,替换

modules=['numpy', {'Integral':integral_as_quad}] 

modules=[{'Integral': integral_as_quad}, 'sympy'] 

这个想法是,在这个阶段我们还不需要 NumPy 函数,我们只想用我们的可调用函数替换 Integral。列表的顺序modules很重要:字典首先是为了防止 SymPy 将 Integral 保留为 Integral。

现在 L(1) 返回正确的数量。

import sympy as sp
import numpy as np
from scipy.integrate import quad

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]

a, x = sp.symbols('a,x')
I = sp.Integral(sp.tanh(a*x), (x,0,1))
L = sp.lambdify(a, I, modules=[{'Integral': integral_as_quad}, 'sympy'])

推荐阅读