The CPM Procedure

Example 4.23 Multiproject Scheduling

This example illustrates multiproject scheduling. Consider a Survey project that contains three phases, Plan, Prepare, and Implement, with each phase containing more than one activity. You can consider each phase of the project as a subproject within the master project, Survey. Each subproject in turn contains the lowest level activities, also referred to as the leaf tasks. The Activity data set, containing the task durations, project hierarchy, and the precedence constraints, is displayed in Output 4.23.1.

The PROJECT and ACTIVITY variables together define the project hierarchy using the parent/child relationship. Thus, the subproject, 'Plan', contains the two leaf tasks, 'plan sur' and 'design q'. Precedence constraints are specified between leaf tasks as well as between subprojects. For example, the subproject 'Prepare' is followed by the subproject 'Implement'. Durations are specified for all the tasks in the project, except for the master project 'Survey'.

In addition to the Activity data set, define a Holiday data set, also displayed in Output 4.23.1.

Output 4.23.1: Survey Project

Survey Project
Activity Data Set SURVEY

Obs id activity duration succ1 succ2 succ3 project
1 Plan Survey plan sur 4 hire per design q   Plan
2 Hire Personnel hire per 5 trn per     Prepare
3 Design Questionnaire design q 3 trn per select h print q Plan
4 Train Personnel trn per 3       Prepare
5 Select Households select h 3       Prepare
6 Print Questionnaire print q 4       Prepare
7 Conduct Survey cond sur 10 analyze     Implement
8 Analyze Results analyze 6       Implement
9 Plan Plan 6       Survey
10 Prepare Prepare 8 Implement     Survey
11 Implement Implement 18       Survey
12 Survey Project Survey .        

Survey Project
Holiday Data Set HOLIDATA

Obs hol
1 09APR04



The following statements invoke PROC CPM with a PROJECT statement identifying the parent task for each subtask in the Survey project. The calendar followed is a weekday calendar with a holiday defined on April 9, 2004. The ORDERALL option on the PROJECT statement creates the ordering variables ES_ASC and LS_ASC in the Schedule data set, and the ADDWBS option creates a work breakdown structure code for the project. The Schedule data set is displayed in Output 4.23.2, after being sorted by the variable ES_ASC.

The PROJ_DUR variable is missing for all the leaf tasks, and it contains the project duration for the supertasks. The project duration is computed as the span of all the subtasks of the supertask. The PROJ_LEV variable specifies the level of the subtask within the tree defining the project hierarchy, starting with the level '0' for the master project (or the root), 'Survey'. The variable WBS_CODE contains the Work Breakdown Structure code defined by the CPM procedure using the project hierarchy.

proc cpm data=survey date='29mar04'd out=survout1
         interval=weekday holidata=holidata;
   activity   activity;
   successor  succ1-succ3;
   duration   duration;
   id         id;
   holiday    hol;
   project    project / orderall addwbs;
   run;

proc sort;
   by es_asc;
   run;

title 'Conducting a Market Survey';
title2 'Early and Late Start Schedule';
proc print;
   run;

Output 4.23.2: Survey Project Schedule

Conducting a Market Survey
Early and Late Start Schedule

