5.2.7. MILP Warmstart¶
When solving MILP problems, MindOpt provides methods to load an initial solution into the optimization model. Such an approach can often accelerate the solving process, known as the warm-start.
MindOpt provides two methods to warm start an optimization model: setting the Start
attribute of variables or reading the solution from a .mst
file. MindOpt supports not only warm starting by a complete solution but also accepts a partial solution. This means that users are allowed to specify values for only a subset of variables.
When warm-start is successfully enabled, MindOpt will show messages such as “accept new sol: obj 1 bnd vio 0 int vio 0 mipgap 1 time 0”
to indicate an initial solution with objective value 1 is loaded. Otherwise, a warming message “initial solution is not accepted”
will be displayed.
5.2.7.1. Set Variable Attribute Start¶
Warm-start can be enabled via setting the variable attribute Start
. Calling methods in different programming languages are listed as follows:
Language |
Method |
C |
|
C++ |
|
JAVA |
|
Python |
|
Taking C language as an example:
67 /* Add variables. */
68 CHECK_RESULT(MDOaddvar(m, 0, NULL, NULL, 1.0, 0, 10.0, MDO_INTEGER, "x0"));
69 CHECK_RESULT(MDOaddvar(m, 0, NULL, NULL, 2.0, 0, MDO_INFINITY, MDO_INTEGER, "x1"));
70 CHECK_RESULT(MDOaddvar(m, 0, NULL, NULL, 1.0, 0, MDO_INFINITY, MDO_INTEGER, "x2"));
71 CHECK_RESULT(MDOaddvar(m, 0, NULL, NULL, 1.0, 0, MDO_INFINITY, MDO_CONTINUOUS, "x3"));
72
73 /* Add constraints. */
74 CHECK_RESULT(MDOaddconstr(m, 4, row1_idx, row1_val, MDO_GREATER_EQUAL, 1.0, "c0"));
75 CHECK_RESULT(MDOaddconstr(m, 3, row2_idx, row2_val, MDO_EQUAL, 1.0, "c1"));
76
77 /* Add an initial solution */
78 int var_idx_start = 0;
79 int var_num = 4;
80 double var_val[] = { 1.0, 0.0, 0.0, 0.0 };
81 CHECK_RESULT(MDOsetdblattrarray(m, "Start", var_idx_start, var_num, &(*var_val)));
Complete example codes are provided in MdoMiloWarmstart.c.
1/**
2 * Description
3 * -----------
4 *
5 * Mixed Integer Linear optimization (row-wise input).
6 *
7 * Formulation
8 * -----------
9 *
10 * Minimize
11 * obj: 1 x0 + 2 x1 + 1 x2 + 1 x3
12 * Subject To
13 * c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
14 * c1 : 1 x0 - 1 x2 + 6 x3 = 1
15 * Bounds
16 * 0 <= x0 <= 10
17 * 0 <= x1
18 * 0 <= x2
19 * 0 <= x3
20 * Integers
21 * x0 x1 x2
22 * End
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
27#include "Mindopt.h"
28
29/* Macro to check the return code */
30#define RELEASE_MEMORY \
31 MDOfreemodel(m); \
32 MDOfreeenv(env);
33#define CHECK_RESULT(code) { int res = code; if (res != 0) { fprintf(stderr, "Bad code: %d\n", res); exit(res); } }
34#define MODEL_NAME "MILP_01"
35#define MODEL_SENSE "ModelSense"
36#define STATUS "Status"
37#define OBJ_VAL "ObjVal"
38#define X "X"
39
40int main(void)
41{
42 /* Variables. */
43 MDOenv *env;
44 MDOmodel *m;
45 double obj, x;
46 int status, i;
47
48 /* Model data. */
49 int row1_idx[] = { 0, 1, 2, 3 };
50 double row1_val[] = { 1.0, 1.0, 2.0, 3.0 };
51 int row2_idx[] = { 0, 2, 3 };
52 double row2_val[] = { 1.0, -1.0, 6.0 };
53
54 /*------------------------------------------------------------------*/
55 /* Step 1. Create a model and change the parameters. */
56 /*------------------------------------------------------------------*/
57 CHECK_RESULT(MDOemptyenv(&env));
58 CHECK_RESULT(MDOstartenv(env));
59 CHECK_RESULT(MDOnewmodel(env, &m, MODEL_NAME, 0, NULL, NULL, NULL, NULL, NULL));
60
61 /*------------------------------------------------------------------*/
62 /* Step 2. Input model. */
63 /*------------------------------------------------------------------*/
64 /* Change to minimization problem. */
65 CHECK_RESULT(MDOsetintattr(m, MODEL_SENSE, MDO_MINIMIZE));
66
67 /* Add variables. */
68 CHECK_RESULT(MDOaddvar(m, 0, NULL, NULL, 1.0, 0, 10.0, MDO_INTEGER, "x0"));
69 CHECK_RESULT(MDOaddvar(m, 0, NULL, NULL, 2.0, 0, MDO_INFINITY, MDO_INTEGER, "x1"));
70 CHECK_RESULT(MDOaddvar(m, 0, NULL, NULL, 1.0, 0, MDO_INFINITY, MDO_INTEGER, "x2"));
71 CHECK_RESULT(MDOaddvar(m, 0, NULL, NULL, 1.0, 0, MDO_INFINITY, MDO_CONTINUOUS, "x3"));
72
73 /* Add constraints. */
74 CHECK_RESULT(MDOaddconstr(m, 4, row1_idx, row1_val, MDO_GREATER_EQUAL, 1.0, "c0"));
75 CHECK_RESULT(MDOaddconstr(m, 3, row2_idx, row2_val, MDO_EQUAL, 1.0, "c1"));
76
77 /* Add an initial solution */
78 int var_idx_start = 0;
79 int var_num = 4;
80 double var_val[] = { 1.0, 0.0, 0.0, 0.0 };
81 CHECK_RESULT(MDOsetdblattrarray(m, "Start", var_idx_start, var_num, &(*var_val)));
82
83 /*------------------------------------------------------------------*/
84 /* Step 3. Solve the problem and populate optimization result. */
85 /*------------------------------------------------------------------*/
86 CHECK_RESULT(MDOoptimize(m));
87 CHECK_RESULT(MDOgetintattr(m, STATUS, &status));
88 if (status == MDO_OPTIMAL)
89 {
90 CHECK_RESULT(MDOgetdblattr(m, OBJ_VAL, &obj));
91 printf("The optimal objective value is %f\n", obj);
92 for (int i = 0; i < 4; ++i)
93 {
94 CHECK_RESULT(MDOgetdblattrelement(m, X, i, &x));
95 printf("x[%d] = %f\n", i, x);
96 }
97 }
98 else
99 {
100 printf("No feasible solution.\n");
101 }
102
103
104 /*------------------------------------------------------------------*/
105 /* Step 4. Free the model. */
106 /*------------------------------------------------------------------*/
107 RELEASE_MEMORY;
108
109 return 0;
110}
Taking C++ as an example:
47 /* Add variables. */
48 std::vector<MDOVar> x;
49 x.push_back(model.addVar(0.0, 10.0, 1.0, MDO_INTEGER, "x0"));
50 x.push_back(model.addVar(0.0, MDO_INFINITY, 2.0, MDO_INTEGER, "x1"));
51 x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, MDO_INTEGER, "x2"));
52 x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, MDO_CONTINUOUS,"x3"));
53
54 /* Add constraints. */
55 model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], MDO_GREATER_EQUAL, 1.0, "c0");
56 model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3], MDO_EQUAL, 1.0, "c1");
57
58 /* Add an initial solution */
59 x[0].set(MDO_DoubleAttr_Start, 1);
60 x[1].set(MDO_DoubleAttr_Start, 0);
61 x[2].set(MDO_DoubleAttr_Start, 0);
62 x[3].set(MDO_DoubleAttr_Start, 0);
Complete example codes are provided in MdoMiloWarmstart.cpp.
1/**
2 * Description
3 * -----------
4 *
5 * Mixed Integer Linear optimization (row-wise input).
6 *
7 * Formulation
8 * -----------
9 *
10 * Minimize
11 * obj: 1 x0 + 2 x1 + 1 x2 + 1 x3
12 * Subject To
13 * c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
14 * c1 : 1 x0 - 1 x2 + 6 x3 = 1
15 * Bounds
16 * 0 <= x0 <= 10
17 * 0 <= x1
18 * 0 <= x2
19 * 0 <= x3
20 * Integers
21 * x0 x1 x2
22 * End
23 */
24
25#include <iostream>
26#include <vector>
27#include "MindoptCpp.h"
28
29using namespace std;
30
31int main(void)
32{
33 /*------------------------------------------------------------------*/
34 /* Step 1. Create a model and change the parameters. */
35 /*------------------------------------------------------------------*/
36 MDOEnv env = MDOEnv();
37 MDOModel model = MDOModel(env);
38
39 try
40 {
41 /*------------------------------------------------------------------*/
42 /* Step 2. Input model. */
43 /*------------------------------------------------------------------*/
44 /* Change to minimization problem. */
45 model.set(MDO_IntAttr_ModelSense, MDO_MINIMIZE);
46
47 /* Add variables. */
48 std::vector<MDOVar> x;
49 x.push_back(model.addVar(0.0, 10.0, 1.0, MDO_INTEGER, "x0"));
50 x.push_back(model.addVar(0.0, MDO_INFINITY, 2.0, MDO_INTEGER, "x1"));
51 x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, MDO_INTEGER, "x2"));
52 x.push_back(model.addVar(0.0, MDO_INFINITY, 1.0, MDO_CONTINUOUS,"x3"));
53
54 /* Add constraints. */
55 model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], MDO_GREATER_EQUAL, 1.0, "c0");
56 model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3], MDO_EQUAL, 1.0, "c1");
57
58 /* Add an initial solution */
59 x[0].set(MDO_DoubleAttr_Start, 1);
60 x[1].set(MDO_DoubleAttr_Start, 0);
61 x[2].set(MDO_DoubleAttr_Start, 0);
62 x[3].set(MDO_DoubleAttr_Start, 0);
63
64 /*------------------------------------------------------------------*/
65 /* Step 3. Solve the problem and populate optimization result. */
66 /*------------------------------------------------------------------*/
67 model.optimize();
68 if(model.get(MDO_IntAttr_Status) == MDO_OPTIMAL)
69 {
70 cout << "Optimal objective value is: " << model.get(MDO_DoubleAttr_ObjVal) << "." << endl;
71 cout << "Decision variables:" << endl;
72 int i = 0;
73 for (auto v : x)
74 {
75 cout << "x[" << i << "] = " << v.get(MDO_DoubleAttr_X) << endl;
76 }
77 }
78 else
79 {
80 cout<< "No feasible solution." << endl;
81 }
82 }
83 catch (MDOException& e)
84 {
85 cout << "Error code = " << e.getErrorCode() << endl;
86 cout << e.getMessage() << endl;
87 }
88 catch (...)
89 {
90 cout << "Error during optimization." << endl;
91 }
92
93 return static_cast<int>(MDO_OKAY);
94}
5.2.7.2. Read A .mst File¶
Warm-Start can be enabled via a .mst
file.
Calling methods in different programming languages are listed as follows:
Language |
Method |
C |
|
C++ |
|
JAVA |
|
Python |
|
A .mst
file consists of multiple lines in the format of “variable value”.
Here is an example:
1x0 1
2x1 0
3x2 0
MindOpt reads a .mst
file and automatically sets the initial values of variables, eliminating the need for users to manually specify the Start
attribute of variables.
Users can list the initial values of all variables in the .mst
file or only for a subset of variables. If the same variable appears multiple times in the file, the last assignment is used.
Note
When using the write
function in MindOpt to save a solution to a .mst
file, all continuous variables will be ignored. If users want to save the value of all variables, it is recommended to save the solution to a .sol
file.
Taking Python as an example, read an initial solution from a .mst
file:
38 # Add variables.
39 x = []
40 x.append(model.addVar(0.0, 10.0, 1.0, 'I', "x0"))
41 x.append(model.addVar(0.0, float('inf'), 2.0, 'I', "x1"))
42 x.append(model.addVar(0.0, float('inf'), 1.0, 'I', "x2"))
43 x.append(model.addVar(0.0, float('inf'), 1.0, 'C', "x3"))
44
45 # Read an initial solution from mst file
46 model.read("solution.mst")
47
48 # Add constraints.
49 model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3] >= 1, "c0")
50 model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3] == 1, "c1")
51
52 # Step 3. Solve the problem and populate optimization result.
53 model.optimize()
Complete example codes are provided in mdo_milo_ws.py.
1"""
2/**
3 * Description
4 * -----------
5 *
6 * Mixed Integer Linear optimization (row-wise input).
7 *
8 * Formulation
9 * -----------
10 *
11 * Minimize
12 * obj: 1 x0 + 2 x1 + 1 x2 + 1 x3
13 * Subject To
14 * c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
15 * c1 : 1 x0 - 1 x2 + 6 x3 = 1
16 * Bounds
17 * 0 <= x0 <= 10
18 * 0 <= x1
19 * 0 <= x2
20 * 0 <= x3
21 * Integers
22 * x0 x1 x2
23 * End
24 */
25"""
26from mindoptpy import *
27
28if __name__ == "__main__":
29
30 # Step 1. Create a model.
31 model = Model("MILP_WS")
32
33 try:
34 # Step 2. Input model.
35 # Change to minimization problem.
36 model.modelsense = MDO.MINIMIZE
37
38 # Add variables.
39 x = []
40 x.append(model.addVar(0.0, 10.0, 1.0, 'I', "x0"))
41 x.append(model.addVar(0.0, float('inf'), 2.0, 'I', "x1"))
42 x.append(model.addVar(0.0, float('inf'), 1.0, 'I', "x2"))
43 x.append(model.addVar(0.0, float('inf'), 1.0, 'C', "x3"))
44
45 # Read an initial solution from mst file
46 model.read("solution.mst")
47
48 # Add constraints.
49 model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3] >= 1, "c0")
50 model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3] == 1, "c1")
51
52 # Step 3. Solve the problem and populate optimization result.
53 model.optimize()
54
55 if model.status == MDO.OPTIMAL:
56 print(f"Optimal objective value is: {model.objval}")
57 print("Decision variables: ")
58 for v in x:
59 print(f"x[{v.VarName}] = {v.X}")
60 else:
61 print("No feasible solution.")
62 except MindoptError as e:
63 print("Received Mindopt exception.")
64 print(" - Code : {}".format(e.errno))
65 print(" - Reason : {}".format(e.message))
66 except Exception as e:
67 print("Received other exception.")
68 print(" - Reason : {}".format(e))
69 finally:
70 # Step 4. Free the model.
71 model.dispose()