pyomo icon indicating copy to clipboard operation
pyomo copied to clipboard

GAMS solver sets incorrect termination condition on timeout for MIP model solved with CPLEX

Open joelgoop opened this issue 3 years ago • 0 comments

Summary

When I try to solve a MIP model using the Pyomo GAMS solver and CPLEX and it terminates due to the time limit, GAMS returns (extracted from the .lst file):

**** SOLVER STATUS     3 Resource Interrupt        
**** MODEL STATUS      8 Integer Solution          

As I understand these codes, the solver has found an integer solution, but was interrupted by the time limit, which means that the solution is not necessarily optimal.

However, Pyomo interprets this as an optimal solution and returns

results.solver.status == SolverStatus.ok
results.solver.termination_condition == TerminationCondition.optimal

Steps to reproduce the issue

I cannot reproduce my entire model here, but this issue will occur whenever modelstat 8 and solvestat 3 are returned from a GAMS model. I can trigger that by applying a low value for the time limit (with the GAMS option reslim) to a MIP model that would otherwise take longer to solve.

 opt = SolverFactory("gams")

 res = opt.solve(
    model,
    solver="cplex",
    mtype="mip",
    add_options=["option optcr = 0.0002;", "option reslim = 10;"],
    keepfiles=True
 )

This is the statuses given in resultsstat.dat:

MODELSTAT    8.000000000000000
SOLVESTAT    3.000000000000000

But the Pyomo result shows:

res.solver.status
>>> <SolverStatus.ok: 'ok'>

res.solver.termination_condition
>>> <TerminationCondition.optimal: 'optimal'>

Error Message

Expected: res.solver.termination_condition == TerminationCondition.maxTimeLimit Actual: res.solver.termination_condition == TerminationCondition.optimal.

Information on your system

Pyomo version: 6.4.1 Python version: 3.9.1 Operating system: Linux How Pyomo was installed (PyPI, conda, source): PyPI Solver (if applicable): GAMS 24.7.4

Additional information

In GAMS.py, the correct termination condition is first set based on solvestat == 3:

https://github.com/Pyomo/pyomo/blob/85382448f469e60397cefbdb1c26cb685362ea13/pyomo/solvers/plugins/solvers/GAMS.py#L405-L407

However, later in the file, the termination condition is overwritten based on modelstat == 8 (meaning there is an integer solution, but it is not proven optimal):

https://github.com/Pyomo/pyomo/blob/85382448f469e60397cefbdb1c26cb685362ea13/pyomo/solvers/plugins/solvers/GAMS.py#L457-L460

(These references point to the GAMSDirect solver class, but the same checks happen in GAMSShell.)

joelgoop avatar Jul 06 '22 09:07 joelgoop