Reorganize instance package

master
Alinson S. Xavier 5 years ago
parent 3543a2ba92
commit f90f295620
No known key found for this signature in database
GPG Key ID: DCA0DAD4D2F58624

1
.gitignore vendored

@ -58,7 +58,6 @@ eggs/
env.bak/ env.bak/
env/ env/
htmlcov/ htmlcov/
instance/
ipython_config.py ipython_config.py
lib/ lib/
lib64/ lib64/

@ -3,15 +3,9 @@
# Released under the modified BSD license. See COPYING.md for more details. # Released under the modified BSD license. See COPYING.md for more details.
from .benchmark import BenchmarkRunner from .benchmark import BenchmarkRunner
from .classifiers import ( from .classifiers import Classifier, Regressor
Classifier,
Regressor,
)
from .classifiers.adaptive import AdaptiveClassifier from .classifiers.adaptive import AdaptiveClassifier
from .classifiers.sklearn import ( from .classifiers.sklearn import ScikitLearnRegressor, ScikitLearnClassifier
ScikitLearnRegressor,
ScikitLearnClassifier,
)
from .classifiers.threshold import MinPrecisionThreshold from .classifiers.threshold import MinPrecisionThreshold
from .components.component import Component from .components.component import Component
from .components.dynamic_lazy import DynamicLazyConstraintsComponent from .components.dynamic_lazy import DynamicLazyConstraintsComponent
@ -22,12 +16,12 @@ from .components.static_lazy import StaticLazyConstraintsComponent
from .components.steps.convert_tight import ConvertTightIneqsIntoEqsStep from .components.steps.convert_tight import ConvertTightIneqsIntoEqsStep
from .components.steps.drop_redundant import DropRedundantInequalitiesStep from .components.steps.drop_redundant import DropRedundantInequalitiesStep
from .components.steps.relax_integrality import RelaxIntegralityStep from .components.steps.relax_integrality import RelaxIntegralityStep
from .instance import ( from .instance.base import Instance
Instance, from .instance.picklegz import (
PickleGzInstance, PickleGzInstance,
write_pickle_gz, write_pickle_gz,
write_pickle_gz_multiple,
read_pickle_gz, read_pickle_gz,
write_pickle_gz_multiple,
) )
from .log import setup_logger from .log import setup_logger
from .solvers.gurobi import GurobiSolver from .solvers.gurobi import GurobiSolver

@ -8,7 +8,7 @@ from typing import Dict, List
import pandas as pd import pandas as pd
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.solvers.learning import LearningSolver from miplearn.solvers.learning import LearningSolver
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

@ -7,7 +7,7 @@ from typing import Any, List, TYPE_CHECKING, Tuple, Dict, Hashable
import numpy as np import numpy as np
from miplearn.features import TrainingSample, Features from miplearn.features import TrainingSample, Features
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.types import LearningSolveStats from miplearn.types import LearningSolveStats
if TYPE_CHECKING: if TYPE_CHECKING:

@ -12,7 +12,7 @@ from miplearn.classifiers import Regressor
from miplearn.classifiers.sklearn import ScikitLearnRegressor from miplearn.classifiers.sklearn import ScikitLearnRegressor
from miplearn.components.component import Component from miplearn.components.component import Component
from miplearn.features import TrainingSample, Features from miplearn.features import TrainingSample, Features
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.types import LearningSolveStats from miplearn.types import LearningSolveStats
if TYPE_CHECKING: if TYPE_CHECKING:

