这里的根本问题在于你似乎有一个多目标优化问题。你有三个你感兴趣的事情,你可以将它们视为目标或“软约束条件”:
- 让班级人数相似
- 最小化每个班级的级别数
- 如果班级中有任何学生,则需要有足够的来自该级别的学生。
请注意,我已经在AMPL中编写了优化模型。由于你正在使用Python,像PuLP和pyomo这样的Python类似的优化建模语言也可以使用。该模型不应太难翻译。
这是一个整数规划模型和数据文件,突出了第1个目标,同时保持问题(整数)线性。通过这个目标,优化问题找到了与你在示例中给出的相同的解决方案。希望你可以在此基础上添加其他限制和/或目标项,并获得更好的解决方案。
目标是最小化最大班级人数。感兴趣的变量是y[i,j]。对于i在LEVEL,j在CLASS,y[i,j]是分配到班级j的来自级别i的学生数量。它假设你有输入每个班级中来自每个级别的最小学生人数(如果有)。
目标函数可能不是你想要的,但它是尝试平衡班级大小的一种线性方式。我也不能保证这是解决问题最有效的方法。可能有更好的定制算法适用于此问题,但我只需要表达约束和目标,而不编写算法。对于你的使用来说,它可能已经足够好了。
在neos-server.org上使用Gurobi求解器(你可以使用lpsolve或另一个开源优化求解器),我得到了解决方案
y :=
1 1 14
1 2 9
1 3 0
2 1 6
2 2 0
2 3 18
3 1 6
3 2 16
3 3 8
;
模型:
set LEVEL ordered;
set CLASS;
param maxClassSize {CLASS};
param minLevelNumberInClass {LEVEL, CLASS};
param numInLevel {LEVEL};
var z >= 0;
var y{LEVEL, CLASS} integer, >= 0;
var x{LEVEL, CLASS} binary;
#minimize maximum class size
minimize obj:
z;
subject to allStudentsAssigned {i in LEVEL}:
sum {j in CLASS} y[i,j] = numInLevel[i];
#z is the largest of all classes sizes
subject to minMaxZ {j in CLASS}:
z >= sum {i in LEVEL} y[i,j];
subject to maxClassSizeCon {j in CLASS}:
sum {i in LEVEL} y[i,j] <= maxClassSize[j];
#xij = 1 if any students from level i are in class j
subject to defineX {i in LEVEL, j in CLASS}:
y[i,j] <= min(numInLevel[i], maxClassSize[j]) * x[i,j];
#if any students from level i are assigned to class j, then there is a minimum
#if x[i,j] = 1, y[i,j] >= minLevelNumberInClass[i,j]
subject to minLevel {i in LEVEL, j in CLASS}:
minLevelNumberInClass[i,j] * x[i,j] <= y[i,j];
您例子中所需的数据文件:
set LEVEL := 1 2 3;
set CLASS := 1 2 3;
param minLevelNumberInClass:
1 2 3 :=
1 6 6 6
2 6 6 6
3 6 6 6
;
param maxClassSize :=
1 77
2 77
3 77
;
param numInLevel :=
1 23
2 24
3 30
;