Skip to content

Commit 0a1e064

Browse files
committed
Simplify API of _get_results function.
The function now returns a boolean that indicates whether a solution is available or not.
1 parent 0bb5788 commit 0a1e064

File tree

1 file changed

+23
-18
lines changed

1 file changed

+23
-18
lines changed

pyomo/solvers/plugins/solvers/xpress_direct.py

+23-18
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,9 @@ def _apply_solver(self):
225225

226226
def _get_mip_results(self, results, soln):
227227
"""Sets up `results` and `soln` and returns whether there is a solution
228-
to query."""
228+
to query.
229+
Returns `True` if a feasible solution is available, `False` otherwise.
230+
"""
229231
xprob = self._solver_model
230232
xp = xpress
231233
xprob_attrs = xprob.attributes
@@ -301,14 +303,13 @@ def _get_mip_results(self, results, soln):
301303
except (XpressDirect.XpressException, AttributeError):
302304
pass
303305

304-
# TODO: Pyomo only queries solution if the LP status is optimal.
305-
# This seems wrong at first glance
306-
return (xprob_attrs.lpstatus == xp.lp_optimal and mip_sols > 0,
307-
mip_sols > 0)
306+
return mip_sols > 0
308307

309308
def _get_lp_results(self, results, soln):
310309
"""Sets up `results` and `soln` and returns whether there is a solution
311-
to query."""
310+
to query.
311+
Returns `True` if a feasible solution is available, `False` otherwise.
312+
"""
312313
xprob = self._solver_model
313314
xp = xpress
314315
xprob_attrs = xprob.attributes
@@ -377,14 +378,18 @@ def _get_lp_results(self, results, soln):
377378
results.problem.lower_bound = xprob_attrs.lpobjval
378379
except (XpressDirect.XpressException, AttributeError):
379380
pass
380-
381-
return (xprob_attrs.lpstatus == xp.lp_optimal,
382-
xprob_attrs.lpstatus in [xp.lp_optimal, xp.lp_cutoff,
383-
xp.lp_cutoff_in_dual])
381+
382+
# Not all solution information will be available in all cases, it is
383+
# up to the caller/user to check the actual status and figure which
384+
# of x, slack, duals, reduced costs are valid.
385+
return xprob_attrs.lpstatus in [xp.lp_optimal, xp.lp_cutoff,
386+
xp.lp_cutoff_in_dual]
384387

385388
def _get_nlp_results(self, results, soln):
386389
"""Sets up `results` and `soln` and returns whether there is a solution
387-
to query."""
390+
to query.
391+
Returns `True` if a feasible solution is available, `False` otherwise.
392+
"""
388393
xprob = self._solver_model
389394
xp = xpress
390395
xprob_attrs = xprob.attributes
@@ -400,7 +405,7 @@ def _get_nlp_results(self, results, soln):
400405
# The problem was non-linear
401406
status = xprob_attrs.xslp_nlpstatus
402407
solstatus = xprob_attrs.xslp_solstatus
403-
have_soln, check_soln = False, False
408+
have_soln = False
404409
optimal = False # *globally* optimal?
405410
if status == xp.nlp_unstarted:
406411
results.solver.status = SolverStatus.unknown
@@ -420,13 +425,13 @@ def _get_nlp_results(self, results, soln):
420425
results.solver.termination_message = "Feasible solution found for non-convex model"
421426
results.solver.termination_condition = TerminationCondition.feasible
422427
soln.status = SolutionStatus.feasible
423-
have_soln, check_soln = True, True
428+
have_soln = True
424429
elif status == xp.nlp_globally_optimal:
425430
results.solver.status = SolverStatus.ok
426431
results.solver.termination_message = "Non-convex model was solved to global optimality"
427432
results.solver.termination_condition = TerminationCondition.optimal
428433
soln.status = SolutionStatus.optimal
429-
have_soln, check_soln = True, True
434+
have_soln = True
430435
optimal = True
431436
elif status == xp.nlp_locally_infeasible:
432437
results.solver.status = SolverStatus.ok
@@ -448,7 +453,7 @@ def _get_nlp_results(self, results, soln):
448453
results.solver.termination_message = "Non-convex solve not finished (numerical issues?)"
449454
results.solver.termination_condition = TerminationCondition.unknown
450455
soln.status = SolutionStatus.unknown
451-
have_soln, check_soln = True, True
456+
have_soln = True
452457
else:
453458
results.solver.status = SolverStatus.error
454459
results.solver.termination_message = "Error for non-convex model: " + str(status)
@@ -465,7 +470,7 @@ def _get_nlp_results(self, results, soln):
465470
except (XpressDirect.XpressException, AttributeError):
466471
pass
467472

468-
return have_soln, check_soln
473+
return have_soln
469474

470475
def _solve_model(self):
471476
xprob = self._solver_model
@@ -769,7 +774,7 @@ def _postsolve(self):
769774

770775
if not hasattr(self, '_get_results'):
771776
raise RuntimeError('Model was solved but `_get_results` property is not set')
772-
have_soln, check_soln = self._get_results(self.results, soln)
777+
have_soln = self._get_results(self.results, soln)
773778
self.results.problem.name = xprob_attrs.matrixname
774779

775780
if xprob_attrs.objsense == 1.0:
@@ -800,7 +805,7 @@ def _postsolve(self):
800805
This code in this if statement is only needed for backwards compatability. It is more efficient to set
801806
_save_results to False and use load_vars, load_duals, etc.
802807
"""
803-
if check_soln:
808+
if have_soln:
804809
soln_variables = soln.variable
805810
soln_constraints = soln.constraint
806811

0 commit comments

Comments
 (0)