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}