Один из способов сделать это в MiniZin c - это расширить модель на Задача оптимизации модели планирования отдельных уроков следующим образом:
Первоначально вычислить teacher_free
как слоты, в которых учитель недоступен, объединены с соседними слотами, где не проводится урок (это делается в два этапа, начиная слева teacher_free_left
и справа teacher_free_right
, соответственно, а затем объединяя результаты в форму teacher_free
).
На следующем этапе real_gap
рассчитывается как интервалы, в которых учитель не свободен и урок не проходит.
В задаче штраф за real_gap
равен затем вводится как (k2
- вес штрафа за разрыв):
int: k2 = 1;
var int: obj = sum(s in STUDENT, t in TIME)
(active[s,t] * (prio_time[s,t] + k*prioTeacher_time[t])) - k2*sum(real_gap);
Здесь все другие расширения модели (с некоторыми дополнительными комментариями):
array[DAY,SLOT] of var 0..1: lesson = array2d(DAY, SLOT, [sum(s in STUDENT)(active[s,time(d,z)]) | d in DAY, z in SLOT]);
array[DAY,SLOT] of var 0..1: teacher_free_left;
array[DAY,SLOT] of var 0..1: teacher_free_right;
array[DAY,SLOT] of var 0..1: teacher_free;
array[DAY,SLOT] of var 0..1: real_gap;
predicate equals_and(var 0..1: z, var 0..1: x, var 0..1: y) =
(z <= x /\ z <= y /\ z >= x + y - 1);
predicate equals_or(var 0..1: z, var 0..1: x, var 0..1: y) =
(z >= x /\ z >= y /\ z <= x + y);
% calculate teacher free left
% first slot -> teacher free = no lesson in the slot
% other slots -> teacher free = teacher out or (left slot teacher free and no lesson in slot)
array[DAY,SLOT] of var 0..1: teacher_free_left_temp;
constraint forall(d in DAY)
(teacher_free_left_temp[d,1]=1-lesson[d,1]);
constraint forall(d in DAY, z in 2..maxSlots)
(equals_and(teacher_free_left_temp[d,z], teacher_free_left[d,z-1], 1-lesson[d,z]));
constraint forall(d in DAY, z in SLOT)
(equals_or(teacher_free_left[d,z], 1 - bool2int(z in teacher[d]), teacher_free_left_temp[d,z]));
% calculate teacher free right
% last slot -> teacher free = no lesson in the slot
% other slots -> teacher free = teacher out or (right slot teacher free and no lesson in slot)
array[DAY,SLOT] of var 0..1: teacher_free_right_temp;
constraint forall(d in DAY)
(teacher_free_right_temp[d,maxSlots]=1-lesson[d,maxSlots]);
constraint forall(d in DAY, z in 1..maxSlots-1)
(equals_and(teacher_free_right_temp[d,z], teacher_free_right[d,z+1], 1-lesson[d,z]));
constraint forall(d in DAY, z in SLOT)
(equals_or(teacher_free_right[d,z], 1 - bool2int(z in teacher[d]), teacher_free_right_temp[d,z]));
% teacher free when teacher free left or teacher free right
constraint forall(d in DAY, z in SLOT)
(equals_or(teacher_free[d,z], teacher_free_left[d,z], teacher_free_right[d,z]));
% real gap when teacher not free and no lesson
constraint forall(d in DAY, z in SLOT)
(equals_and(real_gap[d,z], 1-teacher_free[d,z], 1-lesson[d,z]));