Python fsolve fprime的形状是错误的吗?

时间:2017-10-30 04:25:49

标签: python scipy

以下内容可能不会简单得多,但我找不到如何使其发挥作用......

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被解释为对单个根的估计。

2 个答案:

答案 0 :(得分:1)

我怀疑你期望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的数组{{1} }参数并返回一个长度为2的序列。它还希望x接受一个长度为2的数组并返回一个形状为2x2的数组(雅可比矩阵)。

答案 1 :(得分:0)

感谢大家解释了为什么我得到的行为。实际上没有人告诉我如何解决这个问题,所以我写这个答案是因为我弄明白了。

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

文档说:

  

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

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

  

给出起始估计值,返回由func(x)= 0定义的(非线性)等式的根。

这可以做出明显的事情。为了找到方程的多个根,我们可以让scipy(一如既往)将a(x)解释为n变量的函数,其中nx的长度。要找到多个根,请a进行矢量化,即

a([x1, x2, ..., xn]) = [a(x1), a(x2), ..., a(xn)]

此函数的雅可比是对角矩阵

diag([ap(x1), ap(x2), ..., ap(xn)])

因此我的问题的答案是

更改

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]

或者只是在初始猜测时循环[0.3, 0.7]调用fsolve一次。