5.6.10. Java 的 MISOCP 建模和优化

在本节中,我们将使用 MindOpt JAVA API 来建模和求解 MIQCP示例2 中的混合整数二阶锥规划问题。

导入 MindOpt 工具包:

25 */

创建优化环境和模型:

29    public static void main(String[] args) {
30        // Create environment and model.
31        MDOEnv env = new MDOEnv();

接下来,我们设置模型名称和求解方向。然后,调用 MDOModel.addVar 添加五个优化变量。它们的下界、上界、类型、名称以及在目标函数中的线性项系数都将作为参数直接传入。

备注

在调用 MDOModel.addVar 时,将类型设置为 'I' 代表这个变量是整形变量。

35            // Step 1. Input model.
36            model.set(MDO.StringAttr.ModelName, "MISOCPEx1");
37
38            // Change to minimization problem.
39            model.set(MDO.IntAttr.ModelSense, MDO.MINIMIZE);
40
41            // Add variables. The linear objective coefficients are specified directly.
42            MDOVar[] x = new MDOVar[5];
43            x[0] = model.addVar(0.0, 10.0, 1.0, 'I', "x0");
44            x[1] = model.addVar(0.0, MDO.INFINITY, 2.0, 'I', "x1");
45            x[2] = model.addVar(0.0, MDO.INFINITY, 1.0, 'I', "x2");
46            x[3] = model.addVar(0.0, MDO.INFINITY, 1.0, 'C', "x3");

备注

由于线性目标系数在创建变量时已直接传入,因此 无需单独调用 MDOModel.setObjective

现在,我们添加线性约束。对于 Java 接口,这需要为每个约束创建一个 MDOExpr 对象,并向其添加项。

  • 约束 c0: \(x_0 + x_1 + 2x_2 + 3x_3 \geq 1\)

  • 约束 c1: \(x_0 - x_2 + 6x_3 = 1\)

使用 MDOModel.addConstr 将它们添加到模型中:

48            // Add linear constraint c0: 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
49            MDOExpr c0_expr = new MDOExpr();
50            c0_expr.addTerms(new double[] { 1.0, 1.0, 2.0, 3.0 }, new MDOVar[] { x[0], x[1], x[2], x[3] });
51            model.addConstr(c0_expr, MDO.GREATER_EQUAL, 1.0, "c0");
52
53            // Add linear constraint c1: 1 x0 - 1 x2 + 6 x3 = 1
54            MDOExpr c1_expr = new MDOExpr();
55            c1_expr.addTerms(new double[] { 1.0, -1.0, 6.0 }, new MDOVar[] { x[0], x[2], x[3] });

最后,我们添加二次(二阶锥)约束:

  • c2: \(x_1^2 + x_2^2 - x_4^2 \leq 0\)

这通过创建一个 MDOQuadExpr 对象并添加二次项来完成。然后使用 MDOModel.addQConstr 将该约束添加到模型中。

58            // Add second-order cone constraint c2: x_1^2 + x_2^2 - x_4^2 <= 0
59            MDOQuadExpr c2_expr = new MDOQuadExpr();
60            // This constraint has no linear part. We only add the quadratic terms.
61            c2_expr.addTerms(
62                    new double[] { 1.0, 1.0, -1.0 },      // values
63                    new MDOVar[] { x[1], x[2], x[4] },     // first variable indices
64                    new MDOVar[] { x[1], x[2], x[4] }      // second variable indices
65            );

模型构建完成后,我们调用 MDOModel.optimize 来求解问题:

69            // Step 2. Solve the problem.

求解后,我们检查求解状态,并获取最优目标值和变量取值。

77            // exist, making it necessary to check the SolCount property.
78            if (model.get(MDO.IntAttr.Status) == MDO.OPTIMAL || model.get(MDO.IntAttr.Status) == MDO.SUB_OPTIMAL
79                    || model.get(MDO.IntAttr.SolCount) > 0) {
80                System.out.println("Optimal objective value is: " + model.get(MDO.DoubleAttr.ObjVal));
81                System.out.println("Decision variables: ");
82                for (int i = 0; i < 5; i++) {
83                    System.out.println("x[" + i + "] = " + x[i].get(MDO.DoubleAttr.X));
84                }
85            } else {
86                System.out.println("No feasible solution.");

最后,我们释放模型和环境以回收资源。

95        } finally {
96            // Step 4. Free the model.
97            model.dispose();

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

  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 */
 26import com.alibaba.damo.mindopt.*;
 27
 28public class MdoMISOCPEx1 {
 29    public static void main(String[] args) {
 30        // Create environment and model.
 31        MDOEnv env = new MDOEnv();
 32        MDOModel model = new MDOModel(env);
 33
 34        try {
 35            // Step 1. Input model.
 36            model.set(MDO.StringAttr.ModelName, "MISOCPEx1");
 37
 38            // Change to minimization problem.
 39            model.set(MDO.IntAttr.ModelSense, MDO.MINIMIZE);
 40
 41            // Add variables. The linear objective coefficients are specified directly.
 42            MDOVar[] x = new MDOVar[5];
 43            x[0] = model.addVar(0.0, 10.0, 1.0, 'I', "x0");
 44            x[1] = model.addVar(0.0, MDO.INFINITY, 2.0, 'I', "x1");
 45            x[2] = model.addVar(0.0, MDO.INFINITY, 1.0, 'I', "x2");
 46            x[3] = model.addVar(0.0, MDO.INFINITY, 1.0, 'C', "x3");
 47            x[4] = model.addVar(0.0, MDO.INFINITY, 0.5, 'C', "x4");
 48
 49            // Add linear constraint c0: 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
 50            MDOExpr c0_expr = new MDOExpr();
 51            c0_expr.addTerms(new double[] { 1.0, 1.0, 2.0, 3.0 }, new MDOVar[] { x[0], x[1], x[2], x[3] });
 52            model.addConstr(c0_expr, MDO.GREATER_EQUAL, 1.0, "c0");
 53
 54            // Add linear constraint c1: 1 x0 - 1 x2 + 6 x3 = 1
 55            MDOExpr c1_expr = new MDOExpr();
 56            c1_expr.addTerms(new double[] { 1.0, -1.0, 6.0 }, new MDOVar[] { x[0], x[2], x[3] });
 57            model.addConstr(c1_expr, MDO.EQUAL, 1.0, "c1");
 58
 59            // Add second-order cone constraint c2: x_1^2 + x_2^2 - x_4^2 <= 0
 60            MDOQuadExpr c2_expr = new MDOQuadExpr();
 61            // This constraint has no linear part. We only add the quadratic terms.
 62            c2_expr.addTerms(
 63                    new double[] { 1.0, 1.0, -1.0 },      // values
 64                    new MDOVar[] { x[1], x[2], x[4] },     // first variable indices
 65                    new MDOVar[] { x[1], x[2], x[4] }      // second variable indices
 66            );
 67            model.addQConstr(c2_expr, MDO.LESS_EQUAL, 0.0, "c2");
 68
 69            // Step 2. Solve the problem.
 70            model.optimize();
 71
 72            // Step 3. Retrieve model status and solution.
 73            // For MIP(MILP,MIQP, MIQCP) problems, if the solving process
 74            // terminates early due to reasons such as timeout or interruption,
 75            // the model status will indicate termination by timeout (or
 76            // interruption, etc.). However, suboptimal solutions may still
 77            // exist, making it necessary to check the SolCount property.
 78            if (model.get(MDO.IntAttr.Status) == MDO.OPTIMAL || model.get(MDO.IntAttr.Status) == MDO.SUB_OPTIMAL
 79                    || model.get(MDO.IntAttr.SolCount) > 0) {
 80                System.out.println("Optimal objective value is: " + model.get(MDO.DoubleAttr.ObjVal));
 81                System.out.println("Decision variables: ");
 82                for (int i = 0; i < 5; i++) {
 83                    System.out.println("x[" + i + "] = " + x[i].get(MDO.DoubleAttr.X));
 84                }
 85            } else {
 86                System.out.println("No feasible solution.");
 87            }
 88        } catch (MDOException e) {
 89            System.out.println("Received Mindopt exception.");
 90            System.out.println(" - Code          : " + e.getErrorCode());
 91            System.out.println(" - Reason        : " + e.getMessage());
 92        } catch (Exception e) {
 93            System.out.println("Received exception.");
 94            System.out.println(" - Reason        : " + e.getMessage());
 95        } finally {
 96            // Step 4. Free the model.
 97            model.dispose();
 98            env.dispose();
 99        }
100    }
101}