5.6.5. MIQCP Modeling and Optimization in JavaΒΆ

In this chapter, we will use MindOpt JAVA API to model and solve the problem in Example of Mixed Integer Quadratically Constrained Programming.

Include the header file:

25import com.alibaba.damo.mindopt.*;

Create an optimization model model:

30        // Create model
31        MDOEnv env = new MDOEnv(); 
32        MDOModel model = new MDOModel(env); 
33        model.set(MDO.StringAttr.ModelName, "MIQCP_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 JAVA API)

36            // Add variables.
37            MDOVar[] x = new MDOVar[4];
38            x[0] = model.addVar(0.0,         10.0, 0.0, 'I', "x0");
39            x[1] = model.addVar(0.0, MDO.INFINITY, 0.0, 'C', "x1");
40            x[2] = model.addVar(0.0, MDO.INFINITY, 0.0, 'C', "x2");
41            x[3] = model.addVar(0.0, MDO.INFINITY, 0.0, 'C', "x3");

Then, we set the qudratic 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            /* Linear part in the objective: 1 x0 + 1 x1 + 1 x2 + 1 x3 */
45            int      obj_nnz = 4;
46            MDOVar[] obj_idx = new MDOVar[] { x[0], x[1], x[2], x[3] };
47            double[] obj_val = new double[] { 1.0,  1.0,  1.0,  1.0 };
75            // Create a QuadExpr for quadratic objective
76            MDOQuadExpr obj = new MDOQuadExpr();
77            // Add objective linear term: 1 x0 + 1 x1 + 1 x2 + 1 x3 
78            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.

48            /* Quadratic part in the objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
49            int      qo_nnz    = 5;
50            MDOVar[] qo_col1   = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
51            MDOVar[] qo_col2   = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
52            double[] qo_values = new double[] { 0.5,  0.5,  0.5,  0.5,  0.5 };
79            // Add quadratic part in objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] 
80            obj.addTerms(qo_values, qo_col1, qo_col2);

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

82            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.

54            /* Linear part in the first constraint: 1 x0 + 1 x1 + 2 x2 + 3 x3 */
55            int      c1_nnz = 4; 
56            MDOVar[] c1_idx = new MDOVar[] { x[0], x[1], x[2], x[3] };
57            double[] c1_val = new double[] { 1.0,  1.0,  2.0,  3.0 };
58            /* Quadratic part in the first constraint: - 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
59            int      qc1_nnz    = 5;
60            MDOVar[] qc1_col1   = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
61            MDOVar[] qc1_col2   = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
62            double[] qc1_values = new double[] { -0.5, -0.5, -0.5, -0.5, -0.5 };
84            // Add 1st quadratic constraint. 
85            MDOQuadExpr c1 = new MDOQuadExpr();
86            c1.addTerms(c1_val, c1_idx);
87            c1.addTerms(qc1_values, qc1_col1, qc1_col2);
64            /* Linear part in the second constraint: 1 x0 - 1 x2 + 6 x3 */
65            int      c2_nnz = 3;
66            MDOVar[] c2_idx = new MDOVar[] { x[0], x[2], x[3] };
67            double[] c2_val = new double[] { 1.0,  -1.0, 6.0 };
68            /* Quadratic part in the second constraint: 1/2 [x1^2] */
69            int      qc2_nnz    = 1;
70            MDOVar[] qc2_col1   = new MDOVar[] { x[1] };
71            MDOVar[] qc2_col2   = new MDOVar[] { x[1] };
72            double[] qc2_values = new double[] { 0.5 };
90            // Add 2nd quadratic constraint. 
91            MDOQuadExpr c2 = new MDOQuadExpr();
92            c2.addTerms(c2_val, c2_idx);
93            c2.addTerms(qc2_values, qc2_col1, qc2_col2);

Then, we call MDOModel.addQConstr to add the quadratic constraints to the model.

88            model.addQConstr(c1, MDO.GREATER_EQUAL, 1.0, "c0");
94            model.addQConstr(c2, MDO.LESS_EQUAL, 1.0, "c1");  

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

110            System.out.println("Exception during optimization");
111            e.printStackTrace();

The complete example code is shown in MdoMIQCPEx1.java :

  1/**
  2 *  Description
  3 *  -----------
  4 *
  5 *   Mixed Integer Quadratically constrained quadratic optimization (row-wise input).
  6
  7 *  Formulation
  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 *
 13 *  Subject To
 14 *   c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 - 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] >= 1
 15 *   c1 : 1 x0 - 1 x2 + 6 x3 + 1/2 [x1^2] <= 1
 16 *  Bounds
 17 *    0 <= x0 <= 10
 18 *    0 <= x1
 19 *    0 <= x2
 20 *    0 <= x3
 21 *    x0 integer 
 22 *  End
 23 */
 24
 25import com.alibaba.damo.mindopt.*;
 26import java.util.*;
 27
 28public class MdoQcoEx1 { 
 29    public static void main(String[] args) throws MDOException {
 30        // Create model
 31        MDOEnv env = new MDOEnv(); 
 32        MDOModel model = new MDOModel(env); 
 33        model.set(MDO.StringAttr.ModelName, "MIQCP_01");
 34
 35        try {
 36            // Add variables.
 37            MDOVar[] x = new MDOVar[4];
 38            x[0] = model.addVar(0.0,         10.0, 0.0, 'I', "x0");
 39            x[1] = model.addVar(0.0, MDO.INFINITY, 0.0, 'C', "x1");
 40            x[2] = model.addVar(0.0, MDO.INFINITY, 0.0, 'C', "x2");
 41            x[3] = model.addVar(0.0, MDO.INFINITY, 0.0, 'C', "x3");
 42
 43            /* Prepare model data. */
 44            /* Linear part in the objective: 1 x0 + 1 x1 + 1 x2 + 1 x3 */
 45            int      obj_nnz = 4;
 46            MDOVar[] obj_idx = new MDOVar[] { x[0], x[1], x[2], x[3] };
 47            double[] obj_val = new double[] { 1.0,  1.0,  1.0,  1.0 };
 48            /* Quadratic part in the objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
 49            int      qo_nnz    = 5;
 50            MDOVar[] qo_col1   = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
 51            MDOVar[] qo_col2   = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
 52            double[] qo_values = new double[] { 0.5,  0.5,  0.5,  0.5,  0.5 };
 53
 54            /* Linear part in the first constraint: 1 x0 + 1 x1 + 2 x2 + 3 x3 */
 55            int      c1_nnz = 4; 
 56            MDOVar[] c1_idx = new MDOVar[] { x[0], x[1], x[2], x[3] };
 57            double[] c1_val = new double[] { 1.0,  1.0,  2.0,  3.0 };
 58            /* Quadratic part in the first constraint: - 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] */
 59            int      qc1_nnz    = 5;
 60            MDOVar[] qc1_col1   = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
 61            MDOVar[] qc1_col2   = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
 62            double[] qc1_values = new double[] { -0.5, -0.5, -0.5, -0.5, -0.5 };
 63
 64            /* Linear part in the second constraint: 1 x0 - 1 x2 + 6 x3 */
 65            int      c2_nnz = 3;
 66            MDOVar[] c2_idx = new MDOVar[] { x[0], x[2], x[3] };
 67            double[] c2_val = new double[] { 1.0,  -1.0, 6.0 };
 68            /* Quadratic part in the second constraint: 1/2 [x1^2] */
 69            int      qc2_nnz    = 1;
 70            MDOVar[] qc2_col1   = new MDOVar[] { x[1] };
 71            MDOVar[] qc2_col2   = new MDOVar[] { x[1] };
 72            double[] qc2_values = new double[] { 0.5 };
 73
 74            /* Construct model. */
 75            // Create a QuadExpr for quadratic objective
 76            MDOQuadExpr obj = new MDOQuadExpr();
 77            // Add objective linear term: 1 x0 + 1 x1 + 1 x2 + 1 x3 
 78            obj.addTerms(obj_val, obj_idx);
 79            // Add quadratic part in objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] 
 80            obj.addTerms(qo_values, qo_col1, qo_col2);
 81
 82            model.setObjective(obj, MDO.MINIMIZE);
 83
 84            // Add 1st quadratic constraint. 
 85            MDOQuadExpr c1 = new MDOQuadExpr();
 86            c1.addTerms(c1_val, c1_idx);
 87            c1.addTerms(qc1_values, qc1_col1, qc1_col2);
 88            model.addQConstr(c1, MDO.GREATER_EQUAL, 1.0, "c0");
 89
 90            // Add 2nd quadratic constraint. 
 91            MDOQuadExpr c2 = new MDOQuadExpr();
 92            c2.addTerms(c2_val, c2_idx);
 93            c2.addTerms(qc2_values, qc2_col1, qc2_col2);
 94            model.addQConstr(c2, MDO.LESS_EQUAL, 1.0, "c1");  
 95    
 96            // Solve the problem and populate optimization result.
 97            model.optimize();
 98
 99            if (model.get(MDO.IntAttr.Status) == MDO.OPTIMAL) {
100                System.out.println("Optimal objective value is: " + model.get(MDO.DoubleAttr.ObjVal));
101                System.out.println("Decision variables: ");
102                for (int i = 0; i < 4; i++) {
103                    System.out.println( "x[" + i + "] = " + x[i].get(MDO.DoubleAttr.X));
104                }
105            }
106            else {
107                System.out.println("No feasible solution.");
108            }
109        } catch (Exception e) { 
110            System.out.println("Exception during optimization");
111            e.printStackTrace();
112        } finally { 
113            model.dispose();
114            env.dispose();
115        }
116    }
117}