问题描述:
我有n
个优先约束作业和m
个独立计算机。每个作业都分配了成本c
(以1
时间单位完成作业所需的计算机数量)。完成一项工作需要1
时间单位,只有在c
机器被分配给它的情况下才能完成工作(工作是原子的,不可能完成一半的工作)
简而言之,有n
个工作及其优先约束,m
个机器和截止日期d
(一定数量的时间单位)。
我的目标:
我想检查是否可以将作业分配给计算机,以便所有作业在d
时间单位内完成。如果可以,那么我想打印出一个时间表,为每个作业分配一个时间单位(处理作业的时间单位,见下面的例子)。
示例:
n = 5; // number of jobs
m = 6; // number of machines
d = 4; // deadline (number of time units in which the jobs need to be finished)
Precedences: (read "Job(x,y)<--Job(q,p)" as "job x with cost y needs to be
finished before job q with cost p can be started")
Job(3,1)<--Job(2,3)<--Job(1,4)
Job(5,3)<--Job(4,3)
Job(6,1)
The solution: in this case it's possible to assign jobs to machines such that each job
finishes in <=d time units.
A possible schedule is 1 2 3 3 4 1.
(read schedule as "job 1 and job 6 are done in the first time unit, job 2
is done during the second time unit, jobs 3 and 4 during the third time unit,
job 5 during the fourth time unit")
我目前的做法:(第二次尝试感谢@Ole V.V。反例)
我想做一个回溯方法(我能提出的最佳方法)。目前我在实施它时遇到了麻烦。
我想存储作业及其优先顺序。然后我确定一个集合A,其中包含可以在当前时间单位内解决的所有作业。然后我找到一个集合B(它包含我考虑在此时间单位内解决的所有作业集),其中包含A的所有子集,这些子集可用有限数量的机器m
解决,这样就不能添加其他作业对于每个子集(通过向其中一个子集添加作业,该子集中所有作业的成本超过&#39; m&#39;)。然后我重复这个过程,但没有解决的作业(A \ B),我对B中的每个子集做一个递归调用。当传递的剩余作业集(A \ B)为空(所有作业都已完成)时,我停止如果递归深度为&lt; = d
(如果符合截止日期),则返回找到的计划。
@Ole V.V提供的示例中此方法的示例。 :
步骤是指递归的深度,方框是指作业(第一个数字是作业ID,第二个是时间单位的成本。在步骤0,我明确地写出了子集(我考虑解决的工作集)这一步)。
现在我的问题是存储作业及其优先级,找到可以在当前时间单位中解决的作业(设置A),找到我认为在当前时间单位中解决的作业子集(集B),并将它们放在一个递归函数中,最终输出找到的时间表或者没有找到时间表&#34;如果没有符合截止日期的时间表。
答案 0 :(得分:1)
我相信你贪婪的算法并不总能给你正确的结果。
采取:
Job 1 costs 3
Job 2 costs 3
Job 3 costs 1
Job 4 costs 5
Job 5 costs 1
机器数量是7。
优先顺序是
#1 before #5
#2 before #5
#4 before #3 before #5
截止日期是3。
我相信你的算法会选择
Step 1 jobs 1, 2, total cost 6
Step 2 job 4 cost 5
Step 3 job 3 cost 1
现在作业5尚未运行且已达到截止日期。你的程序会说这是不可能的。
可以使用以下时间表
Step 1 job 4 cost 5
Step 2 jobs 1, 2, 3 total cost 7
Step 3 job 5 cost 1
答案 1 :(得分:1)
您正在考虑的问题显然是NP难度,我们可以从partition problem进行减少,如下所示: 想象一下你有整数s1,s2 ......,sn的分区问题。目的是找到这个集合的分区为两个集合S1和S2,使得S1上的和等于S2的总和。
我们可以通过为每个整数(其成本是整数的值)定义作业来将此问题转换为您的问题,并且我们添加一个额外的作业,必须在所有其他作业之后完成。我们设置d = 3
当且仅当问题有解决方案时,我们才能轻松地显示分区问题的解决方案,因此您的问题是NP难的。
答案 2 :(得分:0)
你的方法似乎很好,但我相信有一种更简单的方法。我建议你使用constraint saisfaction方法。有很多方法可以解决您的问题,例如: mixed-integer programming,MaxSAT。您的任务似乎相当简单,并且您确定不会有任何大数字,因此您可以尝试Minizinc。例如,考虑this调度示例。
如果我们讨论特定于Java的工具,请查看Choco solver。