我在执行此代码时遇到问题,我怀疑这是在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''
答案 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。