日历/计划算法


24

我面临一个不确定的方法。我必须为员工生成日历,每个员工都有特定的工作限制(有些是个人的,有些是普通的)

我正在使用的是:

  • 我有医生
  • 每个医生每周必须工作5天。
  • 每个医生每周必须工作1晚
  • 与其他医生相比,每位医生必须工作等量的夜晚(或尽可能接近)
  • 每个医生在周四晚上和周日晚上的工作量必须与其他医生相同(或尽可能接近)
  • 有些医生不能在某些白天/夜晚工作(由用户输入)
  • 一些医生想在某些白天/夜晚工作(由用户输入)
  • 一些医生希望某些天/夜不工作(由用户输入)

有问题的用户是处理日历的人,我正在尝试构建一个解决方案,该解决方案将自动生成一个遵循所有约束的日历。解决的方法是对每个医生进行大设置输入“添加医生”和“添加约束”,然后输入“生成日历”按钮。对于用户而言,这确实是基本的。

我的问题 :

我不确定如何生成实际计划,我一直在阅读有关神经网络,遗传算法等的信息,它们似乎都是正确的解决方案,但实际上并非如此。

当我查看GA时,要让他们找到具有给定总体的解决方案(我的问题),但是起始总体必须已经服从给定的一组约束,然后可以对其进行优化。在那种情况下,我的起始人口已经是解决方案。我不需要对其进行“优化”。没关系,一个人连续工作3个星期一晚上,只要实际上是正确的,而其他人也工作相同的数量,就意味着其他人也将在某个时间点工作3个星期一晚上,这很好。这让我觉得GA的功能对我来说太“先进”了,因为我的问题已经从GA的起点解决了。

但是话又说回来,GA真的真的像是为此而生的,所以我可能无法正确理解它?

无论如何,因为我从未使用过GA(或神经网络,或任何种类的东西),所以我想确保在从事像这样的学习过程之前,我会选择正确的方法。

我的问题 :

对于像我这样的问题,您认为什么是好的方法/算法/技术?加油站?神经网络?还有其他完全不同的东西吗?

我全神贯注,并在需要时提供更多详细信息,但我想我已经很清楚了:)


22
可能值得一看有关护士名册问题的文献,en.wikipedia.org
Renaud M.

这么方便的术语!呵呵,谢谢您的链接;)
吉尔·桑德

8
我不是该领域的专家,但是,如果您正在寻找的是一种可以节省您开发时间的方法,则可能值得尝试将问题建模为混合整数编程问题(zh.wikipedia)。 org / wiki / Linear_programming#Integer_unknowns),然后将其输入到MIP求解器中,或者作为约束编程问题,然后将其输入到CP求解器中,例如OR-tools(developers.google.com/optimization)。这样,您所要做的就是表达您的问题。
Renaud M.

3
保证线性规划可以得出最佳解决方案!
recursion.ninja

2
@RenaudM。可惜的是,很少有专业程序员能理解这个非常有用的数学领域。每当有人建议在AI领域之外使用模拟退火或遗传算法时,我的直觉反应就是:可以更好地将其建模为线性程序优化
recursion.ninja

Answers:


14

遗传算法和神经网络不适用于此处。它们是元启发法,用于找到足够好的问题的近似解决方案。值得注意的是,两者都要求您找到一个成本函数来评估候选解决方案。一旦有了这样的成本函数,手动为该成本进行优化的算法可能会更容易。

这是一个重要的思想:给定两个时间表,我们需要一种方法来确定时间表A或时间表B是“更好”的。您已经列出了各种条件,但尚不清楚它们之间的关系。不满足一个标准会使整个解决方案失败吗?还是部分失败一个约束只会使其成为比其他约束更糟糕的解决方案?

在最基本的级别上,您可以将一周划分为多个不连续的时间段,并强行使用所有时间空档-医生组合。但是,您可以使用硬失效约束将搜索空间减小到更易于管理的大小。对工作时间和夜班的限制似乎适合于这种搜索空间限制。然后剩下数百种候选解决方案。

要选择最佳的候选解决方案,您需要对它们进行排名。如果一个软约束比所有其他软约束具有明显的优先级,则这相当容易,例如,如果医生不能工作某个班次,那比不希望工作该班次的医生更重要。但是我无法为您决定这些规则-这是一项管理决定。如果两个软约束没有明确的优先顺序,则更加困难,在这种情况下,您将不得不提出某种成本函数,以将两个约束在单个度量标准中的重要性统一起来。


我可能会构造一个贪婪算法,根据一些优先标准填充空白时间表。这可能不是最理想的解决方案,但是比对“最佳”的实际含义进行哲学思考要容易得多。

第一步,您可以填写周末的夜班,并尝试选择最长的时间没有进行周末夜班的医生,还要考虑到“我不能在那里工作”的用户意愿。假设这些愿望是每周一次且不连续的,这意味着下周将挑选一位不能在周末晚上工作的医生。

其他夜晚也可以使用类似的步骤:尝试尊重用户的意愿后,根据谁没有在最长时间内不做夜班来填补医生。对于第三种时隙,该过程类似地重复,即白昼。如果无法协调两个用户的愿望,则可以跟踪用户的愿望被授予的频率,然后以较少的已批准的愿望对医生进行优先排序。

