Move python files to root folder; remove built docs

This commit is contained in:
2020-08-29 11:42:02 -05:00
parent 741af8506b
commit 5663ced0be
116 changed files with 8 additions and 12408 deletions

View File

@@ -0,0 +1,3 @@
# 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.

View File

@@ -0,0 +1,31 @@
# 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.
import numpy as np
import pyomo.environ as pe
from miplearn import Instance, GurobiPyomoSolver, LearningSolver
from miplearn.problems.knapsack import ChallengeA
class CutInstance(Instance):
def to_model(self):
model = pe.ConcreteModel()
model.x = x = pe.Var([0, 1], domain=pe.Binary)
model.OBJ = pe.Objective(expr=x[0] + x[1], sense=pe.maximize)
model.eq = pe.Constraint(expr=2 * x[0] + 2 * x[1] <= 3)
return model
def get_instance_features(self):
return np.zeros(0)
def get_variable_features(self, var, index):
return np.zeros(0)
def test_cut():
challenge = ChallengeA()
gurobi = GurobiPyomoSolver()
solver = LearningSolver(solver=gurobi, time_limit=10)
solver.solve(challenge.training_instances[0])
# assert False

View File

@@ -0,0 +1,140 @@
# 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
import numpy as np
from miplearn import LazyConstraintsComponent, LearningSolver, InternalSolver
from miplearn.classifiers import Classifier
from miplearn.tests import get_test_pyomo_instances
from numpy.linalg import norm
E = 0.1
def test_lazy_fit():
instances, models = get_test_pyomo_instances()
instances[0].found_violated_lazy_constraints = ["a", "b"]
instances[1].found_violated_lazy_constraints = ["b", "c"]
classifier = Mock(spec=Classifier)
component = LazyConstraintsComponent(classifier=classifier)
component.fit(instances)
# Should create one classifier for each violation
assert "a" in component.classifiers
assert "b" in component.classifiers
assert "c" in component.classifiers
# Should provide correct x_train to each classifier
expected_x_train_a = np.array([[67., 21.75, 1287.92], [70., 23.75, 1199.83]])
expected_x_train_b = np.array([[67., 21.75, 1287.92], [70., 23.75, 1199.83]])
expected_x_train_c = np.array([[67., 21.75, 1287.92], [70., 23.75, 1199.83]])
actual_x_train_a = component.classifiers["a"].fit.call_args[0][0]
actual_x_train_b = component.classifiers["b"].fit.call_args[0][0]
actual_x_train_c = component.classifiers["c"].fit.call_args[0][0]
assert norm(expected_x_train_a - actual_x_train_a) < E
assert norm(expected_x_train_b - actual_x_train_b) < E
assert norm(expected_x_train_c - actual_x_train_c) < E
# Should provide correct y_train to each classifier
expected_y_train_a = np.array([1.0, 0.0])
expected_y_train_b = np.array([1.0, 1.0])
expected_y_train_c = np.array([0.0, 1.0])
actual_y_train_a = component.classifiers["a"].fit.call_args[0][1]
actual_y_train_b = component.classifiers["b"].fit.call_args[0][1]
actual_y_train_c = component.classifiers["c"].fit.call_args[0][1]
assert norm(expected_y_train_a - actual_y_train_a) < E
assert norm(expected_y_train_b - actual_y_train_b) < E
assert norm(expected_y_train_c - actual_y_train_c) < E
def test_lazy_before():
instances, models = get_test_pyomo_instances()
instances[0].build_lazy_constraint = Mock(return_value="c1")
solver = LearningSolver()
solver.internal_solver = Mock(spec=InternalSolver)
component = LazyConstraintsComponent(threshold=0.10)
component.classifiers = {"a": Mock(spec=Classifier),
"b": Mock(spec=Classifier)}
component.classifiers["a"].predict_proba = Mock(return_value=[[0.95, 0.05]])
component.classifiers["b"].predict_proba = Mock(return_value=[[0.02, 0.80]])
component.before_solve(solver, instances[0], models[0])
# Should ask classifier likelihood of each constraint being violated
expected_x_test_a = np.array([[67., 21.75, 1287.92]])
expected_x_test_b = np.array([[67., 21.75, 1287.92]])
actual_x_test_a = component.classifiers["a"].predict_proba.call_args[0][0]
actual_x_test_b = component.classifiers["b"].predict_proba.call_args[0][0]
assert norm(expected_x_test_a - actual_x_test_a) < E
assert norm(expected_x_test_b - actual_x_test_b) < E
# Should ask instance to generate cut for constraints whose likelihood
# of being violated exceeds the threshold
instances[0].build_lazy_constraint.assert_called_once_with(models[0], "b")
# Should ask internal solver to add generated constraint
solver.internal_solver.add_constraint.assert_called_once_with("c1")
def test_lazy_evaluate():
instances, models = get_test_pyomo_instances()
component = LazyConstraintsComponent()
component.classifiers = {"a": Mock(spec=Classifier),
"b": Mock(spec=Classifier),
"c": Mock(spec=Classifier)}
component.classifiers["a"].predict_proba = Mock(return_value=[[1.0, 0.0]])
component.classifiers["b"].predict_proba = Mock(return_value=[[0.0, 1.0]])
component.classifiers["c"].predict_proba = Mock(return_value=[[0.0, 1.0]])
instances[0].found_violated_lazy_constraints = ["a", "b", "c"]
instances[1].found_violated_lazy_constraints = ["b", "d"]
assert component.evaluate(instances) == {
0: {
"Accuracy": 0.75,
"F1 score": 0.8,
"Precision": 1.0,
"Recall": 2/3.,
"Predicted positive": 2,
"Predicted negative": 2,
"Condition positive": 3,
"Condition negative": 1,
"False negative": 1,
"False positive": 0,
"True negative": 1,
"True positive": 2,
"Predicted positive (%)": 50.0,
"Predicted negative (%)": 50.0,
"Condition positive (%)": 75.0,
"Condition negative (%)": 25.0,
"False negative (%)": 25.0,
"False positive (%)": 0,
"True negative (%)": 25.0,
"True positive (%)": 50.0,
},
1: {
"Accuracy": 0.5,
"F1 score": 0.5,
"Precision": 0.5,
"Recall": 0.5,
"Predicted positive": 2,
"Predicted negative": 2,
"Condition positive": 2,
"Condition negative": 2,
"False negative": 1,
"False positive": 1,
"True negative": 1,
"True positive": 1,
"Predicted positive (%)": 50.0,
"Predicted negative (%)": 50.0,
"Condition positive (%)": 50.0,
"Condition negative (%)": 50.0,
"False negative (%)": 25.0,
"False positive (%)": 25.0,
"True negative (%)": 25.0,
"True positive (%)": 25.0,
}
}

