Rename before/after_solve to before/after_solve_mip

master
Alinson S. Xavier 5 years ago
parent bcaf26b18c
commit 6ae052c8d0

@ -21,14 +21,14 @@ class Component(ABC):
strategy. strategy.
""" """
def before_solve( def before_solve_mip(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
instance: Instance, instance: Instance,
model: Any, model: Any,
) -> None: ) -> None:
""" """
Method called by LearningSolver before the problem is solved. Method called by LearningSolver before the MIP is solved.
Parameters Parameters
---------- ----------
@ -42,7 +42,7 @@ class Component(ABC):
return return
@abstractmethod @abstractmethod
def after_solve( def after_solve_mip(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
instance: Instance, instance: Instance,
@ -51,7 +51,7 @@ class Component(ABC):
training_data: TrainingSample, training_data: TrainingSample,
) -> None: ) -> None:
""" """
Method called by LearningSolver after the problem is solved to optimality. Method called by LearningSolver after the MIP is solved.
Parameters Parameters
---------- ----------

@ -21,11 +21,11 @@ class CompositeComponent(Component):
def __init__(self, children): def __init__(self, children):
self.children = children self.children = children
def before_solve(self, solver, instance, model): def before_solve_mip(self, solver, instance, model):
for child in self.children: for child in self.children:
child.before_solve(solver, instance, model) child.before_solve_mip(solver, instance, model)
def after_solve( def after_solve_mip(
self, self,
solver, solver,
instance, instance,
@ -34,7 +34,7 @@ class CompositeComponent(Component):
training_data, training_data,
): ):
for child in self.children: for child in self.children:
child.after_solve(solver, instance, model, stats, training_data) child.after_solve_mip(solver, instance, model, stats, training_data)
def fit(self, training_instances): def fit(self, training_instances):
for child in self.children: for child in self.children:

