Search code examples
mathematical-optimizationcplexopl

MS-RCPSP in OPL, CPLEX, adding multiple predecessors for a task


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());
}


Solution

  • 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());
    }