5.1.4. Modeling and optimization in Python

This topic describes how to use the Python API of MindOpt to build a model and solve the problem in Examples of linear programming problems.

5.1.4.1. Input by row: mdo_lo_ex1

Load the Python package.

24from mindoptpy import *

Create an optimization model.

31    # Step 1. Create a model and change the parameters.
32    model = MdoModel()

Call mindoptpy.MdoModel.set_int_attr() to set the target function to Minimization, call mindoptpy.MdoModel.add_var() to add four optimization variables, and define the upper bound, lower bound, names, and types of the variables. For more information about how to use mindoptpy.MdoModel.set_int_attr() and mindoptpy.MdoModel.add_var(), see Python API.

35        # Step 2. Input model.
36        # Change to minimization problem.
37        model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
38        
39        # Add variables.
40        x = []
41        x.append(model.add_var(0.0,         10.0, 1.0, None, "x0", False))
42        x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x1", False))
43        x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x2", False))
44        x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x3", False))

Add linear constraints.

46        # Add constraints.
47        # Note that the nonzero elements are inputted in a row-wise order here.
48        model.add_cons(1.0, MDO_INFINITY, 1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], "c0")
49        model.add_cons(1.0,          1.0, 1.0 * x[0]              - 1.0 * x[2] + 6.0 * x[3], "c1")

Call mindoptpy.MdoModel.solve_prob() to solve the optimization problem, and call mindoptpy.MdoModel.display_results() to view the optimization result.

51        # Step 3. Solve the problem and populate the result.
52        model.solve_prob()
53        model.display_results()

Call mindoptpy.MdoModel.free_mdl() to release the memory.

63        # Step 4. Free the model.
64        model.free_mdl()

The linked file mdo_lo_ex1.py provides complete source code:

 1"""
 2/**
 3 *  Description
 4 *  -----------
 5 *
 6 *  Linear optimization (row-wise input).
 7 *
 8 *  Formulation
 9 *  -----------
10 *
11 *  Minimize
12 *    obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
13 *  Subject To
14 *   c1 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
15 *   c2 : 1 x0 - 1 x2 + 6 x3 = 1
16 *  Bounds
17 *    0 <= x0 <= 10
18 *    0 <= x1
19 *    0 <= x2
20 *    0 <= x3
21 *  End
22 */
23"""
24from mindoptpy import *
25
26
27if __name__ == "__main__":
28
29    MDO_INFINITY = MdoModel.get_infinity()
30
31    # Step 1. Create a model and change the parameters.
32    model = MdoModel()
33
34    try:
35        # Step 2. Input model.
36        # Change to minimization problem.
37        model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
38        
39        # Add variables.
40        x = []
41        x.append(model.add_var(0.0,         10.0, 1.0, None, "x0", False))
42        x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x1", False))
43        x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x2", False))
44        x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x3", False))
45
46        # Add constraints.
47        # Note that the nonzero elements are inputted in a row-wise order here.
48        model.add_cons(1.0, MDO_INFINITY, 1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], "c0")
49        model.add_cons(1.0,          1.0, 1.0 * x[0]              - 1.0 * x[2] + 6.0 * x[3], "c1")
50
51        # Step 3. Solve the problem and populate the result.
52        model.solve_prob()
53        model.display_results()
54
55    except MdoError as e:
56        print("Received Mindopt exception.")
57        print(" - Code          : {}".format(e.code))
58        print(" - Reason        : {}".format(e.message))
59    except Exception as e:
60        print("Received exception.")
61        print(" - Reason        : {}".format(e))
62    finally:
63        # Step 4. Free the model.
64        model.free_mdl()

5.1.4.2. Input by column: mdo_lo_ex2

In the following code, a model is built for the preceding problem, but non-zero elements of the matrix are sorted by column and then input.

If you input only the lower bound and upper bound of constraints when you call mindoptpy.MdoModel.add_cons(), the constraint matrix is empty (without non-zero elements). After inputting constraints, create a column object mindoptpy.MdoCol() to store the positions (indexes) and non-zero values of non-zero elements corresponding to the constraints in this column. Call mindoptpy.MdoModel.add_var() to create a variable, and specify the target function coefficient, upper and lower bounds, as well as non-zero element, variable name, and variable type corresponding to each constraint in this column.

Call mindoptpy.MdoModel.get_status() to check the optimization status of the solver, and call mindoptpy.MdoModel.get_real_attr() and mindoptpy.MdoVar.get_real_attr() to obtain the target value and optimal solution. For more information about how to use mindoptpy.MdoModel.get_real_attr() and mindoptpy.MdoVar.get_real_attr(), see Python API.

