Python scipy.optimize使用fsolve

时间:2018-01-24 18:22:28

标签: python scipy

我试图通过python找到19个引文和19个未知变量的解决方案,如下所示:

import numpy as np
from scipy.optimize import fsolve

def f(x) :
    y = np.zeros(np.size(x))
    y[0] = -29.79 + 1.795*x[1] + 6.33*x[0] + -0.305*x[3] - 0.024*x[1]*x[3] + 0.222*x[0]*x[3] -2.063*x[4] + 0.122*x[1]*x[4] + 0.864*x[0]*x[4] + x[5] - x[6]
    y[1] = -23.269 + 1.795*x[0] + 4.547*x[2] - 0.342*x[1] - 0.024*x[0]*x[3] + 0.072*x[2]*x[3] - 0.052*x[1]*x[3] - 1.545*x[4] + 0.122*x[0]*x[4] + 0.367*x[2]*x[4] + 0.114*x[1]*x[4] + x[7] - x[8]
    y[2] = 0.587 + 4.547*x[1] + 0.046*x[3] + 0.072*x[1]*x[3] - 0.211*x[4] + 0.367*x[1]*x[4] + x[9] - x[10]
    y[3] = -1.657 - 0.305*x[0] - 0.230*x[1] + 0.046*x[2] - 0.024*x[0]*x[1] + 0.072*x[1]*x[2] + 0.111*x[0]**2.0 - 0.026*x[1]**2.0 + 0.78981 + x[11]**2.0
    y[4] = -0.106 - 2.063*x[0] - 1.545*x[1] - 0.211*x[2] + 0.122*x[0]*x[1] + 0.367*x[1]*x[2] + 0.432*x[0]**2.0 + 0.057*x[1]**2.0 + 1.34744 + x[12]**2.0
    y[5] = x[0] - 0.3 + x[13]**2.0
    y[6] = -x[0] + 0.1 + x[14]**2.0
    y[7] = x[1] - 80 + x[15]**2.0
    y[8] = -x[1] + 30 + x[16]**2.0
    y[9] = x[2] - 230 + x[17]**2.0
    y[10] = -x[2] + 200 + x[18]**2.0
    y[11] = 2*x[3]*x[11]
    y[12] = 2*x[4]*x[12]
    y[13] = 2*x[5]*x[13]
    y[14] = 2*x[6]*x[14]
    y[15] = 2*x[7]*x[15]
    y[16] = 2*x[8]*x[16]
    y[17] = 2*x[9]*x[17]
    y[18] = 2*x[10]*x[18]
    return y

x0 = np.array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])
x =fsolve(f, x0)

print ("x     = ", x)
print ("f(x)     = ", f(x))

我收到了以下结果:

C:\ProgramData\Anaconda3\lib\site-packages\scipy\optimize\minpack.py:161: RuntimeWarning: The iteration is not making good progress, as measured by the 
  improvement from the last five Jacobian evaluations.
  warnings.warn(msg, RuntimeWarning)
x     =  [  9.76123765e-01   5.63951267e-01   1.35631697e+02  -1.60706299e+00
  -1.22811614e+01  -1.75589904e+01  -2.57132821e+01   1.89445174e-02
  -2.20966436e+01  -6.49294303e-03   2.75617457e-01   3.02518539e-01
   2.28775428e-09   9.62647461e-07  -9.50310077e-03   8.91207176e+00
  -7.72046425e-02   1.00080922e+01   5.53841384e-02]
f(x)     =  [ -1.47404306e-01   6.91920501e+00   2.77948881e+00   1.06274971e+01
  -1.69328330e+00   6.76123765e-01  -8.76033456e-01  -1.10256977e-02
   2.94420093e+01   5.79360754e+00   6.43713702e+01  -9.72332696e-01
  -5.61925591e-08  -3.38062351e-05   4.88711821e-01   3.37669797e-01
   3.41192694e+00  -1.29963945e-01   3.05296708e-02]

你能帮我修一下这个错误吗?

1 个答案:

答案 0 :(得分:0)

你的问题看起来是非凸的,这会造成麻烦!

可以找到关于此任务的许多有价值的评论in this answer

非凸优化中的一个常见想法是从多个初始点求解。这实际上改变了这里的事情,但结果仍然有点远离零!

多启动fsolve的示例

import numpy as np
from scipy.optimize import fsolve, minimize
np.set_printoptions(suppress=True)

