将符号表达式转换为数字表达式以在Quad中使用-使用lambdify吗? [英] Conversion of symbolic expression to numeric one for use in quad - use lambdify?
问题描述
我想将包含符号变量的表达式转换为数字表达式,以便随后可以在积分方法"quad"中使用该表达式.
I want to convert an expression containing symbolic variables to a numeric one so that the expression may be subsequently used in an integration method 'quad'.
import numpy
import math as m
import scipy
import sympy
#define constants
gammaee = 5.55e-6
MJpsi = 3.096916
alphaem = 1/137
lambdasq = 0.09
Ca = 3
qOsq = 2
def qbarsq(qsq):
return (qsq+MJpsi**2)/4
def xx(qbarsq, w):
return 4*qbarsq/(4*qbarsq-MJpsi**2+w**2)
from sympy import *
x,NN,a,b,ktsq,qbarsq,w = symbols('x NN a b ktsq qbarsq w')
def xg(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)))))
#prints symbolic derivative of xg
def func(NN,a,b,x,ktsq):
return (-x*diff(log(xg(a,b,NN,ktsq,x)),x))
#print(func(NN,a,b,x,ktsq))
#prints symbolic expression for Rg
def Rg(NN,a,b,ktsq,x):
return 2**(2*func(NN,a,b,x,ktsq)+3)/sqrt(m.pi)*gamma(func(NN,a,b,x,ktsq)+5/2)/gamma(func(NN,a,b,x,ktsq)+4)
#print(Rg(NN,a,b,ktsq,x))
#prints symbolic expression for Fktsq
def FktsqDeriv(NN,a,b,x,ktsq):
return diff(Rg(NN,a,b,ktsq,x)*xg(a,b,NN,ktsq,x),ktsq)
#print(FktsqDeriv(NN,a,b,x,ktsq))
def Fktsq1(qbarsq,ktsq,NN,a,b,w):
return FktsqDeriv(NN,a,b,x,ktsq).subs(x,4*qbarsq/(4*qbarsq-MJpsi**2+w**2))
#print(Fktsq1(qbarsq,ktsq,NN,a,b,w))
# symbolic expression for fA
def fA(ktsq,qbarsq,NN,a,b,w):
return Fktsq1(qbarsq,ktsq,NN,a,b,w)*1/(qbarsq)*1/(qbarsq+ktsq)
print(fA(qbarsq,ktsq,NN,a,b,w))
代码运行到此处并返回正确的函数fA
. fA
是一个符号值表达式,我想传递给quad来执行积分(在ktsq
上)
The code runs up to here and returns the correct function fA
. fA
is a symbolic valued expression which I want to pass onto quad to perform an integration over (over ktsq
)
import scipy.integrate.quadrature as sciquad
def integrated_f(qbarsq,NN,a,b,w):
return sciquad(fA,1,(w**2-MJpsi**2)/4, args=(qbarsq, NN, a, b, w))
我的理解是,这失败了,因为quad
的第一个参数(即函数)是符号类型,而不是quad所需的数字(浮点).如何使函数数字化,从而允许我执行积分?我已经尝试过.subs
和lambdify
函数,但是无法正常工作.前者似乎只有在提供数字的情况下才有效(例如,我不想设置NN=0.1
),并且我尝试了以下方法进行lambdify
My understanding is that this fails because the first argument of quad
, i.e. the function, is of symbolic type and not numeric (=floating point) required for quad. How to make the function numeric and thus allow me to perform the integration? I've tried .subs
and lambdify
function but couldn't get it to work. The former seems to work only if numbers are supplied (i.e set NN=0.1
for example which I don't want to do) and I tried the following for lambdify
def test(ktsq):
return fA(ktsq,qbarsq,NN,a,b,w)
f = lambdify(((qbarsq,NN,a,b,w),), test(ktsq))
#print(f(1,2,3,4,5))
但是当我取消注释打印以检查所有参数是否正常时,这给位置参数个数带来了错误.
but this gave error about number of positional arguments when I uncommented the print to check if all was working.
TypeError: <lambda>() takes 1 positional argument but 5 were given
推荐答案
是的,您应该使用lambdify. lambdify
的第一个参数是一个符号元组,而不是代码中的元组元组.第二个参数是SymPy表达式.示例:
Yes, you should use lambdify. The first argument of lambdify
is a tuple of symbols, not a tuple of tuples as in your code. The second argument is a SymPy expression. Example:
from sympy import *
a, b, c, d, e = symbols('a b c d e')
expr = a*b + 2*c + d/e
f = lambdify((a, b, c, d, e), expr)
print(f(1, 2, 3, 4, 5)) # prints 8.8
在您的情况下,这看起来像
In your case, this would look like
expr = fA(qbarsq, ktsq, NN, a, b, w)
f = lambdify((qbarsq, ktsq, NN, a, b, w), expr, "mpmath")
此处选择mpmath作为后端,因为它可以评估表达式包含的Gamma函数.否则,使用"numpy"后端选项可能会更快.请参阅有关lambdify的更多信息.
Here mpmath is chosen as the backend because it can evaluate Gamma function that your expression contains. Otherwise, it would probably be faster to use "numpy" backend option. See more on lambdify.
print(f(1, 2, 3, 4, 5, 6)) # (-4757.21371513605 + 58978.7828908493j)
它与quad
一起工作的方式...取决于您是实数还是复数.当它们是真实的时,您可以与scipy.integrate.quad
集成:
How it works with quad
... depends on whether you get real or complex numbers. When they are real, you can integrate with scipy.integrate.quad
:
from scipy.integrate import quad
quad(f, 3, 4, args=(2, 3, 4, 5, 6))[0]
返回30049812.82526324
.
如果它们很复杂,SciPy的quad
将对它不了解的mpc
类型感到不满意.但是mpmath
有其自己的quad
,因此请改用它:
If they are complex, SciPy's quad
will be unhappy with mpc
type which it doesn't understand. But mpmath
has its own quad
, so use that instead:
import mpmath as mp
mp.quad(lambda x: f(2, x, 3, 4, 5, 6), [1, 3])
返回mpc(real='7170810.3848631922', imag='-192389955826656.31')
.这里[1,3]是积分的时间间隔.
returns mpc(real='7170810.3848631922', imag='-192389955826656.31')
. Here [1, 3] is the interval of integration.
这篇关于将符号表达式转换为数字表达式以在Quad中使用-使用lambdify吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!