From 235c3e55c222ca02a72bab48a7df47495c137332 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Wed, 14 Jul 2021 08:31:01 -0500 Subject: [PATCH] Make Sample abstract; create MemorySample --- miplearn/features/sample.py | 17 ++++++++++++++++- miplearn/solvers/learning.py | 4 ++-- tests/components/test_dynamic_lazy.py | 8 ++++---- tests/components/test_objective.py | 4 ++-- tests/components/test_primal.py | 4 ++-- tests/components/test_static_lazy.py | 4 ++-- tests/test_features.py | 4 ++-- 7 files changed, 30 insertions(+), 15 deletions(-) diff --git a/miplearn/features/sample.py b/miplearn/features/sample.py index ae85c72..2fd8e9f 100644 --- a/miplearn/features/sample.py +++ b/miplearn/features/sample.py @@ -2,10 +2,25 @@ # Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved. # Released under the modified BSD license. See COPYING.md for more details. +from abc import ABC, abstractmethod from typing import Dict, Optional, Any -class Sample: +class Sample(ABC): + """Abstract dictionary-like class that stores training data.""" + + @abstractmethod + def get(self, key: str) -> Optional[Any]: + pass + + @abstractmethod + def put(self, key: str, value: Any) -> None: + pass + + +class MemorySample(Sample): + """Dictionary-like class that stores training data in-memory.""" + def __init__( self, data: Optional[Dict[str, Any]] = None, diff --git a/miplearn/solvers/learning.py b/miplearn/solvers/learning.py index 986afdb..a072514 100644 --- a/miplearn/solvers/learning.py +++ b/miplearn/solvers/learning.py @@ -15,7 +15,7 @@ from miplearn.components.dynamic_user_cuts import UserCutsComponent from miplearn.components.objective import ObjectiveValueComponent from miplearn.components.primal import PrimalSolutionComponent from miplearn.features.extractor import FeaturesExtractor -from miplearn.features.sample import Sample +from miplearn.features.sample import Sample, MemorySample from miplearn.instance.base import Instance from miplearn.instance.picklegz import PickleGzInstance from miplearn.solvers import _RedirectOutput @@ -150,7 +150,7 @@ class LearningSolver: # Initialize training sample # ------------------------------------------------------- - sample = Sample() + sample = MemorySample() instance.push_sample(sample) # Initialize stats diff --git a/tests/components/test_dynamic_lazy.py b/tests/components/test_dynamic_lazy.py index f29dc47..7e54831 100644 --- a/tests/components/test_dynamic_lazy.py +++ b/tests/components/test_dynamic_lazy.py @@ -11,7 +11,7 @@ from miplearn.classifiers import Classifier from miplearn.classifiers.threshold import MinProbabilityThreshold from miplearn.components import classifier_evaluation_dict from miplearn.components.dynamic_lazy import DynamicLazyConstraintsComponent -from miplearn.features.sample import Sample +from miplearn.features.sample import Sample, MemorySample from miplearn.instance.base import Instance from miplearn.solvers.tests import assert_equals @@ -22,13 +22,13 @@ E = 0.1 def training_instances() -> List[Instance]: instances = [cast(Instance, Mock(spec=Instance)) for _ in range(2)] samples_0 = [ - Sample( + MemorySample( { "lazy_enforced": {"c1", "c2"}, "instance_features_user": [5.0], }, ), - Sample( + MemorySample( { "lazy_enforced": {"c2", "c3"}, "instance_features_user": [5.0], @@ -53,7 +53,7 @@ def training_instances() -> List[Instance]: } ) samples_1 = [ - Sample( + MemorySample( { "lazy_enforced": {"c3", "c4"}, "instance_features_user": [8.0], diff --git a/tests/components/test_objective.py b/tests/components/test_objective.py index 84f5bc6..57ef271 100644 --- a/tests/components/test_objective.py +++ b/tests/components/test_objective.py @@ -10,14 +10,14 @@ from numpy.testing import assert_array_equal from miplearn.classifiers import Regressor from miplearn.components.objective import ObjectiveValueComponent -from miplearn.features.sample import Sample +from miplearn.features.sample import Sample, MemorySample from miplearn.solvers.learning import LearningSolver from miplearn.solvers.pyomo.gurobi import GurobiPyomoSolver @pytest.fixture def sample() -> Sample: - sample = Sample( + sample = MemorySample( { "mip_lower_bound": 1.0, "mip_upper_bound": 2.0, diff --git a/tests/components/test_primal.py b/tests/components/test_primal.py index 16b6c2d..e4f2661 100644 --- a/tests/components/test_primal.py +++ b/tests/components/test_primal.py @@ -12,7 +12,7 @@ from miplearn.classifiers import Classifier from miplearn.classifiers.threshold import Threshold from miplearn.components import classifier_evaluation_dict from miplearn.components.primal import PrimalSolutionComponent -from miplearn.features.sample import Sample +from miplearn.features.sample import Sample, MemorySample from miplearn.problems.tsp import TravelingSalesmanGenerator from miplearn.solvers.learning import LearningSolver from miplearn.solvers.tests import assert_equals @@ -20,7 +20,7 @@ from miplearn.solvers.tests import assert_equals @pytest.fixture def sample() -> Sample: - sample = Sample( + sample = MemorySample( { "var_names": ["x[0]", "x[1]", "x[2]", "x[3]"], "var_categories": ["default", None, "default", "default"], diff --git a/tests/components/test_static_lazy.py b/tests/components/test_static_lazy.py index ed4f91d..2412eb8 100644 --- a/tests/components/test_static_lazy.py +++ b/tests/components/test_static_lazy.py @@ -11,7 +11,7 @@ from numpy.testing import assert_array_equal from miplearn.classifiers import Classifier from miplearn.classifiers.threshold import Threshold, MinProbabilityThreshold from miplearn.components.static_lazy import StaticLazyConstraintsComponent -from miplearn.features.sample import Sample +from miplearn.features.sample import Sample, MemorySample from miplearn.instance.base import Instance from miplearn.solvers.internal import InternalSolver, Constraints from miplearn.solvers.learning import LearningSolver @@ -22,7 +22,7 @@ from miplearn.types import ( @pytest.fixture def sample() -> Sample: - sample = Sample( + sample = MemorySample( { "constr_categories": [ "type-a", diff --git a/tests/test_features.py b/tests/test_features.py index c7b5557..7c192ea 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -5,7 +5,7 @@ import numpy as np from miplearn.features.extractor import FeaturesExtractor -from miplearn.features.sample import Sample +from miplearn.features.sample import Sample, MemorySample from miplearn.solvers.internal import Variables, Constraints from miplearn.solvers.gurobi import GurobiSolver from miplearn.solvers.tests import assert_equals @@ -19,7 +19,7 @@ def test_knapsack() -> None: model = instance.to_model() solver.set_instance(instance, model) extractor = FeaturesExtractor() - sample = Sample() + sample = MemorySample() # after-load # -------------------------------------------------------