def f(x) :
    y = np.zeros(np.size(x))
    y[0] = -29.79 + 1.795*x[1] + 6.33*x[0] + -0.305*x[3] - 0.024*x[1]*x[3] + 0.222*x[0]*x[3] -2.063*x[4] + 0.122*x[1]*x[4] + 0.864*x[0]*x[4] + x[5] - x[6]
    y[1] = -23.269 + 1.795*x[0] + 4.547*x[2] - 0.342*x[1] - 0.024*x[0]*x[3] + 0.072*x[2]*x[3] - 0.052*x[1]*x[3] - 1.545*x[4] + 0.122*x[0]*x[4] + 0.367*x[2]*x[4] + 0.114*x[1]*x[4] + x[7] - x[8]
    y[2] = 0.587 + 4.547*x[1] + 0.046*x[3] + 0.072*x[1]*x[3] - 0.211*x[4] + 0.367*x[1]*x[4] + x[9] - x[10]
    y[3] = -1.657 - 0.305*x[0] - 0.230*x[1] + 0.046*x[2] - 0.024*x[0]*x[1] + 0.072*x[1]*x[2] + 0.111*x[0]**2.0 - 0.026*x[1]**2.0 + 0.78981 + x[11]**2.0
    y[4] = -0.106 - 2.063*x[0] - 1.545*x[1] - 0.211*x[2] + 0.122*x[0]*x[1] + 0.367*x[1]*x[2] + 0.432*x[0]**2.0 + 0.057*x[1]**2.0 + 1.34744 + x[12]**2.0
    y[5] = x[0] - 0.3 + x[13]**2.0
    y[6] = -x[0] + 0.1 + x[14]**2.0
    y[7] = x[1] - 80 + x[15]**2.0
    y[8] = -x[1] + 30 + x[16]**2.0
    y[9] = x[2] - 230 + x[17]**2.0
    y[10] = -x[2] + 200 + x[18]**2.0
    y[11] = 2*x[3]*x[11]
    y[12] = 2*x[4]*x[12]
    y[13] = 2*x[5]*x[13]
    y[14] = 2*x[6]*x[14]
    y[15] = 2*x[7]*x[15]
    y[16] = 2*x[8]*x[16]
    y[17] = 2*x[9]*x[17]
    y[18] = 2*x[10]*x[18]
    return y

x0 = np.array([1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0])
x =fsolve(f, x0)

print('fsolve')
print ("x:")
print(x)
print ("|x|_2:")
print(np.linalg.norm(x))

""" Try more starting-points fsolve """
N = 1000
best_obj = np.inf
best_x = 0
for i in range(N):
    x0 = np.random.uniform(size=x0.shape)
    x = fsolve(f, x0)
    fun = np.linalg.norm(x)
    if fun < best_obj:
        best_obj = fun
        best_x = x

print('-----')
print('multi-start fsolve')
print('x: ')
print(best_x)
print('|x|_2:')
print(np.linalg.norm(best_x))

输出

C:\Miniconda3\lib\site-packages\scipy\optimize\minpack.py:161: RuntimeWarning: The iteration is not making good progress, as measured by the
  improvement from the last five Jacobian evaluations.
  warnings.warn(msg, RuntimeWarning)
fsolve
x:
[   0.97612376    0.56395127  135.63169724   -1.60706299  -12.28116138
  -17.55899044  -25.71328208    0.01894452  -22.09664359   -0.00649294
    0.27561746    0.30251854    0.            0.00000096   -0.0095031
    8.91207176   -0.07720464   10.00809224    0.05538414]
|x|_2:
142.085025055
C:\Miniconda3\lib\site-packages\scipy\optimize\minpack.py:161: RuntimeWarning: The iteration is not making good progress, as measured by the
  improvement from the last ten iterations.
  warnings.warn(msg, RuntimeWarning)
-----
multi-start fsolve
x:
[ 0.35428349  0.2476696   0.18428096  0.13483107  0.83282782  0.75846428
  0.15784569  0.19073984  0.72388253  0.45229748  0.21294132  0.52558176
  0.11637452  0.21832279  0.44927192  0.06217237  0.04219192  0.07791865
  0.07722962]
|x|_2:
1.70295527001

这个问题可以写成QP。在这种情况下,目标的格式为c.T * x + 0.5 * x.T * Q * x

如果Q是正半定的,则它可以在多项式时间内找到凸QP和全局最小值(最小化透视:l2-范数(x))。不确定的情况是伤害的。

也许还有更专业的无限期QP解算器。但问题本身通常是NP难的(如果是非凸的)!