问题
Am I doing something wrong or it is a bug?
c = np.array([-1., 0., 0., 0., 0., 0., 0., 0., 0.])
A_ub = np.array([[ 1., -724., 911., -551., -555., -896., 478., -80., -293.],
[ 1., 566., 42., 937., 233., 883., 392., -909., 57.],
[ 1., -208., -894., 539., 321., 532., -924., 942., 55.],
[ 1., 857., -859., 83., 462., -265., -971., 826., 482.],
[ 1., 314., -424., 245., -424., 194., -443., -104., -429.],
[ 1., 540., 679., 361., 149., -827., 876., 633., 302.],
[ 0., -1., -0., -0., -0., -0., -0., -0., -0.],
[ 0., -0., -1., -0., -0., -0., -0., -0., -0.],
[ 0., -0., -0., -1., -0., -0., -0., -0., -0.],
[ 0., -0., -0., -0., -1., -0., -0., -0., -0.],
[ 0., -0., -0., -0., -0., -1., -0., -0., -0.],
[ 0., -0., -0., -0., -0., -0., -1., -0., -0.],
[ 0., -0., -0., -0., -0., -0., -0., -1., -0.],
[ 0., -0., -0., -0., -0., -0., -0., -0., -1.],
[ 0., 1., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 1., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 1., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 1., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
b_ub = np.array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 1., 1., 1., 1., 1., 1., 1., 1.])
A_eq = np.array([[ 0., 1., 1., 1., 1., 1., 1., 1., 1.]])
b_eq = np.array([[ 1.]])
bounds = [(None, None), (None, None), (None, None), (None, None), (None, None),
(None, None), (None, None), (None, None), (None, None)]
soln = scipy.optimize.linprog(c, A_ub, b_ub, A_eq, b_eq, bounds)
print(soln)
print(A_ub.dot(soln['x']) <= b_ub)
print(A_ub.dot(soln['x']) - b_ub)
print(abs(A_eq.dot(soln['x']) - b_eq))](url)
outputs
fun: 39.866871820032244
message: 'Optimization terminated successfully.'
nit: 19
slack: array([ 0. , 0. , 0. , 0. , 365.161, 0. ,
0. , 0. , 0. , 0. , 0.167, 0.61 ,
0.115, 0.518, 1. , 1. , 1. , 1. ,
0.833, 0.39 , 0.885, 0.482])
status: 0
success: True
x: array([-39.812, -0.281, -0.625, 0. , -0.031, -0.125, 0.625,
0.312, 0.406])
[ True True False False True False False False True False False True
True True True True True True True True True True]
[-121.5 -358.812 240.125 121.781 -357.781 350.656 0.281 0.625
0. 0.031 0.125 -0.625 -0.312 -0.406 -1.281 -1.625
-1. -1.031 -1.125 -0.375 -0.688 -0.594]
[[ 0.719]]
From middle part of A_ub
that must be clear that solution must satisfy soln['x'][1:] > 0
, however, it is clearly not satisfied!
Am I doing something wrong?
Python 3.6 scipy==0.18.1
回答1:
Yes, it looks like a bug. I usually recommend people to use alternatives to scipy's linprog because:
- bad robustness
- bad performance (especially on big sparse problems)
- does not seem to be maintained anymore; not much progress despite open issues
There is currently an interior-point-based solver in development for scipy, which solves this problem correctly. Of course you can also use the much better alternatives available (e.g. through cvxpy).
Here is some code, which shows, that cvxpy's default solver (for these kind of problems; ECOS can solve a much broader class of problems!) ECOS and the not yet incorporated IPM-solver solve it, while linprog-simplex struggles. Keep in mind, that the code will not run on vanilla-scipy as method='interior-point'
is missing:
import numpy as np
from scipy.optimize import linprog
c = np.array([-1., 0., 0., 0., 0., 0., 0., 0., 0.])
A_ub = np.array([[ 1., -724., 911., -551., -555., -896., 478., -80., -293.],
[ 1., 566., 42., 937., 233., 883., 392., -909., 57.],
[ 1., -208., -894., 539., 321., 532., -924., 942., 55.],
[ 1., 857., -859., 83., 462., -265., -971., 826., 482.],
[ 1., 314., -424., 245., -424., 194., -443., -104., -429.],
[ 1., 540., 679., 361., 149., -827., 876., 633., 302.],
[ 0., -1., -0., -0., -0., -0., -0., -0., -0.],
[ 0., -0., -1., -0., -0., -0., -0., -0., -0.],
[ 0., -0., -0., -1., -0., -0., -0., -0., -0.],
[ 0., -0., -0., -0., -1., -0., -0., -0., -0.],
[ 0., -0., -0., -0., -0., -1., -0., -0., -0.],
[ 0., -0., -0., -0., -0., -0., -1., -0., -0.],
[ 0., -0., -0., -0., -0., -0., -0., -1., -0.],
[ 0., -0., -0., -0., -0., -0., -0., -0., -1.],
[ 0., 1., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 1., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 1., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 1., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 1.]])
b_ub = np.array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
0., 0., 1., 1., 1., 1., 1., 1., 1., 1.])
A_eq = np.array([[ 0., 1., 1., 1., 1., 1., 1., 1., 1.]])
b_eq = np.array([[ 1.]])
bounds = [(None, None), (None, None), (None, None), (None, None), (None, None),
(None, None), (None, None), (None, None), (None, None)]
soln = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds, method='simplex')
print('linprog: ', soln)
soln = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds, method='interior-point')
print('linprog IPM: ', soln)
from cvxpy import *
x = Variable(A_eq.shape[1])
constraints = []
constraints.append(A_ub*x <= b_ub)
constraints.append(A_eq*x == b_eq)
objective = Minimize(c*x)
problem = Problem(objective, constraints)
problem.solve(verbose=True)
print(np.round(x.value, 2))
print(problem.value)
Output:
linprog: fun: 39.866871820032244
message: 'Optimization terminated successfully.'
nit: 19
slack: array([ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 3.65161351e+02, 0.00000000e+00,
0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 1.66922982e-01, 6.10104031e-01,
1.14953670e-01, 5.18298274e-01, 1.00000000e+00,
1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
8.33077018e-01, 3.89895969e-01, 8.85046330e-01,
4.81701726e-01])
status: 0
success: True
x: array([ -3.98125000e+01, -2.81250000e-01, -6.25000000e-01,
0.00000000e+00, -3.12500000e-02, -1.25000000e-01,
6.25000000e-01, 3.12500000e-01, 4.06250000e-01])
linprog IPM: con: array([ -3.93646007e-08])
fun: 108.56853369114262
message: 'Optimization terminated successfully.'
nit: 9
slack: array([ 1.23442489e+02, -1.13909794e-05, -7.46066462e-07,
3.12539380e+02, 2.20799190e+02, -1.41898576e-05,
2.48742446e-09, 3.71114180e-01, 1.07937459e-09,
1.33093066e-08, 3.70892271e-01, 2.03637625e-09,
2.57993546e-01, 2.36290348e-08, 9.99999998e-01,
6.28885820e-01, 9.99999999e-01, 9.99999987e-01,
6.29107729e-01, 9.99999998e-01, 7.42006454e-01,
9.99999976e-01])
status: 0
success: True
x: array([ -1.08568534e+02, 2.48742446e-09, 3.71114180e-01,
1.07937459e-09, 1.33093066e-08, 3.70892271e-01,
2.03637625e-09, 2.57993546e-01, 2.36290348e-08])
ECOS 2.0.4 - (C) embotech GmbH, Zurich Switzerland, 2012-15. Web: www.embotech.com/ECOS
It pcost dcost gap pres dres k/t mu step sigma IR | BT
0 +2.934e+01 -6.533e+02 +2e+03 3e-01 5e-01 1e+00 8e+01 --- --- 1 1 - | - -
1 +9.527e+01 -1.952e+02 +9e+02 1e-01 2e-01 8e+00 4e+01 0.6128 2e-01 1 1 1 | 0 0
2 +9.281e+01 -1.256e+01 +3e+02 4e-02 6e-02 5e+00 1e+01 0.6888 1e-01 1 1 1 | 0 0
3 +1.004e+02 +6.363e+01 +1e+02 2e-02 2e-02 2e+00 5e+00 0.7367 1e-01 1 1 1 | 0 0
4 +1.075e+02 +9.684e+01 +3e+01 5e-03 6e-03 9e-01 1e+00 0.8307 1e-01 1 1 1 | 0 0
5 +1.086e+02 +1.084e+02 +4e-01 6e-05 7e-05 1e-02 2e-02 0.9872 1e-04 1 1 1 | 0 0
6 +1.086e+02 +1.086e+02 +5e-03 7e-07 8e-07 1e-04 2e-04 0.9890 1e-04 1 1 1 | 0 0
7 +1.086e+02 +1.086e+02 +5e-05 8e-09 9e-09 1e-06 2e-06 0.9890 1e-04 1 0 0 | 0 0
8 +1.086e+02 +1.086e+02 +6e-07 8e-11 1e-10 2e-08 3e-08 0.9890 1e-04 1 0 0 | 0 0
OPTIMAL (within feastol=9.6e-11, reltol=5.2e-09, abstol=5.6e-07).
Runtime: 0.000424 seconds.
[[-108.57]
[ -0. ]
[ 0.37]
[ -0. ]
[ 0. ]
[ 0.37]
[ -0. ]
[ 0.26]
[ 0. ]]
108.56853545568384
来源:https://stackoverflow.com/questions/43106053/why-does-scipy-optimize-linprog-return-a-solution-that-does-not-satisfy-constrai