@ -21,7 +21,7 @@ from miplearn.classifiers.threshold import MinPrecisionThreshold, Threshold
from miplearn.components import classifier_evaluation_dict from miplearn.components import classifier_evaluation_dict
from miplearn.components.component import Component from miplearn.components.component import Component
from miplearn.features import TrainingSample, Features from miplearn.features import TrainingSample, Features
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.types import ( from miplearn.types import (
Solution, Solution,
LearningSolveStats, LearningSolveStats,

@ -11,7 +11,7 @@ from miplearn.types import VarIndex, Solution
if TYPE_CHECKING: if TYPE_CHECKING:
from miplearn.solvers.internal import InternalSolver from miplearn.solvers.internal import InternalSolver
from miplearn.instance import Instance from miplearn.instance.base import Instance
@dataclass @dataclass

@ -0,0 +1,3 @@
# MIPLearn: Extensible Framework for Learning-Enhanced Mixed-Integer Optimization
# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.

@ -2,12 +2,9 @@
# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved. # Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details. # Released under the modified BSD license. See COPYING.md for more details.
import gzip
import logging import logging
import os
import pickle
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Any, List, Optional, Hashable, IO, cast from typing import Any, List, Optional, Hashable
from miplearn.features import TrainingSample, Features from miplearn.features import TrainingSample, Features
from miplearn.types import VarIndex from miplearn.types import VarIndex
@ -15,29 +12,11 @@ from miplearn.types import VarIndex
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def write_pickle_gz(obj: Any, filename: str) -> None:
logger.info(f"Writing: {filename}")
os.makedirs(os.path.dirname(filename), exist_ok=True)
with gzip.GzipFile(filename, "wb") as file:
pickle.dump(obj, cast(IO[bytes], file))
def read_pickle_gz(filename: str) -> Any:
logger.info(f"Reading: {filename}")
with gzip.GzipFile(filename, "rb") as file:
return pickle.load(cast(IO[bytes], file))
def write_pickle_gz_multiple(objs: List[Any], dirname: str) -> None:
for (i, obj) in enumerate(objs):
write_pickle_gz(obj, f"{dirname}/{i:05d}.pkl.gz")
# noinspection PyMethodMayBeStatic # noinspection PyMethodMayBeStatic
class Instance(ABC): class Instance(ABC):
""" """
Abstract class holding all the data necessary to generate a concrete model of the Abstract class holding all the data necessary to generate a concrete model of the
problem. proble.
In the knapsack problem, for example, this class could hold the number of items, In the knapsack problem, for example, this class could hold the number of items,
their weights and costs, as well as the size of the knapsack. Objects their weights and costs, as well as the size of the knapsack. Objects
@ -184,111 +163,3 @@ class Instance(ABC):
Save any pending changes made to the instance to the underlying data store. Save any pending changes made to the instance to the underlying data store.
""" """
pass pass
def lazy_load(func):
def inner(self, *args):
if self.instance is None:
self.instance = self._load()
self.features = self.instance.features
self.training_data = self.instance.training_data
return func(self, *args)
return inner
class PickleGzInstance(Instance):
"""
An instance backed by a gzipped pickle file.
The instance is only loaded to memory after an operation is called (for example,
`to_model`).
Parameters
----------
filename: str
Path of the gzipped pickle file that should be loaded.
"""
# noinspection PyMissingConstructor
def __init__(self, filename: str) -> None:
assert os.path.exists(filename), f"File not found: {filename}"
self.instance: Optional[Instance] = None
self.filename: str = filename
@lazy_load
def to_model(self) -> Any:
assert self.instance is not None
return self.instance.to_model()
@lazy_load
def get_instance_features(self) -> List[float]:
assert self.instance is not None
return self.instance.get_instance_features()
@lazy_load
def get_variable_features(self, var_name: str, index: VarIndex) -> List[float]:
assert self.instance is not None
return self.instance.get_variable_features(var_name, index)
@lazy_load
def get_variable_category(
self,
var_name: str,
index: VarIndex,
) -> Optional[Hashable]:
assert self.instance is not None
return self.instance.get_variable_category(var_name, index)
@lazy_load
def get_constraint_features(self, cid: str) -> Optional[List[float]]:
assert self.instance is not None
return self.instance.get_constraint_features(cid)
@lazy_load
def get_constraint_category(self, cid: str) -> Optional[Hashable]:
assert self.instance is not None
return self.instance.get_constraint_category(cid)
@lazy_load
def has_static_lazy_constraints(self) -> bool:
assert self.instance is not None
return self.instance.has_static_lazy_constraints()
@lazy_load
def has_dynamic_lazy_constraints(self):
assert self.instance is not None
return self.instance.has_dynamic_lazy_constraints()
@lazy_load
def is_constraint_lazy(self, cid: str) -> bool:
assert self.instance is not None
return self.instance.is_constraint_lazy(cid)
@lazy_load
def find_violated_lazy_constraints(self, model):
assert self.instance is not None
return self.instance.find_violated_lazy_constraints(model)
@lazy_load
def build_lazy_constraint(self, model, violation):
assert self.instance is not None
return self.instance.build_lazy_constraint(model, violation)
@lazy_load
def find_violated_user_cuts(self, model):
assert self.instance is not None
return self.instance.find_violated_user_cuts(model)
@lazy_load
def build_user_cut(self, model, violation):
assert self.instance is not None
return self.instance.build_user_cut(model, violation)
def _load(self) -> Instance:
obj = read_pickle_gz(self.filename)
assert isinstance(obj, Instance)
return obj
def flush(self) -> None:
write_pickle_gz(self.instance, self.filename)

@ -0,0 +1,137 @@
# MIPLearn: Extensible Framework for Learning-Enhanced Mixed-Integer Optimization
# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
import gzip
import os
import pickle
from typing import Optional, Any, List, Hashable, cast, IO
from miplearn.instance.base import logger, Instance
from miplearn.types import VarIndex
def lazy_load(func):
def inner(self, *args):
if self.instance is None:
self.instance = self._load()
self.features = self.instance.features
self.training_data = self.instance.training_data
return func(self, *args)
return inner
class PickleGzInstance(Instance):
"""
An instance backed by a gzipped pickle file.
The instance is only loaded to memory after an operation is called (for example,
`to_model`).
Parameters
----------
filename: str
Path of the gzipped pickle file that should be loaded.
"""
# noinspection PyMissingConstructor
def __init__(self, filename: str) -> None:
assert os.path.exists(filename), f"File not found: {filename}"
self.instance: Optional[Instance] = None
self.filename: str = filename
@lazy_load
def to_model(self) -> Any:
assert self.instance is not None
return self.instance.to_model()
@lazy_load
def get_instance_features(self) -> List[float]:
assert self.instance is not None
return self.instance.get_instance_features()
@lazy_load
def get_variable_features(self, var_name: str, index: VarIndex) -> List[float]:
assert self.instance is not None
return self.instance.get_variable_features(var_name, index)
@lazy_load
def get_variable_category(
self,
var_name: str,
index: VarIndex,
) -> Optional[Hashable]:
assert self.instance is not None
return self.instance.get_variable_category(var_name, index)
@lazy_load
def get_constraint_features(self, cid: str) -> Optional[List[float]]:
assert self.instance is not None
return self.instance.get_constraint_features(cid)
@lazy_load
def get_constraint_category(self, cid: str) -> Optional[Hashable]:
assert self.instance is not None
return self.instance.get_constraint_category(cid)
@lazy_load
def has_static_lazy_constraints(self) -> bool:
assert self.instance is not None
return self.instance.has_static_lazy_constraints()
@lazy_load
def has_dynamic_lazy_constraints(self):
assert self.instance is not None
return self.instance.has_dynamic_lazy_constraints()
@lazy_load
def is_constraint_lazy(self, cid: str) -> bool:
assert self.instance is not None
return self.instance.is_constraint_lazy(cid)
@lazy_load
def find_violated_lazy_constraints(self, model):
assert self.instance is not None
return self.instance.find_violated_lazy_constraints(model)
@lazy_load
def build_lazy_constraint(self, model, violation):
assert self.instance is not None
return self.instance.build_lazy_constraint(model, violation)
@lazy_load
def find_violated_user_cuts(self, model):
assert self.instance is not None
return self.instance.find_violated_user_cuts(model)
@lazy_load
def build_user_cut(self, model, violation):
assert self.instance is not None
return self.instance.build_user_cut(model, violation)
def _load(self) -> Instance:
obj = read_pickle_gz(self.filename)
assert isinstance(obj, Instance)
return obj
def flush(self) -> None:
write_pickle_gz(self.instance, self.filename)
def write_pickle_gz(obj: Any, filename: str) -> None:
logger.info(f"Writing: {filename}")
os.makedirs(os.path.dirname(filename), exist_ok=True)
with gzip.GzipFile(filename, "wb") as file:
pickle.dump(obj, cast(IO[bytes], file))
def read_pickle_gz(filename: str) -> Any:
logger.info(f"Reading: {filename}")
with gzip.GzipFile(filename, "rb") as file:
return pickle.load(cast(IO[bytes], file))
def write_pickle_gz_multiple(objs: List[Any], dirname: str) -> None:
for (i, obj) in enumerate(objs):
write_pickle_gz(obj, f"{dirname}/{i:05d}.pkl.gz")

@ -8,7 +8,7 @@ import pyomo.environ as pe
from scipy.stats import uniform, randint from scipy.stats import uniform, randint
from scipy.stats.distributions import rv_frozen from scipy.stats.distributions import rv_frozen
from miplearn.instance import Instance from miplearn.instance.base import Instance
class ChallengeA: class ChallengeA:

@ -8,7 +8,7 @@ import pyomo.environ as pe
from scipy.stats import uniform, randint from scipy.stats import uniform, randint
from scipy.stats.distributions import rv_frozen from scipy.stats.distributions import rv_frozen
from miplearn.instance import Instance from miplearn.instance.base import Instance
class ChallengeA: class ChallengeA:

@ -9,7 +9,7 @@ from scipy.spatial.distance import pdist, squareform
from scipy.stats import uniform, randint from scipy.stats import uniform, randint
from scipy.stats.distributions import rv_frozen from scipy.stats.distributions import rv_frozen
from miplearn.instance import Instance from miplearn.instance.base import Instance
class ChallengeA: class ChallengeA:

@ -8,7 +8,7 @@ from io import StringIO
from random import randint from random import randint
from typing import List, Any, Dict, Optional, cast, Tuple, Union from typing import List, Any, Dict, Optional, cast, Tuple, Union
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.solvers import _RedirectOutput from miplearn.solvers import _RedirectOutput
from miplearn.solvers.internal import ( from miplearn.solvers.internal import (
InternalSolver, InternalSolver,

@ -6,7 +6,7 @@ import logging
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.types import ( from miplearn.types import (
LPSolveStats, LPSolveStats,
IterationCallback, IterationCallback,

@ -14,7 +14,8 @@ from miplearn.components.dynamic_user_cuts import UserCutsComponent
from miplearn.components.objective import ObjectiveValueComponent from miplearn.components.objective import ObjectiveValueComponent
from miplearn.components.primal import PrimalSolutionComponent from miplearn.components.primal import PrimalSolutionComponent
from miplearn.features import FeaturesExtractor, TrainingSample from miplearn.features import FeaturesExtractor, TrainingSample
from miplearn.instance import Instance, PickleGzInstance from miplearn.instance.base import Instance
from miplearn.instance.picklegz import PickleGzInstance
from miplearn.solvers import _RedirectOutput from miplearn.solvers import _RedirectOutput
from miplearn.solvers.internal import InternalSolver from miplearn.solvers.internal import InternalSolver
from miplearn.solvers.pyomo.gurobi import GurobiPyomoSolver from miplearn.solvers.pyomo.gurobi import GurobiPyomoSolver

@ -14,7 +14,7 @@ from pyomo.core import Var, Constraint
from pyomo.opt import TerminationCondition from pyomo.opt import TerminationCondition
from pyomo.opt.base.solvers import SolverFactory from pyomo.opt.base.solvers import SolverFactory
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.solvers import _RedirectOutput from miplearn.solvers import _RedirectOutput
from miplearn.solvers.internal import ( from miplearn.solvers.internal import (
InternalSolver, InternalSolver,

@ -7,7 +7,7 @@ from unittest.mock import Mock
from miplearn.classifiers import Classifier from miplearn.classifiers import Classifier
from miplearn.components.steps.convert_tight import ConvertTightIneqsIntoEqsStep from miplearn.components.steps.convert_tight import ConvertTightIneqsIntoEqsStep
from miplearn.components.steps.relax_integrality import RelaxIntegralityStep from miplearn.components.steps.relax_integrality import RelaxIntegralityStep
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.problems.knapsack import GurobiKnapsackInstance from miplearn.problems.knapsack import GurobiKnapsackInstance
from miplearn.solvers.gurobi import GurobiSolver from miplearn.solvers.gurobi import GurobiSolver
from miplearn.solvers.learning import LearningSolver from miplearn.solvers.learning import LearningSolver

@ -10,7 +10,7 @@ from miplearn.classifiers import Classifier
from miplearn.components.steps.drop_redundant import DropRedundantInequalitiesStep from miplearn.components.steps.drop_redundant import DropRedundantInequalitiesStep
from miplearn.components.steps.relax_integrality import RelaxIntegralityStep from miplearn.components.steps.relax_integrality import RelaxIntegralityStep
from miplearn.features import TrainingSample, Features from miplearn.features import TrainingSample, Features
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.solvers.gurobi import GurobiSolver from miplearn.solvers.gurobi import GurobiSolver
from miplearn.solvers.internal import InternalSolver from miplearn.solvers.internal import InternalSolver
from miplearn.solvers.learning import LearningSolver from miplearn.solvers.learning import LearningSolver

@ -4,7 +4,7 @@
from unittest.mock import Mock from unittest.mock import Mock
from miplearn.components.component import Component from miplearn.components.component import Component
from miplearn.instance import Instance from miplearn.instance.base import Instance
def test_xy_instance(): def test_xy_instance():

@ -17,7 +17,7 @@ from miplearn.features import (
Features, Features,
InstanceFeatures, InstanceFeatures,
) )
from miplearn.instance import Instance from miplearn.instance.base import Instance
E = 0.1 E = 0.1

@ -12,7 +12,7 @@ from gurobipy import GRB
from networkx import Graph from networkx import Graph
from miplearn.components.dynamic_user_cuts import UserCutsComponent from miplearn.components.dynamic_user_cuts import UserCutsComponent
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.solvers.gurobi import GurobiSolver from miplearn.solvers.gurobi import GurobiSolver
from miplearn.solvers.learning import LearningSolver from miplearn.solvers.learning import LearningSolver

@ -11,7 +11,7 @@ from numpy.testing import assert_array_equal
from miplearn.classifiers import Regressor from miplearn.classifiers import Regressor
from miplearn.components.objective import ObjectiveValueComponent from miplearn.components.objective import ObjectiveValueComponent
from miplearn.features import TrainingSample, InstanceFeatures, Features from miplearn.features import TrainingSample, InstanceFeatures, Features
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.solvers.learning import LearningSolver from miplearn.solvers.learning import LearningSolver
from miplearn.solvers.pyomo.gurobi import GurobiPyomoSolver from miplearn.solvers.pyomo.gurobi import GurobiPyomoSolver
from tests.fixtures.knapsack import get_knapsack_instance from tests.fixtures.knapsack import get_knapsack_instance

@ -12,7 +12,7 @@ from miplearn.classifiers.threshold import Threshold
from miplearn.components import classifier_evaluation_dict from miplearn.components import classifier_evaluation_dict
from miplearn.components.primal import PrimalSolutionComponent from miplearn.components.primal import PrimalSolutionComponent
from miplearn.features import TrainingSample, VariableFeatures, Features from miplearn.features import TrainingSample, VariableFeatures, Features
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.problems.tsp import TravelingSalesmanGenerator from miplearn.problems.tsp import TravelingSalesmanGenerator
from miplearn.solvers.learning import LearningSolver from miplearn.solvers.learning import LearningSolver

@ -17,7 +17,7 @@ from miplearn.features import (
ConstraintFeatures, ConstraintFeatures,
Features, Features,
) )
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.solvers.internal import InternalSolver from miplearn.solvers.internal import InternalSolver
from miplearn.solvers.learning import LearningSolver from miplearn.solvers.learning import LearningSolver
from miplearn.types import ( from miplearn.types import (

@ -6,7 +6,7 @@ from typing import Any
from pyomo import environ as pe from pyomo import environ as pe
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.solvers.gurobi import GurobiSolver from miplearn.solvers.gurobi import GurobiSolver
from miplearn.solvers.pyomo.base import BasePyomoSolver from miplearn.solvers.pyomo.base import BasePyomoSolver
from tests.solvers import _is_subclass_or_instance from tests.solvers import _is_subclass_or_instance

@ -1,7 +1,7 @@
# MIPLearn: Extensible Framework for Learning-Enhanced Mixed-Integer Optimization # MIPLearn: Extensible Framework for Learning-Enhanced Mixed-Integer Optimization
# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved. # Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details. # Released under the modified BSD license. See COPYING.md for more details.
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.problems.knapsack import KnapsackInstance, GurobiKnapsackInstance from miplearn.problems.knapsack import KnapsackInstance, GurobiKnapsackInstance
from miplearn.solvers.gurobi import GurobiSolver from miplearn.solvers.gurobi import GurobiSolver
from miplearn.solvers.internal import InternalSolver from miplearn.solvers.internal import InternalSolver

@ -5,7 +5,7 @@ from typing import Any
import pyomo.environ as pe import pyomo.environ as pe
from miplearn.instance import Instance from miplearn.instance.base import Instance
from miplearn.solvers.gurobi import GurobiSolver from miplearn.solvers.gurobi import GurobiSolver
from miplearn.solvers.pyomo.base import BasePyomoSolver from miplearn.solvers.pyomo.base import BasePyomoSolver
from tests.solvers import _is_subclass_or_instance from tests.solvers import _is_subclass_or_instance

@ -0,0 +1,3 @@
# MIPLearn: Extensible Framework for Learning-Enhanced Mixed-Integer Optimization
# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.

@ -3,12 +3,12 @@
# Released under the modified BSD license. See COPYING.md for more details. # Released under the modified BSD license. See COPYING.md for more details.
import tempfile import tempfile
from miplearn.instance import write_pickle_gz, PickleGzInstance from miplearn.instance.picklegz import write_pickle_gz, PickleGzInstance
from miplearn.solvers.gurobi import GurobiSolver from miplearn.solvers.gurobi import GurobiSolver
from tests.fixtures.knapsack import get_knapsack_instance from tests.fixtures.knapsack import get_knapsack_instance
def test_pickled() -> None: def test_usage() -> None:
original = get_knapsack_instance(GurobiSolver()) original = get_knapsack_instance(GurobiSolver())
file = tempfile.NamedTemporaryFile() file = tempfile.NamedTemporaryFile()
write_pickle_gz(original, file.name) write_pickle_gz(original, file.name)

@ -8,7 +8,7 @@ import tempfile
import dill import dill
from miplearn.instance import PickleGzInstance, write_pickle_gz, read_pickle_gz from miplearn.instance.picklegz import PickleGzInstance, write_pickle_gz, read_pickle_gz
from miplearn.solvers.gurobi import GurobiSolver from miplearn.solvers.gurobi import GurobiSolver
from miplearn.solvers.learning import LearningSolver from miplearn.solvers.learning import LearningSolver
from . import _get_knapsack_instance, get_internal_solvers from . import _get_knapsack_instance, get_internal_solvers

Loading…
Cancel
Save