View File

@@ -0,0 +1,47 @@
# 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
import numpy as np
from miplearn import ObjectiveValueComponent
from miplearn.classifiers import Regressor
from miplearn.tests import get_test_pyomo_instances
def test_usage():
instances, models = get_test_pyomo_instances()
comp = ObjectiveValueComponent()
comp.fit(instances)
assert instances[0].lower_bound == 1183.0
assert instances[0].upper_bound == 1183.0
assert np.round(comp.predict(instances), 2).tolist() == [[1183.0, 1183.0],
[1070.0, 1070.0]]
def test_obj_evaluate():
instances, models = get_test_pyomo_instances()
reg = Mock(spec=Regressor)
reg.predict = Mock(return_value=np.array([1000.0, 1000.0]))
comp = ObjectiveValueComponent(regressor=reg)
comp.fit(instances)
ev = comp.evaluate(instances)
assert ev == {
'Lower bound': {
'Explained variance': 0.0,
'Max error': 183.0,
'Mean absolute error': 126.5,
'Mean squared error': 19194.5,
'Median absolute error': 126.5,
'R2': -5.012843605607331,
},
'Upper bound': {
'Explained variance': 0.0,
'Max error': 183.0,
'Mean absolute error': 126.5,
'Mean squared error': 19194.5,
'Median absolute error': 126.5,
'R2': -5.012843605607331,
}
}

View File

@@ -0,0 +1,99 @@
# 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
import numpy as np
from miplearn import PrimalSolutionComponent
from miplearn.classifiers import Classifier
from miplearn.tests import get_test_pyomo_instances
def test_predict():
instances, models = get_test_pyomo_instances()
comp = PrimalSolutionComponent()
comp.fit(instances)
solution = comp.predict(instances[0])
assert "x" in solution
assert 0 in solution["x"]
assert 1 in solution["x"]
assert 2 in solution["x"]
assert 3 in solution["x"]
def test_evaluate():
instances, models = get_test_pyomo_instances()
clf_zero = Mock(spec=Classifier)
clf_zero.predict_proba = Mock(return_value=np.array([
[0., 1.], # x[0]
[0., 1.], # x[1]
[1., 0.], # x[2]
[1., 0.], # x[3]
]))
clf_one = Mock(spec=Classifier)
clf_one.predict_proba = Mock(return_value=np.array([
[1., 0.], # x[0] instances[0]
[1., 0.], # x[1] instances[0]
[0., 1.], # x[2] instances[0]
[1., 0.], # x[3] instances[0]
]))
comp = PrimalSolutionComponent(classifier=[clf_zero, clf_one],
threshold=0.50)
comp.fit(instances[:1])
assert comp.predict(instances[0]) == {"x": {0: 0,
1: 0,
2: 1,
3: None}}
assert instances[0].solution == {"x": {0: 1,
1: 0,
2: 1,
3: 1}}
ev = comp.evaluate(instances[:1])
assert ev == {'Fix one': {0: {'Accuracy': 0.5,
'Condition negative': 1,
'Condition negative (%)': 25.0,
'Condition positive': 3,
'Condition positive (%)': 75.0,
'F1 score': 0.5,
'False negative': 2,
'False negative (%)': 50.0,
'False positive': 0,
'False positive (%)': 0.0,
'Precision': 1.0,
'Predicted negative': 3,
'Predicted negative (%)': 75.0,
'Predicted positive': 1,
'Predicted positive (%)': 25.0,
'Recall': 0.3333333333333333,
'True negative': 1,
'True negative (%)': 25.0,
'True positive': 1,
'True positive (%)': 25.0}},
'Fix zero': {0: {'Accuracy': 0.75,
'Condition negative': 3,
'Condition negative (%)': 75.0,
'Condition positive': 1,
'Condition positive (%)': 25.0,
'F1 score': 0.6666666666666666,
'False negative': 0,
'False negative (%)': 0.0,
'False positive': 1,
'False positive (%)': 25.0,
'Precision': 0.5,
'Predicted negative': 2,
'Predicted negative (%)': 50.0,
'Predicted positive': 2,
'Predicted positive (%)': 50.0,
'Recall': 1.0,
'True negative': 2,
'True negative (%)': 50.0,
'True positive': 1,
'True positive (%)': 25.0}}}
def test_primal_parallel_fit():
instances, models = get_test_pyomo_instances()
comp = PrimalSolutionComponent()
comp.fit(instances, n_jobs=2)
assert len(comp.classifiers) == 2