Remove sample.after_load

master
Alinson S. Xavier 4 years ago
parent b4a267a524
commit cd9e5d4144
No known key found for this signature in database
GPG Key ID: DCA0DAD4D2F58624

@ -52,6 +52,8 @@ class DynamicConstraintsComponent(Component):
cids: Dict[Hashable, List[str]] = {} cids: Dict[Hashable, List[str]] = {}
constr_categories_dict = instance.get_constraint_categories() constr_categories_dict = instance.get_constraint_categories()
constr_features_dict = instance.get_constraint_features() constr_features_dict = instance.get_constraint_features()
instance_features = sample.get("instance_features_user")
assert instance_features is not None
for cid in self.known_cids: for cid in self.known_cids:
# Initialize categories # Initialize categories
if cid in constr_categories_dict: if cid in constr_categories_dict:
@ -66,10 +68,8 @@ class DynamicConstraintsComponent(Component):
cids[category] = [] cids[category] = []
# Features # Features
features = [] features: List[float] = []
assert sample.after_load is not None features.extend(instance_features)
assert sample.after_load.instance is not None
features.extend(sample.after_load.instance.to_list())
if cid in constr_features_dict: if cid in constr_features_dict:
features.extend(constr_features_dict[cid]) features.extend(constr_features_dict[cid])
for ci in features: for ci in features:

@ -103,8 +103,10 @@ class PrimalSolutionComponent(Component):
) )
def sample_predict(self, sample: Sample) -> Solution: def sample_predict(self, sample: Sample) -> Solution:
assert sample.after_load is not None var_names = sample.get("var_names")
assert sample.after_load.variables is not None var_categories = sample.get("var_categories")
assert var_names is not None
assert var_categories is not None
# Compute y_pred # Compute y_pred
x, _ = self.sample_xy(None, sample) x, _ = self.sample_xy(None, sample)
@ -125,12 +127,10 @@ class PrimalSolutionComponent(Component):
).T ).T
# Convert y_pred into solution # Convert y_pred into solution
assert sample.after_load.variables.names is not None solution: Solution = {v: None for v in var_names}
assert sample.after_load.variables.categories is not None
solution: Solution = {v: None for v in sample.after_load.variables.names}
category_offset: Dict[Hashable, int] = {cat: 0 for cat in x.keys()} category_offset: Dict[Hashable, int] = {cat: 0 for cat in x.keys()}
for (i, var_name) in enumerate(sample.after_load.variables.names): for (i, var_name) in enumerate(var_names):
category = sample.after_load.variables.categories[i] category = var_categories[i]
if category not in category_offset: if category not in category_offset:
continue continue
offset = category_offset[category] offset = category_offset[category]
@ -150,24 +150,21 @@ class PrimalSolutionComponent(Component):
) -> Tuple[Dict[Category, List[List[float]]], Dict[Category, List[List[float]]]]: ) -> Tuple[Dict[Category, List[List[float]]], Dict[Category, List[List[float]]]]:
x: Dict = {} x: Dict = {}
y: Dict = {} y: Dict = {}
assert sample.after_load is not None
assert sample.after_load.instance is not None
assert sample.after_load.variables is not None
assert sample.after_load.variables.names is not None
assert sample.after_load.variables.categories is not None
instance_features = sample.get("instance_features_user") instance_features = sample.get("instance_features_user")
mip_var_values = sample.get("mip_var_values") mip_var_values = sample.get("mip_var_values")
var_features = sample.get("lp_var_features") var_features = sample.get("lp_var_features")
var_names = sample.get("var_names")
var_categories = sample.get("var_categories")
if var_features is None: if var_features is None:
var_features = sample.get("var_features") var_features = sample.get("var_features")
assert instance_features is not None assert instance_features is not None
assert var_features is not None assert var_features is not None
assert var_names is not None
assert var_categories is not None
for (i, var_name) in enumerate(sample.after_load.variables.names): for (i, var_name) in enumerate(var_names):
# Initialize categories # Initialize categories
category = sample.after_load.variables.categories[i] category = var_categories[i]
if category is None: if category is None:
continue continue
if category not in x.keys(): if category not in x.keys():

