mirror of
https://github.com/ANL-CEEESA/MIPLearn.git
synced 2025-12-06 01:18:52 -06:00
Implement component.fit, component.fit_xy
This commit is contained in:
97
tests/components/test_component.py
Normal file
97
tests/components/test_component.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# 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 unittest.mock import Mock
|
||||
|
||||
from miplearn import Component, Instance
|
||||
|
||||
|
||||
def test_xy_instance():
|
||||
def _xy_sample(instance, sample):
|
||||
print(sample)
|
||||
x = {
|
||||
"s1": {
|
||||
"category_a": [
|
||||
[1, 2, 3],
|
||||
[3, 4, 6],
|
||||
],
|
||||
"category_b": [
|
||||
[7, 8, 9],
|
||||
],
|
||||
},
|
||||
"s2": {
|
||||
"category_a": [
|
||||
[0, 0, 0],
|
||||
[0, 5, 3],
|
||||
[2, 2, 0],
|
||||
],
|
||||
"category_c": [
|
||||
[0, 0, 0],
|
||||
[0, 0, 1],
|
||||
],
|
||||
},
|
||||
"s3": {
|
||||
"category_c": [
|
||||
[1, 1, 1],
|
||||
],
|
||||
},
|
||||
}
|
||||
y = {
|
||||
"s1": {
|
||||
"category_a": [[1], [2]],
|
||||
"category_b": [[3]],
|
||||
},
|
||||
"s2": {
|
||||
"category_a": [[4], [5], [6]],
|
||||
"category_c": [[8], [9], [10]],
|
||||
},
|
||||
"s3": {
|
||||
"category_c": [[11]],
|
||||
},
|
||||
}
|
||||
return x[sample], y[sample]
|
||||
|
||||
comp = Component()
|
||||
instance_1 = Mock(spec=Instance)
|
||||
instance_1.training_data = ["s1", "s2"]
|
||||
instance_2 = Mock(spec=Instance)
|
||||
instance_2.training_data = ["s3"]
|
||||
comp.xy_sample = _xy_sample
|
||||
x_expected = {
|
||||
"category_a": [
|
||||
[1, 2, 3],
|
||||
[3, 4, 6],
|
||||
[0, 0, 0],
|
||||
[0, 5, 3],
|
||||
[2, 2, 0],
|
||||
],
|
||||
"category_b": [
|
||||
[7, 8, 9],
|
||||
],
|
||||
"category_c": [
|
||||
[0, 0, 0],
|
||||
[0, 0, 1],
|
||||
[1, 1, 1],
|
||||
],
|
||||
}
|
||||
y_expected = {
|
||||
"category_a": [
|
||||
[1],
|
||||
[2],
|
||||
[4],
|
||||
[5],
|
||||
[6],
|
||||
],
|
||||
"category_b": [
|
||||
[3],
|
||||
],
|
||||
"category_c": [
|
||||
[8],
|
||||
[9],
|
||||
[10],
|
||||
[11],
|
||||
],
|
||||
}
|
||||
x_actual, y_actual = comp.xy_instances([instance_1, instance_2])
|
||||
assert x_actual == x_expected
|
||||
assert y_actual == y_expected
|
||||
@@ -130,177 +130,6 @@ def test_xy_sample_without_lp_solution() -> None:
|
||||
assert_array_equal(y_actual["default"], y_expected["default"])
|
||||
|
||||
|
||||
def test_x_y_fit() -> None:
|
||||
comp = PrimalSolutionComponent()
|
||||
training_instances = cast(
|
||||
List[Instance],
|
||||
[
|
||||
Mock(spec=Instance),
|
||||
Mock(spec=Instance),
|
||||
],
|
||||
)
|
||||
|
||||
# Construct first instance
|
||||
training_instances[0].get_variable_category = Mock( # type: ignore
|
||||
side_effect=lambda var_name, index: {
|
||||
0: "default",
|
||||
1: None,
|
||||
2: "default",
|
||||
3: "default",
|
||||
}[index]
|
||||
)
|
||||
training_instances[0].get_variable_features = Mock( # type: ignore
|
||||
side_effect=lambda var, index: {
|
||||
0: [0.0, 0.0],
|
||||
1: [0.0, 1.0],
|
||||
2: [1.0, 0.0],
|
||||
3: [1.0, 1.0],
|
||||
}[index]
|
||||
)
|
||||
training_instances[0].training_data = [
|
||||
{
|
||||
"Solution": {
|
||||
"x": {
|
||||
0: 0.0,
|
||||
1: 1.0,
|
||||
2: 0.0,
|
||||
3: 0.0,
|
||||
}
|
||||
},
|
||||
"LP solution": {
|
||||
"x": {
|
||||
0: 0.1,
|
||||
1: 0.1,
|
||||
2: 0.1,
|
||||
3: 0.1,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"Solution": {
|
||||
"x": {
|
||||
0: 0.0,
|
||||
1: 1.0,
|
||||
2: 1.0,
|
||||
3: 0.0,
|
||||
}
|
||||
},
|
||||
"LP solution": {
|
||||
"x": {
|
||||
0: 0.2,
|
||||
1: 0.2,
|
||||
2: 0.2,
|
||||
3: 0.2,
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
# Construct second instance
|
||||
training_instances[1].get_variable_category = Mock( # type: ignore
|
||||
side_effect=lambda var_name, index: {
|
||||
0: "default",
|
||||
1: None,
|
||||
2: "default",
|
||||
3: "default",
|
||||
}[index]
|
||||
)
|
||||
training_instances[1].get_variable_features = Mock( # type: ignore
|
||||
side_effect=lambda var, index: {
|
||||
0: [0.0, 0.0],
|
||||
1: [0.0, 2.0],
|
||||
2: [2.0, 0.0],
|
||||
3: [2.0, 2.0],
|
||||
}[index]
|
||||
)
|
||||
training_instances[1].training_data = [
|
||||
{
|
||||
"Solution": {
|
||||
"x": {
|
||||
0: 1.0,
|
||||
1: 1.0,
|
||||
2: 1.0,
|
||||
3: 1.0,
|
||||
}
|
||||
},
|
||||
"LP solution": {
|
||||
"x": {
|
||||
0: 0.3,
|
||||
1: 0.3,
|
||||
2: 0.3,
|
||||
3: 0.3,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"Solution": None,
|
||||
"LP solution": None,
|
||||
},
|
||||
]
|
||||
|
||||
# Test x
|
||||
x_expected = {
|
||||
"default": np.array(
|
||||
[
|
||||
[0.0, 0.0, 0.1],
|
||||
[1.0, 0.0, 0.1],
|
||||
[1.0, 1.0, 0.1],
|
||||
[0.0, 0.0, 0.2],
|
||||
[1.0, 0.0, 0.2],
|
||||
[1.0, 1.0, 0.2],
|
||||
[0.0, 0.0, 0.3],
|
||||
[2.0, 0.0, 0.3],
|
||||
[2.0, 2.0, 0.3],
|
||||
]
|
||||
)
|
||||
}
|
||||
x_actual = comp.x(training_instances)
|
||||
assert len(x_actual.keys()) == 1
|
||||
assert_array_equal(x_actual["default"], x_expected["default"])
|
||||
|
||||
# Test y
|
||||
y_expected = {
|
||||
"default": np.array(
|
||||
[
|
||||
[True, False],
|
||||
[True, False],
|
||||
[True, False],
|
||||
[True, False],
|
||||
[False, True],
|
||||
[True, False],
|
||||
[False, True],
|
||||
[False, True],
|
||||
[False, True],
|
||||
]
|
||||
)
|
||||
}
|
||||
y_actual = comp.y(training_instances)
|
||||
assert len(y_actual.keys()) == 1
|
||||
assert_array_equal(y_actual["default"], y_expected["default"])
|
||||
|
||||
# Test fit
|
||||
classifier = Mock(spec=Classifier)
|
||||
threshold = Mock(spec=Threshold)
|
||||
classifier_factory = Mock(return_value=classifier)
|
||||
threshold_factory = Mock(return_value=threshold)
|
||||
comp = PrimalSolutionComponent(
|
||||
classifier=classifier_factory,
|
||||
threshold=threshold_factory,
|
||||
)
|
||||
comp.fit(training_instances)
|
||||
|
||||
# Should build and train classifier for "default" category
|
||||
classifier_factory.assert_called_once()
|
||||
assert_array_equal(x_actual["default"], classifier.fit.call_args[0][0])
|
||||
assert_array_equal(y_actual["default"], classifier.fit.call_args[0][1])
|
||||
|
||||
# Should build and train threshold for "default" category
|
||||
threshold_factory.assert_called_once()
|
||||
assert classifier == threshold.fit.call_args[0][0]
|
||||
assert_array_equal(x_actual["default"], threshold.fit.call_args[0][1])
|
||||
assert_array_equal(y_actual["default"], threshold.fit.call_args[0][2])
|
||||
|
||||
|
||||
def test_predict() -> None:
|
||||
comp = PrimalSolutionComponent()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user