将bessel函数与2个变量集成

时间:2014-12-08 14:58:09

标签: python lambda integration

我在执行此代码时遇到问题,我怀疑这是在bessel函数J1中使用带有多个变量的lambda函数引起的问题。函数q(theta)给出错误。 INTEGRATEZI只是一种从0到10 ** 10的积分方法(Gauss-Kronrod方法)。

from scipy.special import j1 as J1
from cmath import sin, cos
import scipy
from scipy import array


def cml(function):
    return (scipy.real(function)**2 - scipy.imag(function)**2)

def quad_routine(func, a, b, x_list, w_list):
    c_1 = (b-a)/2.0
    c_2 = (b+a)/2.0
    eval_points = map(lambda x: c_1*x+c_2, x_list)
    func_evals = map(func, eval_points)
    return c_1 * sum(array(func_evals) * array(w_list))

def quad_kronrod_15(func, a, b):
    x_kr = [-0.991455371120813,-0.949107912342759, -0.864864423359769, -0.741531185599394, -0.586087235467691,-0.405845151377397, -0.207784955007898, 0.0, 0.207784955007898,0.405845151377397, 0.586087235467691, 0.741531185599394, 0.864864423359769, 0.949107912342759, 0.991455371120813]
    w_kr = [0.022935322010529, 0.063092092629979, 0.104790010322250, 0.140653259715525, 0.169004726639267, 0.190350578064785, 0.204432940075298, 0.209482141084728, 0.204432940075298, 0.190350578064785, 0.169004726639267, 0.140653259715525,  0.104790010322250, 0.063092092629979, 0.022935322010529]
    return quad_routine(func,a,b,x_kr, w_kr)

class Memoize(object):
    def __init__(self, func):
        self.func = func
        self.eval_points = {}
    def __call__(self, *args):
        if args not in self.eval_points:
            self.eval_points[args] = self.func(*args)
        return self.eval_points[args]

def quadt(func,a,b):
    func = Memoize(func) #  Memoize function to skip repeated function calls.
    k15 = quad_kronrod_15(func,a,b)
    return k15

def INTEGRATEZI(func, **kwargs):       # INTEGRATEZI short for Integrating from zero to infinity
    def real_func(x):
        return scipy.real(func(x))
    def imag_func(x):
        return scipy.imag(func(x))
    real_integral = quadt(real_func, 0, 10**10)
    imag_integral = quadt(imag_func, 0, 10**10)
    return (real_integral + 1j*imag_integral)
r = 2.0
p = lambda theta: r*sin(theta)
z = lambda theta: r*cos(theta)
q = lambda theta: (p(theta) + z(theta) + INTEGRATEZI(lambda kp: (J1(kp * p(theta))) ))
print q(0.5)

这是错误报告:

%run "C:/Users/ENVY14-i7-SPECTRE/Documents/University/Year 3/project/123123.py"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
C:\Users\ENVY14-i7-SPECTRE\AppData\Local\Enthought\Canopy\App\appdata\canopy-1.4.1.1975.win-x86_64\lib\site-packages\IPython\utils\py3compat.pyc in execfile(fname, glob, loc)
    195             else:
    196                 filename = fname
--> 197             exec compile(scripttext, filename, 'exec') in glob, loc
    198     else:
    199         def execfile(fname, *where):

C:\Users\ENVY14-i7-SPECTRE\Documents\University\Year 3\project\123123.py in <module>()
     45 z = lambda theta: r*cos(theta)
     46 q = lambda theta: (p(theta) + z(theta) + INTEGRATEZI(lambda kp: (J1(kp * p(theta))) ))
---> 47 print q(0.5)

C:\Users\ENVY14-i7-SPECTRE\Documents\University\Year 3\project\123123.py in <lambda>(theta)
     44 p = lambda theta: r*sin(theta)
     45 z = lambda theta: r*cos(theta)
---> 46 q = lambda theta: (p(theta) + z(theta) + INTEGRATEZI(lambda kp: (J1(kp * p(theta))) ))
     47 print q(0.5)

C:\Users\ENVY14-i7-SPECTRE\Documents\University\Year 3\project\123123.py in INTEGRATEZI(func, **kwargs)
     38     def imag_func(x):
     39         return scipy.imag(func(x))
---> 40     real_integral = quadt(real_func, 0, 10**10)
     41     imag_integral = quadt(imag_func, 0, 10**10)
     42     return (real_integral + 1j*imag_integral)

C:\Users\ENVY14-i7-SPECTRE\Documents\University\Year 3\project\123123.py in quadt(func, a, b)
     30 def quadt(func,a,b):
     31     func = Memoize(func) #  Memoize function to skip repeated function calls.
---> 32     k15 = quad_kronrod_15(func,a,b)
     33     return k15
     34 