O
b
s
p
r
o
j
e
c
t
P
R
O
J
_
D
U
R
P
R
O
J
_
L
E
V
W
B
S
_
C
O
D
E
a
c
t
i
v
i
t
y
s
u
c
c
1
s
u
c
c
2
s
u
c
c
3
d
u
r
a
t
i
o
n
i
d
E
_
S
T
A
R
T
E
_
F
I
N
I
S
H
L
_
S
T
A
R
T
L
_
F
I
N
I
S
H
T
_
F
L
O
A
T
F
_
F
L
O
A
T
E
S
_
A
S
C
L
S
_
A
S
C
1   28 0 0 Survey       . Survey Project 29MAR04 06MAY04 29MAR04 06MAY04 0 0 0 0
2 Survey 7 1 0.0 Plan       6 Plan 29MAR04 06APR04 29MAR04 07APR04 1 1 1 1
3 Plan . 2 0.0.0 plan sur hire per design q   4 Plan Survey 29MAR04 01APR04 29MAR04 01APR04 0 0 2 2
4 Plan . 2 0.0.1 design q trn per select h print q 3 Design Questionnaire 02APR04 06APR04 05APR04 07APR04 1 0 3 3
5 Survey 8 1 0.1 Prepare Implement     8 Prepare 02APR04 14APR04 02APR04 14APR04 0 0 4 4
6 Prepare . 2 0.1.0 hire per trn per     5 Hire Personnel 02APR04 08APR04 02APR04 08APR04 0 0 5 5
7 Prepare . 2 0.1.2 select h       3 Select Households 07APR04 12APR04 12APR04 14APR04 2 2 6 8
8 Prepare . 2 0.1.3 print q       4 Print Questionnaire 07APR04 13APR04 08APR04 14APR04 1 1 7 6
9 Prepare . 2 0.1.1 trn per       3 Train Personnel 12APR04 14APR04 12APR04 14APR04 0 0 8 7
10 Survey 16 1 0.2 Implement       18 Implement 15APR04 06MAY04 15APR04 06MAY04 0 0 9 9
11 Implement . 2 0.2.0 cond sur analyze     10 Conduct Survey 15APR04 28APR04 15APR04 28APR04 0 0 10 10
12 Implement . 2 0.2.1 analyze       6 Analyze Results 29APR04 06MAY04 29APR04 06MAY04 0 0 11 11



Next, a Gantt chart of the master project schedule is produced with the subtasks of each project indented under the parent task. To produce the required indentation, prefix the Activity description (saved in the variable id) by a suitable number of blanks using a simple DATA step. The following program shows the DATA step and the invocation of the GANTT procedure; the resulting Gantt chart is plotted in Output 4.23.3. Note the precedence constraints between the two supertasks 'Prepare' and 'Implement'.

data gant;
length id $26.;
set survout1;
if proj_lev=1 then id="   "||id;
else if proj_lev=2 then id="      "||id;
run;

goptions hpos=80 vpos=43;
title c=black h=2 'Conducting a Market Survey';
title2 c=black h=1.5 'Project Schedule';
proc gantt graphics data=gant holidata=holidata;
   chart / holiday=(hol)
           interval=weekday
           skip=2 height=1.8
           nojobnum
           compress noextrange
           activity=activity succ=(succ1-succ3)
           cprec=cyan cmile=magenta
           caxis=black;
   id   id;
   run;

Output 4.23.3: Gantt Chart of Schedule

Gantt Chart of Schedule


PROJ_LEV, WBS_CODE, and other project-related variables can be used to display selected information about specific subprojects, summary information about subprojects at a given level of the hierarchy, and more. For example, the following statements display the summary schedule of the first level subtasks of the Survey project (Output 4.23.4).


title 'Market Survey';
title2 'Summary Schedule';
proc print data=survout1;
   where proj_lev=1;
   id activity;
   var proj_dur duration e_start--t_float;
   run;

Output 4.23.4: Survey Project Summary

Market Survey
Summary Schedule

activity PROJ_DUR duration E_START E_FINISH L_START L_FINISH T_FLOAT
Plan 7 6 29MAR04 06APR04 29MAR04 07APR04 1
Prepare 8 8 02APR04 14APR04 02APR04 14APR04 0
Implement 16 18 15APR04 06MAY04 15APR04 06MAY04 0



The variable WBS_CODE in the Schedule data set (see Output 4.23.2) contains the Work Breakdown structure code defined by the CPM procedure. This code is defined to be '0.1' for the subproject 'Prepare'. Thus, the values of WBS_CODE for all subtasks of this subproject are prefixed by '0.1'. To produce reports for the subproject 'Prepare', you can use a simple WHERE clause to subset the required observations from the Schedule data set, as shown in the following statements.


title 'Market Survey';
title2 'Sub-Project Schedule';
proc print data=survout1;
   where substr(WBS_CODE,1,3) = "0.1";
   id activity;
   var project--activity duration e_start--t_float;
   run;

Output 4.23.5: Subproject Schedule

