5.3.4. QP Modeling and Optimization in Python

In this section, we will utilize MindOpt Python API to model and solve the quadratic optimization problem in Example of Quadratic Programming.

Import MindOpt Python package:

25from mindoptpy import *

Create an optimization model model with name “QP_01”:

30    # Step 1. Create model.
31    model = Model("QP_01")

Next, we call Model.addVar() to add four variables and define their lower bounds, upper bounds, names and types (please refer to Python API for more details) :

36        # Add variables.
37        x = []
38        x.append(model.addVar(0.0,         10.0, 0.0, 'C', "x0")) 
39        x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x1"))
40        x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x2"))
41        x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x3"))

Then, we add the linear constraints.

43        # Add constraints.
44        # Note that the nonzero elements are inputted in a row-wise order here.
45        model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3] >= 1, "c0")
46        model.addConstr(1.0 * x[0]              - 1.0 * x[2] + 6.0 * x[3] == 1, "c1")

Then, we set the objective function. We first create a quadratic expression using the class QuadExpr. There are two ways to construct it: The first way is to use the method QuadExpr.addTerms() in QuadExpr to input the linear part and quadratic part separately. The second way is to directly input a quadratic expression.

Subsequently, we use Model.setObjective() to set the objective function and set the problem to minimization.

47        # Add objective: 1 x0 + 1 x1 + 1 x2 + 1 x3 + 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
48        obj = QuadExpr()
49
50        #option-I
51        obj.addTerms([1.0, 1.0, 1.0, 1.0], [x[0], x[1], x[2], x[3]])
52        obj.addTerms([0.5, 0.5, 0.5, 0.5, 0.5], [x[0], x[1], x[2], x[3], x[0]], [x[0], x[1], x[2], x[3], x[1]])
53        
54        #option II
55        # obj = 1*x[0] + 1*x[1] + 1*x[2] + 1*x[3] + 0.5 * x[0]*x[0] + 0.5 * x[1]*x[1] + 0.5 * x[2]*x[2] + 0.5 * x[3]*x[3] + 0.5*x[0]*x[1]
56        
57        # Set objective and change to minimization problem.
58        model.setObjective(obj, MDO.MINIMIZE)

Once the model is constructed, we call Model.optimize() to solve the problem:

62        model.optimize()

We can check the solution status via the attribute Status, and retrieive the optimal objective value and solutions via attributes ObjVal and X. For other attribute information, please refer to Attributes.

64        if model.status == MDO.OPTIMAL:
65            print(f"Optimal objective value is: {model.objval}")
66            print("Decision variables:")
67            for v in x:
68                print(f"x[{v.VarName}] = {v.X}")
69        else:
70            print("No feasible solution.")

Finally, we free the model by calling Model.dispose().

80        model.dispose()

The complete python code is shown in mdo_qo_ex1.py:

 1"""
 2/**
 3 *  Description
 4 *  -----------
 5 *
 6 *  Quadratuc optimization (row-wise input).
 7 *
 8 *  Formulation
 9 *  -----------
10 *
11 *  Minimize
12 *    obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
13 *         + 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
14 *  Subject To
15 *   c1 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
16 *   c2 : 1 x0 - 1 x2 + 6 x3 = 1
17 *  Bounds
18 *    0 <= x0 <= 10
19 *    0 <= x1
20 *    0 <= x2
21 *    0 <= x3
22 *  End
23 */
24"""
25from mindoptpy import *
26
27
28if __name__ == "__main__":
29
30    # Step 1. Create model.
31    model = Model("QP_01")
32
33    try:
34        # Step 2. Input model.
35
36        # Add variables.
37        x = []
38        x.append(model.addVar(0.0,         10.0, 0.0, 'C', "x0")) 
39        x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x1"))
40        x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x2"))
41        x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x3"))
42
43        # Add constraints.
44        # Note that the nonzero elements are inputted in a row-wise order here.
45        model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3] >= 1, "c0")
46        model.addConstr(1.0 * x[0]              - 1.0 * x[2] + 6.0 * x[3] == 1, "c1")
47
48        # Add objective: 1 x0 + 1 x1 + 1 x2 + 1 x3 + 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
49        obj = QuadExpr()
50
51        #option-I
52        obj.addTerms([1.0, 1.0, 1.0, 1.0], [x[0], x[1], x[2], x[3]])
53        obj.addTerms([0.5, 0.5, 0.5, 0.5, 0.5], [x[0], x[1], x[2], x[3], x[0]], [x[0], x[1], x[2], x[3], x[1]])
54        
55        #option II
56        # obj = 1*x[0] + 1*x[1] + 1*x[2] + 1*x[3] + 0.5 * x[0]*x[0] + 0.5 * x[1]*x[1] + 0.5 * x[2]*x[2] + 0.5 * x[3]*x[3] + 0.5*x[0]*x[1]
57        
58        # Set objective and change to minimization problem.
59        model.setObjective(obj, MDO.MINIMIZE)
60
61        # Step 3. Solve the problem and populate optimization result.
62        model.optimize()
63
64        if model.status == MDO.OPTIMAL:
65            print(f"Optimal objective value is: {model.objval}")
66            print("Decision variables:")
67            for v in x:
68                print(f"x[{v.VarName}] = {v.X}")
69        else:
70            print("No feasible solution.")
71    except MindoptError as e:
72        print("Received Mindopt exception.")
73        print(" - Code          : {}".format(e.code))
74        print(" - Reason        : {}".format(e.message))
75    except Exception as e:
76        print("Received other exception.")
77        print(" - Reason        : {}".format(e))
78    finally:
79        # Step 4. Free the model.
80        model.dispose()