5.7.6. SDP Modeling and Optimization in C#

In this chapter, we will use MindOpt C# API to model and solve the problem in Examples of semidefinite programming.

5.7.6.1. SDP Example I

Step I: Create an optimization model

Create an empty optimization model:

44            // Create model
45            MDOEnv env = new MDOEnv(); 
46            MDOModel model = new MDOModel(env); 
47            model.Set(MDO.StringAttr.ModelName, "SDP_01");

Step II: SDP model input

We use MDOModel.AddPsdVar to create a new semidefinite matrix variable representing \(\mathbf{X}\) in our example and simultaneously set its corresponding coefficient matrix \(\mathbf{C}\) in the objective function.

  • The first argument is the coefficient matrix, which is an instance of the MDOMatrix created using the MDOMatrix.Coo method. Note that the dimensions of the coefficient matrix should match the matrix variables.

  • The second argument is the name of the variable.

51                // Add variables.
52                MDOPsdVar psd_var = model.AddPsdVar(MDOMatrix.Coo(dim_mat, dim_mat, C_nz_indices, C_nz_values), "X0");

Next, we input the first constraint. We use MDOModel.AddPsdConstr to establish a constraint with a semidefinite matrix variable.

  • The first argument is the semidefinite expression in the constraint, i.e., \(\langle \mathbf{A},\mathbf{X} \rangle\). We create it using the initialization method MDOPsdExpr.MDOPsdExpr.

  • The second argument is the type of the constraint, where MDO.EQUAL (‘=’) represents an equality constraint.

  • The third argument is the right-hand side value of the constraint (in this case, 1.0). The last argument is the name of the constraint.

54                /* Add constraints. */
55                MDOPsdExpr psd_expr = new MDOPsdExpr(psd_var, MDOMatrix.Coo(dim_mat, dim_mat, A_nz_indices, A_nz_values));
56                model.AddPsdConstr(psd_expr, MDO.EQUAL, 1.0, "C0");

Finally, we use MDOModel.SetObjective to set the rest of the objective function (in this case, 0), and change the optimization direction to maximization (-1).

58                /* Set objective function. */
59                MDOLinExpr obj = new MDOLinExpr();
60                model.SetObjective(obj, MDO.MAXIMIZE);

Step III: Solve SDP model

Solve the optimization problem via MDOModel.Optimize.

62                // Solve the problem and populate optimization result.
63                model.Optimize();

Step IV: Obtain the solution of SDP problem

We use the generic function MDOModel.Get to retrieve the optimal objective function value, i.e., the ObjVal attribute.

65                if (model.Get(MDO.IntAttr.Status) == MDO.Status.OPTIMAL)
66                {
67                    Console.WriteLine($"Optimal objective value is: {model.Get(MDO.DoubleAttr.ObjVal)}");
68                }
69                else
70                {
71                    Console.WriteLine("No feasible solution.");
72                }

