我们直接从题目入手学习0-1规划模型。
问题一:
可以看出,这是一个标准的指派问题。引进0-1变量。
建立数学模型得:
import cvxpy as cp
import numpy as np
c = np.array([[4,8,7,15,12],
[7,9,17,14,10],
[6,9,12,8,7],
[6,7,14,6,10],
[6,9,12,10,6]])
x = cp.Variable((5,5),integer = True)
obj = cp.Minimize(cp.sum(cp.multiply(c,x)))
con = [0 <= x, x <= 1, cp.sum(x, axis = 0, keepdims = True) == 1,
cp.sum(x, axis = 1, keepdims = True) == 1]
prob = cp.Problem(obj, con)
prob.solve(solver = 'GLPK_MI')
print("最优值为", prob.value)
print("最优解为:", x.value)
问题二:选修课策略问题
某学校规定,运筹学专业的学生毕业时必须至少学习过两门数学课、三门运筹学课和两门计算机课。这些课程的编号、名称、学分、所属类别和先修课要求如表1所示。
问题:毕业时学生最少可以学习这些课程中哪些课程。
如果某个学生既希望选修课程的数量少,又希望所获得的学分多,他可以选修哪些课程。
模型的建立:
1.不考虑学分情形
记
i
=
1
,
2
,
⋯
,
9
i=1,2,\cdots,9
i=1,2,⋯,9表示九门课程的编号。设
x
i
=
1
x_{i} = 1
xi=1表示第
i
i
i门课程选修,
x
i
=
0
x_{i} = 0
xi=0表示第i门课程不选。问题的目标为选修的课程总数最少,即:
min
Z
=
∑
i
=
1
9
x
i
\min Z=\sum_{i=1}^{9}x_{i}
minZ=∑i=19xi
约束条件包括两个方面:
第一个方面是课程数量的约束:
每个人至少要学习两门数学课,则
x
1
+
x
2
+
x
3
+
x
4
+
x
5
≥
2
x_{1}+x_{2}+x_{3}+x_{4}+x_{5} \ge 2
x1+x2+x3+x4+x5≥2
每个人至少要学习三运筹学课,则
x
3
+
x
5
+
x
6
+
x
8
+
x
9
≥
3
x_{3}+x_{5}+x_{6}+x_{8}+x_{9} \ge 3
x3+x5+x6+x8+x9≥3
每个人至少要学习两门计算机课,则
x
4
+
x
6
+
x
7
+
x
9
≥
2
x_{4}+x_{6}+x_{7}+x_{9} \ge 2
x4+x6+x7+x9≥2
第二方面是先修课程的关系约束:
“最优化方法”的先修课是“微积分”和“线性代数”,有:
x
3
≤
x
1
,
x
3
≤
x
2
x_{3} \le x_{1},x_{3}\le x_{2}
x3≤x1,x3≤x2
“数据结构”的先修课程是“计算机编程”,有:
x
4
≤
x
7
x_{4}\le x_{7}
x4≤x7
“应用统计”的先修课是“微积分”和“线性代数”,有:
x
5
≤
x
1
,
x
5
≤
x
2
x_{5}\le x_{1},x_{5}\le x_{2}
x5≤x1,x5≤x2
“计算机模拟”的先修课程是“计算机编程”,有:
x
6
≤
x
7
x_{6}\le x_{7}
x6≤x7
“预测理论”的先修课程是“应用统计”,有:
x
8
≤
x
5
x_{8} \le x_{5}
x8≤x5
“数学实验”是“微积分”和“线性代数”,有:
x
9
≤
x
1
,
x
9
≤
x
2
x_{9}\le x_{1},x_{9}\le x_{2}
x9≤x1,x9≤x2
总的0-1规划模型为:
min
Z
=
∑
i
=
1
9
x
i
s.t.
{
x
1
+
x
2
+
x
3
+
x
4
+
x
5
≥
2
x
3
+
x
5
+
x
6
+
x
8
+
x
9
≥
3
x
4
+
x
6
+
x
7
+
x
9
≥
2
x
3
≤
x
1
,
x
3
≤
x
2
x
4
≤
x
7
x
5
≤
x
1
,
x
5
≤
x
2
x
6
≤
x
7
x
8
≤
x
5
x
9
≤
x
1
,
x
9
≤
x
2
x
1
,
x
2
,
⋯
,
x
9
=
0
或
1
\begin{array}{l} \min Z=\sum_{i=1}^{9} x_{i} \ \text { s.t. }\left\{\begin{array}{l} x_{1}+x_{2}+x_{3}+x_{4}+x_{5} \geq 2 \ x_{3}+x_{5}+x_{6}+x_{8}+x_{9} \geq 3 \ x_{4}+x_{6}+x_{7}+x_{9} \geq 2 \ x_{3} \leq x_{1}, x_{3} \leq x_{2} \ x_{4} \leq x_{7} \ x_{5} \leq x_{1}, x_{5} \leq x_{2} \ x_{6} \leq x_{7} \ x_{8} \leq x_{5} \ x_{9} \leq x_{1}, x_{9} \leq x_{2} \ x_{1}, x_{2}, \cdots, x_{9}=0 \text { 或 } 1 \end{array}\right. \end{array}
minZ=∑i=19xi s.t. ⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧x1+x2+x3+x4+x5≥2x3+x5+x6+x8+x9≥3x4+x6+x7+x9≥2x3≤x1,x3≤x2x4≤x7x5≤x1,x5≤x2x6≤x7x8≤x5x9≤x1,x9≤x2x1,x2,⋯,x9=0 或 1
import cvxpy as cp
import numpy as np
c = np.array([1,1,1,1,1,1,1,1,1])
x = cp.Variable(9,integer = True)
A = array([[-1,-1,-1,-1,-1,0,0,0,0],
[0,0,-1,0,-1,-1,0,-1,-1],
[0,0,0,-1,0,-1,-1,0,-1],
[-1,0,1,0,0,0,0,0,0],
[0,-1,1,0,0,0,0,0,0],
[0,0,0,1,0,0,-1,0,0],
[-1,0,0,0,1,0,0,0,0],
[0,-1,0,0,1,0,0,0,0],
[0,0,0,0,0,1,-1,0,0],
[0,0,0,0,-1,0,0,1,0],
[-1,0,0,0,0,0,0,0,1],
[0,-1,0,0,0,0,0,0,1]])
b = array([-2,-3,-2,0,0,0,0,0,0,0,0,0])
obj = cp.Minimize(cp.sum(cp.multiply(c,x)))
con = [A * x <= b, 0 <= x, x <= 1]
prob = cp.Problem(obj, con)
prob.solve(solver = 'GLPK_MI')
print("最优值为", prob.value)
print("最优解为:", x.value)
2.考虑学分情形
此时总的双目标0-1规划模型为:
min
Z
1
=
∑
i
=
1
9
x
i
max
Z
2
=
∑
i
=
1
9
c
i
x
i
\begin{array}{l} \min Z_{1}=\sum_{i=1}^{9} x_{i} \ \max Z_{2}=\sum_{i=1}^{9} c_{i} x_{i} \end{array}
minZ1=∑i=19ximaxZ2=∑i=19cixi
我们这里采取先计算上选修课数量最少,再去求解学分最高。
import cvxpy as cp
import numpy as np
from numpy import array
c = np.array([-5,-4,-4,-3,-4,-3,-2,-2,-3])
A = array([[-1,-1,-1,-1,-1,0,0,0,0],
[0,0,-1,0,-1,-1,0,-1,-1],
[0,0,0,-1,0,-1,-1,0,-1],
[-1,0,1,0,0,0,0,0,0],
[0,-1,1,0,0,0,0,0,0],
[0,0,0,1,0,0,-1,0,0],
[-1,0,0,0,1,0,0,0,0],
[0,-1,0,0,1,0,0,0,0],
[0,0,0,0,0,1,-1,0,0],
[0,0,0,0,-1,0,0,1,0],
[-1,0,0,0,0,0,0,0,1],
[0,-1,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1]])
b = array([-2,-3,-2,0,0,0,0,0,0,0,0,0,6])
x = cp.Variable(9,integer = True)
obj = cp.Minimize(c*x)
con = [A * x <= b, 0 <= x, x <= 1]
prob = cp.Problem(obj, con)
prob.solve(solver = 'GLPK_MI')
print("最优值为", -prob.value)
print("最优解为:", x.value)
鉴于笔者水平有限,疏漏难所在免,欢迎指正错误!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)