Resource-Constrained Project Scheduling Problem

/***************************************************************/
/*                                                             */
/*          S A S   S A M P L E   L I B R A R Y                */
/*                                                             */
/*    NAME: clpe15                                             */
/*   TITLE: Resource-Constrained Project Scheduling Problem    */
/*          with Calendars (clpe15)                            */
/* PRODUCT: OR                                                 */
/*  SYSTEM: ALL                                                */
/*    KEYS: OR                                                 */
/*   PROCS: CLP                                                */
/*    DATA:                                                    */
/*                                                             */
/* SUPPORT:                             UPDATE:                */
/*     REF:                                                    */
/*    MISC: Example 15 from the CLP Procedure chapter of the   */
/*          Constraint Programming book.                       */
/*                                                             */
/***************************************************************/

data StartTime;
   input Start1-Start14 S T _TYPE_ $ _RHS_;
   datalines;
   0   0   0   0   0   0   0   0   0   0   0   0   .   .   .  10  LOWERBD   .
  40  40  40  40  40  40  40  40  40  40  40  40   .   .   .  40  UPPERBD   .
   .   .   .   .   .   .   .   .   .   .   .   .   5   6   0   .  FIXED     .
;

proc print data=StartTime;
run;

   data Precedence;
   input S Start1-Start12 T _TYPE_ $ _RHS_;
   datalines;
   -1   1   .   .   .   .   .   .   .   .   .   .   .   .  GE   0
   -1   .   1   .   .   .   .   .   .   .   .   .   .   .  GE   0
   -1   .   .   1   .   .   .   .   .   .   .   .   .   .  GE   0
   -1   .   .   .   .   .   1   .   .   .   .   .   .   .  GE   0
   -1   .   .   .   .   .   .   1   .   .   .   .   .   .  GE   0
    .  -1   .   .   1   .   .   .   .   .   .   .   .   .  GE   1
    .   .  -1   .   .   1   .   .   .   .   .   .   .   .  GE   2
    .   .   .  -1   .   .   .   .   .   .   .   .   .   1  GE   2
    .   .   .   .  -1   .   .   .   .   .   .   .   .   1  GE   6
    .   .   .   .   .  -1   .   .   .   .   .   .   .   1  GE   3
    .   .   .   .   .   .  -1   .   .   .   .   .   1   .  GE   6
    .   .   .   .   .   .   .  -1   1   .   .   .   .   .  GE   1
    .   .   .   .   .   .   .  -1   .   1   .   .   .   .  GE   1
    .   .   .   .   .   .   .  -1   .   .   1   .   .   .  GE   1
    .   .   .   .   .   .   .   .  -1   .   .   1   .   .  GE   3
    .   .   .   .   .   .   .   .   .  -1   .   .   1   .  GE   3
    .   .   .   .   .   .   .   .   .   .  -1   .   1   .  GE   4
    .   .   .   .   .   .   .   .   .   .   .  -1   1   .  GE   2
    .   .   .   .   .   .   .   .   .   .   .   .  -1   1  GE   4
    ;

proc print data=Precedence;
run;

data Objective;
   input T _TYPE_ $ _RHS_;
   datalines;
   1  MIN   .
;

proc print data=Objective;
run;

data ConData;
   set StartTime Precedence Objective;
run;




proc clp condata=ConData out=OutData usecondatavars=1;
   /* set lower and upper bounds for the objective function */
   obj lb=10 ub=40;

   /* Post a cumulative constraint for the resource */
   cumulative (start=(Start1-Start14)
               duration=(1 2 2 6 3 6 1 3 3 4 2 4 1 1)
               demand=(4 2 3 3 2 3 1 2 2 1 2 2 4 8)
               capacity=8);
run;



data durdata;
   input Dur1-Dur12;
   datalines;
   1   2   2   6   3   6   1   3   3   4   2   4
;

data demdata;
   input Dem1-Dem12;
   datalines;
   4   2   3   3   2   3   1   2   2   1   2   2
;