@ -74,16 +74,15 @@ class StaticLazyConstraintsComponent(Component):
sample: Sample, sample: Sample,
) -> None: ) -> None:
assert solver.internal_solver is not None assert solver.internal_solver is not None
assert sample.after_load is not None static_lazy_count = sample.get("static_lazy_count")
assert sample.after_load.instance is not None assert static_lazy_count is not None
logger.info("Predicting violated (static) lazy constraints...") logger.info("Predicting violated (static) lazy constraints...")
if sample.after_load.instance.lazy_constraint_count == 0: if static_lazy_count == 0:
logger.info("Instance does not have static lazy constraints. Skipping.") logger.info("Instance does not have static lazy constraints. Skipping.")
self.enforced_cids = set(self.sample_predict(sample)) self.enforced_cids = set(self.sample_predict(sample))
logger.info("Moving lazy constraints to the pool...") logger.info("Moving lazy constraints to the pool...")
constraints = sample.after_load.constraints constraints = ConstraintFeatures.from_sample(sample)
assert constraints is not None
assert constraints.lazy is not None assert constraints.lazy is not None
assert constraints.names is not None assert constraints.names is not None
selected = [ selected = [

@ -82,9 +82,9 @@ class ConstraintFeatures:
basis_status: Optional[List[str]] = None basis_status: Optional[List[str]] = None
categories: Optional[List[Optional[Hashable]]] = None categories: Optional[List[Optional[Hashable]]] = None
dual_values: Optional[List[float]] = None dual_values: Optional[List[float]] = None
names: Optional[List[str]] = None
lazy: Optional[List[bool]] = None lazy: Optional[List[bool]] = None
lhs: Optional[List[List[Tuple[str, float]]]] = None lhs: Optional[List[List[Tuple[str, float]]]] = None
names: Optional[List[str]] = None
rhs: Optional[List[float]] = None rhs: Optional[List[float]] = None
sa_rhs_down: Optional[List[float]] = None sa_rhs_down: Optional[List[float]] = None
sa_rhs_up: Optional[List[float]] = None sa_rhs_up: Optional[List[float]] = None
@ -92,6 +92,23 @@ class ConstraintFeatures:
slacks: Optional[List[float]] = None slacks: Optional[List[float]] = None
user_features: Optional[List[Optional[List[float]]]] = None user_features: Optional[List[Optional[List[float]]]] = None
@staticmethod
def from_sample(sample: "Sample") -> "ConstraintFeatures":
return ConstraintFeatures(
basis_status=sample.get("lp_constr_basis_status"),
categories=sample.get("constr_categories"),
dual_values=sample.get("lp_constr_dual_values"),
lazy=sample.get("constr_lazy"),
lhs=sample.get("constr_lhs"),
names=sample.get("constr_names"),
rhs=sample.get("constr_rhs"),
sa_rhs_down=sample.get("lp_constr_sa_rhs_down"),
sa_rhs_up=sample.get("lp_constr_sa_rhs_up"),
senses=sample.get("constr_senses"),
slacks=sample.get("lp_constr_slacks"),
user_features=sample.get("constr_features_user"),
)
def to_list(self, index: int) -> List[float]: def to_list(self, index: int) -> List[float]:
features: List[float] = [] features: List[float] = []
for attr in [ for attr in [
@ -146,13 +163,11 @@ class Features:
class Sample: class Sample:
def __init__( def __init__(
self, self,
after_load: Optional[Features] = None,
data: Optional[Dict[str, Any]] = None, data: Optional[Dict[str, Any]] = None,
) -> None: ) -> None:
if data is None: if data is None:
data = {} data = {}
self._data: Dict[str, Any] = data self._data: Dict[str, Any] = data
self.after_load = after_load
def get(self, key: str) -> Optional[Any]: def get(self, key: str) -> Optional[Any]:
if key in self._data: if key in self._data:

@ -176,7 +176,6 @@ class LearningSolver:
"Features (after-load) extracted in %.2f seconds" "Features (after-load) extracted in %.2f seconds"
% (time.time() - initial_time) % (time.time() - initial_time)
) )
sample.after_load = features
callback_args = ( callback_args = (
self, self,

@ -27,16 +27,18 @@ def training_instances() -> List[Instance]:
instances = [cast(Instance, Mock(spec=Instance)) for _ in range(2)] instances = [cast(Instance, Mock(spec=Instance)) for _ in range(2)]
samples_0 = [ samples_0 = [
Sample( Sample(
after_load=Features(instance=InstanceFeatures()), {
data={"lazy_enforced": {"c1", "c2"}}, "lazy_enforced": {"c1", "c2"},
"instance_features_user": [5.0],
},
), ),
Sample( Sample(
after_load=Features(instance=InstanceFeatures()), {
data={"lazy_enforced": {"c2", "c3"}}, "lazy_enforced": {"c2", "c3"},
"instance_features_user": [5.0],
},
), ),
] ]
samples_0[0].after_load.instance.to_list = Mock(return_value=[5.0]) # type: ignore
samples_0[1].after_load.instance.to_list = Mock(return_value=[5.0]) # type: ignore
instances[0].get_samples = Mock(return_value=samples_0) # type: ignore instances[0].get_samples = Mock(return_value=samples_0) # type: ignore
instances[0].get_constraint_categories = Mock( # type: ignore instances[0].get_constraint_categories = Mock( # type: ignore
return_value={ return_value={
@ -56,11 +58,12 @@ def training_instances() -> List[Instance]:
) )
samples_1 = [ samples_1 = [
Sample( Sample(
after_load=Features(instance=InstanceFeatures()), {
data={"lazy_enforced": {"c3", "c4"}}, "lazy_enforced": {"c3", "c4"},
"instance_features_user": [8.0],
},
) )
] ]
samples_1[0].after_load.instance.to_list = Mock(return_value=[8.0]) # type: ignore
instances[1].get_samples = Mock(return_value=samples_1) # type: ignore instances[1].get_samples = Mock(return_value=samples_1) # type: ignore
instances[1].get_constraint_categories = Mock( # type: ignore instances[1].get_constraint_categories = Mock( # type: ignore
return_value={ return_value={

@ -10,8 +10,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 InstanceFeatures, Features, Sample from miplearn.features import Sample
from miplearn.solvers.internal import MIPSolveStats, LPSolveStats
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
@ -19,7 +18,7 @@ from miplearn.solvers.pyomo.gurobi import GurobiPyomoSolver
@pytest.fixture @pytest.fixture
def sample() -> Sample: def sample() -> Sample:
sample = Sample( sample = Sample(
data={ {
"mip_lower_bound": 1.0, "mip_lower_bound": 1.0,
"mip_upper_bound": 2.0, "mip_upper_bound": 2.0,
"lp_instance_features": [1.0, 2.0, 3.0], "lp_instance_features": [1.0, 2.0, 3.0],

@ -26,14 +26,7 @@ from miplearn.solvers.tests import assert_equals
@pytest.fixture @pytest.fixture
def sample() -> Sample: def sample() -> Sample:
sample = Sample( sample = Sample(
after_load=Features( {
instance=InstanceFeatures(),
variables=VariableFeatures(
names=["x[0]", "x[1]", "x[2]", "x[3]"],
categories=["default", None, "default", "default"],
),
),
data={
"var_names": ["x[0]", "x[1]", "x[2]", "x[3]"], "var_names": ["x[0]", "x[1]", "x[2]", "x[3]"],
"var_categories": ["default", None, "default", "default"], "var_categories": ["default", None, "default", "default"],
"mip_var_values": [0.0, 1.0, 1.0, 0.0], "mip_var_values": [0.0, 1.0, 1.0, 0.0],
@ -52,15 +45,6 @@ def sample() -> Sample:
], ],
}, },
) )
sample.after_load.instance.to_list = Mock(return_value=[5.0]) # type: ignore
sample.after_load.variables.to_list = Mock( # type:ignore
side_effect=lambda i: [
[0.0, 0.0],
None,
[1.0, 0.0],
[1.0, 1.0],
][i]
)
return sample return sample

@ -28,23 +28,7 @@ from miplearn.types import (
@pytest.fixture @pytest.fixture
def sample() -> Sample: def sample() -> Sample:
sample = Sample( sample = Sample(
after_load=Features( {
instance=InstanceFeatures(
lazy_constraint_count=4,
),
constraints=ConstraintFeatures(
names=["c1", "c2", "c3", "c4", "c5"],
categories=[
"type-a",
"type-a",
"type-a",
"type-b",
"type-b",
],
lazy=[True, True, True, True, False],
),
),
data={
"constr_categories": [ "constr_categories": [
"type-a", "type-a",
"type-a", "type-a",
@ -139,9 +123,7 @@ def test_usage_with_solver(instance: Instance) -> None:
# Should ask internal solver to verify if constraints in the pool are # Should ask internal solver to verify if constraints in the pool are
# satisfied and add the ones that are not # satisfied and add the ones that are not
assert sample.after_load is not None c = ConstraintFeatures.from_sample(sample)[[False, False, True, False, False]]
assert sample.after_load.constraints is not None
c = sample.after_load.constraints[[False, False, True, False, False]]
internal.are_constraints_satisfied.assert_called_once_with(c, tol=1.0) internal.are_constraints_satisfied.assert_called_once_with(c, tol=1.0)
internal.are_constraints_satisfied.reset_mock() internal.are_constraints_satisfied.reset_mock()
internal.add_constraints.assert_called_once_with(c) internal.add_constraints.assert_called_once_with(c)

Loading…
Cancel
Save