#26195·scipy

BUG: optimize.linprog TestLinprogIPSparse.test_bug_6139 fails with OpenBLAS due to deprecated interior-point solver

Author: naipatilCreated Sep 16, 2026Updated Sep 17, 2026
Labelsdefectscipy.optimize

Describe your issue.

Two scipy.optimize.linprog tests still exercise the deprecated method='interior-point' solver and fail a tight assert_allclose (rtol=atol=1e-08) when SciPy is linked against OpenBLAS.

  • optimize/tests/test_linprog.py::TestLinprogIPSparse::test_bug_6139
  • optimize/tests/test_linprog.py::TestLinprogIPSparsePresolve::test_bug_6139

Reproduced on SciPy 1.14.1, 1.15.x, 1.16.3, and 1.17.0.

The solver still converges to essentially the expected solution [5, 4.95, 5]; the max absolute difference is about 8.86e-08 (relative ~1.79e-08), just outside the test tolerance. The same problem with method='highs', 'highs-ipm', or 'simplex' does not fail.

This looks like numerical sensitivity in the legacy interior-point sparse path (_linprog_ip._sym_solve) plus a too-tight check, not a wrong optimum. The tests remain in the suite even though 'interior-point' was deprecated and scheduled for removal.

Related:

  • PR #15512 made HiGHS the default and deprecated 'interior-point' (removal was documented for 1.11.0).
  • #15707 still tracks removing the deprecated linprog methods.
  • #20216 skipped the dense TestLinprogIPDense.test_bug_6139 variant for the same family of failures.
  • #25488 reports the same two sparse tests failing with -march=znver5 / Skylake.

Please consider skipping, xfailing, or dropping these remaining LinprogIP* tests, and/or finishing removal of the deprecated solver, consistent with #20216.

Reproducing Code Example

python
import numpy as np
from scipy.optimize import linprog
from numpy.testing import assert_allclose, assert_equal


def _assert_success(res, desired_fun=None, desired_x=None, rtol=1e-8, atol=1e-8):
    if not res.success:
        raise AssertionError(f"linprog status {res.status}, message: {res.message}")
    assert_equal(res.status, 0)
    if desired_fun is not None:
        assert_allclose(res.fun, desired_fun,
                        err_msg="converged to an unexpected objective value",
                        rtol=rtol, atol=atol)
    if desired_x is not None:
        assert_allclose(res.x, desired_x,
                        err_msg="converged to an unexpected solution",
                        rtol=rtol, atol=atol)


c = np.array([1, 1, 1])
A_eq = np.array([[1., 0., 0.], [-1000., 0., -1000.]])
b_eq = np.array([5.00000000e+00, -1.00000000e+04])
A_ub = -np.array([[0., 1000000., 1010000.]])
b_ub = -np.array([10000000.])
bounds = (None, None)

method = "interior-point"
# method = "highs"      # passes
# method = "highs-ipm"  # passes
options = {"sparse": True, "cholesky": False, "sym_pos": False}

res = linprog(c, A_ub, b_ub, A_eq, b_eq, bounds, method=method, options=options)
print(f"result fun: {res.fun}")
print(f"result x:   {res.x}")

_assert_success(res, desired_fun=14.95, desired_x=np.array([5, 4.95, 5]))

Error message

FAILED optimize/tests/test_linprog.py::TestLinprogIPSparse::test_bug_6139 - AssertionError:
Not equal to tolerance rtol=1e-08, atol=1e-08
converged to an unexpected solution
Mismatched elements: 2 / 3 (66.7%)
Max absolute difference among violations: 8.8555848e-08
Max relative difference among violations: 1.78900703e-08
 ACTUAL: array([5.  , 4.95, 5.  ])
 DESIRED: array([5.  , 4.95, 5.  ])

FAILED optimize/tests/test_linprog.py::TestLinprogIPSparsePresolve::test_bug_6139 - AssertionError:
Not equal to tolerance rtol=1e-08, atol=1e-08
converged to an unexpected solution
Mismatched elements: 2 / 3 (66.7%)
Max absolute difference among violations: 8.8555848e-08
Max relative difference among violations: 1.78900703e-08
 ACTUAL: array([5.  , 4.95, 5.  ])
 DESIRED: array([5.  , 4.95, 5.  ])

Switching method to 'highs' or 'highs-ipm' succeeds.

SciPy/NumPy/Python version and system information

Reproduced with SciPy 1.14.1, 1.15.x, 1.16.3, 1.17.0 linked against OpenBLAS.

  • Python: 3.11, 3.12, 3.13
  • OS: Rocky Linux 8, Rocky Linux 9, Ubuntu
  • CPU: x86-64 (znver4 / znver5 / znver6)

Happy to add scipy.show_config() from a specific build if useful.