Python &引用;ValueError:包含多个元素的数组的真值不明确;使用scipy.integrate.dblquad时

Python &引用;ValueError:包含多个元素的数组的真值不明确;使用scipy.integrate.dblquad时,python,numpy,scipy,Python,Numpy,Scipy,我正在尝试对这个函数执行双重积分 def prob(x,y): ch=np.sqrt((3-y)**2+x**2) hb=np.sqrt((4-x)**2+y**2) 如果np.isclose(4*y,12-3*x): #如果没有if语句,满足条件的任何x,y值都将返回nan 返回0.5 其他: 返回值(np.arccos((ch**2+hb**2-25)/(2*ch*hb))/(2*np.pi) 从scipy导入集成为整数 整数dblquad(概率(x,y),0,4,λx:0,λx:3)

我正在尝试对这个函数执行双重积分

def prob(x,y):
ch=np.sqrt((3-y)**2+x**2)
hb=np.sqrt((4-x)**2+y**2)
如果np.isclose(4*y,12-3*x):
#如果没有if语句,满足条件的任何x,y值都将返回nan
返回0.5
其他:
返回值(np.arccos((ch**2+hb**2-25)/(2*ch*hb))/(2*np.pi)

从scipy导入集成为整数
整数dblquad(概率(x,y),0,4,λx:0,λx:3)
但是,我得到了指向if语句的错误消息

ValueError:包含多个元素的数组的真值不明确。使用a.any()或a.all()

简单地说,如果在if语句中使用math.isclose而不是np.isclose,我会得到指向同一语句的错误消息

TypeError:只有大小为1的数组才能转换为Python标量

据我所知,布尔数组与这些错误有关,但检查所有内容(包括if语句)都会生成标量布尔值


有没有办法解决这个问题?

也许这是印刷错误

从我所做的编辑来看,您好像在打电话:

integ.dblquad(prob(x, y), 0, 4, lambda x: 0, lambda x: 3)
integ.dblquad(prob, 0, 4, lambda x: 0, lambda x: 3)
事实上,你应该打电话:

integ.dblquad(prob(x, y), 0, 4, lambda x: 0, lambda x: 3)
integ.dblquad(prob, 0, 4, lambda x: 0, lambda x: 3)
我相信您可能有和array
x
和array
y
在第一次调用
dblquad
时导致错误

例如


嗯,你得到的错误在诊断方面是很有帮助的。问题是,它将返回一个布尔数组,并且试图将这样一个数组强制为单个值(if子句执行此操作)会引发错误。(一)

如何修复它更多地取决于您想要实现什么。假设
prob(x,y)
应返回与x/y尺寸相同的numpy数组,其中在条件为真的位置,值替换为0.5,则可以使用:

output = (np.arccos((ch**2 + hb**2 - 25) / (2 * ch * hb)))/(2*np.pi)
output[np.isclose(4 * y, 12 - 3 * x)] = .5
return output
请注意,这可能不是解决实际问题的最佳方法。将NaN保持在计算失败的位置通常更有意义(这就是NaN的用途)。如果您想将NaN替换为0.5,那么最好测试NaN,而不是根据您的数学条件:

output = (np.arccos((ch**2 + hb**2 - 25) / (2 * ch * hb)))/(2*np.pi)
output[np.isnan(output)] = .5
return output

(1) 有人可能会争辩说,任何非空数组的计算结果都应该是
True
,类似于非numpython中的列表,并且不管值是什么(即
np.asarray([False])
的计算结果是
True
)。就我个人而言,我很高兴numpy会提出一个异常,而不是试图猜测在那种情况下我想要什么(可能是
all
any
len(array)>0
,或者这里需要重写的元素操作)。

简短回答-您需要提供完整的回溯和调用规范。您需要正确调用
dblquad

===

当你打电话时,什么是
x,y

integ.dblquad(prob(x,y), 0, 4, lambda x: 0, lambda x: 3)
如果使用这两个变量,甚至在调用
dblquad
之前,错误可能会上升

dblquad
的第一个参数应该是函数,而不是数组。使用
prob
代替
prob(x,y)
可能有效

给定2个标量
prob
有效:

In [674]: prob(1,2)                                                                                    
Out[674]: 0.4685835209054995
给定两个数组,我们得到模糊度误差:

In [675]: prob(np.arange(3),np.arange(1,4))                                                            
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-675-4b16a88f567e> in <module>
----> 1 prob(np.arange(3),np.arange(1,4))

<ipython-input-673-e31785dd54a5> in prob(x, y)
      2     ch = np.sqrt((3-y)**2 + x**2)
      3     hb = np.sqrt((4-x)**2 + y**2)
----> 4     if np.isclose(4 * y, 12 - 3 * x):
      5         # Without the if statement, any x, y values that satisfy the condition will return nan
      6         return 0.5

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
它生成一个布尔数组,不能在
if
子句中使用

使用
math.isclose
会引发错误,因为
math
函数只接受标量。它们不适用于数组(多值数组)

正确使用
dblquad
,它可以工作:

In [678]: integ.dblquad(prob, 0,4,lambda x:0, lambda x:3)                                              
Out[678]: (4.42854383700761, 1.8525461432365937e-08)
dblquad
将标量值传递给函数,因此使用
isclose
(numpy或math)不是问题

使用带有标量输入的
math
函数更快:

def probm(x,y):
    ch = math.sqrt((3-y)**2 + x**2)
    hb = math.sqrt((4-x)**2 + y**2)
    if math.isclose(4 * y, 12 - 3 * x):
        # Without the if statement, any x, y values that satisfy the condition will return nan
        return 0.5
    else:
        return (math.acos((ch**2 + hb**2 - 25) / (2 * ch * hb)))/(2*math.pi)

In [683]: integ.dblquad(probm, 0,4,lambda x:0, lambda x:3)                                             
Out[683]: (4.428543836134556, 1.8890715880459652e-08)
更快:

In [685]: timeit integ.dblquad(prob, 0,4,lambda x:0, lambda x:3)                                       
11.7 s ± 24.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [686]: timeit integ.dblquad(probm, 0,4,lambda x:0, lambda x:3)                                      
272 ms ± 1.12 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

我已回滚您的编辑。请不要编辑问题中的代码,尤其是以使整个问题无效的方式。你总是可以投票以打字错误告终。哦,我高中时犯了一个错误,我不知道。谢谢你指出。我忘了如果没有(x,y)它应该是prob,我在想类似的事情,但真正的问题是@Grrr修改了问题中的代码,使其无法回答。相关?: