From beee252fa25599b13948b9c7b095534ed7bcc14f Mon Sep 17 00:00:00 2001 From: Alinson S Xavier Date: Wed, 13 Jan 2021 11:04:33 -0600 Subject: [PATCH] simulate_perfect: Do not overwrite original file --- miplearn/components/lazy_dynamic.py | 2 +- .../steps/tests/convert_tight_test.py | 12 +++------- miplearn/components/tests/test_relaxation.py | 3 ++- miplearn/extractors.py | 15 ++++++++----- miplearn/solvers/learning.py | 18 +++++++++------ .../solvers/tests/test_learning_solver.py | 22 +++++++++++++++++-- 6 files changed, 46 insertions(+), 26 deletions(-) diff --git a/miplearn/components/lazy_dynamic.py b/miplearn/components/lazy_dynamic.py index baf2eca..71429da 100644 --- a/miplearn/components/lazy_dynamic.py +++ b/miplearn/components/lazy_dynamic.py @@ -61,7 +61,7 @@ class DynamicLazyConstraintsComponent(Component): self.classifiers = {} violation_to_instance_idx = {} - for (idx, instance) in enumerate(training_instances): + for (idx, instance) in enumerate(InstanceIterator(training_instances)): for v in instance.found_violated_lazy_constraints: if isinstance(v, list): v = tuple(v) diff --git a/miplearn/components/steps/tests/convert_tight_test.py b/miplearn/components/steps/tests/convert_tight_test.py index a1e60de..cf37840 100644 --- a/miplearn/components/steps/tests/convert_tight_test.py +++ b/miplearn/components/steps/tests/convert_tight_test.py @@ -69,9 +69,7 @@ class TestInstanceMin(Instance): def test_convert_tight_infeasibility(): - comp = ConvertTightIneqsIntoEqsStep( - check_converted=True, - ) + comp = ConvertTightIneqsIntoEqsStep() comp.classifiers = { "c1": Mock(spec=Classifier), "c2": Mock(spec=Classifier), @@ -94,9 +92,7 @@ def test_convert_tight_infeasibility(): def test_convert_tight_suboptimality(): - comp = ConvertTightIneqsIntoEqsStep( - check_converted=True, - ) + comp = ConvertTightIneqsIntoEqsStep(check_optimality=True) comp.classifiers = { "c1": Mock(spec=Classifier), "c2": Mock(spec=Classifier), @@ -119,9 +115,7 @@ def test_convert_tight_suboptimality(): def test_convert_tight_optimal(): - comp = ConvertTightIneqsIntoEqsStep( - check_converted=True, - ) + comp = ConvertTightIneqsIntoEqsStep() comp.classifiers = { "c1": Mock(spec=Classifier), "c2": Mock(spec=Classifier), diff --git a/miplearn/components/tests/test_relaxation.py b/miplearn/components/tests/test_relaxation.py index eb249f1..a8579b0 100644 --- a/miplearn/components/tests/test_relaxation.py +++ b/miplearn/components/tests/test_relaxation.py @@ -134,7 +134,8 @@ def test_drop_redundant_with_check_dropped(): solver, internal, instance, classifiers = _setup() component = DropRedundantInequalitiesStep( - check_dropped=True, violation_tolerance=1e-3 + check_feasibility=True, + violation_tolerance=1e-3, ) component.classifiers = classifiers diff --git a/miplearn/extractors.py b/miplearn/extractors.py index 06b1705..a113c70 100644 --- a/miplearn/extractors.py +++ b/miplearn/extractors.py @@ -29,12 +29,15 @@ class InstanceIterator: self.current += 1 if isinstance(result, str): logger.debug("Read: %s" % result) - if result.endswith(".gz"): - with gzip.GzipFile(result, "rb") as file: - result = pickle.load(file) - else: - with open(result, "rb") as file: - result = pickle.load(file) + try: + if result.endswith(".gz"): + with gzip.GzipFile(result, "rb") as file: + result = pickle.load(file) + else: + with open(result, "rb") as file: + result = pickle.load(file) + except pickle.UnpicklingError: + raise Exception(f"Invalid instance file: {result}") return result diff --git a/miplearn/solvers/learning.py b/miplearn/solvers/learning.py index ac81aaf..5a89987 100644 --- a/miplearn/solvers/learning.py +++ b/miplearn/solvers/learning.py @@ -11,6 +11,7 @@ import gzip from copy import deepcopy from typing import Optional, List from p_tqdm import p_map +from tempfile import NamedTemporaryFile from . import RedirectOutput from .. import ( @@ -211,13 +212,16 @@ class LearningSolver: details. """ if self.simulate_perfect: - self._solve( - instance=instance, - model=model, - output=output, - tee=tee, - ) - self.fit([instance]) + if not isinstance(instance, str): + raise Exception("Not implemented") + with tempfile.NamedTemporaryFile(suffix=os.path.basename(instance)) as tmp: + self._solve( + instance=instance, + model=model, + output=tmp.name, + tee=tee, + ) + self.fit([tmp.name]) return self._solve( instance=instance, model=model, diff --git a/miplearn/solvers/tests/test_learning_solver.py b/miplearn/solvers/tests/test_learning_solver.py index 4216a01..6bd6841 100644 --- a/miplearn/solvers/tests/test_learning_solver.py +++ b/miplearn/solvers/tests/test_learning_solver.py @@ -7,8 +7,11 @@ import pickle import tempfile import os -from miplearn import DynamicLazyConstraintsComponent -from miplearn import LearningSolver +from miplearn import ( + LearningSolver, + GurobiSolver, + DynamicLazyConstraintsComponent, +) from . import _get_instance, _get_internal_solvers @@ -109,3 +112,18 @@ def test_solve_fit_from_disk(): os.remove(filename) for filename in output: os.remove(filename) + + +def test_simulate_perfect(): + internal_solver = GurobiSolver() + instance = _get_instance(internal_solver) + with tempfile.NamedTemporaryFile(suffix=".pkl", delete=False) as tmp: + pickle.dump(instance, tmp) + tmp.flush() + solver = LearningSolver( + solver=internal_solver, + simulate_perfect=True, + ) + + stats = solver.solve(tmp.name) + assert stats["Lower bound"] == stats["Predicted LB"]