5.6.4. Python 的MIQCP建模与优化¶
在本节中,我们将使用 MindOpt Python API,以按行输入的形式来建模以及求解 MIQCP题示例 中的问题。
首先,引入 Python 包:
26from mindoptpy import *
并创建优化模型,并赋予一个名称:
31 # Step 1. Create model.
32 model = Model("MIQCP_01")
调用 Model.addVar()
来添加四个优化变量,定义其下界、上界、名称和类型(有关函数的详细使用方式,请参考 Python API):
37 # Add variables.
38 x = []
39 x.append(model.addVar(0.0, 10.0, 0.0, 'I', "x0"))
40 x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x1"))
41 x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x2"))
42 x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x3"))
接着 ,我们来设置目标函数。首先使用类 QuadExpr
创建一个二次表达式,然后有两种方式来构建:
第一种是利用 QuadExpr
中的方法 QuadExpr.addTerms()
分别输入线性部分和二次部分;
第二种是直接输入一个二次表达式。
最后再用 Model.setObjective()
来设置目标函数并将问题设置为 最小化。
50 # Add objective: 1 x0 + 1 x1 + 1 x2 + 1 x3 + 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
51 obj = QuadExpr()
52
53 #option-I
54 obj.addTerms([1.0, 1.0, 1.0, 1.0], [x[0], x[1], x[2], x[3]])
55 obj.addTerms([0.5, 0.5, 0.5, 0.5, 0.5], [x[0], x[1], x[2], x[3], x[0]], [x[0], x[1], x[2], x[3], x[1]])
56
57 #option II
58 # obj = 1*x[0] + 1*x[1] + 1*x[2] + 1*x[3] + 0.5 * x[0]*x[0] + 0.5 * x[1]*x[1] + 0.5 * x[2]*x[2] + 0.5 * x[3]*x[3] + 0.5*x[0]*x[1]
59
60 # Set objective and change to minimization problem.
61 model.setObjective(obj, MDO.MINIMIZE)
然后,我们开始添加二次约束。二次约束中的二次表示式的构建方式与目标函数中的一致。这里我们采用上文中的第一种方式来构建。
44 # Add constraints.
45 # Note that the nonzero elements are inputted in a row-wise order here.
46 model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3] - \
47 0.5 * x[0] * x[0] - 0.5 * x[1] * x[1] - 0.5 * x[2] * x[2] - 0.5 * x[3] * x[3] - 0.5 * x[0] * x[1] >= 1, "c0")
48 model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3] + 0.5 * x[1] * x[1] <= 1, "c1")
问题输入完成后,再调用 Model.optimize()
求解优化问题:
64 model.optimize()
然后,通过属性 Status 和属性 ObjVal 来查看优化结果和最优目标值,并通过属性 X 来查看变量的取值。 其他的属性值请查看 属性 章节。
66 if model.status == MDO.OPTIMAL:
67 print(f"Optimal objective value is: {model.objval}")
68 print("Decision variables:")
69 for v in x:
70 print(f"x[{v.VarName}] = {v.X}")
71 else:
72 print("No feasible solution.")
最后,我们调用 Model.dispose()
来释放模型:
82 model.dispose()
示例 mdo_miqcp_ex1.py 提供了完整源代码:
1"""
2/**
3 * Description
4 * -----------
5 *
6 * Mixed Integer Quadratically constrained quadratic optimization (row-wise input).
7 *
8 * Formulation
9 * -----------
10 * Minimize
11 * obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
12 * + 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
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 * Integer
22 * x0
23 * End
24 */
25"""
26from mindoptpy import *
27
28
29if __name__ == "__main__":
30
31 # Step 1. Create model.
32 model = Model("MIQCP_01")
33
34 try:
35 # Step 2. Input model.
36
37 # Add variables.
38 x = []
39 x.append(model.addVar(0.0, 10.0, 0.0, 'I', "x0"))
40 x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x1"))
41 x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x2"))
42 x.append(model.addVar(0.0, float('inf'), 0.0, 'C', "x3"))
43
44 # Add constraints.
45 # Note that the nonzero elements are inputted in a row-wise order here.
46 model.addConstr(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3] - \
47 0.5 * x[0] * x[0] - 0.5 * x[1] * x[1] - 0.5 * x[2] * x[2] - 0.5 * x[3] * x[3] - 0.5 * x[0] * x[1] >= 1, "c0")
48 model.addConstr(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3] + 0.5 * x[1] * x[1] <= 1, "c1")
49
50 # Add objective: 1 x0 + 1 x1 + 1 x2 + 1 x3 + 1/2 [ x0^2 + x1^2 + x2^2 + x3^2 + x0 x1]
51 obj = QuadExpr()
52
53 #option-I
54 obj.addTerms([1.0, 1.0, 1.0, 1.0], [x[0], x[1], x[2], x[3]])
55 obj.addTerms([0.5, 0.5, 0.5, 0.5, 0.5], [x[0], x[1], x[2], x[3], x[0]], [x[0], x[1], x[2], x[3], x[1]])
56
57 #option II
58 # obj = 1*x[0] + 1*x[1] + 1*x[2] + 1*x[3] + 0.5 * x[0]*x[0] + 0.5 * x[1]*x[1] + 0.5 * x[2]*x[2] + 0.5 * x[3]*x[3] + 0.5*x[0]*x[1]
59
60 # Set objective and change to minimization problem.
61 model.setObjective(obj, MDO.MINIMIZE)
62
63 # Step 3. Solve the problem and populate optimization result.
64 model.optimize()
65
66 if model.status == MDO.OPTIMAL:
67 print(f"Optimal objective value is: {model.objval}")
68 print("Decision variables:")
69 for v in x:
70 print(f"x[{v.VarName}] = {v.X}")
71 else:
72 print("No feasible solution.")
73 except MindoptError as e:
74 print("Received Mindopt exception.")
75 print(" - Code : {}".format(e.errno))
76 print(" - Reason : {}".format(e.message))
77 except Exception as e:
78 print("Received other exception.")
79 print(" - Reason : {}".format(e))
80 finally:
81 # Step 4. Free the model.
82 model.dispose()