data SchedOut;
   set outdata;
   set durdata;
   set demdata;
   array st{12} Start1-Start12;
   array dur{12} Dur1-Dur12;
   array dem{12} Dem1-Dem12;
   do tid = 1 to 12;
      Task=tid;
      Start=st{tid};
      Duration=dur{tid};
      End=Start + Duration;
      Demand=Dem{tid};
      output;
   end;
   keep Task Start Duration End Demand;
run;

proc print data=SchedOut noobs;
run;


proc print data=SchedOut noobs;
run;

data resin;
   input per obstype $ demand;
   datalines;
   0 RESLEVEL 100
;

data indata;
   set schedout;
   atype = 'MS';
   adate = start;
;

proc cpm data=indata out=out resout=resout resin=resin;
   aligntype atype;
   aligndate adate;
   activity task;
   duration duration;
   resource demand / per=per obstype=obstype;
run;

%annomac;

proc sql noprint;
   select count(*) into :cnt from schedout;
   select max(end) into :ms from schedout;
   select min(start) into :pi from schedout;
quit;

data anno;
   %dclanno;       /* set length and type for annotate variables */
   %system(2,2,4); /* define annotate reference system           */
   set resout(where=(_time_ < &ms.)) end=lastobs;
   length lab $16;
   length TEXT $27;
   x1 = _time_;
   x2 = x1 +1;
   y1 = &cnt + 0.5;
   y2 = y1 - rdemand;
   %bar(x1,y1,x2,y2,blue,0,l1);
   if lastobs then do;
      do i = 1 to &cnt.-1;
         c = put(i,z2.);
         %label(14.2, y1 - i, c, red, 0, 0, 0.8, 'arial', 0);
      end;
      %label(14.2, y1 - 0.4 ,"RES", red,0, 0, 0.8, 'arial', 0);
      %label(14.2, y1, "LEVL", red,0, 0, 0.8, 'arial', 0);

      y2 = y1 -8;
      %line(0, y2, 5, y2, red, 1, 3);
      y2 = y2 + 4;
      %draw(5, y2, red, 1, 3);
      %draw(6, y2, red, 1, 3);
      y2 = y2 + 4;
      %draw(6, y2, red, 1, 3);
      %draw(7, y2, red, 1, 3);
      y2 = y2 - 8;
      %draw(7, y2, red, 1, 3);
      %draw(14, y2, red, 1, 3);
   end;
 run;

goptions vpos=30 ftext='arial';

proc gantt data=schedout annotate=anno;
   chart / s_start=start s_finish=end maxdate=15
           pcompress
           nolegend nojobnum height=0.8;
   id task demand;
run;




/***************************************************************/
/*                                                             */
/*          S A S   S A M P L E   L I B R A R Y                */
/*                                                             */
/*    NAME: clpe15 (part b)                                    */
/*   TITLE: Resource-Constrained Project Scheduling Problem    */
/*          with Optional Tasks                                */
/* PRODUCT: OR                                                 */
/*  SYSTEM: ALL                                                */
/*    KEYS: OR                                                 */
/*   PROCS: CLP                                                */
/*    DATA:                                                    */
/*                                                             */
/* SUPPORT:                             UPDATE:                */
/*     REF:                                                    */
/*    MISC: Example 9b from the CLP Procedure chapter of the   */
/*          Constraint Programming book.                       */
/*                                                             */
/***************************************************************/

data StartTime2;
   input Start1-Start14 S T _TYPE_ $ _RHS_;
   datalines;
   0   0   0   0   0   0   0   0   0   0   0   0   .   .   .   .  LOWERBD   .
  12  12  12  12  12  12  12  12  12  12  12  12   .   .   .   .  UPPERBD   .
   .   .   .   .   .   .   .   .   .   .   .   .   5   6   0  12  FIXED     .
;

proc print data=StartTime2;
run;