Market Survey
Sub-Project Schedule

activity project PROJ_DUR PROJ_LEV WBS_CODE activity duration E_START E_FINISH L_START L_FINISH T_FLOAT
Prepare Survey 8 1 0.1 Prepare 8 02APR04 14APR04 02APR04 14APR04 0
hire per Prepare . 2 0.1.0 hire per 5 02APR04 08APR04 02APR04 08APR04 0
select h Prepare . 2 0.1.2 select h 3 07APR04 12APR04 12APR04 14APR04 2
print q Prepare . 2 0.1.3 print q 4 07APR04 13APR04 08APR04 14APR04 1
trn per Prepare . 2 0.1.1 trn per 3 12APR04 14APR04 12APR04 14APR04 0



In the first invocation of PROC CPM, the Survey project is scheduled with only a specification for the project start date. Continuing, this example shows how you can impose additional constraints on the master project or on the individual subprojects.

First, suppose that you impose a FINISHBEFORE constraint on the Survey project by specifying the FBDATE to be May 10, 2004. The following program schedules the project with a project start and finish specification. The resulting summary schedule for the subprojects is shown in Output 4.23.6. The late finish time of the project is the 7th of May because there is a weekend on the 8th and 9th of May, 2004.

proc cpm data=survey date='29mar04'd out=survout2
         interval=weekday holidata=holidata
         fbdate='10may04'd; /* project finish date */
   activity   activity;
   successor  succ1-succ3;
   duration   duration;
   id         id;
   holiday    hol;
   project    project / orderall addwbs;
   run;

title 'Market Survey';
title2 'Summary Schedule: FBDATE Option';
proc print data=survout2;
   where proj_lev=1;  /* First level subprojects */
   id activity;
   var proj_dur duration e_start--t_float;
   run;

Output 4.23.6: Summary Schedule: FBDATE Option

Market Survey
Summary Schedule: FBDATE Option

activity PROJ_DUR duration E_START E_FINISH L_START L_FINISH T_FLOAT
Plan 7 6 29MAR04 06APR04 30MAR04 08APR04 2
Prepare 8 8 02APR04 14APR04 05APR04 15APR04 1
Implement 16 18 15APR04 06MAY04 16APR04 07MAY04 1



The procedure computes the backward pass of the schedule starting from the project finish date. Thus, the critical path is computed in the context of the entire project. If you want to obtain individual critical paths for each subproject, use the SEPCRIT option on the PROJECT statement. You can see the effect of this option in Output 4.23.7: all the subprojects have T_FLOAT = '0'.

proc cpm data=survey date='29mar04'd out=survout3
         interval=weekday holidata=holidata fbdate='10may04'd;
   activity   activity;
   successor  succ1-succ3;
   duration   duration;
   id         id;
   holiday    hol;
   project    project / orderall addwbs sepcrit;
   run;


title 'Market Survey';
title2 'Summary Schedule: FBDATE and SEPCRIT Options';
proc print data=survout3;
   where proj_lev=1;
   id activity;
   var proj_dur duration e_start--t_float;
run;

Output 4.23.7: Summary Schedule: FBDATE and SEPCRIT Options

Market Survey
Summary Schedule: FBDATE and SEPCRIT Options

activity PROJ_DUR duration E_START E_FINISH L_START L_FINISH T_FLOAT
Plan 7 6 29MAR04 06APR04 29MAR04 06APR04 0
Prepare 8 8 02APR04 14APR04 02APR04 14APR04 0
Implement 16 18 15APR04 06MAY04 15APR04 06MAY04 0



Now, suppose that, in addition to imposing a FINISHBEFORE constraint on the entire project, the project manager for each subproject specifies a desired duration for his or her subproject. In the present example, the variable duration has values '6', '8', and '18' for the three subprojects. By default these values are not used in either the backward or forward pass, even though they may represent desired durations for the corresponding subprojects. You can specify the USEPROJDUR option on the PROJECT statement to indicate that the procedure should use these specified durations to determine the late finish schedule for each of the subprojects. In other words, if the USEPROJDUR option is specified, the late finish for each subproject is constrained to be less than or equal to

