diff --git a/README.md b/README.md index 93f50a6..1aef580 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,22 @@ MIPLearn ======== -**MIPLearn** is an optimization package designed to efficiently handle discrete optimization problems that need to be repeatedly solved with only relatively minor changes to input data. - -The package uses Machine Learning techniques to extract information from previously solved instances and uses this information, when solving new instances, to construct a number of hints which can help a traditional Mixed-Integer Programming (MIP) solver, such as CPLEX or Gurobi, to more efficiently find the optimal solution and prove its optimality. For particular classes of problems, this approach has been shown to provide significant performance benefits (see references below). - -This software is in alpha stage. Expect bugs and incomplete features. Suggestions and pull requests are very welcome. +**MIPLearn** is a flexible and extensible framework for *Learning-Enhanced Mixed-Integer Optimization*. It was designed to efficiently handle discrete optimization problems that need to be repeatedly solved with only relatively minor changes to the input data. The package uses Machine Learning (ML) to automatically identify patterns in previously solved instances of the problem, or in the solution process itself, and produces hints that can guide a traditional MIP solver, such as CPLEX and Gurobi, towards the optimal solution faster. For particular classes of problems, this approach has been shown to provide significant performance benefits (see references below). Features -------- -* **MIPLearn provides a reference *Learning-Enhanced MIP Solver*,** which can automatically predict, based on previously solved instances (i) partial solutions which are likely to work well as MIP starts, (ii) an initial set of lazy constraints to enforce and (iii) affine subspaces where the solution is likely to reside. The reference solver can internally use CPLEX or Gurobi. +* **MIPLearn proposes a flexible, problem-agnostic way** for users to describe optimization problems to a Learning-Enhanced Solver, from both the MIP perspective and from the ML perspective. MIP formulations are specified as [Pyomo](https://www.pyomo.org/) models, while features describing instances and decision variables are specified as [NumPy](https://numpy.org/) arrays. Users can easily experiment with different mathematical formulations and ML encodings. + +* **MIPLearn provides a reference implementation of a *Learning-Enhanced Solver*,** which can use the above problem specification to automatically predict, based on previously solved instances: (i) partial solutions which are likely to work well as MIP starts, (ii) an initial set of lazy constraints to enforce and (iii) affine subspaces where the solution is likely to reside. This process is entirely transparent to the user: the most suitable ML models are automatically selected, trained and cross-validated with no user intervention. -* **MIPLearn provides a flexible, problem-agnostic and formulation-agnostic framework** that allows users to model their own optimization problems. MIP formulations are provided to the learning-enhanced solver as [Pyomo](https://www.pyomo.org/) models, while features describing particular instances are provided as [NumPy](https://numpy.org/) arrays. The user can experiment with different MIP formulations and ML encodings. +* **MIPLearn is customizable and extensible**. For MIP and ML researchers exploring new techniques to accelerate MIP performance based on historical data, each component of the reference solver can be individually replaced or customized. The reference solver can use many open-source and commercial MIP solvers as backend, including Cbc, SCIP, CPLEX and Gurobi. -* **MIPLearn provides a set of benchmark instances,** with problems from different domains, which can be used to quickly evaluate new learning-enhanced MIP techniques in a measurable and reproducible way. +* **MIPLearn provides a set of benchmark problems and random instance generators,** covering applications from different domains, which can be used to quickly evaluate new learning-enhanced MIP techniques in a measurable and reproducible way. Installation ------------ -The package is currently only available for Python+Pyomo, although a Julia+JuMP version is planned. It can be installed using `pip` as follows: +The package is currently only available for Python and Pyomo. It can be installed using `pip` as follows: ```bash pip install git+ssh://git@github.com/iSoron/miplearn.git @@ -27,9 +25,9 @@ pip install git+ssh://git@github.com/iSoron/miplearn.git Usage ----- -### LearningSolver +### Using `LearningSolver` -The main class provided by this package is `LearningSolver`, a reference Learning-Enhanced MIP solver which automatically extracts information from previous runs to accelerate the solution of new instances. Assuming we already have a list of instances to solve, `LearningSolver` can be called as follows: +The main class provided by this package is `LearningSolver`, a reference learning-enhanced MIP solver which automatically extracts information from previous runs to accelerate the solution of new instances. Assuming we already have a list of instances to solve, `LearningSolver` can be used as follows: ```python from miplearn import LearningSolver @@ -41,15 +39,17 @@ for instance in all_instances: solver.fit() ``` -During the first call to `solver.solve(instance)`, the instance will be solved from scratch, since no historical information is available. The solver, however, will already start gathering information to accelerate future solves. After each solve, we call `solver.fit()` to train all the internal Machine Learning models based on the information gathered so far. As this operation can be expensive, it may also be performed after a larger batch of instances has been solved, instead of after every solve. After the first call to `solver.fit()`, subsequent calls to `solver.solve(instance)` will automatically use the trained Machine Learning models to accelerate the solution process. - -By default, `LearningSolver` uses Cbc as its internal MIP solver. Alternative solvers can be specified through the `parent_solver`a argument, as follows. Persistent Pyomo solvers are supported. +During the first call to `solver.solve(instance)`, the solver will process the instance from scratch, since no historical information is available, but it will already start gathering information. By calling `solver.fit()`, we instruct the solver to train all the internal Machine Learning models based on the information gathered so far. As this operation can be expensive, it may be performed after a larger batch of instances has been solved, instead of after every solve. After the first call to `solver.fit()`, subsequent calls to `solver.solve(instance)` will automatically use the trained Machine Learning models to accelerate the solution process. +Selecting the internal MIP solver +--------------------------------- +By default, `LearningSolver` uses Cbc as its internal MIP solver. Alternative solvers can be specified through the `parent_solver`a argument, as follows. Persistent Pyomo solvers are supported. To select Gurobi, for example: ```python from miplearn import LearningSolver import pyomo.environ as pe -solver = LearningSolver(parent_solver=pe.SolverFactory("gurobi_persistent")) +gurobi = pe.SolverFactory("gurobi_persistent") +solver = LearningSolver(parent_solver=gurobi) ``` ### Describing problem instances @@ -63,14 +63,26 @@ Instances to be solved by `LearningSolver` must derive from the abstract class ` The first method is used by `LearningSolver` to construct a concrete Pyomo model, which will be provided to the internal MIP solver. The user should keep a reference to this Pyomo model, in order to retrieve, for example, the optimal variable values. -The second and third methods provide an encoding of the instance, which can be used by the ML models to make predictions. In the knapsack problem, for example, an implementation may decide to provide as instance features the average weights, average prices, number of items and the size of the knapsack. The weight and the price of each individual item could be provided as variable features. It is not necessary to have a one-to-one correspondence between features and problem instances. +The second and third methods provide an encoding of the instance, which can be used by the ML models to make predictions. In the knapsack problem, for example, an implementation may decide to provide as instance features the average weights, average prices, number of items and the size of the knapsack. The weight and the price of each individual item could be provided as variable features. See `miplearn/problems/knapsack.py` for a concrete example. + +An optional method which can be implemented is `instance.get_variable_category(var, index)`, which returns a category (a string, an integer or any hashable type) for each decision variable. If two variables have the same category, `LearningSolver` will use the same internal ML model to predict the values of both variables. By default, all variables belong to the `"default"` category, and therefore only one ML model is used for all variables. + +It is not necessary to have a one-to-one correspondence between features and problem instances. One important (and deliberate) limitation of MIPLearn, however, is that `get_instance_features()` must always return arrays of same length for all relevant instances of the problem. Similarly, `get_variable_features(var, index)` must also always return arrays of same length for all variables in each category. It is up to the user to decide how to encode variable-length characteristics of the problem into fixed-length vectors. In graph problems, for example, graph embeddings can be used to reduce the (variable-length) lists of nodes and edges into a fixed-length structure that still preserves some properties of the graph. Different instance encodings may have significant impact on performance. + + +### Obtaining heuristic solutions + +By default, `LearningSolver` uses Machine Learning to accelerate the MIP solution process, but keeps all optimality guarantees typically provided by MIP solvers. In the default mode of operation, predicted optimal solutions, for example, are used only as MIP starts. + +For more signifcant performance benefits, `LearningSolver` can also be configured to place additional trust in the Machine Learning predictors, using the `mode="heuristic"` constructor argument. When operating in this mode, if a ML model is statistically shown (through stratified k-fold cross validation) to have exceptionally high accuracy, the solver may decide to restrict the search space based on its predictions. Parts of the solution which the ML models cannot predict accurately will still be explored using traditional (branch-and-bound) methods. This mode naturally loses all optimality guarantees, but, for particular applications, it has been shown to quickly produce optimal or near-optimal solutions (see references below). -An optional method which can be implemented is `instance.get_variable_category(var, index)`, which assigns a category for each decision variable. If two variables belong to the same category, `LearningSolver` will use the same internal ML model to predict the values of both variables. By default, all variables belong to the `"default"` category, and therefore only one ML model is used for all variables. +**Note:** *The heuristic mode should only be used if the solver is first trained on a large and statistically representative set of training instances.* -**Note:** Only binary and continuous decision variables are currently supported. -**Note:** One important (and deliberate) limitation of `MIPLearn` is that `get_instance_features()` must always return arrays of same length for all relevant instances of the problem. Similarly, `get_variable_features(var, index)` must also always return arrays of same length for all variables in each category. It is up to the user to decide how to encode variable-length characteristics of the problem into fixed-length vectors. In graph problems, for example, graph embeddings can be used to reduce the (variable-length) lists of nodes and edges into a fixed-length structure that still preserves some properties of the graph. Different instance encodings may have significant impact on performance. +Current Limitations +------------------- +* Only binary and continuous decision variables are currently supported. References ---------- @@ -84,5 +96,5 @@ Authors License ------- - MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization + MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. diff --git a/miplearn/__init__.py b/miplearn/__init__.py index 48a470f..463ccd8 100644 --- a/miplearn/__init__.py +++ b/miplearn/__init__.py @@ -1,4 +1,4 @@ -# MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization +# MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization # Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. # Written by Alinson S. Xavier diff --git a/miplearn/instance.py b/miplearn/instance.py index 40c454c..a90744f 100644 --- a/miplearn/instance.py +++ b/miplearn/instance.py @@ -1,4 +1,4 @@ -# MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization +# MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization # Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. # Written by Alinson S. Xavier diff --git a/miplearn/problems/knapsack.py b/miplearn/problems/knapsack.py index eef184e..265cd0b 100644 --- a/miplearn/problems/knapsack.py +++ b/miplearn/problems/knapsack.py @@ -1,4 +1,4 @@ -# MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization +# MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization # Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. # Written by Alinson S. Xavier diff --git a/miplearn/problems/stab.py b/miplearn/problems/stab.py index 24d9c76..5c7d1e0 100644 --- a/miplearn/problems/stab.py +++ b/miplearn/problems/stab.py @@ -1,4 +1,4 @@ -# MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization +# MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization # Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. # Written by Alinson S. Xavier diff --git a/miplearn/solvers.py b/miplearn/solvers.py index 9214b85..72c81a2 100644 --- a/miplearn/solvers.py +++ b/miplearn/solvers.py @@ -1,4 +1,4 @@ -# MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization +# MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization # Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. # Written by Alinson S. Xavier @@ -19,10 +19,10 @@ class LearningSolver: threads=4, parent_solver=pe.SolverFactory('cbc'), ws_predictor=LogisticWarmStartPredictor(), - fix_variables=False): + mode="exact"): self.parent_solver = parent_solver self.parent_solver.options["threads"] = threads - self.fix_variables = fix_variables + self.mode = mode self.x_train = {} self.y_train = {} self.ws_predictors = {} @@ -55,7 +55,7 @@ class LearningSolver: assert ws.shape == (len(var_index_pairs), 2) for i in range(len(var_index_pairs)): var, index = var_index_pairs[i] - if self.fix_variables: + if self.mode == "heuristic": if ws[i,0] == 1: var[index].fix(0) elif ws[i,1] == 1: diff --git a/miplearn/tests/test_solver.py b/miplearn/tests/test_solver.py index deea525..414f18e 100644 --- a/miplearn/tests/test_solver.py +++ b/miplearn/tests/test_solver.py @@ -1,4 +1,4 @@ -# MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization +# MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization # Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. # Written by Alinson S. Xavier diff --git a/miplearn/tests/test_stab.py b/miplearn/tests/test_stab.py index e306b80..08ea704 100644 --- a/miplearn/tests/test_stab.py +++ b/miplearn/tests/test_stab.py @@ -1,4 +1,4 @@ -# MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization +# MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization # Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. # Written by Alinson S. Xavier diff --git a/miplearn/tests/test_transformer.py b/miplearn/tests/test_transformer.py index a027dbd..a9de951 100644 --- a/miplearn/tests/test_transformer.py +++ b/miplearn/tests/test_transformer.py @@ -1,4 +1,4 @@ -# MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization +# MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization # Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. # Written by Alinson S. Xavier diff --git a/miplearn/tests/test_warmstart_logistic.py b/miplearn/tests/test_warmstart_logistic.py index bfbe85b..047add0 100644 --- a/miplearn/tests/test_warmstart_logistic.py +++ b/miplearn/tests/test_warmstart_logistic.py @@ -1,4 +1,4 @@ -# MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization +# MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization # Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. # Written by Alinson S. Xavier diff --git a/miplearn/transformers.py b/miplearn/transformers.py index e75f9a1..3be565c 100644 --- a/miplearn/transformers.py +++ b/miplearn/transformers.py @@ -1,4 +1,4 @@ -# MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization +# MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization # Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. # Written by Alinson S. Xavier diff --git a/miplearn/warmstart.py b/miplearn/warmstart.py index 4ebb594..1f95f88 100644 --- a/miplearn/warmstart.py +++ b/miplearn/warmstart.py @@ -1,4 +1,4 @@ -# MIPLearn: A Machine-Learning Framework for Mixed-Integer Optimization +# MIPLearn, an extensible framework for Learning-Enhanced Mixed-Integer Optimization # Copyright (C) 2019-2020 Argonne National Laboratory. All rights reserved. # Written by Alinson S. Xavier