The linked file mdo_lo_ex2.py provides complete source code:

 1"""
 2/**
 3 *  Description
 4 *  -----------
 5 *
 6 *  Linear optimization (column-wise input).
 7 *
 8 *  Formulation
 9 *  -----------
10 *
11 *  Minimize
12 *    obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
13 *  Subject To
14 *   c1 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
15 *   c2 : 1 x0 - 1 x2 + 6 x3 = 1
16 *  Bounds
17 *    0 <= x0 <= 10
18 *    0 <= x1
19 *    0 <= x2
20 *    0 <= x3
21 *  End
22 */
23"""
24from mindoptpy import *
25
26
27if __name__ == "__main__":
28
29    MDO_INFINITY = MdoModel.get_infinity()
30
31    # Step 1. Create a model and change the parameters.
32    model = MdoModel()
33
34    try:
35        # Step 2. Input model.
36        # Change to minimization problem.
37        model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
38
39        # Add empty constraints. 
40        cons = []
41        cons.append(model.add_cons(1.0, MDO_INFINITY, None, "c0"))
42        cons.append(model.add_cons(1.0, 1.0,          None, "c1"))
43        
44        # Input columns. 
45        col = []
46        for j in range(4):
47            col.append(MdoCol())
48        col[0].add_term(cons[0], 1.0)
49        col[0].add_term(cons[1], 1.0)
50        col[1].add_term(cons[0], 1.0)
51        col[2].add_term(cons[0], 2.0)
52        col[2].add_term(cons[1], -1.0)
53        col[3].add_term(cons[0], 3.0)
54        col[3].add_term(cons[1], 6.0)
55
56        # Add variables.
57        # Note that the nonzero elements are inputted in a column-wise order here.
58        x = []
59        x.append(model.add_var(0.0,         10.0, 1.0, col[0], "x0", False))
60        x.append(model.add_var(0.0, MDO_INFINITY, 1.0, col[1], "x1", False))
61        x.append(model.add_var(0.0, MDO_INFINITY, 1.0, col[2], "x2", False))
62        x.append(model.add_var(0.0, MDO_INFINITY, 1.0, col[3], "x3", False))
63
64        # Step 3. Solve the problem and populate the result.
65        model.solve_prob()
66        model.display_results()
67
68        status_code, status_msg = model.get_status()
69        if status_msg == "OPTIMAL":
70            print("Optimizer terminated with an OPTIMAL status (code {0}).".format(status_code))
71            print("Primal objective : {0}".format(round(model.get_real_attr(MDO_REAL_ATTR.PRIMAL_OBJ_VAL), 2)))
72            for curr_x in x:
73                print(" - x[{0}]          : {1}".format(curr_x.get_index(), round(curr_x.get_real_attr(MDO_REAL_ATTR.PRIMAL_SOLN), 2)))
74        else:
75            print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))
76
77    except MdoError as e:
78        print("Received Mindopt exception.")
79        print(" - Code          : {}".format(e.code))
80        print(" - Reason        : {}".format(e.message))
81    except Exception as e:
82        print("Received exception.")
83        print(" - Explanation   : {}".format(e))
84    finally:
85        # Step 4. Free the model.
86        model.free_mdl()

5.1.4.3. Advanced example: mdo_lo_ex3

The following code shows how to use other advanced API examples, such as inputting data into a model, modifying a model, obtaining a basic solution, and performing a hot start. For more information about how to use the API, see API Reference.

