我正在尝试将fsolve应用于数组:
from __future__ import division
from math import fsum
from numpy import *
from scipy.optimize import fsolve
from scipy.constants import pi
nu = 0.05
cn = [0]
cn.extend([pi*n - pi/4 for n in range(1, 5 +1)])
b = linspace(200, 600, 400)
a = fsolve(lambda a: 1/b + fsum([1/(b+cn[i]) for i in range(1, 5 +1)]) - nu*(sqrt(a) - 1)**2, 3)
默认情况下不允许:
TypeError: only length-1 arrays can be converted to Python scalars
有没有办法将fsolve应用于数组?
修改:
#!/usr/bin/env python
from __future__ import division
import numpy as np
from scipy.optimize import fsolve
nu = np.float64(0.05)
cn = np.pi * np.arange(6) - np.pi / 4.
cn[0] = 0.
b = np.linspace(200, 600, 400)
cn.shape = (6,1)
cn_grid = np.repeat(cn, b.size, axis=1)
K = np.sum(1/(b + cn_grid), axis=0)
f = lambda a: K - nu*(np.sqrt(a) - 1)**2
a0 = 3. * np.ones(K.shape)
a = fsolve(f, a0)
print a
解决它。
答案 0 :(得分:3)
fsum
适用于python标量,所以你应该看numpy进行矢量化。你的方法可能失败了,因为你试图总结一个包含五个numpy数组的列表,而不是五个数字或一个numpy数组。
首先,我将使用numpy重新计算cn
:
import numpy as np
cn = np.pi * np.arange(6) - np.pi / 4.
cn[0] = 0.
接下来,我将分别计算前一个fsum结果,因为它是一个常量向量。这是一种方式,尽管可能有更有效的方法:
cn.shape = (6,1)
cn_grid = np.repeat(cn, b.size, axis=1)
K = np.sum(1/(b + cn_grid), axis=0)
根据K
重新定义您的功能现在应该有效:
f = lambda a: K - nu*(np.sqrt(a) - 1)**2
要使用fsolve
查找解决方案,请为其提供适当的初始向量以进行迭代。这使用零向量:
a0 = np.zeros(K.shape)
a = fsolve(f, a0)
或者您可以使用a0 = 3
:
a0 = 3. * np.ones(K.shape)
a = fsolve(f, a0)
此功能是可逆的,因此您可以针对两个确切的解决方案检查f(a) = 0
:
a = (1 - np.sqrt(K/nu))**2
或
a = (1 + np.sqrt(K/nu))**2
fsolve
似乎是从a0 = 0
开始的第一个解决方案,而a0 = 3
的第二个解决方案。
答案 1 :(得分:1)
你可以定义一个最小化的函数(应该是原始函数的平方)然后使用一个简单的最小化器(你最好定义函数的导数):
funcOrig = lambda a: (K - nu*(np.sqrt(a) - 1)**2)
func2 = lambda a: funcOrig(a)**2
dotfunc2 = lambda a: 2*funcOrig(a)* (-nu * 2 * ( np.sqrt(a)-1) * 1./2./np.sqrt(a))
ret = scipy.optimize.fmin_l_bfgs_b(func2, np.ones(400)+1, fprime=dotfunc2, pgtol=1e-20)