如何修复在使用数组参数进行积分时“只能将长度为1的数组转换为Python标量”

如何修复在使用数组参数进行积分时“只能将长度为1的数组转换为Python标量”,python,numpy,scipy,integrate,quad,Python,Numpy,Scipy,Integrate,Quad,我正在使用scipy.integrate中的quad来获取对象有限范围内的积分。假设目标对象处于打击中: ∫expm(A*X).expm(B*X)dx 其中A和B都是numpy矩阵 为了解决这个问题,我使用了blow代码: from scipy.integrate import quad from scipy.linalg import expm import numpy as np def integrand(X, A, B): return np.dot(expm(A*X),ex

我正在使用scipy.integrate中的quad来获取对象有限范围内的积分。假设目标对象处于打击中:

∫expm(A*X).expm(B*X)dx
其中A和B都是numpy矩阵

为了解决这个问题,我使用了blow代码:

from scipy.integrate import quad
from scipy.linalg import expm
import numpy as np

def integrand(X, A, B):
    return np.dot(expm(A*X),expm(B*X))


A = np.array([[1, 2], [3, 4]])
B = np.array([[1, 2], [3, 4]])

I= quad(integrand, 0, 1, args=(A,B))
但对于结果,我得到了以下错误:

TypeError: only length-1 arrays can be converted to Python scalars

我知道,当函数需要一个值,而您传递的是一个数组时,会出现将仅长度为1的数组转换为Python标量的错误。但我的问题是基于数组的。那么我该如何修复它。

正如注释中所指出的,quad需要一个标量函数。通过将索引添加为输出,始终可以将函数传递给标量:

def integrand(X, A, B, ix=None):
    """ pass ix=None to return the matrix, ix = 0,1,2,3 to return an element"""
    output = np.dot(expm(A*X),expm(B*X))
    if ix is None:
        return output
    i, j = ix//2, ix%2
    return output[i,j]
I= np.array([quad(integrand, 0, 1, args=(A,B, i))[0]
for i in range(4)]).reshape(2,2)
I
>>array([[1031.61668602, 1502.47836021],
       [2253.71754031, 3285.33422634]])
请注意,这是非常低效的,因为您要计算4次积分,只要这不打扰您

或者,使用trapz:

进行矢量化计算。事实上,expm只适用于方阵,而不适用于方阵列表,这需要对矩阵形状进行一些处理

从四边形导入四边形 将numpy作为np导入 从scipy.linalg导入expm A=np.数组[[1,2],[3,4]] B=np.数组[[1,2],[3,4]] def integrandX: expAX=np.array[expmA*x表示x中的x] expAX=np.moveaxisexpAX,0,-1 expBX=np.array[expmB*x代表x中的x] expBX=np.moveaxisexpBX,0,-1 返回np.einsumij…,jk…->ik…,expAX,expBX val,err=quad被积函数,0,1 printval
仔细检查有关quad函数参数的文档。@hpaulj您能给我推荐一个合适的文档吗?您不知道在哪里可以找到您使用的Python代码的文档吗?你们是怎么找到如何调用quad的?好吧,让我们更明确一点,quad集成了一个标量函数。你的函数返回一个数组。我不太会使用“quad”,我是通过搜索并阅读“scipy”网站上的相关文档找到它的。但它们只是一个简单的例子。如果我说你能推荐我吗,我指的是更详细的文件@hpauljyes我用你的想法通过索引来解决这个问题,但是对于大型矩阵和更复杂的集成来说,它太慢了。所以我用另一种方式尝试了你的推荐,速度提高了。它真的很有用而且很棒
x_i = np.linspace(0,1,60)
np.trapz([integrand(x, A, B) for x in x_i], x=x_i, axis=0)
>>array([[1034.46472361, 1506.62915374],
   [2259.94373062, 3294.40845422]])
[[1031.61668602 1502.47836021]
 [2253.71754031 3285.33422633]]