因此,起初您的问题定义中有一些不寻常的事情:
- 这不是一个真正的优化问题,因为您的目标函数根据定义是固定的(每个班次有 7 名护士,每个班次的每个护士都有相同的价格)
- 在您的问题中,您定义了每班 7 名护士,最多 5 个工作日。所以你需要 7 名护士在 7 天三班倒。这等于 147 名护士/班次。但是,在五个工作日的上限和每天只有一个班次的情况下,您只有 20 名护士在 5 个班次上,这等于 100 名护士/班次。
我已经在 Mathprog 中构建了问题,但代码应该或多或少等于 AMPL。我从护士、日班和轮班的三组开始。
set shifts := {1,2,3};
set days := {1,2,3,4,5,6,7};
set nurses := {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
shedule 被定义为一组二进制变量:
var schedule{nurses, days, shifts}, binary;
简单目标包含本周所有护士/班次的总和以及相关价格:
minimize cost: sum{i in nurses, j in days}(schedule[i,j,1]*c_morning+schedule[i,j,2]*c_day+schedule[i,j,3]*c_night);
对于您的第一个约束,可以将每位护士的所有轮班总和限制为五个,因为每天只有一个轮班:
s.t. working_days{n in nurses}:
sum{i in days, j in shifts}(schedule[n,i,j]) <= 5;
休息日是问题中最难的部分。为简单起见,我创建了另一个仅包含天数的集合,其中一名护士可以连续完成四个夜班。您还可以使用原始天数来制定约束并排除前四天。
set nigth_days := {5,6,7};
s.t. rest{n in nurses,i in nigth_days}:
(schedule[n,i-4,3]+schedule[n,i-3,3]+schedule[n,i-2,3]+schedule[n,i-1,3]+sum{j in shifts}(schedule[n,i,j])) <= 4;
由于夜班后没有早班,我使用了与其他日子相同的尝试。第七天被排除在外,因为没有第八天我们可以找早班。
set yester_days := {1,2,3,4,5,6};
s.t. night_morning{i in yester_days, n in nurses}:
(schedule[n,i,3]+schedule[n,i+1,1]) <= 1;
应该满足每班四名护士的需求(我减少了人数,因为超过 4 名护士是不可行的,因为 5 班的限制)
s.t. demand_shift{i in days, j in shifts}:
sum{n in nurses}(schedule[n,i,j]) = 4;
第五个限制条件是将每天的班次限制为最多一班。
s.t. one_shift{n in nurses, i in days}:
sum{ j in shifts}(schedule[n,i,j]) <= 1;