data Precedence;
   input S Start1-Start12 T _TYPE_ $ _RHS_;
   datalines;
  -1   1   .   .   .   .   .   .   .   .   .   .   .   .  GE   0
  -1   .   1   .   .   .   .   .   .   .   .   .   .   .  GE   0
  -1   .   .   1   .   .   .   .   .   .   .   .   .   .  GE   0
  -1   .   .   .   .   .   1   .   .   .   .   .   .   .  GE   0
  -1   .   .   .   .   .   .   1   .   .   .   .   .   .  GE   0
   .  -1   .   .   1   .   .   .   .   .   .   .   .   .  GE   1
   .   .  -1   .   .   1   .   .   .   .   .   .   .   .  GE   2
   .   .   .  -1   .   .   .   .   .   .   .   .   .   1  GE   2
   .   .   .   .  -1   .   .   .   .   .   .   .   .   1  GE   6
   .   .   .   .   .  -1   .   .   .   .   .   .   .   1  GE   3
   .   .   .   .   .   .  -1   .   .   .   .   .   1   .  GE   6
   .   .   .   .   .   .   .  -1   1   .   .   .   .   .  GE   1
   .   .   .   .   .   .   .  -1   .   1   .   .   .   .  GE   1
   .   .   .   .   .   .   .  -1   .   .   1   .   .   .  GE   1
   .   .   .   .   .   .   .   .  -1   .   .   1   .   .  GE   3
   .   .   .   .   .   .   .   .   .  -1   .   .   1   .  GE   3
   .   .   .   .   .   .   .   .   .   .  -1   .   1   .  GE   4
   .   .   .   .   .   .   .   .   .   .   .  -1   1   .  GE   2
   .   .   .   .   .   .   .   .   .   .   .   .  -1   1  GE   4
;

data Demand;
   input Demand1-Demand14 _TYPE_ $ _RHS_;
   datalines;
   0   0   0   0   0   .   .   .   .   .   .   .   .   .  LOWERBD   .
   4   2   3   3   2   .   .   .   .   .   .   .   .   .  UPPERBD   .
   .   .   .   .   .   2   1   1   2   1   2   2   4   8  FIXED     .
;

proc print data=Demand;
run;

data Binary;
   input X1-X3 _TYPE_ $ _RHS_;
   datalines;
   1   1   1  BINARY   .
;

proc print data=Binary;
run;

data Usage;
   input Demand1-Demand5 X1-X3 _TYPE_ $ _RHS_;
   datalines;
   1   .   .   .   .   4   .   .  EQ   4
   .   1   .   .   .   .   2   .  EQ   2
   .   .   1   .   .   .   .   3  EQ   3
   .   .   .   1   .   3   .   .  EQ   3
   .   .   .   .   1   .   2   .  EQ   2
;

proc print data=Usage;
run;

data Objective2;
   input X1-X3 _TYPE_ $ _RHS_;
   datalines;
  15  12   5  MIN   .
;

proc print data=Objective2;
run;

data ConData2;
   set StartTime2 Precedence Demand Binary Usage Objective2;
run;


proc clp condata=ConData2 out=OutData2 usecondatavars=1;
   /* set lower and upper bounds for the objective function */
   obj lb=0 ub=32;

   /* Define a cumulative constraint for the resource */
   cumulative (start=(Start1-Start14)
               demand=(Demand1-Demand14)
               dur=(1 2 2 6 3 6 1 3 3 4 2 4 1 1)
               capacity=8);
run;



data durdata;
   input Dur1-Dur12;
   datalines;
   1   2   2   6   3   6   1   3   3   4   2   4
;

data SchedOut2;
   set outdata2;
   set durdata;
   array st{12} Start1-Start12;
   array dur{12} Dur1-Dur12;
   array dem{12} Demand1-Demand12;
   do tid = 1 to 12;
      Task=tid;
      Start=st{tid};
      Duration=dur{tid};
      End=Start + Duration;
      Demand=dem{tid};
      if Demand > 0 then output;
   end;
   keep Task Start Duration End Demand;
run;

proc print data=SchedOut2 noobs;
run;