5.6.9. Python 的 MISOCP 建模和优化¶
在本节中,我们将使用 MindOpt Python API 来建模和求解 MIQCP示例2 中的混合整数二阶锥规划问题。
首先,导入 MindOpt Python 工具包:
27"""
创建一个名为 "MISOCPEx1" 的优化模型 model:
32 # Step 1. Create a model.
接下来,我们调用 Model.addVar() 添加五个优化变量。它们的下界、上界、类型、名称以及在目标函数中的线性项系数都将作为参数指定。
备注
通过参数 vtype 将类型设置为 'I' 代表这个变量是整形变量。
38 # Add variables. The linear objective coefficients are specified directly.
39 x = []
40 x.append(model.addVar(lb=0.0, ub=10.0, obj=1.0, vtype='I', name="x0"))
41 x.append(model.addVar(lb=0.0, ub=float('inf'), obj=2.0, vtype='I', name="x1"))
42 x.append(model.addVar(lb=0.0, ub=float('inf'), obj=1.0, vtype='I', name="x2"))
43 x.append(model.addVar(lb=0.0, ub=float('inf'), obj=1.0, vtype='C', name="x3"))
然后,将求解方向设置为 最小化。
46 # Set the optimization sense.
备注
由于线性目标系数 (1, 2, 1, 1, 0.5) 在创建变量时已通过 obj 参数直接传入,因此 无需单独调用 Model.setObjective()。
现在,我们添加约束。对于 Python 接口,可以使用重载的算术运算符自然地构建线性和二次表达式。
约束 c0: \(x_0 + x_1 + 2x_2 + 3x_3 \geq 1\)
约束 c1: \(x_0 - x_2 + 6x_3 = 1\)
二次(SOCP)约束 c2: \(x_1^2 + x_2^2 - x_4^2 \leq 0\)
使用 Model.addConstr() 将它们添加到模型中:
48
49 # Add constraints. Expressions are built using overloaded operators.
50 # c0: 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
51 model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3] >= 1.0, "c0")
52
53 # c1: 1 x0 - 1 x2 + 6 x3 = 1
54 model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3] == 1.0, "c1")
55
56 # c2: x_1^2 + x_2^2 - x_4^2 <= 0
模型构建完成后,我们调用 Model.optimize() 来求解问题:
59 # Step 3. Solve the problem.
我们可以通过属性 Status 检查求解状态,并通过属性 ObjVal 和 X 获取最优目标值和解。有关其他属性信息,请参阅 属性。
67 # exist, making it necessary to check the SolCount property.
68 if model.status == MDO.OPTIMAL or model.status == MDO.SUB_OPTIMAL or model.solcount > 0:
69 print(f"Optimal objective value is: {model.objval}")
70 print("Decision variables:")
71 for v in model.getVars():
最后,我们调用 Model.dispose() 来释放模型。
84 # Step 5. Free the model.
完整的 Python 代码见 mdo_misocp_ex1.py:
1"""
2/**
3 * Description
4 * -----------
5 *
6 * Formulation
7 * -----------
8 *
9 Minimize
10 * obj: 1 x0 + 2 x1 + 1 x2 + 1 x3 + 0.5 x_4
11 *
12 *
13 * Subject To
14 * c0 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
15 * c1 : 1 x0 - 1 x2 + 6 x3 = 1
16 * c2 : x_1^2 + x_2^2 - x_4^2 <= 0
17 * Bounds
18 * 0 <= x0 <= 10
19 * 0 <= x1
20 * 0 <= x2
21 * 0 <= x3
22 * 0 <= x4
23 * Integer
24 * x0, x1, x2
25 * End
26 */
27"""
28from mindoptpy import *
29
30if __name__ == "__main__":
31
32 # Step 1. Create a model.
33 model = Model("MISOCPEx1")
34
35 try:
36 # Step 2. Input model.
37
38 # Add variables. The linear objective coefficients are specified directly.
39 x = []
40 x.append(model.addVar(lb=0.0, ub=10.0, obj=1.0, vtype='I', name="x0"))
41 x.append(model.addVar(lb=0.0, ub=float('inf'), obj=2.0, vtype='I', name="x1"))
42 x.append(model.addVar(lb=0.0, ub=float('inf'), obj=1.0, vtype='I', name="x2"))
43 x.append(model.addVar(lb=0.0, ub=float('inf'), obj=1.0, vtype='C', name="x3"))
44 x.append(model.addVar(lb=0.0, ub=float('inf'), obj=0.5, vtype='C', name="x4"))
45
46 # Set the optimization sense.
47 model.modelSense = MDO.MINIMIZE
48
49 # Add constraints. Expressions are built using overloaded operators.
50 # c0: 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
51 model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3] >= 1.0, "c0")
52
53 # c1: 1 x0 - 1 x2 + 6 x3 = 1
54 model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3] == 1.0, "c1")
55
56 # c2: x_1^2 + x_2^2 - x_4^2 <= 0
57 model.addConstr(x[1] * x[1] + x[2] * x[2] - x[4] * x[4] <= 0.0, "c2")
58
59 # Step 3. Solve the problem.
60 model.optimize()
61
62 # Step 4. Retrieve model status and solution.
63 # For MIP(MILP, MIQP, MIQCP) problems, if the solving process
64 # terminates early due to reasons such as timeout or interruption,
65 # the model status will indicate termination by timeout (or
66 # interruption, etc.). However, suboptimal solutions may still
67 # exist, making it necessary to check the SolCount property.
68 if model.status == MDO.OPTIMAL or model.status == MDO.SUB_OPTIMAL or model.solcount > 0:
69 print(f"Optimal objective value is: {model.objval}")
70 print("Decision variables:")
71 for v in model.getVars():
72 print(f"{v.VarName} = {v.X}")
73 else:
74 print("No feasible solution.")
75
76 except MindoptError as e:
77 print("Received Mindopt exception.")
78 print(f" - Code : {e.errno}")
79 print(f" - Reason : {e.message}")
80 except Exception as e:
81 print("Received other exception.")
82 print(f" - Reason : {e}")
83 finally:
84 # Step 5. Free the model.
85 model.dispose()