Skip to content

Commit dc66798

Browse files
committed
Add test exercising cuOpt UnboundedOrInfeasible status (11)
An unbounded LP with no variable bounds triggers cuOpt's presolver to return UnboundedOrInfeasible (status 11); the test asserts the plugin maps it to TerminationCondition.infeasibleOrUnbounded, SolverStatus.warning, and SolutionStatus.unsure.
1 parent 7cb1cf3 commit dc66798

1 file changed

Lines changed: 19 additions & 0 deletions

File tree

pyomo/solvers/tests/checks/test_cuopt_direct.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,25 @@ def test_infeasible_trivial_constraint(self):
125125
with pytest.raises(ValueError, match=r"Trivial constraint.*infeasible"):
126126
opt.solve(m, skip_trivial_constraints=True)
127127

128+
@unittest.skipIf(not cuopt_available, "The CuOpt solver is not available")
129+
def test_unbounded_or_infeasible_status(self):
130+
# An LP with no variable bounds and an unbounded objective triggers
131+
# cuOpt's presolver to return UnboundedOrInfeasible (status 11), which
132+
# the plugin maps to TerminationCondition.infeasibleOrUnbounded.
133+
m = ConcreteModel()
134+
m.x = Var()
135+
m.y = Var()
136+
m.obj = Objective(expr=m.x + m.y, sense=minimize)
137+
138+
opt = SolverFactory('cuopt')
139+
res = opt.solve(m, load_solutions=False)
140+
141+
self.assertEqual(
142+
res.solver.termination_condition, "infeasibleOrUnbounded"
143+
)
144+
self.assertEqual(res.solver.status, "warning")
145+
self.assertEqual(res.solution[0].status, "unsure")
146+
128147
@unittest.skipIf(not cuopt_available, "The CuOpt solver is not available")
129148
def test_nonlinear_constraint_rejected(self):
130149
m = ConcreteModel()

0 commit comments

Comments
 (0)