Python的fprime的fsolve形状是错误的



以下内容再简单不过了,但我找不到如何使其工作。。。

from scipy.optimize import fsolve
def a(x):
return x*x-x
def ap(x):
return 2*x-1
#works
print(fsolve(a, 0.3))
#works
print(fsolve(a, 0.3, fprime=ap))
#works
print(fsolve(a, [0.3], fprime=ap))
#works
print(fsolve(a, [0.3, 0.7]))
#crashes
print(fsolve(a, [0.3, 0.7], fprime=ap))

当它崩溃时给出错误

TypeError: fsolve: there is a mismatch between the input and output shape of the 'fprime' argument 'ap'.Shape should be (2, 2) but it is (2,).

ap的输出维度似乎肯定应该与输入维度相同。这怎么可能出错(我该如何解决)?

我认为一些悲观的选民错过了这个问题的微妙之处,所以这里有一个更深入的解释来解释我为什么感到困惑:

似乎scipy将a解释为一个变量的函数,[0.3,0.7]fsolve(a, [0.3, 0.7])中开始估计两个根,但在fsolve(a, [0.3, 0.7], fprime=ap)中,它将a解释为两个变量的功能,[.3,.7]是单个根的估计。根据文件(https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fsolve.html),第二个自变量

x0 : ndarray
The starting estimate for the roots of func(x) = 0.

表示它正在寻找根的估计值(复数)。但它在给定fprime的情况下的行为使其听起来像x0被解释为对单个根的估计。

我怀疑您期望fsolve(a, [0.3, 0.7], fprime=ap)返回标量问题的两个解决方案。fsolve不是这样工作的。

当调用fsolve(a, x0, fprime=ap)时,fsolve函数从x0的形状推断出问题的维度。如果x0是标量,则它期望a接受标量,而fprime必须接受标量并返回标量(或1x1数组)。如果x0是一个长度为2的序列(在您的示例中不起作用),fsolve希望a接受一个长度2的数组作为其x参数,并返回一个长度是2的序列。它还期望fprime接受长度为2的数组,并返回形状为2x2的数组(雅可比矩阵)。

感谢所有解释我为什么会有这样的行为的人。但实际上没有人告诉我如何解决这个问题,所以我在找到答案后就写下了这个答案。

这种混乱源于这样一个事实,即scipy文档介于错误和误导之间。

文件上写着:

在给定起始估计的情况下,返回由func(x)=0定义的(非线性)方程的根。

这表明对于标量函数,它可能返回一个根数组。实际行为更接近

返回给定起始估计的func(x)=0定义的(非线性)方程的根。

这样做会让事情变得显而易见。为了找到方程的多个根,我们可以让scipy(一如既往)将a(x)解释为n变量的函数,其中nx的长度。为了找到多个根,让a被矢量化,即

CCD_ 28。

这个函数的雅可比是一个对角矩阵

CCD_ 29。

因此我的问题的答案是

更改

print(fsolve(a, [0.3, 0.7], fprime=ap))

print(fsolve(a, [0.3, 0.7], fprime=lambda x: np.diag(ap(x))))
# correctly outputs
# [ -3.69321143e-16   1.00000000e+00]

或者简单地在CCD_ 30上循环,每次初始猜测调用CCD_。

最新更新