mirror of
https://github.com/ANL-CEEESA/MIPLearn.git
synced 2025-12-06 01:18:52 -06:00
RelaxationComponent: Always use np arrays
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
import logging
|
import logging
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
|
|
||||||
from miplearn import Component
|
from miplearn import Component
|
||||||
@@ -101,6 +102,8 @@ class DropRedundantInequalitiesStep(Component):
|
|||||||
constraints[category] = []
|
constraints[category] = []
|
||||||
x[category] += [instance.get_constraint_features(cid)]
|
x[category] += [instance.get_constraint_features(cid)]
|
||||||
constraints[category] += [cid]
|
constraints[category] += [cid]
|
||||||
|
for category in x.keys():
|
||||||
|
x[category] = np.array(x[category])
|
||||||
if return_constraints:
|
if return_constraints:
|
||||||
return x, constraints
|
return x, constraints
|
||||||
else:
|
else:
|
||||||
@@ -131,7 +134,7 @@ class DropRedundantInequalitiesStep(Component):
|
|||||||
if category not in self.classifiers:
|
if category not in self.classifiers:
|
||||||
continue
|
continue
|
||||||
y[category] = []
|
y[category] = []
|
||||||
# x_cat = np.array(x_cat)
|
x_cat = np.array(x_cat)
|
||||||
proba = self.classifiers[category].predict_proba(x_cat)
|
proba = self.classifiers[category].predict_proba(x_cat)
|
||||||
for i in range(len(proba)):
|
for i in range(len(proba)):
|
||||||
if proba[i][1] >= self.threshold:
|
if proba[i][1] >= self.threshold:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
|
# Copyright (C) 2020, 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 numpy as np
|
||||||
from unittest.mock import Mock, call
|
from unittest.mock import Mock, call
|
||||||
|
|
||||||
from miplearn import LearningSolver, Instance, InternalSolver
|
from miplearn import LearningSolver, Instance, InternalSolver
|
||||||
@@ -28,9 +29,9 @@ def _setup():
|
|||||||
instance = Mock(spec=Instance)
|
instance = Mock(spec=Instance)
|
||||||
instance.get_constraint_features = Mock(
|
instance.get_constraint_features = Mock(
|
||||||
side_effect=lambda cid: {
|
side_effect=lambda cid: {
|
||||||
"c2": [1.0, 0.0],
|
"c2": np.array([1.0, 0.0]),
|
||||||
"c3": [0.5, 0.5],
|
"c3": np.array([0.5, 0.5]),
|
||||||
"c4": [1.0],
|
"c4": np.array([1.0]),
|
||||||
}[cid]
|
}[cid]
|
||||||
)
|
)
|
||||||
instance.get_constraint_category = Mock(
|
instance.get_constraint_category = Mock(
|
||||||
@@ -47,15 +48,19 @@ def _setup():
|
|||||||
"type-b": Mock(spec=Classifier),
|
"type-b": Mock(spec=Classifier),
|
||||||
}
|
}
|
||||||
classifiers["type-a"].predict_proba = Mock(
|
classifiers["type-a"].predict_proba = Mock(
|
||||||
return_value=[
|
return_value=np.array(
|
||||||
[0.20, 0.80],
|
[
|
||||||
[0.05, 0.95],
|
[0.20, 0.80],
|
||||||
]
|
[0.05, 0.95],
|
||||||
|
]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
classifiers["type-b"].predict_proba = Mock(
|
classifiers["type-b"].predict_proba = Mock(
|
||||||
return_value=[
|
return_value=np.array(
|
||||||
[0.02, 0.98],
|
[
|
||||||
]
|
[0.02, 0.98],
|
||||||
|
]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
return solver, internal, instance, classifiers
|
return solver, internal, instance, classifiers
|
||||||
@@ -95,10 +100,10 @@ def test_drop_redundant():
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Should ask ML to predict whether constraint should be removed
|
# Should ask ML to predict whether constraint should be removed
|
||||||
component.classifiers["type-a"].predict_proba.assert_called_once_with(
|
type_a_actual = component.classifiers["type-a"].predict_proba.call_args[0][0]
|
||||||
[[1.0, 0.0], [0.5, 0.5]]
|
type_b_actual = component.classifiers["type-b"].predict_proba.call_args[0][0]
|
||||||
)
|
np.testing.assert_array_equal(type_a_actual, np.array([[1.0, 0.0], [0.5, 0.5]]))
|
||||||
component.classifiers["type-b"].predict_proba.assert_called_once_with([[1.0]])
|
np.testing.assert_array_equal(type_b_actual, np.array([[1.0]]))
|
||||||
|
|
||||||
# Should ask internal solver to remove constraints predicted as redundant
|
# Should ask internal solver to remove constraints predicted as redundant
|
||||||
assert internal.extract_constraint.call_count == 2
|
assert internal.extract_constraint.call_count == 2
|
||||||
@@ -176,14 +181,16 @@ def test_x_y_fit_predict_evaluate():
|
|||||||
}
|
}
|
||||||
component.classifiers["type-a"].predict_proba = Mock(
|
component.classifiers["type-a"].predict_proba = Mock(
|
||||||
return_value=[
|
return_value=[
|
||||||
[0.20, 0.80],
|
np.array([0.20, 0.80]),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
component.classifiers["type-b"].predict_proba = Mock(
|
component.classifiers["type-b"].predict_proba = Mock(
|
||||||
return_value=[
|
return_value=np.array(
|
||||||
[0.50, 0.50],
|
[
|
||||||
[0.05, 0.95],
|
[0.50, 0.50],
|
||||||
]
|
[0.05, 0.95],
|
||||||
|
]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# First mock instance
|
# First mock instance
|
||||||
@@ -203,9 +210,9 @@ def test_x_y_fit_predict_evaluate():
|
|||||||
)
|
)
|
||||||
instances[0].get_constraint_features = Mock(
|
instances[0].get_constraint_features = Mock(
|
||||||
side_effect=lambda cid: {
|
side_effect=lambda cid: {
|
||||||
"c2": [1.0, 0.0],
|
"c2": np.array([1.0, 0.0]),
|
||||||
"c3": [0.5, 0.5],
|
"c3": np.array([0.5, 0.5]),
|
||||||
"c4": [1.0],
|
"c4": np.array([1.0]),
|
||||||
}[cid]
|
}[cid]
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -226,32 +233,47 @@ def test_x_y_fit_predict_evaluate():
|
|||||||
)
|
)
|
||||||
instances[1].get_constraint_features = Mock(
|
instances[1].get_constraint_features = Mock(
|
||||||
side_effect=lambda cid: {
|
side_effect=lambda cid: {
|
||||||
"c3": [0.3, 0.4],
|
"c3": np.array([0.3, 0.4]),
|
||||||
"c4": [0.7],
|
"c4": np.array([0.7]),
|
||||||
"c5": [0.8],
|
"c5": np.array([0.8]),
|
||||||
}[cid]
|
}[cid]
|
||||||
)
|
)
|
||||||
|
|
||||||
expected_x = {
|
expected_x = {
|
||||||
"type-a": [[1.0, 0.0], [0.5, 0.5], [0.3, 0.4]],
|
"type-a": np.array(
|
||||||
"type-b": [[1.0], [0.7], [0.8]],
|
[
|
||||||
|
[1.0, 0.0],
|
||||||
|
[0.5, 0.5],
|
||||||
|
[0.3, 0.4],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
"type-b": np.array(
|
||||||
|
[
|
||||||
|
[1.0],
|
||||||
|
[0.7],
|
||||||
|
[0.8],
|
||||||
|
]
|
||||||
|
),
|
||||||
|
}
|
||||||
|
expected_y = {
|
||||||
|
"type-a": np.array([[0], [0], [1]]),
|
||||||
|
"type-b": np.array([[1], [0], [0]]),
|
||||||
}
|
}
|
||||||
expected_y = {"type-a": [[0], [0], [1]], "type-b": [[1], [0], [0]]}
|
|
||||||
|
|
||||||
# Should build X and Y matrices correctly
|
# Should build X and Y matrices correctly
|
||||||
assert component.x(instances) == expected_x
|
actual_x = component.x(instances)
|
||||||
assert component.y(instances) == expected_y
|
actual_y = component.y(instances)
|
||||||
|
for category in ["type-a", "type-b"]:
|
||||||
|
np.testing.assert_array_equal(actual_x[category], expected_x[category])
|
||||||
|
np.testing.assert_array_equal(actual_y[category], expected_y[category])
|
||||||
|
|
||||||
# Should pass along X and Y matrices to classifiers
|
# Should pass along X and Y matrices to classifiers
|
||||||
component.fit(instances)
|
component.fit(instances)
|
||||||
component.classifiers["type-a"].fit.assert_called_with(
|
for category in ["type-a", "type-b"]:
|
||||||
expected_x["type-a"],
|
actual_x = component.classifiers[category].fit.call_args[0][0]
|
||||||
expected_y["type-a"],
|
actual_y = component.classifiers[category].fit.call_args[0][1]
|
||||||
)
|
np.testing.assert_array_equal(actual_x, expected_x[category])
|
||||||
component.classifiers["type-b"].fit.assert_called_with(
|
np.testing.assert_array_equal(actual_y, expected_y[category])
|
||||||
expected_x["type-b"],
|
|
||||||
expected_y["type-b"],
|
|
||||||
)
|
|
||||||
|
|
||||||
assert component.predict(expected_x) == {"type-a": [[1]], "type-b": [[0], [1]]}
|
assert component.predict(expected_x) == {"type-a": [[1]], "type-b": [[0], [1]]}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user