The linked file mdo_lo_ex3.py provides complete source code:

  1"""
  2/**
  3 *  Description
  4 *  -----------
  5 *
  6 *  Linear optimization (row-wise input).
  7 *
  8 *  Formulation
  9 *  -----------
 10 *
 11 *  Minimize
 12 *    obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
 13 *  Subject To
 14 *   c1 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
 15 *   c2 : 1 x0 - 1 x2 + 6 x3 = 1
 16 *  Bounds
 17 *    0 <= x0 <= 10
 18 *    0 <= x1
 19 *    0 <= x2
 20 *    0 <= x3
 21 *  End
 22 */
 23"""
 24from mindoptpy import *
 25
 26
 27if __name__ == "__main__":
 28
 29    MDO_INFINITY = MdoModel.get_infinity()
 30    WRITE_LP = True
 31
 32    # Step 1. Create a model and change the parameters.
 33    model = MdoModel()
 34
 35    try:
 36        # Step 2. Input model.
 37        print("\nStep 2. Input model.\n")        
 38        # Change to minimization problem.
 39        model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
 40        
 41        # Add variables.
 42        xs = model.add_vars(4, lb=0, ub=MDO_INFINITY, obj=1.0, name="x")
 43        x = [ value for key, value in xs.items() ]
 44        x[0].set_real_attr(MDO_REAL_ATTR.UB, 10.0)
 45
 46        # Add constraints.
 47        # Note that the nonzero elements are inputted in a row-wise order here.
 48        conss = []
 49        conss.append(model.add_cons(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3] >= 1.0, "c0"))
 50        conss.append(model.add_cons(1.0 * x[0]              - 1.0 * x[2] + 6.0 * x[3] == 1.0, "c1"))
 51
 52        # Step 3. Solve the problem and populate the result.
 53        print("\nStep 3. Solve the problem and populate the result.\n")        
 54        model.solve_prob()
 55        model.display_results()
 56        if WRITE_LP:
 57            model.write_prob("Step3.lp");
 58
 59        # Step 4. Add another two variables and then resolve the problem. 
 60        print("\nStep 4. Add another two variables and then resolve the problem.\n")        
 61        # Input columns. 
 62        cols = [ MdoCol() for i in range(2) ]
 63        cols[0].add_terms(conss, [ 1.0, 2.0 ])
 64        cols[1].add_terms(conss, [ 3.4, 4.0 ])
 65        y = []
 66        y.append(model.add_var( 0.0, MDO_INFINITY,  1.0, cols[0], "y0", False))
 67        y.append(model.add_var(-2.0, MDO_INFINITY, -1.0, cols[1], "y1", False))
 68
 69        # Solve the problem. 
 70        model.solve_prob()
 71        model.display_results()
 72        if WRITE_LP:
 73            model.write_prob("Step4.lp");
 74
 75        # Step 5. Add another two constraints and then resolve the problem.     
 76        print("\nStep 5. Add another two constraints and then resolve the problem.\n")
 77        bgn2 = [ 0, 3, 6 ]
 78        indices2 = [
 79            0,   1,        3,
 80            0,        2,   3  
 81        ]
 82        values2 = [
 83            1.0, 1.0,      -2.0,
 84            1.0,      -2.0, 6.0
 85        ]    
 86
 87        lhss2 = [ 0, 1            ]
 88        rhss2 = [ 2, MDO_INFINITY ]
 89
 90        expr = [ MdoExprLinear() for i in range(2) ]
 91        for i in range(2):
 92            for e in range(bgn2[i], bgn2[i + 1]):
 93                expr[i] += values2[e] * x[indices2[e]]
 94                
 95        c2 = model.add_conss( [ expr[i] == [lhss2[i], rhss2[i]] for i in range(2) ] )
 96        for key, value in c2.items():
 97            conss.append(value)
 98
 99        # Solve the problem. 
100        model.solve_prob()
101        model.display_results()
102        if WRITE_LP:
103            model.write_prob("Step5.lp");
104
105        # Step 6. Obtain optimal basis.     
106        print("\nStep 6. Obtain optimal basis.\n")
107        
108        # isFree = 0,
109        # basic = 1,
110        # atUpperBound = 2,
111        # atLowerBound = 3,
112        # superBasic = 4,
113        # isFixed = 5,
114        col_basis = []
115        row_basis = []
116        for var in x:
117            print("Basis status of variable {0} is {1}".format(var.get_index(), var.get_int_attr(MDO_INT_ATTR.COL_BASIS)))
118            col_basis.append(var.get_int_attr(MDO_INT_ATTR.COL_BASIS))
119        for var in y:
120            print("Basis status of variable {0} is {1}".format(var.get_index(), var.get_int_attr(MDO_INT_ATTR.COL_BASIS)))
121            col_basis.append(var.get_int_attr(MDO_INT_ATTR.COL_BASIS))
122        for cons in conss:
123            print("Basis status of constraint {0} is {1}".format(cons.get_index(), cons.get_int_attr(MDO_INT_ATTR.ROW_BASIS)))
124            row_basis.append(cons.get_int_attr(MDO_INT_ATTR.ROW_BASIS))
125
126        if WRITE_LP:
127            model.write_prob("Step6.lp");
128            model.write_soln("Step6.bas");
129
130        # Step 7. Warm-start Simplex.    
131        print("\nStep 7. Warm-start Simplex.\n")
132
133        # Change the objective coefficients. 
134        x[1].set_real_attr("Obj", 3.0);
135        x[2].set_real_attr("Obj", -3.0);
136
137        # Load the basis. 
138        model.set_int_attr_array(MDO_INT_ATTR.ROW_BASIS, 0, row_basis);
139        model.set_int_attr_array(MDO_INT_ATTR.COL_BASIS, 0, col_basis);
140
141        # Solve the problem. 
142        model.solve_prob()
143        model.display_results()
144        if WRITE_LP:
145            model.write_prob("Step7.lp");
146
147        # Step 8. Model query.     
148        print("\nStep 8. Model query.\n")
149
150        # Query 1: Retrieve first constraint. 
151        print("Query 1: Retrieve first constraint.")
152        
153        temp_expr = model.get_expr_linear(conss[0])
154        print(temp_expr)
155        
156        # Query 2: Retrieve second column. 
157        print("Query 2: Retrieve second column.")
158        
159        temp_col = model.get_col(x[1]);
160        print(temp_col)
161
162    except MdoError as e:
163        print("Received Mindopt exception.")
164        print(" - Code          : {}".format(e.code))
165        print(" - Reason        : {}".format(e.message))
166    except Exception as e:
167        print("Received exception.")
168        print(" - Reason        : {}".format(e))
169    finally:
170        # Step 4. Free the model.
171        model.free_mdl()