5.4.5. SDP modeling and optimization in Python language

In this section, we will use the API of MindOpt Python language to model and solve the problem in Examples of SDP Problems.

5.4.5.1. SDP Example 1

First, import the Python package:

23from mindoptpy import *

Step 1: Create a Model

Create an empty MindOpt model.

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

Step 2: Input SDP Model

Change to maximization problem and add a symmetric matrix variable \(\mathbf{X}\).

34        # Step 2. Input model.
35        # Change to maximization problem.
36        model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 0)
37        
38        # Add matrix variable. 
39        model.add_sym_mat(3, "X")

Use mindoptpy.MdoModel.replace_sym_mat_objs() to input the non-zero elements of \(\mathbf{C}\). The first parameter is the index value of the matrix (here is 0). The second and third parameters represent the index of the row and column corresponding to the non-zero elements in the matrix. The last parameter is the value of the non-zero element.

41        # Input objective coefficients. 
42        model.replace_sym_mat_objs(0, [ 0, 0, 1, 2 ], [ 0, 2, 1, 2], [ -3.0, 1.0, -2.0, -3.0])

Next, write the first constraint. We first write an empty constraint, then use mindoptpy.MdoModel.replace_sym_mat_elements() to input non-zero elements of \(\mathbf{A}\). The first and second parameters are: the index value of the constraint (here is 0) and the index value of the matrix (here is 0). The third and fourth parameters represent the index of the row and column corresponding to the non-zero elements in the matrix. The last parameter is the index of the value of the non-zero element.

44        # Input first constraint. 
45        model.add_cons(1.0, 1.0, name="c0")
46        model.replace_sym_mat_elements(0, 0, [ 0, 2, 1, 2 ], [ 0, 0, 1, 2 ], [ 3.0, 1.0, 4.0, 5.0 ])

Step 3: Solve the SDP model

When the model is input, use generic function mindoptpy.MdoModel.solve_prob() to solve the problem and use mindoptpy.MdoModel.display_results() to present the solution results.

48        # Step 3. Solve the problem and populate the result.
49        model.solve_prob()
50        model.display_results()

Step 4: Obtain the solutions of the SDP model

Use the function mindoptpy.MdoModel.get_real_attr() to obtain the optimal objective function value.

54            print("Optimizer terminated with an OPTIMAL status (code {0}).".format(status_code))
55            print(" - Primal objective : {:8.6f}".format(model.get_real_attr(MDO_REAL_ATTR.PRIMAL_OBJ_VAL)))

Finally, use mindoptpy.MdoModel.get_real_attr_sym_mat() to obtain \(\mathbf{X}\). The first parameter defines the attribute value (note: mindoptpy.MdoModel.get_real_attr_sym_mat() is a generic function, so it is declared with the attribute value and MDO_REAL_ATTR.SYM_MAT_PRIMAL_SOLN defines the purpose to obtain the value of the (symmetric matrix) variable. ) The second parameter is the index value of the matrix (here is 0). The third and fourth parameters are the index of the corresponding row and column of the element that needs to be returned in the matrix. The return value soln is the corresponding element in the matrix.

57            soln = model.get_real_attr_sym_mat(MDO_REAL_ATTR.SYM_MAT_PRIMAL_SOLN, 0, 
58                [i * 3 + j for i in range(3) for j in range(3)], 
59                [j * 3 + i for i in range(3) for j in range(3)])           

