Make xy_sample receive features, not instances

This commit is contained in:
2021-03-31 09:57:57 -05:00
parent 8fc9979b37
commit fe7bad885c
12 changed files with 158 additions and 119 deletions

View File

@@ -7,8 +7,7 @@ from miplearn import Component, Instance
def test_xy_instance():
def _xy_sample(instance, sample):
print(sample)
def _xy_sample(features, sample):
x = {
"s1": {
"category_a": [
@@ -54,8 +53,10 @@ def test_xy_instance():
comp = Component()
instance_1 = Mock(spec=Instance)
instance_1.training_data = ["s1", "s2"]
instance_1.features = {}
instance_2 = Mock(spec=Instance)
instance_2.training_data = ["s3"]
instance_2.features = {}
comp.xy_sample = _xy_sample
x_expected = {
"category_a": [

View File

@@ -9,7 +9,7 @@ from miplearn.components.lazy_static import StaticLazyConstraintsComponent
from miplearn.instance import Instance
from miplearn.solvers.internal import InternalSolver
from miplearn.solvers.learning import LearningSolver
from miplearn.types import TrainingSample
from miplearn.types import TrainingSample, Features
def test_usage_with_solver():
@@ -234,32 +234,35 @@ def test_fit():
def test_xy_sample() -> None:
instance = Mock(spec=Instance)
sample: TrainingSample = {
"LazyStatic: Enforced": {"c1", "c2", "c4", "c5"},
"LazyStatic: All": {"c1", "c2", "c3", "c4", "c5"},
"LazyStatic: Enforced": {"c1", "c2", "c4"},
}
instance.features = {
features: Features = {
"Constraints": {
"c1": {
"Category": "type-a",
"User features": [1.0, 1.0],
"Lazy": True,
},
"c2": {
"Category": "type-a",
"User features": [1.0, 2.0],
"Lazy": True,
},
"c3": {
"Category": "type-a",
"User features": [1.0, 3.0],
"Lazy": True,
},
"c4": {
"Category": "type-b",
"User features": [1.0, 4.0, 0.0],
"Lazy": True,
},
"c5": {
"Category": "type-b",
"User features": [1.0, 5.0, 0.0],
"Lazy": False,
},
}
}
@@ -271,7 +274,6 @@ def test_xy_sample() -> None:
],
"type-b": [
[1.0, 4.0, 0.0],
[1.0, 5.0, 0.0],
],
}
y_expected = {
@@ -282,9 +284,10 @@ def test_xy_sample() -> None:
],
"type-b": [
[False, True],
[False, True],
],
}
x_actual, y_actual = StaticLazyConstraintsComponent.xy_sample(instance, sample)
xy = StaticLazyConstraintsComponent.xy_sample(features, sample)
assert xy is not None
x_actual, y_actual = xy
assert x_actual == x_expected
assert y_actual == y_expected

View File

@@ -11,35 +11,10 @@ from numpy.testing import assert_array_equal
from miplearn.instance import Instance
from miplearn.classifiers import Regressor
from miplearn.components.objective import ObjectiveValueComponent
from miplearn.types import TrainingSample
from miplearn.types import TrainingSample, Features
from tests.fixtures.knapsack import get_test_pyomo_instances
def test_xy_sample() -> None:
instance = cast(Instance, Mock(spec=Instance))
instance.features = {
"Instance": {
"User features": [1.0, 2.0],
}
}
sample: TrainingSample = {
"Lower bound": 1.0,
"Upper bound": 2.0,
"LP value": 3.0,
}
x_expected = {
"Lower bound": [[1.0, 2.0, 3.0]],
"Upper bound": [[1.0, 2.0, 3.0]],
}
y_expected = {
"Lower bound": [[1.0]],
"Upper bound": [[2.0]],
}
x_actual, y_actual = ObjectiveValueComponent.xy_sample(instance, sample)
assert x_actual == x_expected
assert y_actual == y_expected
def test_x_y_predict() -> None:
# Construct instance
instance = cast(Instance, Mock(spec=Instance))
@@ -125,3 +100,54 @@ def test_obj_evaluate():
"R2": -5.012843605607331,
},
}
def test_xy_sample_with_lp() -> None:
features: Features = {
"Instance": {
"User features": [1.0, 2.0],
}
}
sample: TrainingSample = {
"Lower bound": 1.0,
"Upper bound": 2.0,
"LP value": 3.0,
}
x_expected = {
"Lower bound": [[1.0, 2.0, 3.0]],
"Upper bound": [[1.0, 2.0, 3.0]],
}
y_expected = {
"Lower bound": [[1.0]],
"Upper bound": [[2.0]],
}
xy = ObjectiveValueComponent.xy_sample(features, sample)
assert xy is not None
x_actual, y_actual = xy
assert x_actual == x_expected
assert y_actual == y_expected
def test_xy_sample_without_lp() -> None:
features: Features = {
"Instance": {
"User features": [1.0, 2.0],
}
}
sample: TrainingSample = {
"Lower bound": 1.0,
"Upper bound": 2.0,
}
x_expected = {
"Lower bound": [[1.0, 2.0]],
"Upper bound": [[1.0, 2.0]],
}
y_expected = {
"Lower bound": [[1.0]],
"Upper bound": [[2.0]],
}
xy = ObjectiveValueComponent.xy_sample(features, sample)
assert xy is not None
x_actual, y_actual = xy
assert x_actual == x_expected
assert y_actual == y_expected

View File

@@ -1,22 +1,22 @@
# MIPLearn: Extensible Framework for Learning-Enhanced Mixed-Integer Optimization
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
from typing import cast, List
from unittest.mock import Mock, call
from typing import cast
from unittest.mock import Mock
import numpy as np
from numpy.testing import assert_array_equal
from miplearn import Classifier
from miplearn.classifiers.threshold import Threshold, MinPrecisionThreshold
from miplearn.classifiers.threshold import Threshold
from miplearn.components.primal import PrimalSolutionComponent
from miplearn.instance import Instance
from miplearn.types import TrainingSample
from miplearn.types import TrainingSample, Features
def test_xy_sample_with_lp_solution() -> None:
instance = cast(Instance, Mock(spec=Instance))
instance.features = {
features: Features = {
"Variables": {
"x": {
0: {
@@ -56,34 +56,28 @@ def test_xy_sample_with_lp_solution() -> None:
},
}
x_expected = {
"default": np.array(
[
[0.0, 0.0, 0.1],
[1.0, 0.0, 0.1],
[1.0, 1.0, 0.1],
]
)
"default": [
[0.0, 0.0, 0.1],
[1.0, 0.0, 0.1],
[1.0, 1.0, 0.1],
]
}
y_expected = {
"default": np.array(
[
[True, False],
[False, True],
[True, False],
]
)
"default": [
[True, False],
[False, True],
[True, False],
]
}
x_actual, y_actual = PrimalSolutionComponent.xy_sample(instance, sample)
assert len(x_actual.keys()) == 1
assert len(y_actual.keys()) == 1
assert_array_equal(x_actual["default"], x_expected["default"])
assert_array_equal(y_actual["default"], y_expected["default"])
xy = PrimalSolutionComponent.xy_sample(features, sample)
assert xy is not None
x_actual, y_actual = xy
assert x_actual == x_expected
assert y_actual == y_expected
def test_xy_sample_without_lp_solution() -> None:
comp = PrimalSolutionComponent()
instance = cast(Instance, Mock(spec=Instance))
instance.features = {
features: Features = {
"Variables": {
"x": {
0: {
@@ -115,28 +109,24 @@ def test_xy_sample_without_lp_solution() -> None:
},
}
x_expected = {
"default": np.array(
[
[0.0, 0.0],
[1.0, 0.0],
[1.0, 1.0],
]
)
"default": [
[0.0, 0.0],
[1.0, 0.0],
[1.0, 1.0],
]
}
y_expected = {
"default": np.array(
[
[True, False],
[False, True],
[True, False],
]
)
"default": [
[True, False],
[False, True],
[True, False],
]
}
x_actual, y_actual = comp.xy_sample(instance, sample)
assert len(x_actual.keys()) == 1
assert len(y_actual.keys()) == 1
assert_array_equal(x_actual["default"], x_expected["default"])
assert_array_equal(y_actual["default"], y_expected["default"])
xy = PrimalSolutionComponent.xy_sample(features, sample)
assert xy is not None
x_actual, y_actual = xy
assert x_actual == x_expected
assert y_actual == y_expected
def test_predict() -> None:

View File

@@ -44,6 +44,7 @@ def test_knapsack() -> None:
},
"Sense": "<",
"RHS": 67.0,
"Lazy": False,
"Category": "eq_capacity",
"User features": [0.0],
}