5.5.6. MIQP Modeling and Optimization in C#ΒΆ

In this chapter, we will use MindOpt C# API to model and solve the problem in Example of Mixed Integer Quadratic Programming.

Create an optimization model model:

32            // Create model
33            MDOEnv env = new MDOEnv(); 
34            MDOModel model = new MDOModel(env); 
35            model.Set(MDO.StringAttr.ModelName, "MIQP_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)

42                // Add variables.
43                MDOVar[] x = new MDOVar[4];
44                x[0] = model.AddVar(0.0,         10.0, 1.0, 'I', "x0");
45                x[1] = model.AddVar(0.0, MDO.INFINITY, 1.0, 'C', "x1");
46                x[2] = model.AddVar(0.0, MDO.INFINITY, 1.0, 'C', "x2");
47                x[3] = model.AddVar(0.0, MDO.INFINITY, 1.0, 'C', "x3");

We input the linear constraints into model:

49                // Add constraints.
50                double[][] consV = new double[][]
51                {
52                    new double[] { 1.0, 1.0, 2.0, 3.0},
53                    new double[] { 1.0, 0,  -1.0, 6.0} 
54                };
55
56                MDOLinExpr tempLinExpr1 = new MDOLinExpr();
57                tempLinExpr1.AddTerms(consV[0], x);
58                model.AddConstr(tempLinExpr1, MDO.GREATER_EQUAL, 1.0, "c0");
59
60                MDOLinExpr tempLinExpr2 = new MDOLinExpr();
61                tempLinExpr2.AddTerms(consV[1], x);
62                model.AddConstr(tempLinExpr2, MDO.EQUAL, 1.0, "c1");   

Then, we create 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, obj_val represents the corresponding non-zero coefficient values in obj_idx.

64                // Create a QuadExpr for quadratic objective
65                MDOQuadExpr obj = new MDOQuadExpr();
66
67                // Add objective linear term: 1 x0 + 1 x1 + 1 x2 + 1 x3 
68                int      obj_nnz = 4;
69                MDOVar[] obj_idx = new MDOVar[] { x[0], x[1], x[2], x[3] };
70                double[] obj_val = new double[] { 1.0,  1.0,  1.0,  1.0 };
71                obj.AddTerms(obj_val, obj_idx);

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.

73                // Add quadratic part in objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] 
74                int      qo_nnz    = 5;
75                MDOVar[] qo_col1   = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
76                MDOVar[] qo_col2   = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
77                double[] qo_values = new double[] { 0.5,  0.5,  0.5,  0.5,  0.5 };
78                obj.AddTerms(qo_values, qo_col1, qo_col2);

Lastly, we call MDOModel.SetObjective to set the objective and the direction to be optimized.

80                model.SetObjective(obj, MDO.MINIMIZE);

Once the model is constructed, we call MDOModel.Optimize to solve the problem:

83                model.Optimize();

The complete example code is shown in MdoMIQPEx1.cs :

  1/**
  2 *  Description
  3 *  -----------
  4 *  Linear optimization (row-wise input).
  5 *
  6 *  Formulation
  7 *  -----------
  8 *
  9 *  Minimize
 10 *    obj: 1 x0 + 1 x1 + 1 x2 + 1 x3 
 11 *         + 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
 12 *  Subject To
 13 *   c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
 14 *   c1 : 1 x0 - 1 x2 + 6 x3 = 1
 15 *  Bounds
 16 *    0 <= x0 <= 10
 17 *    0 <= x1
 18 *    0 <= x2
 19 *    0 <= x3
 20  *  x0 Integer
 21 *  End
 22 */
 23
 24using Mindopt;
 25
 26namespace Example
 27{
 28    public class MdoQoEx1
 29    {
 30        public static void Main(string[] args)
 31        {
 32            // Create model
 33            MDOEnv env = new MDOEnv(); 
 34            MDOModel model = new MDOModel(env); 
 35            model.Set(MDO.StringAttr.ModelName, "MIQP_01");
 36
 37            try
 38            {
 39                // Change to minimization problem.
 40                model.Set(MDO.IntAttr.ModelSense, MDO.MINIMIZE);
 41
 42                // Add variables.
 43                MDOVar[] x = new MDOVar[4];
 44                x[0] = model.AddVar(0.0,         10.0, 1.0, 'I', "x0");
 45                x[1] = model.AddVar(0.0, MDO.INFINITY, 1.0, 'C', "x1");
 46                x[2] = model.AddVar(0.0, MDO.INFINITY, 1.0, 'C', "x2");
 47                x[3] = model.AddVar(0.0, MDO.INFINITY, 1.0, 'C', "x3");
 48
 49                // Add constraints.
 50                double[][] consV = new double[][]
 51                {
 52                    new double[] { 1.0, 1.0, 2.0, 3.0},
 53                    new double[] { 1.0, 0,  -1.0, 6.0} 
 54                };
 55
 56                MDOLinExpr tempLinExpr1 = new MDOLinExpr();
 57                tempLinExpr1.AddTerms(consV[0], x);
 58                model.AddConstr(tempLinExpr1, MDO.GREATER_EQUAL, 1.0, "c0");
 59
 60                MDOLinExpr tempLinExpr2 = new MDOLinExpr();
 61                tempLinExpr2.AddTerms(consV[1], x);
 62                model.AddConstr(tempLinExpr2, MDO.EQUAL, 1.0, "c1");   
 63
 64                // Create a QuadExpr for quadratic objective
 65                MDOQuadExpr obj = new MDOQuadExpr();
 66
 67                // Add objective linear term: 1 x0 + 1 x1 + 1 x2 + 1 x3 
 68                int      obj_nnz = 4;
 69                MDOVar[] obj_idx = new MDOVar[] { x[0], x[1], x[2], x[3] };
 70                double[] obj_val = new double[] { 1.0,  1.0,  1.0,  1.0 };
 71                obj.AddTerms(obj_val, obj_idx);
 72
 73                // Add quadratic part in objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] 
 74                int      qo_nnz    = 5;
 75                MDOVar[] qo_col1   = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
 76                MDOVar[] qo_col2   = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
 77                double[] qo_values = new double[] { 0.5,  0.5,  0.5,  0.5,  0.5 };
 78                obj.AddTerms(qo_values, qo_col1, qo_col2);
 79
 80                model.SetObjective(obj, MDO.MINIMIZE);
 81                
 82                // Solve the problem and populate optimization result.
 83                model.Optimize();
 84
 85                if (model.Get(MDO.IntAttr.Status) == MDO.Status.OPTIMAL)
 86                {
 87                    Console.WriteLine($"Optimal objective value is: {model.Get(MDO.DoubleAttr.ObjVal)}");
 88                    Console.WriteLine("Decision variables: ");
 89                    for (int i = 0; i < 4; i++)
 90                        Console.WriteLine( $"x[{i}] = {x[i].Get(MDO.DoubleAttr.X)}");
 91                }
 92                else
 93                {
 94                    Console.WriteLine("No feasible solution.");
 95                }
 96            }
 97            catch (Exception e)
 98            { 
 99                Console.WriteLine("Exception during optimization");
100                Console.WriteLine(e.Message);
101            }
102            finally
103            { 
104                model.Dispose();
105                env.Dispose();
106            }
107        }
108    }
109}