Repository: scipy/scipy

Issue:
linprog with method=interior-point produced incorrect answer for a simple input
optimize.linprog with method='interior-point' produces wrong answer for a following program:

```
minimize  x + 5y
subject to
-7y <= -6
x >= 0
```


### Reproducing code example:
```
import scipy.optimize
c = [1, 5]
A = [[0, -7]]
b = [-6]
bounds = [(0, None), (None, None)]
res1 = scipy.optimize.linprog(c, A, b, bounds=bounds)
res2 = scipy.optimize.linprog(c, A, b, bounds=bounds, method='interior-point')
print res1
print
print res2
assert not (res1.success and res2.success) or abs(res1.fun - res2.fun) < 1
```

### Output:
```
     fun: 4.2857142857142856
 message: 'Optimization terminated successfully.'
     nit: 1
   slack: array([ 0.])
  status: 0
 success: True
       x: array([ 0.        ,  0.85714286])

     con: array([], dtype=float64)
     fun: 0.0
 message: 'The solution was determined in presolve as there are no non-trivial constraints.'
     nit: 0
   slack: array([-6.])
  status: 0
 success: True
       x: array([ 0.,  0.])
Traceback (most recent call last):
  File "buglinprog.py", line 37, in <module>
    assert not (res1.success and res2.success) or abs(res1.fun - res2.fun) < 1
AssertionError

```

### Scipy/Numpy/Python version information:
```
('1.0.1', '1.8.2', sys.version_info(major=2, minor=7, micro=6, releaselevel='final', serial=0))
```




Discussion:
I'll look into it.
In the meantime, use `options = {"presolve":False}`
It's a problem with the presolve routine. I get an error, actually.
Thanks!
Please don't lose faith in `linprog` because of these issues : ) 
There are several instances of bugs in `simplex` similar to the one you reported in #8662, so I'd typically recommend `interior-point`.

But the problem seems too simple for `interior-point`'s own good. It tries to apply simple rules successively to simplify a problem like this, but this problem seems to expose a mistake in these rules. For example, the presolve routine should see that `x` is not involved in the inequality constraint, so it will determine the value of x that minimizes `x` in the objective subject only to the bound constraint ( `x = 0` ), then remove `x` from the problem entirely. It should then recognize that the inequality constraint on `y` can be turned into a simple bound, and then the value of `y` can be chosen to minimize `5y` in the objective (`y = 6/7`). Anyway, these rules can be trickier to get perfect than the main routine, which is just a bunch of linear algebra operations. Sorry for the trouble but thanks for exposing this.
Thanks for the detailed reply! It is really nice that you react to issues so fast. I'm just playing with LP and have detected some abnormalities. I hope my reports are useful and will help you make scipy a little better :)

Resolving patch:
diff --git a/scipy/optimize/_linprog_ip.py b/scipy/optimize/_linprog_ip.py
--- a/scipy/optimize/_linprog_ip.py
+++ b/scipy/optimize/_linprog_ip.py
@@ -558,6 +558,8 @@ def where(A):
             return (c, c0, A_ub, b_ub, A_eq, b_eq, bounds,
                     x, undo, complete, status, message)
 
+    ub_mod = ub
+    lb_mod = lb
     if np.any(i_f):
         c0 += c[i_f].dot(lb[i_f])
         b_eq = b_eq - A_eq[:, i_f].dot(lb[i_f])
@@ -569,6 +571,9 @@ def where(A):
         # record of variables to be added back in
         undo = [np.where(i_f)[0], lb[i_f]]
         # don't remove these entries from bounds; they'll be used later.
+        # but we _also_ need a version of the bounds with these removed
+        lb_mod = lb[i_nf]
+        ub_mod = ub[i_nf]
 
     # no constraints indicates that problem is trivial
     if A_eq.size == 0 and A_ub.size == 0:
@@ -593,8 +598,8 @@ def where(A):
             message = ("The solution was determined in presolve as there are "
                        "no non-trivial constraints.")
         complete = True
-        x[c < 0] = ub[c < 0]
-        x[c > 0] = lb[c > 0]
+        x[c < 0] = ub_mod[c < 0]
+        x[c > 0] = lb_mod[c > 0]
         # if this is not the last step of presolve, should convert bounds back
         # to array and return here
 


Test patch:
diff --git a/scipy/optimize/tests/test_linprog.py b/scipy/optimize/tests/test_linprog.py
--- a/scipy/optimize/tests/test_linprog.py
+++ b/scipy/optimize/tests/test_linprog.py
@@ -615,6 +615,17 @@ def test_unbounded_below_and_above(self):
                       method=self.method, options=self.options)
         _assert_success(res, desired_x=b, desired_fun=np.sum(b))
 
+    def test_bug_8663(self):
+        A = [[0, -7]]
+        b = [-6]
+        c = [1, 5]
+        bounds = [(0, None), (None, None)]
+        res = linprog(c, A_eq=A, b_eq=b, bounds=bounds,
+                      method=self.method, options=self.options)
+        _assert_success(res,
+                        desired_x=[0, 6./7],
+                        desired_fun=5*6./7)
+
 
 class TestLinprogSimplex(LinprogCommonTests):
     method = "simplex"