1

我正在尝试将 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

解决它。

4

2 回答 2

3

fsum适用于 python 标量,因此您应该使用 numpy 进行矢量化。您的方法可能失败了,因为您试图对五个 numpy 数组的列表求和,而不是五个数字或单个 numpy 数组。

首先,我会cn使用 numpy 重新计算:

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.

于 2012-05-31T08:48:30.947 回答
1

您可以定义 aa 函数来最小化(它应该是原始函数的平方),然后使用简单的最小化器(最好还定义函数的导数):

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)      
于 2012-05-31T11:49:26.120 回答