scipy.optimize.linprog 似乎解决了任务,但 return x 不是吗?

scipy.optimize.linprog seems to solve the task but doesn't return the x?

我正在尝试使用 scipy.optimize.linprog 求解一个非常简单的线性程序,看起来该函数可以执行我希望它执行的操作,但不知何故它没有 return 'x'(它 return 正确的最小函数值)

仅举一个简单的例子(用 matlab 表示法),我有一个二维 a=[a1; a2] 和简单的线性约束 [1, 2] * a = 1,并希望最小化 a 的 L1 范数。最优应该是 a=[0, 0.5].

据我所知,我可以通过使用一个额外的变量 s 以标准形式制定这个,例如 b>=abs(a)(即 a-b<=0 和 -a-b<=0)并最小化总和(b) 受制于这些约束和原来的等式约束 [1, 2] * a = 1.

所以我定义x=[a; b],插入scipy的linprog,return成功,得到正确答案:sum(b)的最优值为0.5。但是,它 returns 的 x 充满了 nan 而不是 [0; 0.5; 0; 0.5]

代码如下:

A = np.array([1,2]).reshape([1,2])
b_eq = np.array([1])
ones = np.ones([2,])
zeros = np.zeros([2,])
zerosm = np.zeros([1, 2])
eye = np.eye(2)
c = np.hstack([zeros, ones])
A_ub = np.vstack([np.hstack([eye, -eye]), np.hstack([-eye, -eye])])
b_ub = np.hstack([zeros, zeros])
A_eq = np.hstack([A, zerosm])
res = scipy.optimize.linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=(None, None),
                             A_eq=A_eq, b_eq=b_eq)

结果:

success: True
 status: 0
    fun: 0.5
      x: array([ nan,  nan,  nan,  nan])
    nit: 3
  slack: array([ 0.,  0.,  0.,  1.])
message: 'Optimization terminated successfully.'

即x 是 nan 而不是解决方案。函数值是正确的 (0.5),而且松弛度看起来很好——根据 scipy 文档,松弛度为 0 表示约束处于活动状态,因此第一个和第三个零表示 a1=b1=0,第二个零表示 a2=b2 并且它们不为零(否则第 4 个松弛也将为 0)。这再次符合预期,因为 [0, 0.5] 是解决方案。

我做错了什么?这是一个错误吗? (使用 scipy 0.15.1)

谢谢!

很明显,您运行遇到了一个自 0.15.1 版以来已修复的错误。

当我 运行 你的代码使用 scipy 0.18.0 时,我得到:

In [3]: import scipy.optimize

In [4]: %paste
A = np.array([1,2]).reshape([1,2])
b_eq = np.array([1])
ones = np.ones([2,])
zeros = np.zeros([2,])
zerosm = np.zeros([1, 2])
eye = np.eye(2)
c = np.hstack([zeros, ones])
A_ub = np.vstack([np.hstack([eye, -eye]), np.hstack([-eye, -eye])])
b_ub = np.hstack([zeros, zeros])
A_eq = np.hstack([A, zerosm])
res = scipy.optimize.linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=(None, None),
                             A_eq=A_eq, b_eq=b_eq)

## -- End pasted text --

In [5]: res
Out[5]: 
     fun: 0.5
 message: 'Optimization terminated successfully.'
     nit: 4
   slack: array([ 0.,  0.,  0.,  1.])
  status: 0
 success: True
       x: array([ 0. ,  0.5,  0. ,  0.5])

我尝试用 scipy 1.3.1 解决你的问题,效果很好:

con: array([  7.07545134e-12])
     fun: 0.49999999999882094
 message: 'Optimization terminated successfully.'
     nit: 4
   slack: array([  1.07107656e-11,  -4.48552306e-12,  -4.75552930e-12,
         1.00000000e+00])
  status: 0
 success: True
       x: array([ -7.73314746e-12,   5.00000000e-01,   2.97761815e-12,
         5.00000000e-01])