5.1.4. Python 的建模与优化¶
在本节中,我们将使用 MindOpt Python 语言的 API 来建模以及求解 线性规划问题示例 中的问题。
5.1.4.1. 按行输入: mdo_lo_ex1¶
首先,引入 Python 包:
24from mindoptpy import *
并创建优化模型:
31 # Step 1. Create a model and change the parameters.
32 model = MdoModel()
接下来,我们通过 mindoptpy.MdoModel.set_int_attr()
将目标函数设置为 最小化 ,并调用 mindoptpy.MdoModel.add_var()
来添加四个优化变量,定义其下界、上界、名称和类型(有关 mindoptpy.MdoModel.set_int_attr()
和 mindoptpy.MdoModel.add_var()
的详细使用方式,请参考 Python 接口函数):
35 # Step 2. Input model.
36 # Change to minimization problem.
37 model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
38
39 # Add variables.
40 x = []
41 x.append(model.add_var(0.0, 10.0, 1.0, None, "x0", False))
42 x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x1", False))
43 x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x2", False))
44 x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x3", False))
接着,我们开始添加线性约束:
46 # Add constraints.
47 # Note that the nonzero elements are inputted in a row-wise order here.
48 model.add_cons(1.0, MDO_INFINITY, 1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], "c0")
49 model.add_cons(1.0, 1.0, 1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3], "c1")
问题输入完成后,再调用 mindoptpy.MdoModel.solve_prob()
求解优化问题,并用 mindoptpy.MdoModel.display_results()
来查看优化结果:
51 # Step 3. Solve the problem and populate the result.
52 model.solve_prob()
53 model.display_results()
最后,我们调用 mindoptpy.MdoModel.free_mdl()
来释放内存:
63 # Step 4. Free the model.
64 model.free_mdl()
文件链接 mdo_lo_ex1.py 提供了完整源代码:
1"""
2/**
3 * Description
4 * -----------
5 *
6 * Linear optimization (row-wise input).
7 *
8 * Formulation
9 * -----------
10 *
11 * Minimize
12 * obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
13 * Subject To
14 * c1 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
15 * c2 : 1 x0 - 1 x2 + 6 x3 = 1
16 * Bounds
17 * 0 <= x0 <= 10
18 * 0 <= x1
19 * 0 <= x2
20 * 0 <= x3
21 * End
22 */
23"""
24from mindoptpy import *
25
26
27if __name__ == "__main__":
28
29 MDO_INFINITY = MdoModel.get_infinity()
30
31 # Step 1. Create a model and change the parameters.
32 model = MdoModel()
33
34 try:
35 # Step 2. Input model.
36 # Change to minimization problem.
37 model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
38
39 # Add variables.
40 x = []
41 x.append(model.add_var(0.0, 10.0, 1.0, None, "x0", False))
42 x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x1", False))
43 x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x2", False))
44 x.append(model.add_var(0.0, MDO_INFINITY, 1.0, None, "x3", False))
45
46 # Add constraints.
47 # Note that the nonzero elements are inputted in a row-wise order here.
48 model.add_cons(1.0, MDO_INFINITY, 1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3], "c0")
49 model.add_cons(1.0, 1.0, 1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3], "c1")
50
51 # Step 3. Solve the problem and populate the result.
52 model.solve_prob()
53 model.display_results()
54
55 except MdoError as e:
56 print("Received Mindopt exception.")
57 print(" - Code : {}".format(e.code))
58 print(" - Reason : {}".format(e.message))
59 except Exception as e:
60 print("Received exception.")
61 print(" - Reason : {}".format(e))
62 finally:
63 # Step 4. Free the model.
64 model.free_mdl()
5.1.4.2. 按列输入: mdo_lo_ex2¶
在下面的代码中,我们依然对上述问题进行建模,但改以 按列排列 的方式输入矩阵的非零元。
在时调用 mindoptpy.MdoModel.add_cons()
时,仅输入约束的下界(left-hand-side;LHS)和上界(right-hand-side;RHS),约束矩阵则为空(无非零元素)。待约束输入后,再创建 列对象 mindoptpy.MdoCol()
来保存该列在各约束中相对应的非零元位置(索引)和非零值。最后,调用 mindoptpy.MdoModel.add_var()
创建变量,并输入其相应的目标函数系数、下界和上界、各约束在此列中相对应的非零元、变量名以及变量类型。
此外,我们还调用 mindoptpy.MdoModel.get_status()
来检查求解器的优化状态,并通过 mindoptpy.MdoModel.get_real_attr()
和 mindoptpy.MdoVar.get_real_attr()
来获取目标值和最优解(关于 mindoptpy.MdoModel.get_real_attr()
和 mindoptpy.MdoVar.get_real_attr()
的详细使用方式,请参考 Python 接口函数)。
文件链接 mdo_lo_ex2.py 提供了完整源代码:
1"""
2/**
3 * Description
4 * -----------
5 *
6 * Linear optimization (column-wise input).
7 *
8 * Formulation
9 * -----------
10 *
11 * Minimize
12 * obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
13 * Subject To
14 * c1 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
15 * c2 : 1 x0 - 1 x2 + 6 x3 = 1
16 * Bounds
17 * 0 <= x0 <= 10
18 * 0 <= x1
19 * 0 <= x2
20 * 0 <= x3
21 * End
22 */
23"""
24from mindoptpy import *
25
26
27if __name__ == "__main__":
28
29 MDO_INFINITY = MdoModel.get_infinity()
30
31 # Step 1. Create a model and change the parameters.
32 model = MdoModel()
33
34 try:
35 # Step 2. Input model.
36 # Change to minimization problem.
37 model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
38
39 # Add empty constraints.
40 cons = []
41 cons.append(model.add_cons(1.0, MDO_INFINITY, None, "c0"))
42 cons.append(model.add_cons(1.0, 1.0, None, "c1"))
43
44 # Input columns.
45 col = []
46 for j in range(4):
47 col.append(MdoCol())
48 col[0].add_term(cons[0], 1.0)
49 col[0].add_term(cons[1], 1.0)
50 col[1].add_term(cons[0], 1.0)
51 col[2].add_term(cons[0], 2.0)
52 col[2].add_term(cons[1], -1.0)
53 col[3].add_term(cons[0], 3.0)
54 col[3].add_term(cons[1], 6.0)
55
56 # Add variables.
57 # Note that the nonzero elements are inputted in a column-wise order here.
58 x = []
59 x.append(model.add_var(0.0, 10.0, 1.0, col[0], "x0", False))
60 x.append(model.add_var(0.0, MDO_INFINITY, 1.0, col[1], "x1", False))
61 x.append(model.add_var(0.0, MDO_INFINITY, 1.0, col[2], "x2", False))
62 x.append(model.add_var(0.0, MDO_INFINITY, 1.0, col[3], "x3", False))
63
64 # Step 3. Solve the problem and populate the result.
65 model.solve_prob()
66 model.display_results()
67
68 status_code, status_msg = model.get_status()
69 if status_msg == "OPTIMAL":
70 print("Optimizer terminated with an OPTIMAL status (code {0}).".format(status_code))
71 print("Primal objective : {0}".format(round(model.get_real_attr(MDO_REAL_ATTR.PRIMAL_OBJ_VAL), 2)))
72 for curr_x in x:
73 print(" - x[{0}] : {1}".format(curr_x.get_index(), round(curr_x.get_real_attr(MDO_REAL_ATTR.PRIMAL_SOLN), 2)))
74 else:
75 print("Optimizer terminated with a(n) {0} status (code {1}).".format(status_msg, status_code))
76
77 except MdoError as e:
78 print("Received Mindopt exception.")
79 print(" - Code : {}".format(e.code))
80 print(" - Reason : {}".format(e.message))
81 except Exception as e:
82 print("Received exception.")
83 print(" - Explanation : {}".format(e))
84 finally:
85 # Step 4. Free the model.
86 model.free_mdl()
5.1.4.3. 进阶使用示例:mdo_lo_ex3¶
在下面的代码中,我们展示了其他进阶 API 使用方式,如:输入模型、修改模型、获取基解、热启动的例子;关于 API 的完整使用方法,请参考 完整的API说明 。
文件链接 mdo_lo_ex3.py 提供了完整代码:
1"""
2/**
3 * Description
4 * -----------
5 *
6 * Linear optimization (row-wise input).
7 *
8 * Formulation
9 * -----------
10 *
11 * Minimize
12 * obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
13 * Subject To
14 * c1 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
15 * c2 : 1 x0 - 1 x2 + 6 x3 = 1
16 * Bounds
17 * 0 <= x0 <= 10
18 * 0 <= x1
19 * 0 <= x2
20 * 0 <= x3
21 * End
22 */
23"""
24from mindoptpy import *
25
26
27if __name__ == "__main__":
28
29 MDO_INFINITY = MdoModel.get_infinity()
30 WRITE_LP = True
31
32 # Step 1. Create a model and change the parameters.
33 model = MdoModel()
34
35 try:
36 # Step 2. Input model.
37 print("\nStep 2. Input model.\n")
38 # Change to minimization problem.
39 model.set_int_attr(MDO_INT_ATTR.MIN_SENSE, 1)
40
41 # Add variables.
42 xs = model.add_vars(4, lb=0, ub=MDO_INFINITY, obj=1.0, name="x")
43 x = [ value for key, value in xs.items() ]
44 x[0].set_real_attr(MDO_REAL_ATTR.UB, 10.0)
45
46 # Add constraints.
47 # Note that the nonzero elements are inputted in a row-wise order here.
48 conss = []
49 conss.append(model.add_cons(1.0 * x[0] + 1.0 * x[1] + 2.0 * x[2] + 3.0 * x[3] >= 1.0, "c0"))
50 conss.append(model.add_cons(1.0 * x[0] - 1.0 * x[2] + 6.0 * x[3] == 1.0, "c1"))
51
52 # Step 3. Solve the problem and populate the result.
53 print("\nStep 3. Solve the problem and populate the result.\n")
54 model.solve_prob()
55 model.display_results()
56 if WRITE_LP:
57 model.write_prob("Step3.lp");
58
59 # Step 4. Add another two variables and then resolve the problem.
60 print("\nStep 4. Add another two variables and then resolve the problem.\n")
61 # Input columns.
62 cols = [ MdoCol() for i in range(2) ]
63 cols[0].add_terms(conss, [ 1.0, 2.0 ])
64 cols[1].add_terms(conss, [ 3.4, 4.0 ])
65 y = []
66 y.append(model.add_var( 0.0, MDO_INFINITY, 1.0, cols[0], "y0", False))
67 y.append(model.add_var(-2.0, MDO_INFINITY, -1.0, cols[1], "y1", False))
68
69 # Solve the problem.
70 model.solve_prob()
71 model.display_results()
72 if WRITE_LP:
73 model.write_prob("Step4.lp");
74
75 # Step 5. Add another two constraints and then resolve the problem.
76 print("\nStep 5. Add another two constraints and then resolve the problem.\n")
77 bgn2 = [ 0, 3, 6 ]
78 indices2 = [
79 0, 1, 3,
80 0, 2, 3
81 ]
82 values2 = [
83 1.0, 1.0, -2.0,
84 1.0, -2.0, 6.0
85 ]
86
87 lhss2 = [ 0, 1 ]
88 rhss2 = [ 2, MDO_INFINITY ]
89
90 expr = [ MdoExprLinear() for i in range(2) ]
91 for i in range(2):
92 for e in range(bgn2[i], bgn2[i + 1]):
93 expr[i] += values2[e] * x[indices2[e]]
94
95 c2 = model.add_conss( [ expr[i] == [lhss2[i], rhss2[i]] for i in range(2) ] )
96 for key, value in c2.items():
97 conss.append(value)
98
99 # Solve the problem.
100 model.solve_prob()
101 model.display_results()
102 if WRITE_LP:
103 model.write_prob("Step5.lp");
104
105 # Step 6. Obtain optimal basis.
106 print("\nStep 6. Obtain optimal basis.\n")
107
108 # isFree = 0,
109 # basic = 1,
110 # atUpperBound = 2,
111 # atLowerBound = 3,
112 # superBasic = 4,
113 # isFixed = 5,
114 col_basis = []
115 row_basis = []
116 for var in x:
117 print("Basis status of variable {0} is {1}".format(var.get_index(), var.get_int_attr(MDO_INT_ATTR.COL_BASIS)))
118 col_basis.append(var.get_int_attr(MDO_INT_ATTR.COL_BASIS))
119 for var in y:
120 print("Basis status of variable {0} is {1}".format(var.get_index(), var.get_int_attr(MDO_INT_ATTR.COL_BASIS)))
121 col_basis.append(var.get_int_attr(MDO_INT_ATTR.COL_BASIS))
122 for cons in conss:
123 print("Basis status of constraint {0} is {1}".format(cons.get_index(), cons.get_int_attr(MDO_INT_ATTR.ROW_BASIS)))
124 row_basis.append(cons.get_int_attr(MDO_INT_ATTR.ROW_BASIS))
125
126 if WRITE_LP:
127 model.write_prob("Step6.lp");
128 model.write_soln("Step6.bas");
129
130 # Step 7. Warm-start Simplex.
131 print("\nStep 7. Warm-start Simplex.\n")
132
133 # Change the objective coefficients.
134 x[1].set_real_attr("Obj", 3.0);
135 x[2].set_real_attr("Obj", -3.0);
136
137 # Load the basis.
138 model.set_int_attr_array(MDO_INT_ATTR.ROW_BASIS, 0, row_basis);
139 model.set_int_attr_array(MDO_INT_ATTR.COL_BASIS, 0, col_basis);
140
141 # Solve the problem.
142 model.solve_prob()
143 model.display_results()
144 if WRITE_LP:
145 model.write_prob("Step7.lp");
146
147 # Step 8. Model query.
148 print("\nStep 8. Model query.\n")
149
150 # Query 1: Retrieve first constraint.
151 print("Query 1: Retrieve first constraint.")
152
153 temp_expr = model.get_expr_linear(conss[0])
154 print(temp_expr)
155
156 # Query 2: Retrieve second column.
157 print("Query 2: Retrieve second column.")
158
159 temp_col = model.get_col(x[1]);
160 print(temp_col)
161
162 except MdoError as e:
163 print("Received Mindopt exception.")
164 print(" - Code : {}".format(e.code))
165 print(" - Reason : {}".format(e.message))
166 except Exception as e:
167 print("Received exception.")
168 print(" - Reason : {}".format(e))
169 finally:
170 # Step 4. Free the model.
171 model.free_mdl()