The complete example code is provided in mdo_sdo_ex1.cs :

 1/**
 2 *  Description
 3 *  -----------
 4 *
 5 *  Semidefinite optimization (row-wise input).
 6 *
 7 *  Formulation
 8 *  -----------
 9 *
10 *  Maximize 
11 *  obj: tr(C X) 
12 * 
13 *  Subject To
14 *    c0 : tr(A X) = 1
15 *         X is p.s.d.
16 *
17 *  Matrix
18 *    C = [ -3  0  1 ]  A = [ 3 0 1 ]
19 *        [  0 -2  0 ]      [ 0 4 0 ]
20 *        [  1  0 -3 ]      [ 1 0 5 ]
21 *  End
22 */
23
24using Mindopt;
25
26namespace Example
27{
28    public class MdoSdoEx1
29    {
30        public static void Main(string[] args)
31        {
32            /* Model data. */
33            int    num_mats = 1;
34            int    dim_mat = 3;                                 /* Dimension of the matrix variables. */
35
36            int      C_nnz = 4;
37            int[]    C_nz_indices = new int[]    {  0,   2,    4,    8    }; /* Nonzero vectorized index of obj coeff. */
38            double[] C_nz_values  = new double[] { -3.0, 1.0,  -2.0, -3.0 }; /* Nonzero values of obj coeff. */
39
40            int      A_nnz = 4;
41            int[]    A_nz_indices = new int[]    { 0,    2,    4,    8    }; /* Nonzero vectorized index of constr coeff. */
42            double[] A_nz_values  = new double[] { 3.0,  1.0,  4.0,  5.0  }; /* Nonzero values of constr coeff. */
43
44            // Create model
45            MDOEnv env = new MDOEnv(); 
46            MDOModel model = new MDOModel(env); 
47            model.Set(MDO.StringAttr.ModelName, "SDP_01");
48
49            try
50            {
51                // Add variables.
52                MDOPsdVar psd_var = model.AddPsdVar(MDOMatrix.Coo(dim_mat, dim_mat, C_nz_indices, C_nz_values), "X0");
53        
54                /* Add constraints. */
55                MDOPsdExpr psd_expr = new MDOPsdExpr(psd_var, MDOMatrix.Coo(dim_mat, dim_mat, A_nz_indices, A_nz_values));
56                model.AddPsdConstr(psd_expr, MDO.EQUAL, 1.0, "C0");
57
58                /* Set objective function. */
59                MDOLinExpr obj = new MDOLinExpr();
60                model.SetObjective(obj, MDO.MAXIMIZE);
61
62                // Solve the problem and populate optimization result.
63                model.Optimize();
64
65                if (model.Get(MDO.IntAttr.Status) == MDO.Status.OPTIMAL)
66                {
67                    Console.WriteLine($"Optimal objective value is: {model.Get(MDO.DoubleAttr.ObjVal)}");
68                }
69                else
70                {
71                    Console.WriteLine("No feasible solution.");
72                }
73            }
74            catch (Exception e)
75            { 
76                Console.WriteLine("Exception during optimization");
77                Console.WriteLine(e.Message);
78            }
79            finally
80            { 
81                model.Dispose();
82                env.Dispose();
83            }
84        }
85    }
86}

5.7.6.2. SDP Example II

Step I: Create an optimization model

Create an empty optimization model:

61            // Create model
62            MDOEnv env = new MDOEnv(); 
63            MDOModel model = new MDOModel(env); 
64            model.Set(MDO.StringAttr.ModelName, "SDP_02");

Step II: SDP model input

We use MDOModel.AddPsdVar to create two new semidefinite matrix variables (in this case, \(\mathbf{X}_0, \mathbf{X}_1\)) and simultaneously set their corresponding coefficient matrices (in this case, \(\mathbf{C}_0, \mathbf{C}_1\)) in the objective function.

69                MDOPsdVar psd_var0 = model.AddPsdVar(MDOMatrix.Coo(dim_mat[0], dim_mat[0], C0_nz_indices, C0_nz_values), "X0");
70                MDOPsdVar psd_var1 = model.AddPsdVar(MDOMatrix.Coo(dim_mat[1], dim_mat[1], C1_nz_indices, C1_nz_values), "X1");

We then use MDOModel.AddVar to create two linear variables representing \(x_0,x_1\) in this example.

  • The first and second arguments are the lower and upper bounds of the variables.

  • The third argument is the coefficient of the variable in the objective function.

  • The fourth argument is the type of the variable, which is continuous variable type (‘C’) in this case. The last argument is the name of the variable.

71                MDOVar    var0     = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x0");
72                MDOVar    var1     = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x1"); 

