@@ -225,7 +225,9 @@ def _apply_solver(self):
225
225
226
226
def _get_mip_results (self , results , soln ):
227
227
"""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
+ """
229
231
xprob = self ._solver_model
230
232
xp = xpress
231
233
xprob_attrs = xprob .attributes
@@ -301,14 +303,13 @@ def _get_mip_results(self, results, soln):
301
303
except (XpressDirect .XpressException , AttributeError ):
302
304
pass
303
305
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
308
307
309
308
def _get_lp_results (self , results , soln ):
310
309
"""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
+ """
312
313
xprob = self ._solver_model
313
314
xp = xpress
314
315
xprob_attrs = xprob .attributes
@@ -377,14 +378,18 @@ def _get_lp_results(self, results, soln):
377
378
results .problem .lower_bound = xprob_attrs .lpobjval
378
379
except (XpressDirect .XpressException , AttributeError ):
379
380
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 ]
384
387
385
388
def _get_nlp_results (self , results , soln ):
386
389
"""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
+ """
388
393
xprob = self ._solver_model
389
394
xp = xpress
390
395
xprob_attrs = xprob .attributes
@@ -400,7 +405,7 @@ def _get_nlp_results(self, results, soln):
400
405
# The problem was non-linear
401
406
status = xprob_attrs .xslp_nlpstatus
402
407
solstatus = xprob_attrs .xslp_solstatus
403
- have_soln , check_soln = False , False
408
+ have_soln = False
404
409
optimal = False # *globally* optimal?
405
410
if status == xp .nlp_unstarted :
406
411
results .solver .status = SolverStatus .unknown
@@ -420,13 +425,13 @@ def _get_nlp_results(self, results, soln):
420
425
results .solver .termination_message = "Feasible solution found for non-convex model"
421
426
results .solver .termination_condition = TerminationCondition .feasible
422
427
soln .status = SolutionStatus .feasible
423
- have_soln , check_soln = True , True
428
+ have_soln = True
424
429
elif status == xp .nlp_globally_optimal :
425
430
results .solver .status = SolverStatus .ok
426
431
results .solver .termination_message = "Non-convex model was solved to global optimality"
427
432
results .solver .termination_condition = TerminationCondition .optimal
428
433
soln .status = SolutionStatus .optimal
429
- have_soln , check_soln = True , True
434
+ have_soln = True
430
435
optimal = True
431
436
elif status == xp .nlp_locally_infeasible :
432
437
results .solver .status = SolverStatus .ok
@@ -448,7 +453,7 @@ def _get_nlp_results(self, results, soln):
448
453
results .solver .termination_message = "Non-convex solve not finished (numerical issues?)"
449
454
results .solver .termination_condition = TerminationCondition .unknown
450
455
soln .status = SolutionStatus .unknown
451
- have_soln , check_soln = True , True
456
+ have_soln = True
452
457
else :
453
458
results .solver .status = SolverStatus .error
454
459
results .solver .termination_message = "Error for non-convex model: " + str (status )
@@ -465,7 +470,7 @@ def _get_nlp_results(self, results, soln):
465
470
except (XpressDirect .XpressException , AttributeError ):
466
471
pass
467
472
468
- return have_soln , check_soln
473
+ return have_soln
469
474
470
475
def _solve_model (self ):
471
476
xprob = self ._solver_model
@@ -769,7 +774,7 @@ def _postsolve(self):
769
774
770
775
if not hasattr (self , '_get_results' ):
771
776
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 )
773
778
self .results .problem .name = xprob_attrs .matrixname
774
779
775
780
if xprob_attrs .objsense == 1.0 :
@@ -800,7 +805,7 @@ def _postsolve(self):
800
805
This code in this if statement is only needed for backwards compatability. It is more efficient to set
801
806
_save_results to False and use load_vars, load_duals, etc.
802
807
"""
803
- if check_soln :
808
+ if have_soln :
804
809
soln_variables = soln .variable
805
810
soln_constraints = soln .constraint
806
811
0 commit comments