【问题标题】:Schedule minizinc no overlapping计划 minizinc 没有重叠
【发布时间】:2015-07-01 21:04:13
【问题描述】:

我想做一个没有重叠的时间表,只能在 1 个时间段预订 1 位教师。我想创建一个像教师一样的 2darray 行,时间段是列。

【问题讨论】:

  • 您的问题到底是什么?您可以定义一个决策变量的二维数组(矩阵),如下所示:array[Teachers,Timeslots] of var Presentations: X。但我想这并不是您真正要问的。
  • 我的问题是我如何构建一个约束条件,让一个老师不能在同一时间段被预订两次,所以我现在把这个结果放在我的问题末尾。
  • 你明白我的意思吗?

标签: constraints scheduled-tasks minizinc


【解决方案1】:

用于此类约束的一般约束(“某些东西应该是不同的”)是两个全局约束 all_different 或 alldifferent_except_0。

注意:我更改为 3 个教师、3 个时间段和 5 个演示文稿,以便更一般地使用 alldifferent_except_0,因为可能存在没有教师/演示文稿时间段的作业。

另外,我不确定我是否会像你一样使用特定的表示,因为它的表示取决于模型中的进一步约束(如果有的话)。

这里有一些可能有用的方法。

1) 只有一个“时间表”矩阵的简单模型

如果您只想分配 T 个教师、TS 时隙和 P 个演示文稿而没有进一步的约束,那么时间表矩阵上的单个约束“all_different_except_0”就足够了(连同下面解释的总和)。 “时间表”的维度是 T x TS(教师 x 时隙),我们分配演示文稿的位置,如果没有该教师和时隙的演示文稿,则为 0。

include "globals.mzn"; 

set of int: Timeslots = 1..3;
set of int: Teachers = 1..3; 
set of int: Presentations = 1..5;

solve satisfy;

% Decision variables
array[Teachers, Timeslots] of var {0} union Presentations: timetable;

constraint 
    alldifferent_except_0(array1d(timetable))

    % ensure that there are 5 assigned presentations
   /\ sum([timetable[t,ts]>0 | t in Teachers, ts in Presentations]) = card(Presentations)
;

% output [....];

这种模型的缺点是不容易说明可能需要的进一步约束,而且我们必须计算“时间表”矩阵中非 0 分配的数量,以确保正好有 5 个演示文稿分配的。

所以我们将扩展更多决策变量。

2) 添加决策变量

此模型将原始演示文稿与上面显示的“时间表”矩阵及其约束联系起来。这意味着我们可以保持对“时间表”的约束以确保唯一性,并且我们也可以对其他决策变量进行约束。这是一个包含两个原始数组“presentation_teacher”和“presentation_time”及其约束的模型。

 include "globals.mzn"; 
 set of int: Timeslots = 1..3;
 set of int: Teachers = 1..3; 
 set of int: Presentations = 1..5;

 % Decision variables
 % Which teacher has this presentation
 array[Presentations] of var Teachers: presentation_teacher;

 % Which timeslot for this presentation
 array[Presentations] of var Timeslots: presentation_time;

 % Which combination of teacher and timeslot for a presentation, if any
 array[Teachers, Timeslots] of var {0} union Presentations: timetable;
 solve satisfy;

 constraint

   alldifferent_except_0(array1d(timetable))
   % This constraint is not needed now
   % /\ sum([timetable[t,ts]>0 | t in Teachers, ts in Presentations]) = card(Presentations)

   /\ % connect timetable and presentation_teacher and presentation_time
  forall(p in Presentations) (
     timetable[presentation_teacher[p],presentation_time[p]] = p
  )
 ;

约束“forall(p in Presentations) (...)”连接两个表示:“时间表”表示和两个添加的数组。

3) 替代版本

为教师确保不同的时间段和演示文稿的另一种版本是对“presentation_teacher”、“presentation_time”添加约束。这并不真正需要时间表矩阵,因此在此处跳过。 (可以使用时间表方法添加这些约束可能会更快。)

include "globals.mzn"; 
set of int: Timeslots = 1..3;
set of int: Teachers = 1..3; 
set of int: Presentations = 1..5;

% Decision variables

% Which teacher has this presentation
array[Presentations] of var Teachers: presentation_teacher;

% Which timeslot for this presentation
array[Presentations] of var Timeslots: presentation_time;

solve satisfy;

constraint 
  % variant A
  forall(t in Teachers) (
      % the time for this teacher is distinct (or 0)
     alldifferent_except_0([presentation_time[p] * (presentation_teacher[p]=t) | p in Presentations])
  )

 /\ 
 % variant B
 forall(t in Teachers) (
    % combination of (time + teacher) for this teacher is unique
    alldifferent([presentation_time[p]+(presentation_teacher[p]*card(Presentations)) | p in Presentations])
 )

;

此模型有两个变体,第一个(“A”)使用 alldifferent_except_0 来确保每个教师的演示文稿都是不同的。

对于每位教师,它会循环遍历所有演示文稿(“p”)并挑选分配给“这位”教师的时间,并确保它们是不同的。

第二个变体(“B”)是一种 hack,虽然有时非常有用:它构建一个分配给教师的整数列表(时间 + 教师 ID * 演示次数)并确保它们是不同的。

由于此模型没有明确的时间表,因此必须在输出中提取时间表。这是一种方法:

output [
  "Teacher " ++ show(t) ++ " has these presentations" ++ show([p | p in Presentations where fix(presentation_teacher[p]) = t]) ++ "\n"
  | t in Teachers
]
;

如上所述,模型的表示(选择哪些决策变量)很大程度上取决于人们想要进一步做什么。

【讨论】:

  • 感谢 Hakank 解释了很多。非常感谢您的时间和回答!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-01
  • 2020-04-09
  • 2021-04-07
相关资源
最近更新 更多