Skip to content

Commit

Permalink
Trac #29493: Failing tests when using system glpk
Browse files Browse the repository at this point in the history
At the moment there are two failing doctests, when using the glpk from
the system, e.g. on ubuntu eoan
[https://github.com/mkoeppe/sage/runs/542655821]

{{{
sage -t src/sage/numerical/backends/glpk_backend.pyx
**********************************************************************
File "src/sage/numerical/backends/glpk_backend.pyx", line 2287, in
sage.numerical.backends.glpk_backend.GLPKBackend.print_ranges
Failed example:
    p.print_ranges()
Expected:
    glp_print_ranges: optimal basic solution required
    1
Got:
    1
}}}

This doctest was mentioned before in #29317 with a suggestion for a fix.

{{{
 sage -t src/sage/libs/glpk/error.pyx
**********************************************************************
File "src/sage/libs/glpk/error.pyx", line 100, in
sage.libs.glpk.error.setup_glpk_error_handler
Failed example:
    res = p.solve()
Expected:
          0: obj = ...
Got:
    <BLANKLINE>
}}}

The problem is that we have doctests that rely on error-recovery
behavior added by a custom patch
[https://trac.sagemath.org/ticket/20710#comment:18],
which wasn't accepted by upstream. (The doctest for the patch was added
in #20832.)

The present ticket fixes the failures by
 * adding explicit input validation in several functions in the Cython
wrappers so that the GLPK error handler is not reached;
 * changing the default optimization mode from `glp_intopt` to
`glp_simplex_then_intopt`, which is more robust;
 * disabling the test for the error-recovery behavior, which provokes a
crash with unpatched GLPK.

URL: https://trac.sagemath.org/29493
Reported by: gh-kliem
Ticket author(s): Michael Orlitzky, Matthias Koeppe
Reviewer(s): Matthias Koeppe, Michael Orlitzky
  • Loading branch information
Release Manager committed Jun 21, 2020
2 parents 0527ee7 + 8acdf34 commit 55dc391
Show file tree
Hide file tree
Showing 4 changed files with 307 additions and 69 deletions.
19 changes: 15 additions & 4 deletions src/sage/libs/glpk/error.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ from sage.numerical.mip import MIPSolverException

class GLPKError(MIPSolverException):
"""
An error raised by the GLPK library.
A low-level error that is raised by ``sage_glpk_term_hook``.
The GLPK API considers these errors non-recoverable. User code should not try
to catch this exception.
EXAMPLES::
Expand Down Expand Up @@ -68,9 +71,17 @@ def setup_glpk_error_handler():
Setup the GLPK error handler. Called automatically when this module
is imported at Sage startup.
We install this error handler so that an error does not lead to
an immediate error exit of the process. Instead, we raise a
``GLPKError`` for the convenience of developers.
The GLPK API considers errors non-recoverable.
Therefore, user code should not try to catch this exception.
TESTS::
sage: cython('''
sage: cython( # optional - glpk_error_recovery_patch
....: '''
....: # distutils: libraries = glpk z gmp
....: from cysignals.signals cimport sig_on, sig_off
....: from sage.libs.glpk.env cimport glp_term_out
Expand All @@ -97,8 +108,8 @@ def setup_glpk_error_handler():
sage: p.add_constraint(3*x + 2*y <= 6)
sage: p.add_constraint(x >= 0)
sage: p.set_objective(x + y)
sage: res = p.solve()
0: obj = ...
sage: print('output', flush=True); res = p.solve()
output ... 0: obj = ...
sage: res # rel tol 1e-15
2.4
"""
Expand Down
2 changes: 2 additions & 0 deletions src/sage/libs/glpk/lp.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,5 @@ cdef extern from "glpk.h":
double glp_ios_mip_gap(glp_tree *T)
int glp_ios_best_node(glp_tree *tree)
double glp_ios_node_bound(glp_tree *T, int p)

int glp_bf_exists(glp_prob *lp)
2 changes: 1 addition & 1 deletion src/sage/numerical/backends/glpk_backend.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ cdef class GLPKBackend(GenericBackend):
cpdef __copy__(self)
cpdef int print_ranges(self, filename = *) except -1
cpdef double get_row_dual(self, int variable)
cpdef double get_col_dual(self, int variable)
cpdef double get_col_dual(self, int variable) except? -1
cpdef int get_row_stat(self, int variable) except? -1
cpdef int get_col_stat(self, int variable) except? -1
cpdef eval_tab_row(self, int k)
Expand Down
Loading

0 comments on commit 55dc391

Please sign in to comment.