I developed this code using OPL with Cplex for the Multi-Skill Resource-Constrained Project Scheduling Problem (MS-RCPSP), and it performs well when each task is assigned a single predecessor. Now, I aim to enhance the code to handle multiple predecessors for each task. I would greatly appreciate any assistance in achieving this. Thank you in advance.
// Example data
range J = 1..5;//set of tasks
range R = 1..3;//set of resources
range T = 1..6;//index of time
range S = 1..3;//index of skills
range K = 1..3;//Number of resources
//{int} J =asSet(1..5);
//setof(int) P[J] = [{0}, {0}, {0}, {2,3}, {0}];
int P[J] = [0,0,0,2,0]; //the set of the predecessor tasks of Tj
int d[J] = [2,1,3,3,1]; //duration of Task j
int s[J] = [0,0,2,1,0]; //starting time of Task j
// Resource usage matrix
int L[J][K] = [[0,1,0], [2,0,0], [0,0,2], [1,0,0], [0,0,1]]; //the required familiarity level of Sk for Tj
int Q[R][K] = [[0,1,2], [2,2,0], [1,0,1]]; //the level that Rr masters Sk
// Decision Variables
dvar boolean x[J][R]; //decision variable to determine whether Tj is assigned to R
dvar boolean y[J][R][T]; //decision variable to determine whether Tj is executed by Rr at time t
minimize max(j in J) (s[j] + d[j]);
subject to {
forall(i in J)
ct1: s[i] >= max(j in J : P[i]!=0 ) (s[P[i]] + d[P[i]]); //guarantees that the precedence constraints should be satisfied by all the tasks
forall(j in J, k in S)
ct2: sum(r in R) x[j][r] * Q[r][k] >= L[j][k]; //denotes that each task can only be processed by the capable resources
forall(j in J)
ct3: sum(r in R) x[j][r] == 1; //ensures that each task should be processed once
forall(j in J, r in R, t in T)
ct4: sum(j in J) y[j][r][t] <= 1;//each resource can process at most one task at a time
}
execute{
writeln("The value of the objective function is: " + cplex.getObjValue());
}
You can start with
// Example data
range J = 1..5;//set of tasks
range R = 1..3;//set of resources
range T = 1..6;//index of time
range S = 1..3;//index of skills
range K = 1..3;//Number of resources
//{int} J =asSet(1..5);
//setof(int) P[J] = [{0}, {0}, {0}, {2,3}, {0}];
{int} P[J] = [{},{},{},{2},{}]; //the set of the predecessor tasks of Tj
int d[J] = [2,1,3,3,1]; //duration of Task j
int s[J] = [0,0,2,1,0]; //starting time of Task j
// Resource usage matrix
int L[J][K] = [[0,1,0], [2,0,0], [0,0,2], [1,0,0], [0,0,1]]; //the required familiarity level of Sk for Tj
int Q[R][K] = [[0,1,2], [2,2,0], [1,0,1]]; //the level that Rr masters Sk
// Decision Variables
dvar boolean x[J][R]; //decision variable to determine whether Tj is assigned to R
dvar boolean y[J][R][T]; //decision variable to determine whether Tj is executed by Rr at time t
minimize max(j in J) (s[j] + d[j]);
subject to {
forall(i in J) forall(p in P[i])
//ct1:
s[i] >= (s[p] + d[p]); //guarantees that the precedence constraints should be satisfied by all the tasks
forall(j in J, k in S)
ct2: sum(r in R) x[j][r] * Q[r][k] >= L[j][k]; //denotes that each task can only be processed by the capable resources
forall(j in J)
ct3: sum(r in R) x[j][r] == 1; //ensures that each task should be processed once
forall(j in J, r in R, t in T)
ct4: sum(j in J) y[j][r][t] <= 1;//each resource can process at most one task at a time
}
execute{
writeln("The value of the objective function is: " + cplex.getObjValue());
}