Next, we create constraints. We use MDOModel.AddPsdConstr to establish constraints with semidefinite matrix variables.

  • The first argument is the semidefinite expression in the constraint. Since the constraint in this example contains both semidefinite variables and linear variables, we construct the semidefinite expression in two steps.

    • Firstly, we create the semidefinite term using the initialization method MDOPsdExpr.MDOPsdExpr.

    • Then, we add the remaining linear term using the MDOPsdExpr.AddTerms method to obtain the final semidefinite expression for the constraint.

  • The second argument is the type of the constraint, where MDO.EQUAL (‘=’) represents an equality constraint.

  • The third argument is the right-hand side value of the constraint (in this case, 1.0).

  • The last argument is the name of the constraint.

74                /* Add constraints. */
75                MDOPsdExpr psd_expr0 = new MDOPsdExpr(psd_var0, MDOMatrix.Coo(dim_mat[0], dim_mat[0], A0_nz_indices, A0_nz_values));
76                MDOVar[] row0_vars = new MDOVar[] { var0 };
77                psd_expr0.AddTerms(row0_values, row0_vars);
78                model.AddPsdConstr(psd_expr0, MDO.EQUAL, 1.0, "C0");
79
80                MDOPsdExpr psd_expr1 = new MDOPsdExpr(psd_var1, MDOMatrix.Coo(dim_mat[1], dim_mat[1], A1_nz_indices, A1_nz_values));
81                MDOVar[] row1_vars = new MDOVar[] { var1 };
82                psd_expr1.AddTerms(row1_values, row1_vars);        
83                model.AddPsdConstr(psd_expr1, MDO.EQUAL, 2.0, "C1");

Finally, we use MDOModel.SetObjective to set the rest of the objective function (in this case, 0), and change the optimization direction to maximization (-1).

85                /* Set objective function. */
86                MDOLinExpr obj = new MDOLinExpr();
87                model.SetObjective(obj, MDO.MAXIMIZE);

Step III: Solve SDP model

Solve the optimization problem via MDOModel.Optimize.

89                // Solve the problem and populate optimization result.
90                model.Optimize();

Step IV: Obtain the solution of SDP problem

We use the generic function MDOModel.Get to retrieve the optimal objective function value, i.e., the ObjVal attribute.

92                if (model.Get(MDO.IntAttr.Status) == MDO.Status.OPTIMAL)
93                {
94                    Console.WriteLine($"Optimal objective value is: {model.Get(MDO.DoubleAttr.ObjVal)}");
95                }
96                else
97                {
98                    Console.WriteLine("No feasible solution.");
99                }

