Originally posted by: PhilippeLaborie
Yes indeed, the problem coms from this constraint ct5:
ct5: presenceOf(opr[o][t]) == 1 => resSt[o][t] == resEd[o][typeOfPrev(seq[o],opr[o][t],Capacity[o],0)]; //St_resource = Ed_resource of previous task.
This constraint says that the level at the start time of a task is equal to the level at the send time of the previous task (which is what you want), but for the first interval in the sequence, the value of the expression will be Capacity[o], but Capacity[o] is a capacity value and it cannot be used to index an array indexed on task identifier.
You could have a special index (typically 0) for a (non-existing) task that is before the first actual task. For that you just need to index the variables resSt and resEd starting from 0 instead of 1. And then specify a return value of 0 for typeOfPrev(seq[o],opr[o][t]) when the interval is first.
Additionally, I think it would be more efficient to avoid as much as possible the meta-constraints presenceOf(opr[o][t]) => XXX and instead leverage the notion of optionality. When you know that the right side of the implication is satisfied when the interval is absent, you do not need to write the left side condition presenceOf(opr[o][t]) =>.
You can also limit the domain of the variables if you know a reasonable bound. And for instance here I suppose you want that the level of the resource never exceeds Capacity. Same for the horizon of the schedule if you know a reasonable one.
Here is how I would reformulate your model:
using CP;
range Tasks=1..10;
range Operators=1..2;
int Qty[Tasks]=[20,20,40,130,80,70,30,60,40,100];
int Capacity[Operators]=[50,70];
int RepTime[Operators]=[5,7];
int Horizon = 1000;
dvar interval opr[o in Operators][t in Tasks] optional in 0..Horizon size 1..Horizon;
dvar sequence seq[o in Operators] in all(t in Tasks) opr[o][t] types all(t in Tasks) t;
dvar int+ rep[o in Operators][t in Tasks];
dvar int+ resSt[o in Operators][t in 0..10] in 0..Capacity[o];
dvar int+ resEd[o in Operators][t in 0..10] in 0..Capacity[o];
minimize max(o in Operators, t in Tasks) endOf(opr[o][t]);
subject to{
forall(o in Operators) {
resSt[o][0] == 0;
resEd[o][0] == 0;
}
forall(o in Operators, t in Tasks){
ct1: !presenceOf(opr[o][t]) => ( (rep[o][t] == 0) && (resSt[o][t] == 0) && (resEd[o][t] == 0));
ct4: resEd[o][t] == resSt[o][t] + rep[o][t]*Capacity[o] - (sizeOf(opr[o][t]) - rep[o][t]*RepTime[o]);
ct5: resSt[o][t] == resEd[o][typeOfPrev(seq[o],opr[o][t],0,0)];
ct6: noOverlap(seq[o]);
}
forall(t in Tasks) {
ct7: Qty[t] == sum(o in Operators) (sizeOf(opr[o][t]) - rep[o][t]*RepTime[o]); //All tasks are operated for enough duration
}
}
#ConstraintProgramming-General#DecisionOptimization