我的问题是关于 cplex 中的资源约束项目调度问题代码。我正在尝试对其应用抢占
My question is about Resource constraint Project Scheduling Problem code in cplex. I am trying to apply Preemption to it
我正在研究 RCPSP 并想对其应用抢占。
我将每项任务的持续时间分成相等的部分。这样做之后,我无法将优先级约束应用于任务的每个单独单位持续时间。
using CP;
int NbTasks = ...;
int NbRsrcs = ...;
range RsrcIds = 1..NbRsrcs;
int Capacity[r in RsrcIds] = ...;
tuple Task {
key int id;
int pt;
int dmds[RsrcIds];
{int} succs;
{int} pred;
}
{Task} Tasks=...;
tuple sub_task {
Task task;
int p_no;
}
{sub_task} sub_activities = {<t,i > | t in Tasks, i in 1..t.pt };
dvar interval itvs[t in Tasks] size t.pt;
dvar interval a[p in sub_activities] size 1;
cumulFunction rsrcUsage[r in RsrcIds] =
sum (p in sub_activities: p.task.dmds[r]>0) pulse(a[p], p.task.dmds[r]);
minimize max(t in Tasks) endOf(itvs[t]);
subject to {
forall (r in RsrcIds)
rsrcUsage[r] <= Capacity[r];
forall (t1 in Tasks, t2id in t1.succs)
endBeforeStart(itvs[t1], itvs[<t2id>]);
}
execute {
for (var p in sub_activities) {
writeln("subactivity of " + p.task.id + " - " + p.p_no + " starts at " + a[p].start + " Ends at " + a[p].end);
}
}
提前致谢。
首先,您应该添加一些约束,说明由区间 itvs[t] 表示的每个任务跨越单个活动集合 a[],例如:
span(itvs[t], all(i in 1..t.pt) a[])
然后,假设给定任务 t 的各个活动形成了一个链,具有如下约束:
endBeforeStart(a[],[])
但请注意,对于问题的这个先发制人版本,您将失去 CP Optimizer 的主要兴趣之一,即它避免了时间枚举。在这里,如果任务是完全抢占式的,则必须将持续时间为 D 的每个任务划分为 D 个单独的活动。如果您知道您对任务的抢占有一些限制(例如每个人 activity 的最小持续时间大于时间单位),则可以在模型中利用它来创建更少的子活动。
我认为您的模型缺少一个重要的约束条件,即任务不同部分的持续时间总和等于任务处理时间。类似于:
forall (t in Tasks) {
sum(p in sub_activities: p.task==t) lengthOf(a[p]) == t.pt;
}
此外,考虑到整数除法会将结果四舍五入,您可能会错过一些子活动,所以我宁愿使用类似的东西:
{sub_task} sub_activities = {<t,i > | t in Tasks, i in 1..1+(t.pt div t.smin )};
此外,跨任务的大小不能t.pt,但如果允许抢占会更大,所以它应该是这样的:
dvar interval itvs[t in Tasks] size t.pt..H; // H being a large number
最后(但这只是为了稍微加快分辨率),您可以使用任务跨越间隔而不是部分(这将涉及更少的变量)重新制定 objective 中的 makespan 表达式):
minimize max(t in Tasks) endOf(itvs[t]);
此外,如果你的部分有最大持续时间,你需要防止两个连续的部分连续(否则,我想它会被认为是同一部分),所以部分的区间变量链应该有最小延迟 1:
forall(p in sub_activities){
forall(s in sub_activities: s.task==p.task && s.p_no==p.p_no+1){
endBeforeStart(a[p],a[s],1);
presenceOf(a[s])=> presenceOf(a[p]);
}
}
我正在研究 RCPSP 并想对其应用抢占。
我将每项任务的持续时间分成相等的部分。这样做之后,我无法将优先级约束应用于任务的每个单独单位持续时间。
using CP;
int NbTasks = ...;
int NbRsrcs = ...;
range RsrcIds = 1..NbRsrcs;
int Capacity[r in RsrcIds] = ...;
tuple Task {
key int id;
int pt;
int dmds[RsrcIds];
{int} succs;
{int} pred;
}
{Task} Tasks=...;
tuple sub_task {
Task task;
int p_no;
}
{sub_task} sub_activities = {<t,i > | t in Tasks, i in 1..t.pt };
dvar interval itvs[t in Tasks] size t.pt;
dvar interval a[p in sub_activities] size 1;
cumulFunction rsrcUsage[r in RsrcIds] =
sum (p in sub_activities: p.task.dmds[r]>0) pulse(a[p], p.task.dmds[r]);
minimize max(t in Tasks) endOf(itvs[t]);
subject to {
forall (r in RsrcIds)
rsrcUsage[r] <= Capacity[r];
forall (t1 in Tasks, t2id in t1.succs)
endBeforeStart(itvs[t1], itvs[<t2id>]);
}
execute {
for (var p in sub_activities) {
writeln("subactivity of " + p.task.id + " - " + p.p_no + " starts at " + a[p].start + " Ends at " + a[p].end);
}
}
提前致谢。
首先,您应该添加一些约束,说明由区间 itvs[t] 表示的每个任务跨越单个活动集合 a[
然后,假设给定任务 t 的各个活动形成了一个链,具有如下约束:
endBeforeStart(a[
但请注意,对于问题的这个先发制人版本,您将失去 CP Optimizer 的主要兴趣之一,即它避免了时间枚举。在这里,如果任务是完全抢占式的,则必须将持续时间为 D 的每个任务划分为 D 个单独的活动。如果您知道您对任务的抢占有一些限制(例如每个人 activity 的最小持续时间大于时间单位),则可以在模型中利用它来创建更少的子活动。
我认为您的模型缺少一个重要的约束条件,即任务不同部分的持续时间总和等于任务处理时间。类似于:
forall (t in Tasks) {
sum(p in sub_activities: p.task==t) lengthOf(a[p]) == t.pt;
}
此外,考虑到整数除法会将结果四舍五入,您可能会错过一些子活动,所以我宁愿使用类似的东西:
{sub_task} sub_activities = {<t,i > | t in Tasks, i in 1..1+(t.pt div t.smin )};
此外,跨任务的大小不能t.pt,但如果允许抢占会更大,所以它应该是这样的:
dvar interval itvs[t in Tasks] size t.pt..H; // H being a large number
最后(但这只是为了稍微加快分辨率),您可以使用任务跨越间隔而不是部分(这将涉及更少的变量)重新制定 objective 中的 makespan 表达式):
minimize max(t in Tasks) endOf(itvs[t]);
此外,如果你的部分有最大持续时间,你需要防止两个连续的部分连续(否则,我想它会被认为是同一部分),所以部分的区间变量链应该有最小延迟 1:
forall(p in sub_activities){
forall(s in sub_activities: s.task==p.task && s.p_no==p.p_no+1){
endBeforeStart(a[p],a[s],1);
presenceOf(a[s])=> presenceOf(a[p]);
}
}