question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

A numerical bug in scipy.optimize.linprog

See original GitHub issue

Hi. I appreciate for contributors to scipy and extended communities. I learned the history of scipy on wikipedia and confirmed why this library is one of the highest quality OSS. But unfortunately, I found apparently a bug in scipy.optimize.linprog. As I run the following test.py, the LP solver incorrectly reports that LP is infeasible.

Reproducing code example:

#test.py
import codecs
from scipy.optimize import linprog
import numpy as np

c=[0,0,0,0,0,0,0,0,0]
ref = np.array([0.917113,0.270876,-0.395955,-0.196867,0.404834,1])
matA = np.array([
[0.656013,-0.365063,-0.983576,1.11294,0.579682,1],
[0.799693,0.50039,-1.32221,0.327986,0.694136,1],
[1.54842,-0.321544,-1.81128,0.949596,0.634807,1],
[1.12977,-0.271752,-1.74754,1.24775,0.641763,1],
[1.05679,0.506714,-0.583986,-0.627243,0.647723,1],
[1,0,0,0,0,1],
[0,1,0,0,0,1],
[0,0,0,1,0,1],
[0,0,0,0,1,1]
])
matA_in=matA.T.tolist()
vecb_in=ref.tolist()
xrange = [
[0,1],[0,1],[0,1],[0,1],[0,1],[0,1],[0,1],[0,1],[0,1]
]
res = linprog(c, A_eq=matA_in, b_eq=vecb_in,bounds=xrange, method='interior-point')
logfile=codecs.open('pyout.log','w','utf-8')
print(res, file=logfile)
if res.status == 2:
    print("0UNSAT",file=codecs.open('check_result.log','w','utf-8'))
else:
    print("1SAT",file=codecs.open('check_result.log','w','utf-8'))

# But the answer is SAT and
ans_x=np.array([0.04934082, 0, 0, 0.00702774, 0.57388938, 0.2703235, 0, 0.09941856, 0])
# and an evidence of correctness is that 
residual = np.dot(matA_in, ans_x)-ref
print("residual = ",file=logfile)
print(residual,file=logfile)
# we get residual = [-9.9293934e-07 -5.2687482e-07, -6.6600600e-08, -3.0158354e-07, -5.2039340e-07,  0.0000000e+00] 
#test.py end 

Error message:

scipy.optimize.linprog reports the following UNSAT decision.

con: array([-1.69741633, -0.25037501,  1.94817659, -1.35441056, -1.22095061,
       -2.57498303])

scipy.optimize.linprog reports the following UNSAT decision.      fun: 0.0
 message: 'The algorithm terminated successfully and determined that the problem is infeasible.'
     nit: 5
   slack: array([], dtype=float64)
  status: 2
 success: False
       x: array([0.70514251, 0.10725385, 0.53002431, 0.11401373, 0.59845995,
       0.4842205 , 0.62316526, 0.0673947 , 0.34530822]) 

Scipy/Numpy/Python version information:

Here is a version info. Perhaps little bit old?

>> import sys, scipy, numpy; print(scipy.__version__, numpy.__version__, sys.version_info)
1.2.1 1.17.4 sys.version_info(major=3, minor=7, micro=7, releaselevel='final', serial=0)

Can you reproduce this? I don’t have much time to look into the implementation of this library, but I can generate “MANY” similar class of incorrect reports having the same property orz.

A special property of ref and matA is that all row vectors satisfies the following constraint; [1,1,1,1,1,-1].ref=0 [1,1,1,1,1,-1].matA[i]=0, for any i, 0<=i<9

Here ref and matA[i] are on the same hyper-plane which share the same normal vector [1,1,1,1,1,-1]. So my initial guess is that the bug might result from inadequately solving a matrix equation. If a constraint matrix matA is rank-deficient. A matrix inversion could break a solution to Given_matrix*vecX=Given_vecB. In Eigen3 which I use, there are three QR decompositions with such rank-deficiency in mind. eigen.tuxfamily.org/dox/classEigen_1_1FullPivHouseholderQR.html eigen.tuxfamily.org/dox/classEigen_1_1ColPivHouseholderQR.html eigen.tuxfamily.org/dox/classEigen_1_1HouseholderQR.html

IPOPT also fails to figure out a SATsifiable assignment and instead converge incorrectly in a similar setting. But it happens less frequently than scipy.optimize.linprog showed. Another guess is that it counld result from a difficulty of solving an LP using the current floating point arithmetic IEEE754-FP that causes a rounding-error. A similar technical issue might be in scipy.optimize.linprog/interior-point. But not for sure.

Best regards, Masataka Nishi

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:26 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
mdhabercommented, Nov 18, 2020

Thanks. Sorry the existing linprog didn’t work out for you. I know you switched to C++, but in case you prefer Python, HiGHS will be available through the linprog interface in the next release of SciPy.

1reaction
mn-on-githubcommented, Nov 18, 2020

I switched to HiGHS-1.0 (C++ API) and it does not fail in the cases that I reported above. Now the matA grows up >5 rows*800 columns. Excellent! (though nobody know if I could report a bug next month…) I appreciate for @mdhaber, @pv @jajhall and @mckib2 for these fast, sincere and interactive debugging.

Read more comments on GitHub >

github_iconTop Results From Across the Web

scipy.optimize.linprog — SciPy v1.9.3 Manual
Guess values of the decision variables, which will be refined by the optimization algorithm. This argument is currently used only by the 'revised...
Read more >
Some questions about scipy.optimize.linprog - Stack Overflow
I have a linear programming problem with one equality constraint, so A_eq in my case has just one row and B_eq is a...
Read more >
How To Use Python Scipy Linprog
Through this tutorial, we'll learn about “Python Scipy Linprog” and how to maximize or minimize a numerical value as an objective, ...
Read more >
SciPy 0.15.0 Release Notes — SciPy v1.0.0 Reference Guide
The new function scipy.optimize.linprog provides a generic linear programming similar to the way scipy.optimize.minimize provides a generic ...
Read more >
MATLAB linprog - Solve linear programming problems
x = linprog( f , A , b , Aeq , beq , lb , ub , options ) minimizes with the optimization...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found