Please refer to the linked file mdo_sdo_ex1.py for the complete code.

 1"""
 2/**
 3 *  Description
 4 *  -----------
 5 *
 6 *  Semidefinite optimization (row-wise input).
 7 *
 8 *  Formulation
 9 *  -----------
10 *
11 *  Maximize
12 *  obj: tr(C X)
13 *
14 *  Subject To
15 *    c0 : tr(A X) = 1
16 *  Matrix
17 *    C = [ -3  0  1 ]  A = [ 3 0 1 ]
18 *        [  0 -2  0 ]      [ 0 4 0 ]
19 *        [  1  0 -3 ]      [ 1 0 5 ]
20 *  End
21 */
22 """
23from mindoptpy import *
24
25
26if __name__ == "__main__":
27
28    MDO_INFINITY = MdoModel.get_infinity()
29
30    # Step 1. Create a model and change the parameters.
31    model = MdoModel()
32
33    try:
34        # Step 2. Input model.
35        # Change to maximization problem.
36        model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 0)
37        
38        # Add matrix variable. 
39        model.add_sym_mat(3, "X")
40
41        # Input objective coefficients. 
42        model.replace_sym_mat_objs(0, [ 0, 0, 1, 2 ], [ 0, 2, 1, 2], [ -3.0, 1.0, -2.0, -3.0])
43
44        # Input first constraint. 
45        model.add_cons(1.0, 1.0, name="c0")
46        model.replace_sym_mat_elements(0, 0, [ 0, 2, 1, 2 ], [ 0, 0, 1, 2 ], [ 3.0, 1.0, 4.0, 5.0 ])
47       
48        # Step 3. Solve the problem and populate the result.
49        model.solve_prob()
50        model.display_results()
51
52        status_code, status_msg = model.get_status()
53        if status_msg == "OPTIMAL":
54            print("Optimizer terminated with an OPTIMAL status (code {0}).".format(status_code))
55            print(" - Primal objective : {:8.6f}".format(model.get_real_attr(MDO_REAL_ATTR.PRIMAL_OBJ_VAL)))
56            
57            soln = model.get_real_attr_sym_mat(MDO_REAL_ATTR.SYM_MAT_PRIMAL_SOLN, 0, 
58                [i * 3 + j for i in range(3) for j in range(3)], 
59                [j * 3 + i for i in range(3) for j in range(3)])           
60            print("X = ")
61            for i in range(3):
62                print(" (", end="") 
63                for j in range(3):
64                    print(" {0:8.6f}".format(soln[i * 3 + j]), end=""), 
65                print(" )") 
66
67        else:
68            print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))
69
70    except MdoError as e:
71        print("Received Mindopt exception.")
72        print(" - Code          : {}".format(e.code))
73        print(" - Reason        : {}".format(e.message))
74    except Exception as e:
75        print("Received exception.")
76        print(" - Reason        : {}".format(e))
77    finally:
78        # Step 4. Free the model.
79        model.free_mdl()

5.4.5.2. SDP Example 2

First, import the Python package:

30from mindoptpy import *

Step 1: Create a Model

Create an empty MindOpt model.

37    # Step 1. Create a model and change the parameters.
38    model = MdoModel()

Step 2: Input SDP Model

Change to maximization problem and add two scalar variables \(x_0\)\(x_1\) and two symmetric matrix variables \(\mathbf{X}_0\), \(\mathbf{X}_1\).

41        # Step 2. Input model.
42        # Change to maximization problem.
43        model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 0)
44        
45        # Add variables.
46        x = []
47        x.append(model.add_var(0.0, MDO_INFINITY, 0.0, None, "x0", False))
48        x.append(model.add_var(0.0, MDO_INFINITY, 0.0, None, "x1", False))
49        # Add matrix variables. 
50        model.add_sym_mats([ 2, 3 ], [ "X0", "X1" ]);

Use mindoptpy.MdoModel.replace_sym_mat_objs() to input the non-zero elements of \(\mathbf{C}\). The first parameter is the index value of the matrix (here is 0). The second and third parameters represent the index of the row and column corresponding to the non-zero elements in the matrix. The last parameter is the value of the non-zero element.

52        # Input objective coefficients. 
53        model.replace_sym_mat_objs(0, [ 0, 1, 1 ], [ 0, 0, 1 ], [ 2.0, 1.0, 2.0 ]);

Similarly, we then input the non-zero elements of \(\mathbf{C}_1\) in the objective function.

54        model.replace_sym_mat_objs(1, [ 0, 0, 1, 2 ], [ 0, 2, 1, 2], [ 3.0, 1.0, 2.0, 3.0]);

