Python minimum_scalar计算多项式最小值不正确

时间:2019-11-25 17:28:00

标签: python numpy scipy scipy-optimize scipy-optimize-minimize

我正在尝试使用minimum_scalar计算一维多项式的最小值和最大值。

多项式为x ^ {6} -2x ^ {5} -26x ^ {4} + 28x ^ {3} + 145x ^ {2} -26x-80

代码如下所示

import numpy as np
from scipy.optimize import *
ppar = np.array([1, -2, -26, 28, 145, -26, -80])
p = np.poly1d(ppar)
print p

maximum = minimize_scalar(-p, bounds=(-3.978, 3.068), method = 'bounded')
print "(-3.978, 3.068)", -maximum.fun
print maximum

minimum = minimize_scalar(p, bounds=(-3.978, 3.068), method = 'bounded')
print "(-3.978, 3.068)", minimum.fun
print minimum

结果是

   6     5      4      3       2
1 x - 2 x - 26 x + 28 x + 145 x - 26 x - 80
(-3.978, 3.068) 86.0883584933
  status: 0
    nfev: 12
 success: True
     fun: -86.0883584932823
       x: -1.5444720061831096
 message: 'Solution found.'
(-3.978, 3.068) -81.1476243092
  status: 0
    nfev: 11
 success: True
     fun: -81.147624309245643
       x: 0.08767224353999728
 message: 'Solution found.'

但是,一阶多项式的实解应该最大:x = 2.176时为264.155,x = -3.391时最小为-436.947

有人知道我的代码有什么问题吗?还是我错过了什么?

感谢任何帮助评论。

2 个答案:

答案 0 :(得分:1)

多项式在振荡,并且具有多个极值。您得到的只是不同的东西。请注意,本地最小化器找到了 a 个最小值,如果有多个,则报告其中一个。

对于多项式,最好使用专门的最小化器。例如,使用伴随矩阵方法区分并找到导数的根:

In [53]: coef = [-26, 2*145, 3*28, -4*26, -5*2]    # coefficients for the derivative

In [54]: coef = np.asarray(coef, dtype=float)

In [55]: coef /= 6  # make it monic

In [56]: coef
Out[56]: array([ -4.33333333,  48.33333333,  14.        , -17.33333333,  -1.66666667])

In [57]: a = np.diag(np.ones(4), -1)     # build the companion matrix

In [58]: a[:, -1] = -coef

伴随矩阵的特征值是导数的根(反之亦然),因此原始多项式的极值:

In [61]: np.linalg.eigvals(a)
Out[61]: array([-3.39056572, -1.54447197,  0.08767236,  2.17555358,  4.33847842])

In [62]: pp = np.poly1d([1, -2, -26, 28, 145, -26, -80])   # sanity check

In [63]: pp(np.linalg.eigvals(a))
Out[63]: 
array([-436.94699498,   86.08835849,  -81.14762431,  264.15457395,
       -794.0522912 ])

必须警告的一点是,最好避免大次数多项式,因为它们是不稳定的。

答案 1 :(得分:0)

简单的答案是使用scipy.optimize.minimize_scalar,您可以找到局部最小值。详细信息在@ev-br answer中。但是,可以使用global optimization方法在给定范围内找到函数的全局最小值。即使在这种情况下,您也应该准备好防止由于使用引擎盖下的局部最小化器而导致这些方法均会失败。在下一个示例中,您可以看到shgo优化器找不到全局最小值:

import numpy as np
from scipy import optimize

p = np.poly1d([1, -2, -26, 28, 145, -26, -80])

bounds = [(-3.978, 3.068)]

results = {}

results['shgo'] = optimize.shgo(p, bounds)    
results['DA'] = optimize.dual_annealing(p, bounds)    
results['DE'] = optimize.differential_evolution(p, bounds)

print(results['shgo']['x'], results['DA']['x'], results['DE']['x'])
[0.08767235] [-3.39056566] [-3.39056573]