\[ \Variable{E\_ START} + \Variable{duration} \]

and this value is used during the backward pass.

The summary schedule resulting from the use of the USEPROJDUR option is shown in Output 4.23.8. Note the difference in the schedules in Output 4.23.7 and Output 4.23.8. In Output 4.23.7, the computed project duration, PROJ_DUR, is used to set an upper bound on the late finish time of each subproject, while in Output 4.23.8, the specified project duration is used for the same purpose. Here, only the summary schedules are displayed; the effect of the two options on the subtasks within each subproject can be seen by displaying the entire schedule in each case. A Gantt chart of the entire project is displayed in Output 4.23.9.


proc cpm data=survey date='29mar04'd out=survout4
         interval=weekday holidata=holidata fbdate='10may04'd;
   activity   activity;
   successor  succ1-succ3;
   duration   duration;
   id         id;
   holiday    hol;
   project    project / orderall addwbs useprojdur;
   run;


title 'Market Survey';
title2 'Summary Schedule: FBDATE and USEPROJDUR Options';
proc print data=survout4;
   where proj_lev=1;
   id activity;
   var proj_dur duration e_start--t_float;
run;

Output 4.23.8: Summary Schedule: FBDATE and USEPROJDUR Options

Market Survey
Summary Schedule: FBDATE and USEPROJDUR Options

activity PROJ_DUR duration E_START E_FINISH L_START L_FINISH T_FLOAT
Plan 7 6 29MAR04 06APR04 26MAR04 05APR04 -1
Prepare 8 8 02APR04 14APR04 02APR04 14APR04 0
Implement 16 18 15APR04 06MAY04 16APR04 07MAY04 1



data gant4;
   length id $26.;
   set survout4;
   if proj_lev=1 then id="   "||id;
   else if proj_lev=2 then id="      "||id;
   run;

proc sort;
   by es_asc;
   run;

goptions hpos=80 vpos=43;
title h=2 'Market Survey';
title2 h=1.5 'Project Schedule: FBDATE and USEPROJDUR Options';
proc gantt graphics data=gant4 holidata=holidata;
   chart / holiday=(hol)
           interval=weekday
           skip=2 scale=1.5 height=1.8
           nojobnum
           compress noextrange
           activity=activity succ=(succ1-succ3)
           cprec=cyan cmile=magenta
           caxis=black
           ;
   id   id;
   run;

Output 4.23.9: Gantt Chart of Schedule

Gantt Chart of Schedule


The project schedule is further affected by the presence of any alignment dates on the individual activities or subprojects. For example, if the implementation phase of the project has a deadline of May 5, 2004, you can specify an alignment date and type variable with the appropriate values for the subproject 'Implement', as follows, and invoke PROC CPM with the ALIGNDATE and ALIGNTYPE statements, to obtain the new schedule, displayed in Output 4.23.10.

data survey2;
   format aldate date7.;
   set survey;
   if activity="Implement" then do;
      altype="fle";
      aldate='5may04'd;
   end;
   run;

proc cpm data=survey2 date='29mar04'd out=survout5
         interval=weekday holidata=holidata
         fbdate='10jun04'd;
   activity   activity;
   successor  succ1-succ3;
   duration   duration;
   id         id;
   holiday    hol;
   project    project / orderall addwbs sepcrit useprojdur;
   aligntype  altype;
   aligndate  aldate;
   run;

title 'Market Survey';
title2 'USEPROJDUR option and Alignment date';
proc print;
   where proj_lev=1;
   id activity;
   var proj_dur duration e_start--t_float;
   run;

Output 4.23.10: USEPROJDUR option and Alignment Date

Market Survey
USEPROJDUR option and Alignment date

activity PROJ_DUR duration E_START E_FINISH L_START L_FINISH T_FLOAT
Plan 7 6 29MAR04 06APR04 26MAR04 05APR04 -1
Prepare 8 8 02APR04 14APR04 01APR04 13APR04 -1
Implement 16 18 15APR04 06MAY04 14APR04 05MAY04 -1