Replace build_lazy_constraint by enforce_lazy_constraint

This commit is contained in:
2021-04-10 10:05:30 -05:00
parent 735884151d
commit f70363db0d
7 changed files with 99 additions and 46 deletions

View File

@@ -232,8 +232,21 @@ class GurobiSolver(InternalSolver):
@overrides
def get_solution(self) -> Optional[Solution]:
self._raise_if_callback()
assert self.model is not None
if self.cb_where is not None:
if self.cb_where == self.gp.GRB.Callback.MIPNODE:
return {
v.varName: self.model.cbGetNodeRel(v) for v in self.model.getVars()
}
elif self.cb_where == self.gp.GRB.Callback.MIPSOL:
return {
v.varName: self.model.cbGetSolution(v) for v in self.model.getVars()
}
else:
raise Exception(
f"get_solution can only be called from a callback "
f"when cb_where is either MIPNODE or MIPSOL"
)
if self.model.solCount == 0:
return None
return {v.varName: v.x for v in self.model.getVars()}
@@ -481,6 +494,7 @@ class GurobiTestInstanceInfeasible(Instance):
class GurobiTestInstanceRedundancy(Instance):
@overrides
def to_model(self) -> Any:
import gurobipy as gp
from gurobipy import GRB
@@ -525,11 +539,10 @@ class GurobiTestInstanceKnapsack(PyomoTestInstanceKnapsack):
return model
@overrides
def build_lazy_constraint(self, model: Any, violation: Hashable) -> Any:
# TODO: Replace by plain constraint
return ExtractedGurobiConstraint(
lhs=1.0 * model.getVarByName("x[0]"),
sense="<",
rhs=0.0,
name="cut",
)
def enforce_lazy_constraint(
self,
solver: InternalSolver,
model: Any,
violation: Hashable,
) -> None:
solver.add_constraint(model.getVarByName("x[0]") <= 0, name="cut")

View File

@@ -426,6 +426,7 @@ class PyomoTestInstanceInfeasible(Instance):
class PyomoTestInstanceRedundancy(Instance):
@overrides
def to_model(self) -> pe.ConcreteModel:
model = pe.ConcreteModel()
model.x = pe.Var([0, 1], domain=pe.Binary)
@@ -484,6 +485,11 @@ class PyomoTestInstanceKnapsack(Instance):
]
@overrides
def build_lazy_constraint(self, model: Any, violation: Hashable) -> Any:
def enforce_lazy_constraint(
self,
solver: InternalSolver,
model: Any,
violation: Hashable,
) -> None:
model.cut = pe.Constraint(expr=model.x[0] <= 0.0, name="cut")
return model.cut
solver.add_constraint(model.cut)

View File

@@ -88,9 +88,7 @@ def run_basic_usage_tests(solver: InternalSolver) -> None:
)
# Add a brand new constraint
cut = instance.build_lazy_constraint(model, "cut")
assert cut is not None
solver.add_constraint(cut, name="cut")
instance.enforce_lazy_constraint(solver, model, "cut")
# New constraint should be listed
assert_equals(
@@ -199,18 +197,16 @@ def run_iteration_cb_tests(solver: InternalSolver) -> None:
def run_lazy_cb_tests(solver: InternalSolver) -> None:
instance = solver.build_test_instance_knapsack()
model = instance.to_model()
lazy_cb_count = 0
def lazy_cb(cb_solver: InternalSolver, cb_model: Any) -> None:
nonlocal lazy_cb_count
lazy_cb_count += 1
cobj = instance.build_lazy_constraint(model, "cut")
if not cb_solver.is_constraint_satisfied(cobj):
cb_solver.add_constraint(cobj)
relsol = cb_solver.get_solution()
assert relsol is not None
assert relsol["x[0]"] is not None
if relsol["x[0]"] > 0:
instance.enforce_lazy_constraint(cb_solver, cb_model, "cut")
solver.set_instance(instance, model)
solver.solve(lazy_cb=lazy_cb)
assert lazy_cb_count > 0
solution = solver.get_solution()
assert solution is not None
assert_equals(solution["x[0]"], 0.0)