The complete example code is provided in mdo_sdo_ex2.cs :

  1/**
  2 *  Description
  3 *  -----------
  4 *
  5 *  Semidefinite optimization (row-wise input).
  6 *
  7 *  Formulation
  8 *  -----------
  9 *
 10 *  Maximize
 11 *  obj:
 12 *   tr(C0 X0)   + tr(C1 X1)    + 0 x0 + 0 x1
 13 *  Subject To
 14 *   c0 : tr(A00 X0)                + 1 x0        = 1
 15 *   c1 :              tr(A11 X1)          + 1 x1 = 2
 16 *  Bounds
 17 *    0 <= x0
 18 *    0 <= x1
 19 *    X0,X1 are p.s.d.
 20 *
 21 *  Matrix
 22 *    C0 =  [ 2 1 ]   A00 = [ 3 1 ]
 23 *          [ 1 2 ]         [ 1 3 ]
 24 *
 25 *    C1 = [ 3 0 1 ]  A11 = [ 3 0 1 ]
 26 *         [ 0 2 0 ]        [ 0 4 0 ]
 27 *         [ 1 0 3 ]        [ 1 0 5 ]
 28 *  End
 29 */
 30using Mindopt;
 31
 32namespace Example
 33{
 34    public class MdoSdoEx2
 35    {
 36        public static void Main(string[] args)
 37        {
 38            /* Model data. */
 39            int    num_mats = 1;
 40            int[]  dim_mat  = new int[] { 2, 3 };                 /* Dimension of the matrix variables. */
 41
 42            int      C0_nnz = 3;
 43            int[]    C0_nz_indices = new int[]    {  0,   1,   3   };  /* Nonzero vectorized index of obj coeff. */
 44            double[] C0_nz_values  = new double[] {  2.0, 1.0, 2.0 };  /* Nonzero values of obj coeff. */
 45            
 46            int      C1_nnz = 4;
 47            int[]    C1_nz_indices = new int[]    {  0,   2,   4,    8   };   /* Nonzero vectorized index of obj coeff. */
 48            double[] C1_nz_values  = new double[] {  3.0, 1.0, 2.0,  3.0 };   /* Nonzero values of obj coeff. */
 49
 50            int      A0_nnz = 3;
 51            int[]    A0_nz_indices = new int[]    {  0,   1,   3   };    /* Nonzero vectorized index of constr coeff. */
 52            double[] A0_nz_values  = new double[] {  3.0, 1.0, 3.0 };    /* Nonzero values of constr coeff. */
 53
 54            int      A1_nnz = 4;
 55            int[]    A1_nz_indices = new int[]    {  0,   2,   4,    8    };  /* Nonzero vectorized index of constr coeff. */
 56            double[] A1_nz_values  = new double[] {  3.0, 1.0, 4.0,  5.0  };  /* Nonzero values of constr coeff. */
 57            
 58            double[] row0_values = new double[] {  1.0 };
 59            double[] row1_values = new double[] {  1.0 };
 60
 61            // Create model
 62            MDOEnv env = new MDOEnv(); 
 63            MDOModel model = new MDOModel(env); 
 64            model.Set(MDO.StringAttr.ModelName, "SDP_02");
 65
 66            try
 67            {
 68                // Add variables.
 69                MDOPsdVar psd_var0 = model.AddPsdVar(MDOMatrix.Coo(dim_mat[0], dim_mat[0], C0_nz_indices, C0_nz_values), "X0");
 70                MDOPsdVar psd_var1 = model.AddPsdVar(MDOMatrix.Coo(dim_mat[1], dim_mat[1], C1_nz_indices, C1_nz_values), "X1");
 71                MDOVar    var0     = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x0");
 72                MDOVar    var1     = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x1"); 
 73
 74                /* Add constraints. */
 75                MDOPsdExpr psd_expr0 = new MDOPsdExpr(psd_var0, MDOMatrix.Coo(dim_mat[0], dim_mat[0], A0_nz_indices, A0_nz_values));
 76                MDOVar[] row0_vars = new MDOVar[] { var0 };
 77                psd_expr0.AddTerms(row0_values, row0_vars);
 78                model.AddPsdConstr(psd_expr0, MDO.EQUAL, 1.0, "C0");
 79
 80                MDOPsdExpr psd_expr1 = new MDOPsdExpr(psd_var1, MDOMatrix.Coo(dim_mat[1], dim_mat[1], A1_nz_indices, A1_nz_values));
 81                MDOVar[] row1_vars = new MDOVar[] { var1 };
 82                psd_expr1.AddTerms(row1_values, row1_vars);        
 83                model.AddPsdConstr(psd_expr1, MDO.EQUAL, 2.0, "C1");
 84
 85                /* Set objective function. */
 86                MDOLinExpr obj = new MDOLinExpr();
 87                model.SetObjective(obj, MDO.MAXIMIZE);
 88        
 89                // Solve the problem and populate optimization result.
 90                model.Optimize();
 91
 92                if (model.Get(MDO.IntAttr.Status) == MDO.Status.OPTIMAL)
 93                {
 94                    Console.WriteLine($"Optimal objective value is: {model.Get(MDO.DoubleAttr.ObjVal)}");
 95                }
 96                else
 97                {
 98                    Console.WriteLine("No feasible solution.");
 99                }
100            }
101            catch (Exception e)
102            { 
103                Console.WriteLine("Exception during optimization");
104                Console.WriteLine(e.Message);
105            }
106            finally
107            { 
108                model.Dispose();
109                env.Dispose();
110            }
111        }
112    }
113}