如何解决这个组合算法问题

时间:2010-05-04 14:38:29

标签: algorithm language-agnostic genetic-algorithm

我有N人,每人必须参加T次考试。每次考试都需要“一些”时间,例如30分钟(没有提前完成的事情)。考试必须在考官面前进行。

我需要安排每个人在整个时间段内在考官面前进行每次考试,但避免午休,在最短的时间内使用最少数量的考官(即没有/最小考官闲置)< / p>

有以下限制:

  • 一个人不能同时在两个地方
  • 每个人必须参加一次考试
  • 任何人都应该由同一位考官检查两次

我意识到最佳解决方案可能是NP-Complete,我可能最好使用遗传算法来获得最佳估计(类似于此?Seating plan software recommendations (does such a beast even exist?))。

我对遗传算法如何工作感到满意,我正在努力解决的是如何以编程方式对问题进行建模,以便我可以在遗传上操纵参数。

如果每次考试花费相同的时间,那么我将时间段划分为这些长度,然后简单地创建一个时间矩阵与审查员并将候选人放入。但是因为每次考试的时间都是不一定相同,我对如何处理这个问题感到有点迷失。

目前我这样做:

  • 列出所有需要在每个考生和考试之间进行的“考试”
  • 从与测试一样多的审查员开始
  • 反复遍历所有审查员,每个人:找到一个有资格获得审查员的计划外测试(基于限制)
  • 继续,直到所有可以安排的测试
  • 如果有任何未安排的测试,请增加审查员人数并重新开始。

我正在寻找关于如何处理这个问题的更好的建议,因为它目前感觉相当粗糙。

5 个答案:

答案 0 :(得分:1)

正如 julienaubert 所提出的,一个解决方案(我称之为 schedule )是一系列元组(日期,学生,考官,测试),涵盖所有相关学生 - 测试组合(所有N个学生都参加所有T测试吗?)。我知道单个考官可以同时测试几个学生。否则,将需要大量的审查员(每个学生至少一个),我真的怀疑。

如果

,两个元组A和B冲突
  • 学生相同,考试不同,时间段重叠
  • 审查员是相同的,测试是不同的,时间段重叠
  • 该学生已与另一名考试的考官合作

请注意,元组冲突与计划冲突不同(必须另外检查重复的审查员问题)。

下限:

  • 审查员的数量E必须> =最过度劳累的学生的测试总数
  • 总时间必须大于最过度劳累的学生的总测试时间。

可以通过以下方法构建简单,贪婪的计划:

  1. 带上过度劳累的学生和 以随机顺序分配测试, 每个人都有不同的考官。一些 bin-packing可用于重新排序 午餐时间是这样的 保持自由。这将是一件幸福的事 学生:他将完成 最短的时间。
  2. 对于其他学生,如果学生必须参加已经安排的任何考试,请与之前安排的考试分享时间,地点和考官。
  3. 选择过度工作的学生(如:最多的计划外考试),并分配元组,以免违反任何限制,在必要时增加更多时间和审查员
  4. 如果有学生有计划外考试,请转到2。
  5. 改善上述步骤2中的选择对改进至关重要;这种选择可以构成启发式搜索的基础。上述算法试图最大限度地减少所需的审查员数量,但会牺牲学生的时间(学生可能会在早期结束一次考试,最后一次最后一次考试,两者之间没有任何内容)。但是,它保证会产生法律解决方案。与不同的学生一起运行可以用来为GA提供“起始”解决方案,这些解决方案能够得到合法的答案。

    总的来说,我认为像这样的问题没有“完美答案”,因为必须考虑很多因素:学生希望尽量减少自己检查自己的总时间,审查员也是如此;我们希望尽可能减少审查员的数量,但是对于我们可以在单个审查员的房间内堆叠的学生数量也存在实际限制。此外,我们希望安排“公平”,所以没有人明显比其他人更糟糕。因此,您可以做的最好的事情就是让这些旋钮摆弄,结果可以知晓(总时间,每个学生的幸福,每个考官的快乐,考试大小,感知公平)并允许用户探索参数空间并做出明智的选择。

答案 1 :(得分:1)

我建议使用SAT求解器。尽管问题可能是NP难的,但是好的SAT解算器通常可以处理数十万个变量。有两个例子,请查看ChaffMiniSat

答案 2 :(得分:0)

不要过早地限制自己的遗传算法,有many other approaches

更具体地说,如果您可以将两个解决方案的部分组合成一个新解决方案,那么遗传算法才真正有用。这个问题看起来相当困难,至少如果有相同数量的人和考试,那么大多数人都会直接互动。

答案 3 :(得分:0)

以下介绍如何使用GA对其进行建模。

使用您的符号:

  • N(nr考生)
  • T(nr考试)

让个人的基因表达完整的预约时间表。 即个人是特定预订的清单:(i,j,t,d)

  • 我是第一个考生[1,N]
  • j是第j位审查员[1,?]
  • t是考生必须参加[1,T]
  • 的第t次考试
  • d是考试的开始(日期+时间)

使用具有以下属性的适应度函数进行评估:

  • 惩罚(严重)所有双重预定审查员
  • 惩罚审查员空闲时间
  • 对未在其时间段内分配的考生进行处罚
  • 每个考试期间的考试奖励

此功能将具有确定双重预订的所有逻辑等。您在个人中拥有完整的建议时间表,您现在运行逻辑,知道每次预订时每次测试的时间,以确定适合度并增加/减少相应的预订分数。

为了使这项工作顺利进行,请考虑:

  • 启动 - 如果计算成本低廉,请使用尽可能多的信息进行“理智”的预订。
  • 定义适当的GA运算符

以理智的方式开始:

  • 在该时间段内随机选择d
  • 随机置换(1,2,..,N),然后从中挑选i(避免重复),j和t相同

适当的GA运营商:

说您已预订 a b : (A_I,a_j,A_T,A_D) (b_i,b_j,B_T,B_D)

你可以交换a_i和b_i,你可以交换a_j和b_j以及a_d和b_d,但在交换a_t和b_t时可能没有意义。

你也可以骑自行车,最好用一个例子来说明,如果N * T = 4,一个完整的预订是4个元组然后你会沿着i或j或d循环,例如沿着i循环:

a_i = b_i
b_i = c_i
c_i = d_i
d_i = a_i

答案 4 :(得分:0)

您也可以考虑约束编程。查看Prolog或更简单的逻辑编程表达式PyKE