5.2.6. 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.6.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

MDOsetdblattrarray()

C++

MDOVar::set()

JAVA

MDOVar::setAttr()

Python

Var::setAttr()

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.6.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

MDOread()

C++

MDOModel::read()

JAVA

MDOModel::read()

Python

Model::read()

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.code))
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()