mirror of
https://github.com/ANL-CEEESA/MIPLearn.git
synced 2025-12-06 09:28:51 -06:00
Move instance fixtures into the main source; remove duplication
This commit is contained in:
@@ -19,6 +19,7 @@ from miplearn.solvers.internal import (
|
||||
LazyCallback,
|
||||
MIPSolveStats,
|
||||
)
|
||||
from miplearn.solvers.pyomo.base import PyomoTestInstanceKnapsack
|
||||
from miplearn.types import (
|
||||
SolverParams,
|
||||
UserCutCallback,
|
||||
@@ -442,3 +443,77 @@ class GurobiSolver(InternalSolver):
|
||||
params=self.params,
|
||||
lazy_cb_frequency=self.lazy_cb_frequency,
|
||||
)
|
||||
|
||||
@overrides
|
||||
def build_test_instance_infeasible(self) -> Instance:
|
||||
return GurobiTestInstanceInfeasible()
|
||||
|
||||
@overrides
|
||||
def build_test_instance_redundancy(self) -> Instance:
|
||||
return GurobiTestInstanceRedundancy()
|
||||
|
||||
@overrides
|
||||
def build_test_instance_knapsack(self) -> Instance:
|
||||
return GurobiTestInstanceKnapsack(
|
||||
weights=[23.0, 26.0, 20.0, 18.0],
|
||||
prices=[505.0, 352.0, 458.0, 220.0],
|
||||
capacity=67.0,
|
||||
)
|
||||
|
||||
|
||||
class GurobiTestInstanceInfeasible(Instance):
|
||||
@overrides
|
||||
def to_model(self) -> Any:
|
||||
import gurobipy as gp
|
||||
from gurobipy import GRB
|
||||
|
||||
model = gp.Model()
|
||||
x = model.addVars(1, vtype=GRB.BINARY, name="x")
|
||||
model.addConstr(x[0] >= 2)
|
||||
model.setObjective(x[0])
|
||||
return model
|
||||
|
||||
|
||||
class GurobiTestInstanceRedundancy(Instance):
|
||||
def to_model(self) -> Any:
|
||||
import gurobipy as gp
|
||||
from gurobipy import GRB
|
||||
|
||||
model = gp.Model()
|
||||
x = model.addVars(2, vtype=GRB.BINARY, name="x")
|
||||
model.addConstr(x[0] + x[1] <= 1)
|
||||
model.addConstr(x[0] + x[1] <= 2)
|
||||
model.setObjective(x[0] + x[1], GRB.MAXIMIZE)
|
||||
return model
|
||||
|
||||
|
||||
class GurobiTestInstanceKnapsack(PyomoTestInstanceKnapsack):
|
||||
"""
|
||||
Simpler (one-dimensional) knapsack instance, implemented directly in Gurobi
|
||||
instead of Pyomo, used for testing.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
weights: List[float],
|
||||
prices: List[float],
|
||||
capacity: float,
|
||||
) -> None:
|
||||
super().__init__(weights, prices, capacity)
|
||||
|
||||
@overrides
|
||||
def to_model(self) -> Any:
|
||||
import gurobipy as gp
|
||||
from gurobipy import GRB
|
||||
|
||||
model = gp.Model("Knapsack")
|
||||
n = len(self.weights)
|
||||
x = model.addVars(n, vtype=GRB.BINARY, name="x")
|
||||
model.addConstr(
|
||||
gp.quicksum(x[i] * self.weights[i] for i in range(n)) <= self.capacity,
|
||||
"eq_capacity",
|
||||
)
|
||||
model.setObjective(
|
||||
gp.quicksum(x[i] * self.prices[i] for i in range(n)), GRB.MAXIMIZE
|
||||
)
|
||||
return model
|
||||
|
||||
@@ -292,3 +292,15 @@ class InternalSolver(ABC):
|
||||
completely unitialized.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def build_test_instance_infeasible(self) -> Instance:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def build_test_instance_redundancy(self) -> Instance:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def build_test_instance_knapsack(self) -> Instance:
|
||||
pass
|
||||
|
||||
@@ -29,7 +29,9 @@ from miplearn.types import (
|
||||
UserCutCallback,
|
||||
Solution,
|
||||
VariableName,
|
||||
Category,
|
||||
)
|
||||
import numpy as np
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -338,3 +340,88 @@ class BasePyomoSolver(InternalSolver):
|
||||
@overrides
|
||||
def get_sense(self) -> str:
|
||||
return self._obj_sense
|
||||
|
||||
@overrides
|
||||
def build_test_instance_infeasible(self) -> Instance:
|
||||
return PyomoTestInstanceInfeasible()
|
||||
|
||||
@overrides
|
||||
def build_test_instance_redundancy(self) -> Instance:
|
||||
return PyomoTestInstanceRedundancy()
|
||||
|
||||
@overrides
|
||||
def build_test_instance_knapsack(self) -> Instance:
|
||||
return PyomoTestInstanceKnapsack(
|
||||
weights=[23.0, 26.0, 20.0, 18.0],
|
||||
prices=[505.0, 352.0, 458.0, 220.0],
|
||||
capacity=67.0,
|
||||
)
|
||||
|
||||
|
||||
class PyomoTestInstanceInfeasible(Instance):
|
||||
@overrides
|
||||
def to_model(self) -> pe.ConcreteModel:
|
||||
model = pe.ConcreteModel()
|
||||
model.x = pe.Var([0], domain=pe.Binary)
|
||||
model.OBJ = pe.Objective(expr=model.x[0], sense=pe.maximize)
|
||||
model.eq = pe.Constraint(expr=model.x[0] >= 2)
|
||||
return model
|
||||
|
||||
|
||||
class PyomoTestInstanceRedundancy(Instance):
|
||||
def to_model(self) -> pe.ConcreteModel:
|
||||
model = pe.ConcreteModel()
|
||||
model.x = pe.Var([0, 1], domain=pe.Binary)
|
||||
model.OBJ = pe.Objective(expr=model.x[0] + model.x[1], sense=pe.maximize)
|
||||
model.eq1 = pe.Constraint(expr=model.x[0] + model.x[1] <= 1)
|
||||
model.eq2 = pe.Constraint(expr=model.x[0] + model.x[1] <= 2)
|
||||
return model
|
||||
|
||||
|
||||
class PyomoTestInstanceKnapsack(Instance):
|
||||
"""
|
||||
Simpler (one-dimensional) Knapsack Problem, used for testing.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
weights: List[float],
|
||||
prices: List[float],
|
||||
capacity: float,
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.weights = weights
|
||||
self.prices = prices
|
||||
self.capacity = capacity
|
||||
self.varname_to_item: Dict[VariableName, int] = {
|
||||
f"x[{i}]": i for i in range(len(self.weights))
|
||||
}
|
||||
|
||||
@overrides
|
||||
def to_model(self) -> pe.ConcreteModel:
|
||||
model = pe.ConcreteModel()
|
||||
items = range(len(self.weights))
|
||||
model.x = pe.Var(items, domain=pe.Binary)
|
||||
model.OBJ = pe.Objective(
|
||||
expr=sum(model.x[v] * self.prices[v] for v in items),
|
||||
sense=pe.maximize,
|
||||
)
|
||||
model.eq_capacity = pe.Constraint(
|
||||
expr=sum(model.x[v] * self.weights[v] for v in items) <= self.capacity
|
||||
)
|
||||
return model
|
||||
|
||||
@overrides
|
||||
def get_instance_features(self) -> List[float]:
|
||||
return [
|
||||
self.capacity,
|
||||
np.average(self.weights),
|
||||
]
|
||||
|
||||
@overrides
|
||||
def get_variable_features(self, var_name: VariableName) -> List[Category]:
|
||||
item = self.varname_to_item[var_name]
|
||||
return [
|
||||
self.weights[item],
|
||||
self.prices[item],
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user