Next, write the first constraint. We first write \(x_0=1\), then use mindoptpy.MdoModel.replace_sym_mat_elements() to input non-zero elements of \(\mathbf{A}_{00}\). The first and second parameters are the index value of the constraint (here is 0) and the index value of the matrix (here is 0). The third and fourth parameters represent the index of the row and column corresponding to the non-zero elements in the matrix. The last parameter is the value of the non-zero element.

56        # Input first constraint. 
57        model.add_cons(1.0 * x[0] == 1.0, "c0");
58        model.replace_sym_mat_elements(0, 0, [ 0, 1, 1 ], [ 0, 0, 1 ], [ 3.0, 1.0, 3.0 ]);

In the same way, write the second constraint.

60        # Input second constraint. 
61        model.add_cons(1.0 * x[1] == 2.0, "c1");
62        model.replace_sym_mat_elements(1, 1, [ 0, 2, 1, 2 ], [ 0, 0, 1, 2 ], [ 3.0, 1.0, 4.0, 5.0 ]);

Step3: Solve the SDP model

When the model is input, use the generic function mindoptpy.MdoModel.solve_prob() to solve the problem and use the function mindoptpy.MdoModel.display_results() to present the solution results.

64        # Step 3. Solve the problem and populate the result.
65        model.solve_prob()
66        model.display_results()

Step 4: Obtain the solutions of the SDP model

We use the function mindoptpy.MdoModel.get_real_attr() to get the optimal objective function value and the function mindoptpy.MdoModel.get_real_attr_array() to obtain the variables \(x_0\)\(x_1\). The first parameter is the attribute value (note: Mdo_getRealAttrArray() is a generic function, so it is declared with the attribute value and MDO_REAL_ATTR.PRIMAL_SOLN defines the purpose to obtain the values of scalar variables. ) The second and third parameters represent the first index and the last index plus 1, that is, \(x_j\), \(0 \leq j < 2\).

71            print(" - Primal objective : {:8.6f}".format(model.get_real_attr(MDO_REAL_ATTR.PRIMAL_OBJ_VAL)))
72            soln = model.get_real_attr_array(MDO_REAL_ATTR.PRIMAL_SOLN, 0, 2)

Finally, use mindoptpy.MdoModel.get_real_attr_sym_mat() to obtain \(\mathbf{X}_0\) and \(\mathbf{X}_1\). The first parameter defines the attribute value (note: mindoptpy.MdoModel.get_real_attr_sym_mat() is a generic function, so it is declared with the attribute value and MDO_REAL_ATTR.SYM_MAT_PRIMAL_SOLN defines the purpose to obtain the value of the (symmetric matrix) variable. ) The second parameter is the index value of the matrix (here is 0). The third and fourth parameters are the index of the corresponding row and column of the element that needs to be returned in the matrix. The return value soln is the corresponding element in the matrix.

76            soln = model.get_real_attr_sym_mat(MDO_REAL_ATTR.SYM_MAT_PRIMAL_SOLN, 0, 
77                [i * 2 + j for i in range(2) for j in range(2)], 
78                [j * 2 + i for i in range(2) for j in range(2)])           