@ -33,7 +33,7 @@ class UserCutsComponent(Component):
self.classifier_prototype: Classifier = classifier self.classifier_prototype: Classifier = classifier
self.classifiers: Dict[Any, Classifier] = {} self.classifiers: Dict[Any, Classifier] = {}
def before_solve(self, solver, instance, model): def before_solve_mip(self, solver, instance, model):
instance.found_violated_user_cuts = [] instance.found_violated_user_cuts = []
logger.info("Predicting violated user cuts...") logger.info("Predicting violated user cuts...")
violations = self.predict(instance) violations = self.predict(instance)
@ -42,7 +42,7 @@ class UserCutsComponent(Component):
cut = instance.build_user_cut(model, v) cut = instance.build_user_cut(model, v)
solver.internal_solver.add_constraint(cut) solver.internal_solver.add_constraint(cut)
def after_solve( def after_solve_mip(
self, self,
solver, solver,
instance, instance,

@ -33,7 +33,7 @@ class DynamicLazyConstraintsComponent(Component):
self.classifier_prototype: Classifier = classifier self.classifier_prototype: Classifier = classifier
self.classifiers: Dict[Any, Classifier] = {} self.classifiers: Dict[Any, Classifier] = {}
def before_solve(self, solver, instance, model): def before_solve_mip(self, solver, instance, model):
instance.found_violated_lazy_constraints = [] instance.found_violated_lazy_constraints = []
logger.info("Predicting violated lazy constraints...") logger.info("Predicting violated lazy constraints...")
violations = self.predict(instance) violations = self.predict(instance)
@ -54,7 +54,7 @@ class DynamicLazyConstraintsComponent(Component):
solver.internal_solver.add_constraint(cut) solver.internal_solver.add_constraint(cut)
return True return True
def after_solve( def after_solve_mip(
self, self,
solver, solver,
instance, instance,

@ -40,7 +40,7 @@ class StaticLazyConstraintsComponent(Component):
self.use_two_phase_gap = use_two_phase_gap self.use_two_phase_gap = use_two_phase_gap
self.violation_tolerance = violation_tolerance self.violation_tolerance = violation_tolerance
def before_solve(self, solver, instance, model): def before_solve_mip(self, solver, instance, model):
self.pool = [] self.pool = []
if not solver.use_lazy_cb and self.use_two_phase_gap: if not solver.use_lazy_cb and self.use_two_phase_gap:
logger.info("Increasing gap tolerance to %f", self.large_gap) logger.info("Increasing gap tolerance to %f", self.large_gap)
@ -52,7 +52,7 @@ class StaticLazyConstraintsComponent(Component):
if instance.has_static_lazy_constraints(): if instance.has_static_lazy_constraints():
self._extract_and_predict_static(solver, instance) self._extract_and_predict_static(solver, instance)
def after_solve( def after_solve_mip(
self, self,
solver, solver,
instance, instance,

@ -44,7 +44,7 @@ class ObjectiveValueComponent(Component):
self._predicted_ub: Optional[float] = None self._predicted_ub: Optional[float] = None
self._predicted_lb: Optional[float] = None self._predicted_lb: Optional[float] = None
def before_solve( def before_solve_mip(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
instance: Instance, instance: Instance,
@ -63,7 +63,7 @@ class ObjectiveValueComponent(Component):
) )
) )
def after_solve( def after_solve_mip(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
instance: Instance, instance: Instance,

@ -52,7 +52,7 @@ class PrimalSolutionComponent(Component):
self._n_zero = 0 self._n_zero = 0
self._n_one = 0 self._n_one = 0
def before_solve(self, solver, instance, model): def before_solve_mip(self, solver, instance, model):
if len(self.thresholds) > 0: if len(self.thresholds) > 0:
logger.info("Predicting primal solution...") logger.info("Predicting primal solution...")
solution = self.predict(instance) solution = self.predict(instance)
@ -77,7 +77,7 @@ class PrimalSolutionComponent(Component):
else: else:
solver.internal_solver.set_warm_start(solution) solver.internal_solver.set_warm_start(solution)
def after_solve( def after_solve_mip(
self, self,
solver: "LearningSolver", solver: "LearningSolver",
instance: Instance, instance: Instance,

@ -46,7 +46,7 @@ class ConvertTightIneqsIntoEqsStep(Component):
self.converted = [] self.converted = []
self.original_sense = {} self.original_sense = {}
def before_solve(self, solver, instance, _): def before_solve_mip(self, solver, instance, _):
logger.info("Predicting tight LP constraints...") logger.info("Predicting tight LP constraints...")
x, constraints = DropRedundantInequalitiesStep._x_test( x, constraints = DropRedundantInequalitiesStep._x_test(
instance, instance,
@ -73,7 +73,7 @@ class ConvertTightIneqsIntoEqsStep(Component):
logger.info(f"Converted {self.n_converted} inequalities") logger.info(f"Converted {self.n_converted} inequalities")
def after_solve( def after_solve_mip(
self, self,
solver, solver,
instance, instance,

@ -50,7 +50,7 @@ class DropRedundantInequalitiesStep(Component):
self.total_kept = 0 self.total_kept = 0
self.total_iterations = 0 self.total_iterations = 0
def before_solve(self, solver, instance, _): def before_solve_mip(self, solver, instance, _):
self.current_iteration = 0 self.current_iteration = 0
logger.info("Predicting redundant LP constraints...") logger.info("Predicting redundant LP constraints...")
@ -79,7 +79,7 @@ class DropRedundantInequalitiesStep(Component):
self.total_kept += 1 self.total_kept += 1
logger.info(f"Extracted {self.total_dropped} predicted constraints") logger.info(f"Extracted {self.total_dropped} predicted constraints")
def after_solve( def after_solve_mip(
self, self,
solver, solver,
instance, instance,

@ -14,11 +14,11 @@ class RelaxIntegralityStep(Component):
Component that relaxes all integrality constraints before the problem is solved. Component that relaxes all integrality constraints before the problem is solved.
""" """
def before_solve(self, solver, instance, _): def before_solve_mip(self, solver, instance, _):
logger.info("Relaxing integrality...") logger.info("Relaxing integrality...")
solver.internal_solver.relax() solver.internal_solver.relax()
def after_solve( def after_solve_mip(
self, self,
solver, solver,
instance, instance,

@ -86,7 +86,7 @@ class LearningSolver:
If true, use native solver callbacks for enforcing lazy constraints, If true, use native solver callbacks for enforcing lazy constraints,
instead of a simple loop. May not be supported by all solvers. instead of a simple loop. May not be supported by all solvers.
solve_lp_first: bool solve_lp_first: bool
If true, solve LP relaxation first, then solve original MILP. This If true, solve LP relaxation first, then solve original MIP. This
option should be activated if the LP relaxation is not very option should be activated if the LP relaxation is not very
expensive to solve and if it provides good hints for the integer expensive to solve and if it provides good hints for the integer
solution. solution.
@ -187,9 +187,9 @@ class LearningSolver:
training_sample["LP value"] = 0.0 training_sample["LP value"] = 0.0
# Before-solve callbacks # Before-solve callbacks
logger.debug("Running before_solve callbacks...") logger.debug("Running before_solve_mip callbacks...")
for component in self.components.values(): for component in self.components.values():
component.before_solve(self, instance, model) component.before_solve_mip(self, instance, model)
# Define wrappers # Define wrappers
def iteration_cb_wrapper() -> bool: def iteration_cb_wrapper() -> bool:
@ -212,8 +212,8 @@ class LearningSolver:
if self.use_lazy_cb: if self.use_lazy_cb:
lazy_cb = lazy_cb_wrapper lazy_cb = lazy_cb_wrapper
# Solve MILP # Solve MIP
logger.info("Solving MILP...") logger.info("Solving MIP...")
stats = cast( stats = cast(
LearningSolveStats, LearningSolveStats,
self.internal_solver.solve( self.internal_solver.solve(
@ -238,9 +238,9 @@ class LearningSolver:
training_sample["Solution"] = self.internal_solver.get_solution() training_sample["Solution"] = self.internal_solver.get_solution()
# After-solve callbacks # After-solve callbacks
logger.debug("Calling after_solve callbacks...") logger.debug("Calling after_solve_mip callbacks...")
for component in self.components.values(): for component in self.components.values():
component.after_solve(self, instance, model, stats, training_sample) component.after_solve_mip(self, instance, model, stats, training_sample)
# Write to file, if necessary # Write to file, if necessary
if not discard_output and filename is not None: if not discard_output and filename is not None:

@ -80,7 +80,7 @@ def test_drop_redundant():
component.classifiers = classifiers component.classifiers = classifiers
# LearningSolver calls before_solve # LearningSolver calls before_solve
component.before_solve(solver, instance, None) component.before_solve_mip(solver, instance, None)
# Should query list of constraints # Should query list of constraints
internal.get_constraint_ids.assert_called_once() internal.get_constraint_ids.assert_called_once()
@ -123,7 +123,7 @@ def test_drop_redundant():
# LearningSolver calls after_solve # LearningSolver calls after_solve
training_data = {} training_data = {}
component.after_solve(solver, instance, None, {}, training_data) component.after_solve_mip(solver, instance, None, {}, training_data)
# Should query slack for all inequalities # Should query slack for all inequalities
internal.get_inequality_slacks.assert_called_once() internal.get_inequality_slacks.assert_called_once()
@ -147,7 +147,7 @@ def test_drop_redundant_with_check_feasibility():
component.classifiers = classifiers component.classifiers = classifiers
# LearningSolver call before_solve # LearningSolver call before_solve
component.before_solve(solver, instance, None) component.before_solve_mip(solver, instance, None)
# Assert constraints are extracted # Assert constraints are extracted
assert internal.extract_constraint.call_count == 2 assert internal.extract_constraint.call_count == 2

@ -22,14 +22,14 @@ def test_composite():
cc = CompositeComponent([c1, c2]) cc = CompositeComponent([c1, c2])
# Should broadcast before_solve # Should broadcast before_solve
cc.before_solve(solver, instance, model) cc.before_solve_mip(solver, instance, model)
c1.before_solve.assert_has_calls([call(solver, instance, model)]) c1.before_solve_mip.assert_has_calls([call(solver, instance, model)])
c2.before_solve.assert_has_calls([call(solver, instance, model)]) c2.before_solve_mip.assert_has_calls([call(solver, instance, model)])
# Should broadcast after_solve # Should broadcast after_solve
cc.after_solve(solver, instance, model, {}, {}) cc.after_solve_mip(solver, instance, model, {}, {})
c1.after_solve.assert_has_calls([call(solver, instance, model, {}, {})]) c1.after_solve_mip.assert_has_calls([call(solver, instance, model, {}, {})])
c2.after_solve.assert_has_calls([call(solver, instance, model, {}, {})]) c2.after_solve_mip.assert_has_calls([call(solver, instance, model, {}, {})])
# Should broadcast fit # Should broadcast fit
cc.fit([1, 2, 3]) cc.fit([1, 2, 3])

@ -85,7 +85,7 @@ def test_lazy_before():
component.classifiers["a"].predict_proba = Mock(return_value=[[0.95, 0.05]]) component.classifiers["a"].predict_proba = Mock(return_value=[[0.95, 0.05]])
component.classifiers["b"].predict_proba = Mock(return_value=[[0.02, 0.80]]) component.classifiers["b"].predict_proba = Mock(return_value=[[0.02, 0.80]])
component.before_solve(solver, instances[0], models[0]) component.before_solve_mip(solver, instances[0], models[0])
# Should ask classifier likelihood of each constraint being violated # Should ask classifier likelihood of each constraint being violated
expected_x_test_a = np.array([[67.0, 21.75, 1287.92]]) expected_x_test_a = np.array([[67.0, 21.75, 1287.92]])

@ -68,7 +68,7 @@ def test_usage_with_solver():
) )
# LearningSolver calls before_solve # LearningSolver calls before_solve
component.before_solve(solver, instance, None) component.before_solve_mip(solver, instance, None)
# Should ask if instance has static lazy constraints # Should ask if instance has static lazy constraints
instance.has_static_lazy_constraints.assert_called_once() instance.has_static_lazy_constraints.assert_called_once()

Loading…
Cancel
Save