5.5.5. Java 的MIQP建模和优化

在本节中,我们将使用 MindOpt JAVA API,以按行输入的形式来建模以及求解 MIQP题示例 中的问题。

首先,引入头文件:

25import java.util.*;

并创建优化模型:

31        MDOModel model = new MDOModel(env); 
32        model.set(MDO.StringAttr.ModelName, "MIQP_01");

接下来,我们通过 MDOModel.set 将目标函数设置为 最小化,并调用 MDOModel.addVar 来添加四个优化变量,定义其下界、上界、名称和类型(有关 MDOModel.setMDOModel.addVar 的详细使用方式,请参考 JAVA API):

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

接着,我们开始添加线性约束:

64            double[][] consV = new double[][] {
65                { 1.0, 1.0, 2.0, 3.0 },
66                { 1.0, 0,  -1.0, 6.0 } 
67            };
68
69            MDOLinExpr tempLinExpr1 = new MDOLinExpr();
70            tempLinExpr1.addTerms(consV[0], x);
71            model.addConstr(tempLinExpr1, MDO.GREATER_EQUAL, 1.0, "c0");
72
73            MDOLinExpr tempLinExpr2 = new MDOLinExpr();
74            tempLinExpr2.addTerms(consV[1], x);
75            model.addConstr(tempLinExpr2, MDO.EQUAL, 1.0, "c1");    
76    

然后,我们开始设置二次目标函数。我们创建一个二次表达式 MDOQuadExpr , 再调用 MDOQuadExpr.addTerms 来设置目标函数线性部分。这里 obj_idx 表示线性部分的索引,obj_val 表示与 obj_idx 中的索引相对应的非零系数值。

49            int      obj_nnz = 4;
50            MDOVar[] obj_idx = new MDOVar[] { x[0], x[1], x[2], x[3] };
51            double[] obj_val = new double[] { 1.0,  1.0,  1.0,  1.0 };
52            obj.addTerms(obj_val, obj_idx);

然后,调用 MDOQuadExpr.addTerms 来设置目标的二次项系数 \(Q\)。 其中,qo_values 表示要添加的二次项的系数,qo_col1qo_col2 表示与qo_values相对应的二次项的第一个变量和第二个变量。

55            int      qo_nnz    = 5;
56            MDOVar[] qo_col1   = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
57            MDOVar[] qo_col2   = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
58            double[] qo_values = new double[] { 0.5,  0.5,  0.5,  0.5,  0.5 };
59            obj.addTerms(qo_values, qo_col1, qo_col2);

最后,我们调用 MDOModel.setObjective 设定优化目标与方向。

62

问题输入完成后,调用 MDOModel.optimize 求解优化问题:

79

示例 MdoMIQPEx1.java 提供了完整源代码:

  1/**
  2 *  Description
  3 *  -----------
  4 *
  5 *  Mixed IntegerQuadratic 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 *  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
 24import com.alibaba.damo.mindopt.*;
 25import java.util.*;
 26
 27public class MdoMIQPEx1 { 
 28    public static void main(String[] args) throws MDOException {
 29        // Create model
 30        MDOEnv env = new MDOEnv(); 
 31        MDOModel model = new MDOModel(env); 
 32        model.set(MDO.StringAttr.ModelName, "MIQP_01");
 33
 34        try {
 35            // Change to minimization problem.
 36            model.set(MDO.IntAttr.ModelSense, MDO.MINIMIZE);
 37
 38            // Add variables.
 39            MDOVar[] x = new MDOVar[4];
 40            x[0] = model.addVar(0.0,         10.0, 0.0, 'I', "x0");
 41            x[1] = model.addVar(0.0, MDO.INFINITY, 0.0, 'C', "x1");
 42            x[2] = model.addVar(0.0, MDO.INFINITY, 0.0, 'C', "x2");
 43            x[3] = model.addVar(0.0, MDO.INFINITY, 0.0, 'C', "x3");
 44
 45            // Create a QuadExpr for quadratic objective
 46            MDOQuadExpr obj = new MDOQuadExpr();
 47
 48            // Add objective linear term: 1 x0 + 1 x1 + 1 x2 + 1 x3 
 49            int      obj_nnz = 4;
 50            MDOVar[] obj_idx = new MDOVar[] { x[0], x[1], x[2], x[3] };
 51            double[] obj_val = new double[] { 1.0,  1.0,  1.0,  1.0 };
 52            obj.addTerms(obj_val, obj_idx);
 53
 54            // Add quadratic part in objective: 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1] 
 55            int      qo_nnz    = 5;
 56            MDOVar[] qo_col1   = new MDOVar[] { x[0], x[1], x[2], x[3], x[0] };
 57            MDOVar[] qo_col2   = new MDOVar[] { x[0], x[1], x[2], x[3], x[1] };
 58            double[] qo_values = new double[] { 0.5,  0.5,  0.5,  0.5,  0.5 };
 59            obj.addTerms(qo_values, qo_col1, qo_col2);
 60
 61            model.setObjective(obj, MDO.MINIMIZE);
 62
 63            // Add constraints.
 64            double[][] consV = new double[][] {
 65                { 1.0, 1.0, 2.0, 3.0 },
 66                { 1.0, 0,  -1.0, 6.0 } 
 67            };
 68
 69            MDOLinExpr tempLinExpr1 = new MDOLinExpr();
 70            tempLinExpr1.addTerms(consV[0], x);
 71            model.addConstr(tempLinExpr1, MDO.GREATER_EQUAL, 1.0, "c0");
 72
 73            MDOLinExpr tempLinExpr2 = new MDOLinExpr();
 74            tempLinExpr2.addTerms(consV[1], x);
 75            model.addConstr(tempLinExpr2, MDO.EQUAL, 1.0, "c1");    
 76    
 77            // Solve the problem.
 78            model.optimize();
 79
 80            // Step 4. Retrive model status and objective. 
 81            // For MIP(MILP,MIQP, MIQCP) problems, if the solving process
 82            // terminates early due to reasons such as timeout or interruption,
 83            // the model status will indicate termination by timeout (or
 84            // interruption, etc.). However, suboptimal solutions may still
 85            // exist, making it necessary to check the SolCount property.
 86            if (model.get(MDO.IntAttr.Status) == MDO.OPTIMAL || model.get(MDO.IntAttr.Status) == MDO.SUB_OPTIMAL ||
 87                model.get(MDO.IntAttr.SolCount) != 0) {
 88                System.out.println("Optimal objective value is: " + model.get(MDO.DoubleAttr.ObjVal));
 89                System.out.println("Decision variables: ");
 90                for (int i = 0; i < 4; i++) {
 91                    System.out.println( "x[" + i + "] = " + x[i].get(MDO.DoubleAttr.X));
 92                }
 93            }
 94            else {
 95                System.out.println("No feasible solution.");
 96            }
 97        } catch (Exception e) { 
 98            System.out.println("Exception during optimization");
 99            e.printStackTrace();
100        } finally { 
101            model.dispose();
102            env.dispose();
103        }
104    }
105}