实际解决因子复杂性问题(调度程序)

时间:2013-06-19 10:35:00

标签: .net algorithm sorting complexity-theory big-o

鉴于我有这个O(n!)调度问题:

  • 有10个具有不同持续时间的任务,我想在5周的工作周内安排
  • 每天有8个工作小时,分为15分钟。插槽(1天= 8小时= 32个插槽)
  • 任务在“允许的日期和时间范围”方面有不同的要求(例如,任务可能只允许在星期四早上8点到9点之间,另一个只在星期一,星期二和星期三上午10点到11点之间)

请求结果 应该有尽可能多的“连续空闲时段”,以便以后分配更多/其他任务

当前解决方案: 我尝试通过BFS / DFS解决方案组合所有可能的插槽,然后找到最佳组合,没有重叠任务和“最大的空闲插槽块”。由于O(n!)复杂性,该解决方案在性能和/或记忆方面使我丧失。

问题: 什么是计算机科学提供的最“合理”的方法(或者你之前解决了这样的问题),以便在有限的时间内解决这个问题。

6 个答案:

答案 0 :(得分:3)

以下是一些可以相对容易地添加到深度优先搜索方法中的东西,它首先探索了最有前途的孩子:

1)有限差异搜索 - 基本上你通过在探索作为其节点的第x个最佳孩子的孩子时累积x惩罚点来对部分扩展解进行评分,并且丢弃累积超过总惩罚阈值的部分解决方案点。搜索短语有限差异搜索应该会给你很多点击。这至少应该阻止你的搜索运行n!秒。

2)鉴于可能存在非法的推定解决方案,请将其作为爬山过程的开始来改进它,或者至少尝试使其合法化。无论如何,您需要这样做,以消除您的程序生成解决方案的可能性,用户可以在其中找到微不足道的改进。

答案 1 :(得分:2)

您可以使用OptaPlanner解决此问题,这是开源的。

另一种选择是使用贪婪算法快速找到解决方案,首先调度最受约束的任务,最后调度最少约束的任务。接下来,使用local search来a。让贪婪的解决方案有效,b。改善贪心的解决方案。例如,贪婪的解决方案可能会为您留下未计划的任务,因此本地搜索会取消计划冲突的任务并在其位置安排未计划的任务,然后重新计划新的未计划任务。

答案 2 :(得分:1)

我会使用(递归)回溯,因为对任务的限制(允许的日期和时间范围)。

来自维基百科(http://en.wikipedia.org/wiki/Backtracking):

  

回溯是查找所有(或部分)的通用算法   一些计算问题的解决方案,逐步建立   候选人的解决方案,并放弃每个部分候选人c   (“回溯”)一旦确定c不可能   完成了有效的解决方案。

为了你的问题。我想说,让我们为每个任务分配可能的日程安排。这是一般解决方案。

M [level]表示子问题(R [level])

的可能解决方案的集合
Backtracking(level = 0, result={0})
i = 0
Do
    i = i + 1 
    //With i - iterate over the possible solutions to result[level] (iterate over M[level])
    If(R[i] is a good result candidate) 
        k = 1
        While(k<level AND (R[k],R[i] are good solutions together)) k++
        If(k == level) //R[i] is a good result, it's in harmony with the results found before
            result[level] = R[i]
            If(level == N)
                bestResult = Max/Min(bestResult,result)
            Else
                Backtracking(level+1,result) //Backtracks
While(i<M[level])

答案 3 :(得分:0)

可能需要考虑简单的AI,例如https://en.wikipedia.org/wiki/Support_vector_machine

您可以选择一些图书馆:

Support Vector Machine library for C#

此外,Boli has a good solution(递归回溯)。请参阅评论以获取示例视频。

答案 4 :(得分:0)

你的数字非常小,这看起来像是一个蛮力方法的候选者,可以解决映射到一定程度的成功(效用)函数的所有可能的解决方案。

答案 5 :(得分:-1)

我总是喜欢为问题创建自定义解决方案,而不是依赖于通用方法。在这种特定的情况下,问题定义得很清楚,我认为有一个快速可靠的迭代过程可以相对容易地定义:通过遵循“填充天数”的想法将分析基于任务的顺序分配。完成。

该算法将迭代可用的(5)天,将与分配的每个任务相关联的时间相加,并将得到的加法与给定日期的剩余可用时间进行比较。它将包含两个主要部分:


  1. 优先级最高的分配。在开始时,算法将计算给定日期的“灵活性”:它将累计必须在给定日期完成的任务的所有时间段。如果他们消耗所有可用时间,所有这些任务的分配将立即完成,并将直接跳到第二天。在有可用时间的情况下,算法只会为任务分配详细的(时间/日)定义;示例:要在星期一执行的任务,包括给定的时段(例如,9到9:15)。在完成所有详细定义任务的分配之后,它将累计在给定日期剩余任务所需的全部时间;这个值是我在下面称为“当天的剩余”;属于该组的任务(即,在指定日期完成的未分配任务)将被标记,以便下一个点可以正确处理它们。

  2. 默认偏好规则。如果未在上述点中分配给定日期的所有可用时间,则将通过应用通用偏好规则系统来开始所有任务(不属于在给定日期标记的上述任务)的新迭代。 (如下例所示)。在分配任何新任务之前,该算法将检查是否还有足够的时间来考虑所有“当天的剩余”。如果要分配的新任务耗尽可用时间(即,避免分配“当天剩余”),算法将继续迭代“首选任务”(不属于“剩余任务”)当天“)直到找到一个其分配不会耗尽可用时间的人。如果没有找到这样的任务,将立即分配属于“当天剩余”的所有任务,算法将跳到第二天。

  3. 第2点的优惠规则示例:星期一9至9:15;首先检查分配到特定时间的任务,当天是独立的(这不是星期一,因为这些情况已由第1点管理);然后是星期一可能完成的最大任务(更多的插槽)。在最后情况下(例如,在按大小开始最后排序的情况下,任务X将具有星期一的最大优先级的情况下)也可以为任务创建排名。


    上面描述的算法(或这些行中的任何其他算法)代表了我可以针对您遇到的问题提出的最快捷的选择。它主要关注速度和可靠性,因此“多个连续空闲时隙”约束并未完全优化;虽然有创造这些的倾向(主要是在本周的最后几天)。尽管如此,通过提高第2点规则的详细程度(主要是按时间大小分配的任务),可以进一步改善最后一个问题。总之,我确实认为这些方法可以为您提出的问题提供最佳解决方案。