不幸的是,我可以看到几种使用该系统的方法:例如,如果医生被选为周末夜班,但提出“不能在那里工作”的要求,则他们的选择将推迟一周-减少他们的工作量。周末晚上上班的频率要付出同事的代价。如果实施了希望解决程序来查看被拒绝请求的数量,则用户可以输入几个不可能的请求来增强他们想要通过的一个请求。但是,假设具有良好的信誉(以及医生之间相互交换班次的灵活性),则这种算法应能提供足够好的解决方案。


感谢您的回答,我将与我的同事进一步探讨该问题:)为了给您提供更多信息:是的,我们可以对大多数解决方案/标准进行排名,并且可以确定某些解决方案/标准是否优先于其他解决方案/标准。而且,他们现在确实在真诚地工作,而且运作良好。他们是手工操作,请勿过多使用“我无法工作”。因为现在他们真的是手工完成,所以他们现在如何使它工作起来真是太好。因此,一种“可行的”解决方案已经对他们意味着世界,并为他们节省了很多人可以在何时进行工作的集思广益时间
吉尔·桑德

5
@Zil当前正在创建时间表的人们可能已经在使用非正式算法。您可以与他们交谈并尝试了解他们的决策过程,然后对其进行形式化和实施。这比建立和训练神经网络要容易得多。
阿蒙(Amon)

这是我们的第一步:p我们已经与他们开会了!感谢您的所有帮助:)
吉尔·桑德

3
对于此用例,遗传学算法始终不如禁忌搜索和模拟退火,这已通过研究竞赛国际护士名册竞赛证明。(但是,当然,它们仍然比贪婪的算法要好。)
Geoffrey De Smet 2015年

12

您可以使用模拟退火

在我找到第一份工作之前,我做了类似的事情-请参阅https://vimeo.com/20610875(演示从2:50开始,算法从6:15开始解释)。

模拟退火是遗传算法的一种,也许在理论上不适合(因为@amon坚持他的回答),但在实践中效果很好,并且与您的用例差不多。

可以使用源代码(C#),但是尽管它可以正常工作,但恐怕还是很糟糕的,这是几年前的事,并且是自动翻译,我对可维护性一无所知。虽然它产生了非常好的结果。

简而言之,它是如何工作的:

  • 生成1个可能的时间表(可能不是很好,但从物理上来说可能)作为起点。在这一点上,遗传算法不是必需的-您可以蛮力寻找找到的第一个解决方案。我使用了回溯。可以通过分别解决每一天的轮换来克服计算复杂性。如果根本没有解决方案(视情况而定),则此时您可以检测到它。

  • 汇总解决方案-例如,此入门级解决方案需要100份副本作为开始。

  • 随机更改每个解决方案:让医生互相交换轮班,让随机医生离开他们的轮班,然后安排一个随机的人在上面等。

  • 使用适合度函数评估每个解决方案,该函数确定其效果如何。一个男人比另一个晚上工作更多?减去罚分。有人想星期一做,但不是吗?再次减去罚分。

  • 以20个最佳解决方案为例,并分别复制5次,用它们覆盖其余的80个,从而将其带入下一代。优胜劣汰。

  • 冲洗并重复。

数字显然是任意的,您可能需要弄弄参数才能找到适合您的方案的最佳设置。

至于解决方案的变异,模拟退火引入了一种称为温度的方法。基本上,这意味着一开始,您应该对解决方案进行相当困难的更改(例如,始终尝试进行10次交换移位的尝试),并逐渐减少后续迭代的积极性,因此它们变得更加微调(例如,向下每代只进行2次尝试调整)。


4
我在模拟时间表中使用了OptaPlanner(nee Drools Planner)和“模拟退火”。声明模型-轮班有时间和医生。为适应度函数编写声明性规则-硬约束(医生不能做重复的轮班)和惩罚(安讨厌星期一)。编写声明式(多数民众赞成!)换班。OptaPlanner将随机创建开始状态(可能不可行),根据规则计算适应度函数,甚至根据优化算法来操作交换。您可以选择和调整诸如退火计划之类的参数。
Jesvin Jose

6

遗传算法确实适用于此。在我的本科课程期间,我的一位同事写了一篇关于您非常相似的问题的论文。

您可以查找Job Shop计划,Open Shop计划Flow Shop计划可能是有趣的起点

要使用遗传算法,您不需要完美的解决方案,您可以从N个随机候选项开始,并对每个候选项应用适应度函数,例如:

  • 最忙碌的医生与工作较少的忙碌之间分配的夜数之差是成本函数的损失
  • 每次医生每周工作5天以上或每周工作1晚以上,您将受到罚款
  • 您的每个约束,等等...

生成N个候选者时,您会从中选出X个最好的候选者,它们将成为约束更少的对象。与它们一起工作,跨越变异几代人可以得到一个很好的解决方案。

讲完所有这些之后,每当我使用遗传算法,该遗传算法更多地依赖变异而不是杂交时,我可以开发出模拟退火,该退火算法的性能要好得多,并且实现起来也更容易。遗传算法的成本/适合度和变异函数可能与模拟退火中使用的非常相似。我将从这里开始,看看@Konrad Morawski答案

Google搜索为Job Shop和GA找到了不错的结果

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.