C:\Users\ENVY14-i7-SPECTRE\Documents\University\Year 3\project\123123.py in quad_kronrod_15(func, a, b)
     17     x_kr = [-0.991455371120813,-0.949107912342759, -0.864864423359769, -0.741531185599394, -0.586087235467691,-0.405845151377397, -0.207784955007898, 0.0, 0.207784955007898,0.405845151377397, 0.586087235467691, 0.741531185599394, 0.864864423359769, 0.949107912342759, 0.991455371120813]
     18     w_kr = [0.022935322010529, 0.063092092629979, 0.104790010322250, 0.140653259715525, 0.169004726639267, 0.190350578064785, 0.204432940075298, 0.209482141084728, 0.204432940075298, 0.190350578064785, 0.169004726639267, 0.140653259715525,  0.104790010322250, 0.063092092629979, 0.022935322010529]
---> 19     return quad_routine(func,a,b,x_kr, w_kr)
     20 
     21 class Memoize(object):

C:\Users\ENVY14-i7-SPECTRE\Documents\University\Year 3\project\123123.py in quad_routine(func, a, b, x_list, w_list)
     11     c_2 = (b+a)/2.0
     12     eval_points = map(lambda x: c_1*x+c_2, x_list)
---> 13     func_evals = map(func, eval_points)
     14     return c_1 * sum(array(func_evals) * array(w_list))
     15 

C:\Users\ENVY14-i7-SPECTRE\Documents\University\Year 3\project\123123.py in __call__(self, *args)
     25     def __call__(self, *args):
     26         if args not in self.eval_points:
---> 27             self.eval_points[args] = self.func(*args)
     28         return self.eval_points[args]
     29 

C:\Users\ENVY14-i7-SPECTRE\Documents\University\Year 3\project\123123.py in real_func(x)
     35 def INTEGRATEZI(func, **kwargs):       # INTEGRATEZI short for Integrating from zero to infinity
     36     def real_func(x):
---> 37         return scipy.real(func(x))
     38     def imag_func(x):
     39         return scipy.imag(func(x))

C:\Users\ENVY14-i7-SPECTRE\Documents\University\Year 3\project\123123.py in <lambda>(kp)
     44 p = lambda theta: r*sin(theta)
     45 z = lambda theta: r*cos(theta)
---> 46 q = lambda theta: (p(theta) + z(theta) + INTEGRATEZI(lambda kp: (J1(kp * p(theta))) ))
     47 print q(0.5)

TypeError: ufunc 'j1' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe'' 

1 个答案:

答案 0 :(得分:1)

发生错误是因为您提供给Bessel函数的参数:

kp * p(theta)

不是真实的数字。然后Scipy抛出一个类型错误,因为它期望一个实数。

为什么不真实?您正在使用python的复数数学库cmath,其sin函数将结果作为复数返回。所以,例如,

In [9]: cmath.sin(.5)
Out[9]: (0.479425538604203+0j)

有一个(零)虚构组件。但是Scipy的Bessel函数接收一个复杂类型的变量,并且不知道如何处理它。快速解决方法是使用标准math库,或在r*sin(theta)的定义中将r*sin(theta).real替换为r*cos(theta),将r*cos(theta).real替换为p q


要查看此内容,您可以使用python debugger之类的工具来查找引发异常的确切原因。看起来你正在使用IPython,它包含一些易于使用的调试工具。

在你的情况下,在IPython终端上运行你的代码,你会得到一个例外:

In [4]: run code.py

     ... (cut for space) ...

     45 p = lambda theta: r*sin(theta)
     46 z = lambda theta: r*cos(theta)
---> 47 q = lambda theta: (p(theta) + z(theta) + INTEGRATEZI(lambda kp: (J1(kp * p(theta))) ))
     48 print q(0.5)
TypeError: ufunc 'j1' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

在使用TypeError评估该行时,您会看到--->已被提升。但是这一行还有很多事情要做。究竟是什么原因导致了这个问题?

一种简单的检查方法是启动调试器“验尸”。每个变量的值都会在发生异常时及时“冻结”,因此我们可以查看问题所在的位置。

运行代码并看到异常后,在IPython提示符下键入%debug

In [5]: %debug
> /home/eldridge/sandbox/stack/stack.py(47)<lambda>()
     46 z = lambda theta: r*cos(theta)
---> 47 q = lambda theta: (p(theta) + z(theta) + INTEGRATEZI(lambda kp: (J1(kp * p(theta))) ))
     48 print q(0.5)

我们在导致错误的框架中。你认为这个问题可能与贝塞尔函数有关,所以我决定问这个论点是什么。您可以使用p命令打印变量:

ipdb> p kp
42723144.39593506

看起来很好。那么p(theta)呢?

ipdb> p p(theta)
(0.958851077208406+0j)

嗯。这是虚构的。贝塞尔函数能处理复杂的输入吗?我不记得我的数学课程,但我可以尝试看看:

ipdb> p J1(1j)
*** TypeError: TypeError("ufunc 'j1' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''",)

显然不是。

当然,调试器还有很多功能,当你有时间时,值得查看tutorial