Please refer to the linked file mdo_sdo_ex2.py for the complete code.

  1"""
  2/**
  3 *  Description
  4 *  -----------
  5 *
  6 *  Semidefinite optimization (row-wise input).
  7 *
  8 *  Formulation
  9 *  -----------
 10 *
 11 *  Maximize
 12 *  obj: tr(C0 X0)   + tr(C1 X1)    + 0 x0 + 0 x1
 13 *
 14 *  Subject To
 15 *   c0 : tr(A00 X0)                + 1 x0        = 1
 16 *   c1 :              tr(A11 X1)          + 1 x1 = 2
 17 *  Bounds
 18 *    0 <= x0
 19 *    0 <= x1
 20 *  Matrix
 21 *    C0 =  [ 2 1 ]   A00 = [ 3 1 ]
 22 *          [ 1 2 ]         [ 1 3 ]
 23 *
 24 *    C1 = [ 3 0 1 ]  A11 = [ 3 0 1 ]
 25 *         [ 0 2 0 ]        [ 0 4 0 ]
 26 *         [ 1 0 3 ]        [ 1 0 5 ]
 27 *  End
 28 */
 29 """
 30from mindoptpy import *
 31
 32
 33if __name__ == "__main__":
 34
 35    MDO_INFINITY = MdoModel.get_infinity()
 36
 37    # Step 1. Create a model and change the parameters.
 38    model = MdoModel()
 39
 40    try:
 41        # Step 2. Input model.
 42        # Change to maximization problem.
 43        model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 0)
 44        
 45        # Add variables.
 46        x = []
 47        x.append(model.add_var(0.0, MDO_INFINITY, 0.0, None, "x0", False))
 48        x.append(model.add_var(0.0, MDO_INFINITY, 0.0, None, "x1", False))
 49        # Add matrix variables. 
 50        model.add_sym_mats([ 2, 3 ], [ "X0", "X1" ]);
 51
 52        # Input objective coefficients. 
 53        model.replace_sym_mat_objs(0, [ 0, 1, 1 ], [ 0, 0, 1 ], [ 2.0, 1.0, 2.0 ]);
 54        model.replace_sym_mat_objs(1, [ 0, 0, 1, 2 ], [ 0, 2, 1, 2], [ 3.0, 1.0, 2.0, 3.0]);
 55
 56        # Input first constraint. 
 57        model.add_cons(1.0 * x[0] == 1.0, "c0");
 58        model.replace_sym_mat_elements(0, 0, [ 0, 1, 1 ], [ 0, 0, 1 ], [ 3.0, 1.0, 3.0 ]);
 59
 60        # Input second constraint. 
 61        model.add_cons(1.0 * x[1] == 2.0, "c1");
 62        model.replace_sym_mat_elements(1, 1, [ 0, 2, 1, 2 ], [ 0, 0, 1, 2 ], [ 3.0, 1.0, 4.0, 5.0 ]);
 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 : {:8.6f}".format(model.get_real_attr(MDO_REAL_ATTR.PRIMAL_OBJ_VAL)))
 72            soln = model.get_real_attr_array(MDO_REAL_ATTR.PRIMAL_SOLN, 0, 2)
 73            for index, value in enumerate(soln):
 74                print("x[{0}]={1:8.6f}".format(index, value))
 75            
 76            soln = model.get_real_attr_sym_mat(MDO_REAL_ATTR.SYM_MAT_PRIMAL_SOLN, 0, 
 77                [i * 2 + j for i in range(2) for j in range(2)], 
 78                [j * 2 + i for i in range(2) for j in range(2)])           
 79            print("X[0] = ")
 80            for i in range(2):
 81                print(" (", end="") 
 82                for j in range(2):
 83                    print(" {0:8.6f}".format(soln[i * 2 + j]), end=""), 
 84                print(" )") 
 85
 86            soln = model.get_real_attr_sym_mat(MDO_REAL_ATTR.SYM_MAT_PRIMAL_SOLN, 1, 
 87                [i * 3 + j for i in range(3) for j in range(3)], 
 88                [j * 3 + i for i in range(3) for j in range(3)])
 89            print("X[1] = ")
 90            for i in range(3):
 91                print(" (", end=""), 
 92                for j in range(3):
 93                    print(" {0:8.6f}".format(soln[i * 3 + j]), end=""),
 94                print(" )") 
 95
 96        else:
 97            print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))
 98
 99    except MdoError as e:
100        print("Received Mindopt exception.")
101        print(" - Code          : {}".format(e.code))
102        print(" - Reason        : {}".format(e.message))
103    except Exception as e:
104        print("Received exception.")
105        print(" - Reason        : {}".format(e))
106    finally:
107        # Step 4. Free the model.
108        model.free_mdl()