5.4.6. QCP Modeling and Optimization in C#ΒΆ
In this chapter, we will use MindOpt C# API to model and solve the problem in Example of Quadratically Constrained Programming.
Create an optimization model model
:
33 // Create model
34 MDOEnv env = new MDOEnv();
35 MDOModel model = new MDOModel(env);
36 model.Set(MDO.StringAttr.ModelName, "QCP_01");
Next, we set the optimization sense to minimization via MDOModel.Set
. Then, we call MDOModel.AddVar
to add four variables, which define upper bounds, lower bounds, names and types.
(for more details on MDOModel.Set
and MDOModel.AddVar
, please refer to C# API)
40 // Change to minimization problem.
41 model.Set(MDO.IntAttr.ModelSense, MDO.MINIMIZE);
42
43 // Add variables.
44 MDOVar[] x = new MDOVar[4];
45 x[0] = model.AddVar(0.0, 10.0, 0.0, 'C', "x0");
46 x[1] = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x1");
47 x[2] = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x2");
48 x[3] = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x3");
Then, we set the quadratic objective via a quadratic expression MDOQuadExpr
and call MDOQuadExpr.AddTerms
to set the linear part of the objective function. Here obj_idx
represents the indices of the linear terms, and obj_val
represents the corresponding non-zero coefficient values in obj_idx
.
44 MDOVar[] x = new MDOVar[4];
45 x[0] = model.AddVar(0.0, 10.0, 0.0, 'C', "x0");
46 x[1] = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x1");
47 x[2] = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x2");
75 /* Quadratic part in the second constraint: 1/2 [x1^2] */
76 int qc2_nnz = 1;
77 MDOVar[] qc2_col1 = new MDOVar[] { x[1] };
78 MDOVar[] qc2_col2 = new MDOVar[] { x[1] };
We call MDOQuadExpr.AddTerms
to set the quadratic terms of the objective. Here, qo_values
represents the coefficients of all the non-zero quadratic terms, while qo_col1
and qo_col2
respectively represent its row and column indices.
55 /* Quadratic part in the objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
56 int qo_nnz = 5;
57 MDOVar[] qo_col1 = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
58 MDOVar[] qo_col2 = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
59 double[] qo_values = new double[] { 0.5, 0.5, 0.5, 0.5, 0.5 };
85 // Add quadratic part in objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
86 obj.AddTerms(qo_values, qo_col1, qo_col2);
Lastly, we call MDOModel.SetObjective
to set the objective and the direction to be optimized.
88 model.SetObjective(obj, MDO.MINIMIZE);
Now we start to add quadratic constraints to the model. The quadratic expression is constructed in the same way as in the objective.
61 /* Linear part in the first constraint: 1 x0 + 1 x1 + 2 x2 + 3 x3 */
62 int c1_nnz = 4;
63 MDOVar[] c1_idx = new MDOVar[] { x[0], x[1], x[2], x[3] };
64 double[] c1_val = new double[] { 1.0, 1.0, 2.0, 3.0 };
65 /* Quadratic part in the first constraint: - 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
66 int qc1_nnz = 5;
67 MDOVar[] qc1_col1 = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
68 MDOVar[] qc1_col2 = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
69 double[] qc1_values = new double[] { -0.5, -0.5, -0.5, -0.5, -0.5 };
91 MDOQuadExpr c1 = new MDOQuadExpr();
92 c1.AddTerms(c1_val, c1_idx);
93 c1.AddTerms(qc1_values, qc1_col1, qc1_col2);
71 /* Linear part in the second constraint: 1 x0 - 1 x2 + 6 x3 */
72 int c2_nnz = 3;
73 MDOVar[] c2_idx = new MDOVar[] { x[0], x[2], x[3] };
74 double[] c2_val = new double[] { 1.0, -1.0, 6.0 };
75 /* Quadratic part in the second constraint: 1/2 [x1^2] */
76 int qc2_nnz = 1;
77 MDOVar[] qc2_col1 = new MDOVar[] { x[1] };
78 MDOVar[] qc2_col2 = new MDOVar[] { x[1] };
79 double[] qc2_values = new double[] { 0.5 };
97 MDOQuadExpr c2 = new MDOQuadExpr();
98 c2.AddTerms(c2_val, c2_idx);
99 c2.AddTerms(qc2_values, qc2_col1, qc2_col2);
Then, we call MDOModel::AddQConstr
to add the quadratic constraints to the model.
94 model.AddQConstr(c1, MDO.GREATER_EQUAL, 1.0, "c0");
100 model.AddQConstr(c2, MDO.LESS_EQUAL, 1.0, "c1");
Once the model is constructed, we call MDOModel.Optimize
to solve the problem:
102 // Solve the problem and populate optimization result.
103 model.Optimize();
The complete example code is shown in MdoQcoEx1.cs :
1/**
2 * Description
3 * -----------
4 *
5 * Quadratically constrained quadratic optimization (row-wise input).
6 *
7 * Formulation
8 * -----------
9 *
10 * Minimize
11 * obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
12 * + 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
13 *
14 * Subject To
15 * c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 - 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] >= 1
16 * c1 : 1 x0 - 1 x2 + 6 x3 + 1/2 [x1^2] <= 1
17 * Bounds
18 * 0 <= x0 <= 10
19 * 0 <= x1
20 * 0 <= x2
21 * 0 <= x3
22 * End
23 */
24
25using Mindopt;
26
27namespace Example
28{
29 public class MdoQcoEx1
30 {
31 public static void Main(string[] args)
32 {
33 // Create model
34 MDOEnv env = new MDOEnv();
35 MDOModel model = new MDOModel(env);
36 model.Set(MDO.StringAttr.ModelName, "QCP_01");
37
38 try
39 {
40 // Change to minimization problem.
41 model.Set(MDO.IntAttr.ModelSense, MDO.MINIMIZE);
42
43 // Add variables.
44 MDOVar[] x = new MDOVar[4];
45 x[0] = model.AddVar(0.0, 10.0, 0.0, 'C', "x0");
46 x[1] = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x1");
47 x[2] = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x2");
48 x[3] = model.AddVar(0.0, MDO.INFINITY, 0.0, 'C', "x3");
49
50 /* Prepare model data. */
51 /* Linear part in the objective: 1 x0 + 1 x1 + 1 x2 + 1 x3 */
52 int obj_nnz = 4;
53 MDOVar[] obj_idx = new MDOVar[] { x[0], x[1], x[2], x[3] };
54 double[] obj_val = new double[] { 1.0, 1.0, 1.0, 1.0 };
55 /* Quadratic part in the objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
56 int qo_nnz = 5;
57 MDOVar[] qo_col1 = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
58 MDOVar[] qo_col2 = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
59 double[] qo_values = new double[] { 0.5, 0.5, 0.5, 0.5, 0.5 };
60
61 /* Linear part in the first constraint: 1 x0 + 1 x1 + 2 x2 + 3 x3 */
62 int c1_nnz = 4;
63 MDOVar[] c1_idx = new MDOVar[] { x[0], x[1], x[2], x[3] };
64 double[] c1_val = new double[] { 1.0, 1.0, 2.0, 3.0 };
65 /* Quadratic part in the first constraint: - 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
66 int qc1_nnz = 5;
67 MDOVar[] qc1_col1 = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
68 MDOVar[] qc1_col2 = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
69 double[] qc1_values = new double[] { -0.5, -0.5, -0.5, -0.5, -0.5 };
70
71 /* Linear part in the second constraint: 1 x0 - 1 x2 + 6 x3 */
72 int c2_nnz = 3;
73 MDOVar[] c2_idx = new MDOVar[] { x[0], x[2], x[3] };
74 double[] c2_val = new double[] { 1.0, -1.0, 6.0 };
75 /* Quadratic part in the second constraint: 1/2 [x1^2] */
76 int qc2_nnz = 1;
77 MDOVar[] qc2_col1 = new MDOVar[] { x[1] };
78 MDOVar[] qc2_col2 = new MDOVar[] { x[1] };
79 double[] qc2_values = new double[] { 0.5 };
80
81 // Create a QuadExpr for quadratic objective
82 MDOQuadExpr obj = new MDOQuadExpr();
83 // Add objective linear term: 1 x0 + 1 x1 + 1 x2 + 1 x3
84 obj.AddTerms(obj_val, obj_idx);
85 // Add quadratic part in objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
86 obj.AddTerms(qo_values, qo_col1, qo_col2);
87
88 model.SetObjective(obj, MDO.MINIMIZE);
89
90 // Add 1st quadratic constraint.
91 MDOQuadExpr c1 = new MDOQuadExpr();
92 c1.AddTerms(c1_val, c1_idx);
93 c1.AddTerms(qc1_values, qc1_col1, qc1_col2);
94 model.AddQConstr(c1, MDO.GREATER_EQUAL, 1.0, "c0");
95
96 // Add 2nd quadratic constraint.
97 MDOQuadExpr c2 = new MDOQuadExpr();
98 c2.AddTerms(c2_val, c2_idx);
99 c2.AddTerms(qc2_values, qc2_col1, qc2_col2);
100 model.AddQConstr(c2, MDO.LESS_EQUAL, 1.0, "c1");
101
102 // Solve the problem and populate optimization result.
103 model.Optimize();
104
105 if (model.Get(MDO.IntAttr.Status) == MDO.Status.OPTIMAL)
106 {
107 Console.WriteLine($"Optimal objective value is: {model.Get(MDO.DoubleAttr.ObjVal)}");
108 Console.WriteLine("Decision variables: ");
109 for (int i = 0; i < 4; i++)
110 Console.WriteLine( $"x[{i}] = {x[i].Get(MDO.DoubleAttr.X)}");
111 }
112 else
113 {
114 Console.WriteLine("No feasible solution.");
115 }
116 }
117 catch (Exception e)
118 {
119 Console.WriteLine("Exception during optimization");
120 Console.WriteLine(e.Message);
121 }
122 finally
123 {
124 model.Dispose();
125 env.Dispose();
126 }
127 }
128 }
129}