5.6.11. MISOCP Modeling and Optimization in C#¶
In this chapter, we will use MindOpt C# API to model and solve the mixed-integer second-order cone program in MIQCP Example II.
Include the Mindopt namespace:
25 */
26using Mindopt;
Create an optimization environment and model:
34 {
35 // Create environment and model.
36 MDOEnv env = new MDOEnv();
37 MDOModel model = new MDOModel(env);
Next, we set the optimization sense to minimization. Then, we call MDOModel.AddVar to add five variables. Their lower bounds, upper bounds, types, names, and linear objective coefficients are all passed directly as arguments.
Note
To mark a variable as integer, set its type to 'I' in the call to MDOModel.AddVar.
43 // Change to minimization problem.
44 // Add variables. The linear objective coefficients are specified directly.
45 MDOVar[] x = new MDOVar[5];
46 x[0] = model.AddVar(0.0, 10.0, 1.0, 'I', "x0");
47 x[1] = model.AddVar(0.0, MDO.INFINITY, 2.0, 'I', "x1");
48 x[2] = model.AddVar(0.0, MDO.INFINITY, 1.0, 'I', "x2");
49 x[3] = model.AddVar(0.0, MDO.INFINITY, 1.0, 'C', "x3");
Note
Since the linear objective coefficients are passed directly during variable creation, there is no separate call to MDOModel.SetObjective.
We now add the linear constraints. For the C# API, this involves creating an MDOExpr object for each constraint and adding terms to it.
Constraint c0: \(x_0 + x_1 + 2x_2 + 3x_3 \geq 1\)
Constraint c1: \(x_0 - x_2 + 6x_3 = 1\)
These are added to the model using MDOModel.AddConstr:
53 // Add linear constraint c0: 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
54 MDOExpr c0 = new MDOExpr();
55 c0.AddTerms(new double[] { 1.0, 1.0, 2.0, 3.0 }, new MDOVar[] { x[0], x[1], x[2], x[3] });
56 model.AddConstr(c0, MDO.GREATER_EQUAL, 1.0, "c0");
57
58 // Add linear constraint c1: 1 x0 - 1 x2 + 6 x3 = 1
59 MDOExpr c1 = new MDOExpr();
60 c1.AddTerms(new double[] { 1.0, -1.0, 6.0 }, new MDOVar[] { x[0], x[2], x[3] });
Finally, we add the quadratic (second-order cone) constraint:
c2: \(x_1^2 + x_2^2 - x_4^2 \leq 0\)
This is done by creating an MDOQuadExpr object and adding the quadratic terms. The constraint is then added to the model using MDOModel.AddQConstr.
63 // Add second-order cone constraint c2: x_1^2 + x_2^2 - x_4^2 <= 0
64 MDOQuadExpr c2 = new MDOQuadExpr();
65 // This constraint has no linear part. We only add the quadratic terms.
66 c2.AddTerms(
67 new double[] { 1.0, 1.0, -1.0 }, // values
68 new MDOVar[] { x[1], x[2], x[4] }, // first variable indices
69 new MDOVar[] { x[1], x[2], x[4] } // second variable indices
70 );
Once the model is fully constructed, we solve it by calling MDOModel.Optimize:
74 // Step 2. Solve the problem.
After solving, we check the solution status and retrieve the optimal objective value and variable values.
82 // exist, making it necessary to check the SolCount property.
83 if (model.Get(MDO.IntAttr.Status) == MDO.Status.OPTIMAL || model.Get(MDO.IntAttr.Status) == MDO.Status.SUB_OPTIMAL ||
84 model.Get(MDO.IntAttr.SolCount) > 0)
85 {
86 Console.WriteLine($"Optimal objective value is: {model.Get(MDO.DoubleAttr.ObjVal)}");
87 Console.WriteLine("Decision variables: ");
88 for (int i = 0; i < 5; i++)
89 {
90 Console.WriteLine($"x[{i}] = {x[i].Get(MDO.DoubleAttr.X)}");
91 }
Finally, we dispose of the model and environment to free up resources.
110 {
111 // Step 4. Free the model.
112 model.Dispose();
The complete example code is shown in MdoMISOCPEx1.cs :
1/**
2 * Description
3 * -----------
4 *
5 * Formulation
6 * -----------
7 *
8 Minimize
9 * obj: 1 x0 + 2 x1 + 1 x2 + 1 x3 + 0.5 x_4
10 *
11 *
12 * Subject To
13 * c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
14 * c1 : 1 x0 - 1 x2 + 6 x3 = 1
15 * c2 : x_1^2 + x_2^2 - x_4^2 <= 0
16 * Bounds
17 * 0 <= x0 <= 10
18 * 0 <= x1
19 * 0 <= x2
20 * 0 <= x3
21 * 0 <= x4
22 * Integer
23 * x0, x1, x2
24 * End
25 */
26using Mindopt;
27using System;
28
29namespace Example
30{
31 public class MdoMISOCPEx1
32 {
33 public static void Main(string[] args)
34 {
35 // Create environment and model.
36 MDOEnv env = new MDOEnv();
37 MDOModel model = new MDOModel(env);
38 model.Set(MDO.StringAttr.ModelName, "MISOCPEx1");
39
40 try
41 {
42 // Step 1. Input model.
43 // Change to minimization problem.
44 model.Set(MDO.IntAttr.ModelSense, MDO.MINIMIZE);
45
46 // Add variables. The linear objective coefficients are specified directly.
47 MDOVar[] x = new MDOVar[5];
48 x[0] = model.AddVar(0.0, 10.0, 1.0, 'I', "x0");
49 x[1] = model.AddVar(0.0, MDO.INFINITY, 2.0, 'I', "x1");
50 x[2] = model.AddVar(0.0, MDO.INFINITY, 1.0, 'I', "x2");
51 x[3] = model.AddVar(0.0, MDO.INFINITY, 1.0, 'C', "x3");
52 x[4] = model.AddVar(0.0, MDO.INFINITY, 0.5, 'C', "x4");
53
54 // Add linear constraint c0: 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
55 MDOExpr c0 = new MDOExpr();
56 c0.AddTerms(new double[] { 1.0, 1.0, 2.0, 3.0 }, new MDOVar[] { x[0], x[1], x[2], x[3] });
57 model.AddConstr(c0, MDO.GREATER_EQUAL, 1.0, "c0");
58
59 // Add linear constraint c1: 1 x0 - 1 x2 + 6 x3 = 1
60 MDOExpr c1 = new MDOExpr();
61 c1.AddTerms(new double[] { 1.0, -1.0, 6.0 }, new MDOVar[] { x[0], x[2], x[3] });
62 model.AddConstr(c1, MDO.EQUAL, 1.0, "c1");
63
64 // Add second-order cone constraint c2: x_1^2 + x_2^2 - x_4^2 <= 0
65 MDOQuadExpr c2 = new MDOQuadExpr();
66 // This constraint has no linear part. We only add the quadratic terms.
67 c2.AddTerms(
68 new double[] { 1.0, 1.0, -1.0 }, // values
69 new MDOVar[] { x[1], x[2], x[4] }, // first variable indices
70 new MDOVar[] { x[1], x[2], x[4] } // second variable indices
71 );
72 model.AddQConstr(c2, MDO.LESS_EQUAL, 0.0, "c2");
73
74 // Step 2. Solve the problem.
75 model.Optimize();
76
77 // Step 3. Retrieve model status and solution.
78 // For MIP(MILP,MIQP, MIQCP) problems, if the solving process
79 // terminates early due to reasons such as timeout or interruption,
80 // the model status will indicate termination by timeout (or
81 // interruption, etc.). However, suboptimal solutions may still
82 // exist, making it necessary to check the SolCount property.
83 if (model.Get(MDO.IntAttr.Status) == MDO.Status.OPTIMAL || model.Get(MDO.IntAttr.Status) == MDO.Status.SUB_OPTIMAL ||
84 model.Get(MDO.IntAttr.SolCount) > 0)
85 {
86 Console.WriteLine($"Optimal objective value is: {model.Get(MDO.DoubleAttr.ObjVal)}");
87 Console.WriteLine("Decision variables: ");
88 for (int i = 0; i < 5; i++)
89 {
90 Console.WriteLine($"x[{i}] = {x[i].Get(MDO.DoubleAttr.X)}");
91 }
92 }
93 else
94 {
95 Console.WriteLine("No feasible solution.");
96 }
97 }
98 catch (MDOException e)
99 {
100 Console.WriteLine("Received Mindopt exception.");
101 Console.WriteLine(" - Code : " + e.ErrorCode);
102 Console.WriteLine(" - Reason : " + e.Message);
103 }
104 catch (Exception e)
105 {
106 Console.WriteLine("Received exception.");
107 Console.WriteLine(" - Reason : " + e.Message);
108 }
109 finally
110 {
111 // Step 4. Free the model.
112 model.Dispose();
113 env.Dispose();
114 }
115 }
116 }
117}