将符号表达式转换为数字表达式以在Quad中使用-使用lambdify吗? [英] Conversion of symbolic expression to numeric one for use in quad - use lambdify?

查看:209
本文介绍了将符号表达式转换为数字表达式以在Quad中使用-使用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所需的数字(浮点).如何使函数数字化,从而允许我执行积分?我已经尝试过.subslambdify函数,但是无法正常工作.前者似乎只有在提供数字的情况下才有效(例如,我不想设置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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