我正在尝试使用scipy.optimize.curve_fit
将一些数据拟合到函数中,但是继续得到值错误,类似于this post中描述的值,但是将所有输入都按照建议的方式输入到numpy数组中评论似乎没有解决我的问题。
这是我的基本代码:
def RamanHamiltonian(k, omega, delta, epsilon):
H = np.array([[(k+2.0)**2.0 - delta, omega/2.0, 0.0],
[omega/2.0, k**2.0-epsilon,omega/2.0],
[0.0,omega/2.0,(k-2.0)**2.0 + delta]])
return H
def propagateHamiltonianTest(t, omega, delta, epsilon):
k = 0.0
psi0 = np.array([0+1j*0.0, 1.0+1j*0.0, 0.0+1j*0.0])
H = RamanHamiltonian(k, omega, delta ,epsilon)
Energy, V = LA.eig(H)
V = V + 1j*0.0
Vinv = np.conjugate(np.transpose(V))
U = np.diag(np.exp(-1j*np.array(Energy)*t))
a =np.dot(Vinv,psi0)
b = np.dot(U,a)
psi = np.dot(V,b)
pop0 = np.absolute(psi[0])**2.0
return pop0
popt, pcov = optimize.curve_fit(propagateHamiltonianTest,
np.array(tRecoils),
np.array(frac0),
p0=(3.0,0.05,0.03))
以下是tRecoils
和frac0
的值,两者都是24个数组:
tRecoils = array([ 2.88597836, 1.15439135, 1.73158702, 2.19334356, 0.23087827,
2.07790442, 0.11543913, 1.50070875, 2.77053923, 1.61614788,
1.03895221, 2.42422183, 0.92351308, 0.80807394, 0.3463174 ,
0.57719567, 2.6551001 , 0.46175654, 1.84702615, 1.38526961,
2.53966096, 0.69263481, 2.30878269, 1.96246529])
frac0 = array([ 0.15761062, 0.02044625, 0.17275937, 0.02236243, 0.07388558,
0.00967176, 0.01886309, 0.20412516, 0.21667489, 0.21783697,
0.00173812, 0.14038657, 0.03145599, 0.08644404, 0.13153078,
0.18794377, 0.2139092 , 0.17141201, 0.13021916, 0.12671806,
0.21090369, 0.1611094 , 0.08732627, 0.05764911])
我收到此错误:
U = np.diag(np.exp(-1j * np.array(Energy)* t))
ValueError:操作数无法与形状一起广播(3) (24)
因此,由于某些原因,curve_fit读取整个tRecoil
数组而不是按元素方式执行,我似乎无法通过更改输入格式来解决这个问题。
答案 0 :(得分:0)
我认为问题在于如何评估函数propagateHamiltonianTest
的模糊性。它既可以应用于t
的单个值(这是你如何考虑它),也可以应用于整个数组,在这种情况下,numpy将整个数组传递给参数{{1并试图进行矢量化。
事实上,当我在你的数组t
的单个元素上测试你的函数时,它可以工作,但是当你在整个数组上尝试它时,它会失败并出现相同的错误。所以这个问题与tRecoil[0]
无关。如果你可以让你的函数接受整个数组,并返回一个数组,那么它应该与curve_fit
一起工作。
要做到这一点,我必须使用curve_fit
使用一些hacky技巧。这允许我们创建更大的块对角矩阵,其基本上具有沿对角线的每个时间步长产生的每个3×3矩阵。
您的scipy.linalg.block_diag
功能的修改版本如下所示,并附有评论。我已经对它进行了测试,它应该有效。
propagateHamiltonianTest
输出:
from scipy.linalg import block_diag
def propagateHamiltonianTest(t, omega, delta, epsilon):
k = 0.0
psi0 = np.array([0+1j*0.0, 1.0+1j*0.0, 0.0+1j*0.0])
H = RamanHamiltonian(k, omega, delta ,epsilon)
Energy, V = LA.eig(H)
V = V + 1j*0.0
Vinv = np.conjugate(np.transpose(V))
# np.outer(t, Energy).flatten() creates a matrix for all t
U = np.diag(np.exp(-1j*np.outer(t, Energy).flatten()))
a = np.dot(Vinv, psi0)
# This repeats a so that the shape is consitent with U
aa = block_diag(*([a]*t.size))
# Have to add the transpose to make shapes match
b = np.dot(U, aa.T)
# Same block diagonal trick for eigenvector matrix
VV = block_diag(*([V]*t.size))
psi = np.dot(VV, b)
pop0 = np.absolute(psi)**2.0
# Since you want the first value, need to take every 3rd row
# and extract the values you want from the diagonal
return np.diag(pop0[::3])