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}