A simple activity network is used to illustrate the use of the SETFINISHMILESTONE option in a couple of different scenarios.
The following DATA step reads the project network in AON format into a SAS data set named tasks
. The data set (printed in Output 4.28.1) contains an Activity variable (act
), a Successor variable (succ
), a Lag variable (lag
), and a Duration variable (dur
). There are several milestones linked to other activities through different types of precedence constraints. The data set
also contains some alignment constraints as specified by the variables target
and trgttype
. The treatment of the milestones will vary depending on the presence or absence of the alignment constraints. The data set
also contains two variables that indicate the expected early schedule dates for the milestones corresponding to two different
invocations of PROC CPM: the variable notrgtmd
corresponds to the non-aligned schedule and the variable miledate
corresponds to an invocation with the ALIGNDATE statement (the values for these variables are explained later).
data tasks; format act $7. succ $7. lag $4. target date7. trgttype $3. miledate date7. notrgtmd date7. ; input act & succ & lag $ dur target & date7. trgttype $ miledate & date7. notrgtmd & date7. ; datalines; Task 0 Mile 1 ss_0 1 26Jan04 SGE . . Mile 1 Task 2 . 0 . . 26Jan04 26Jan04 Task 2 . . 1 . . . . Task 3 Mile 4 . 1 . . . . Mile 4 . . 0 . . 26Jan04 26Jan04 Task 5 Mile 6 . 1 . . . . Mile 6 Mile 7 FS_1 0 . . 26Jan04 26Jan04 Mile 7 . . 0 . . 27Jan04 27Jan04 Task 8 Mile 9 SS_3 1 . . . . Mile 9 Mile 10 . 0 . . 29Jan04 29Jan04 Mile 10 . . 0 . . 29Jan04 29Jan04 Task 11 Mile 12 . 2 . . . . Mile 12 Mile 13 FS_1 0 28Jan04 SGE 28Jan04 27Jan04 Mile 13 . . 0 . . 29Jan04 28Jan04 ;
Output 4.28.1: Input Data Set
Schedule with option SETFINISHMILESTONE |
Input Data Set |
Obs | act | succ | lag | target | trgttype | miledate | notrgtmd | dur |
---|---|---|---|---|---|---|---|---|
1 | Task 0 | Mile 1 | ss_0 | 26JAN04 | SGE | . | . | 1 |
2 | Mile 1 | Task 2 | . | 26JAN04 | 26JAN04 | 0 | ||
3 | Task 2 | . | . | . | 1 | |||
4 | Task 3 | Mile 4 | . | . | . | 1 | ||
5 | Mile 4 | . | 26JAN04 | 26JAN04 | 0 | |||
6 | Task 5 | Mile 6 | . | . | . | 1 | ||
7 | Mile 6 | Mile 7 | FS_1 | . | 26JAN04 | 26JAN04 | 0 | |
8 | Mile 7 | . | 27JAN04 | 27JAN04 | 0 | |||
9 | Task 8 | Mile 9 | SS_3 | . | . | . | 1 | |
10 | Mile 9 | Mile 10 | . | 29JAN04 | 29JAN04 | 0 | ||
11 | Mile 10 | . | 29JAN04 | 29JAN04 | 0 | |||
12 | Task 11 | Mile 12 | . | . | . | 2 | ||
13 | Mile 12 | Mile 13 | FS_1 | 28JAN04 | SGE | 28JAN04 | 27JAN04 | 0 |
14 | Mile 13 | . | 29JAN04 | 28JAN04 | 0 |
Output 4.28.2: Default Schedule
Schedule with option SETFINISHMILESTONE |
Default Schedule |
O b s |
a c t |
s u c c |
d u r |
l a g |
n o t r g t m 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 |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | Task 0 | Mile 1 | 1 | ss_0 | . | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | 2 | 0 |
2 | Mile 1 | Task 2 | 0 | 26JAN04 | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | 2 | 0 | |
3 | Task 2 | 1 | . | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | 2 | 2 | ||
4 | Task 3 | Mile 4 | 1 | . | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | 2 | 0 | |
5 | Mile 4 | 0 | 26JAN04 | 27JAN04 | 27JAN04 | 29JAN04 | 29JAN04 | 2 | 2 | ||
6 | Task 5 | Mile 6 | 1 | . | 26JAN04 | 26JAN04 | 27JAN04 | 27JAN04 | 1 | 0 | |
7 | Mile 6 | Mile 7 | 0 | FS_1 | 26JAN04 | 27JAN04 | 27JAN04 | 28JAN04 | 28JAN04 | 1 | 0 |
8 | Mile 7 | 0 | 27JAN04 | 28JAN04 | 28JAN04 | 29JAN04 | 29JAN04 | 1 | 1 | ||
9 | Task 8 | Mile 9 | 1 | SS_3 | . | 26JAN04 | 26JAN04 | 26JAN04 | 26JAN04 | 0 | 0 |
10 | Mile 9 | Mile 10 | 0 | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | 0 | 0 | |
11 | Mile 10 | 0 | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | 0 | 0 | ||
12 | Task 11 | Mile 12 | 2 | . | 26JAN04 | 27JAN04 | 26JAN04 | 27JAN04 | 0 | 0 | |
13 | Mile 12 | Mile 13 | 0 | FS_1 | 27JAN04 | 28JAN04 | 28JAN04 | 28JAN04 | 28JAN04 | 0 | 0 |
14 | Mile 13 | 0 | 28JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | 0 | 0 |
First, the CPM procedure is invoked with the default treatment of milestones. The resulting schedule is printed in Output 4.28.2. Note the dates for the milestones. Compare these dates with the values of the early finish dates of the immediate predecessors.
The default behavior of the CPM procedure defines the start times for milestones to be at the beginning of the day after the
predecessor task (with a standard FS_0 relationship) ends. Thus, for example, the activity, 'Mile 4' has E_START=27JAN04 because
its predecessor, 'Task 3', has E_FINISH=26JAN04. The interpretation for these dates are that the early finish corresponds
to the end of the day, while the early start of the milestone 'Mile 4' corresponds to the beginning of the day. However, in
some situations you may want the milestone to be scheduled at the same time as the end of the predecessor activity. In other
words, you may wish the early start time of the milestone 'Mile 4' to be displayed as 26JAN04, with the interpretation that
this time actually denotes the end of the day, rather than the beginning. See the section Finish Milestones for details about the treatment of milestones. In the current example, the variable notrgtmd
contains the desired milestone schedule dates corresponding to this special treatment of milestones. To obtain these desired
dates, you must use the SETFINISHMILESTONE option.
/* Schedule the project */ proc cpm data=tasks out=out0 collapse interval=day date='26jan04'd; activity act; successor succ /lag=(lag); duration dur; id lag notrgtmd; run; title2 'Default Schedule'; proc print; run;
Next, the CPM procedure is invoked with the option SETFINISHMILESTONE and the resulting schedule is printed in Output 4.28.3. Not all milestones are defined to denote the end of the displayed date; such milestones are referred to as finish milestone.
The variables EFINMILE
and LFINMILE
indicate if the milestone is a finish milestone or not, corresponding to the early or late schedule, respectively. For example,
the milestone 'Mile 12' has E_FINISH
= 27JAN04 and the value of EFINMILE
is '1', indicating that the activity finishes at the end of the day on January 27, 2004. The milestone 'Mile 13' (with a
finish-to-start lag of 1 day) finishes at the end of the day on January 28, 2004. In fact, as the late finish schedule indicates,
the value of L_FINISH
for 'Mile 13' (and the project finish time) is the end of the day on 28JAN04. Both the variables EFINMILE
and LFINMILE
have the same values for all the activities in this example.
proc cpm data=tasks out=out1 collapse interval=day date='26jan04'd setfinishmilestone; activity act; successor succ /lag=(lag); duration dur; id lag notrgtmd; run; title 'Schedule with option SETFINISHMILESTONE'; title2 'No Target Dates'; proc print heading=v; id act; var succ lag dur notrgtmd e_start e_finish l_start l_finish efinmile lfinmile; run;
Output 4.28.3: Schedule with SETFINISHMILESTONE Option
Schedule with option SETFINISHMILESTONE |
No Target Dates |
a c t |
s u c c |
l a g |
d u r |
n o t r g t m 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 |
E F I N M I L E |
L F I N M I L E |
---|---|---|---|---|---|---|---|---|---|---|
Task 0 | Mile 1 | ss_0 | 1 | . | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | . | . |
Mile 1 | Task 2 | 0 | 26JAN04 | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | . | . | |
Task 2 | 1 | . | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | . | . | ||
Task 3 | Mile 4 | 1 | . | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | . | . | |
Mile 4 | 0 | 26JAN04 | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | 1 | 1 | ||
Task 5 | Mile 6 | 1 | . | 26JAN04 | 26JAN04 | 27JAN04 | 27JAN04 | . | . | |
Mile 6 | Mile 7 | FS_1 | 0 | 26JAN04 | 26JAN04 | 26JAN04 | 27JAN04 | 27JAN04 | 1 | 1 |
Mile 7 | 0 | 27JAN04 | 27JAN04 | 27JAN04 | 28JAN04 | 28JAN04 | 1 | 1 | ||
Task 8 | Mile 9 | SS_3 | 1 | . | 26JAN04 | 26JAN04 | 26JAN04 | 26JAN04 | . | . |
Mile 9 | Mile 10 | 0 | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | . | . | |
Mile 10 | 0 | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | . | . | ||
Task 11 | Mile 12 | 2 | . | 26JAN04 | 27JAN04 | 26JAN04 | 27JAN04 | . | . | |
Mile 12 | Mile 13 | FS_1 | 0 | 27JAN04 | 27JAN04 | 27JAN04 | 27JAN04 | 27JAN04 | 1 | 1 |
Mile 13 | 0 | 28JAN04 | 28JAN04 | 28JAN04 | 28JAN04 | 28JAN04 | 1 | 1 |
The next invocation of CPM illustrates the effect of alignment constraints on the milestones. As explained in the section
Finish Milestones, imposing an alignment constraint of type SGE
on a milestone may change it from a finish milestone to a start milestone (default behavior) as far as the early schedule
of the project is concerned. In the following program, the CPM procedure is invoked with the SETFINISHMILESTONE option and
the ALIGNDATE and ALIGNTYPE statements. The resulting schedule is printed in Output 4.28.4. The early schedule of the milestones should now correspond to the values in the variable miledate
. Note also that the activities 'Mile 12' and 'Mile 13' are no longer finish milestones, as indicated by missing values for
the variable EFINMILE
. The 'SGE' alignment constraint with a target date of 28JAN04 moves the milestone 'Mile 12' to the beginning of January 28,
2004, instead of the end of January 27, 2004.
proc cpm data=tasks out=out2 collapse interval=day date='26jan04'd setfinishmilestone; activity act; successor succ /lag=(lag); duration dur; aligndate target; aligntype trgttype; id target trgttype lag miledate; run;
title 'Schedule with option SETFINISHMILESTONE'; title2 'Target Dates change Early Schedule for some Milestones'; proc print heading=v; id act; var succ lag target trgttype miledate e_start e_finish l_start l_finish efinmile lfinmile; run;
Output 4.28.4: Effect of Alignment Constraints
Schedule with option SETFINISHMILESTONE |
Target Dates change Early Schedule for some Milestones |
a c t |
s u c c |
l a g |
t a r g e t |
t r g t t y p e |
m i l e d a t e |
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 |
E F I N M I L E |
L F I N M I L E |
---|---|---|---|---|---|---|---|---|---|---|---|
Task 0 | Mile 1 | ss_0 | 26JAN04 | SGE | . | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | . | . |
Mile 1 | Task 2 | . | 26JAN04 | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | . | . | ||
Task 2 | . | . | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | . | . | |||
Task 3 | Mile 4 | . | . | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | . | . | ||
Mile 4 | . | 26JAN04 | 26JAN04 | 26JAN04 | 28JAN04 | 28JAN04 | 1 | 1 | |||
Task 5 | Mile 6 | . | . | 26JAN04 | 26JAN04 | 27JAN04 | 27JAN04 | . | . | ||
Mile 6 | Mile 7 | FS_1 | . | 26JAN04 | 26JAN04 | 26JAN04 | 27JAN04 | 27JAN04 | 1 | 1 | |
Mile 7 | . | 27JAN04 | 27JAN04 | 27JAN04 | 28JAN04 | 28JAN04 | 1 | 1 | |||
Task 8 | Mile 9 | SS_3 | . | . | 26JAN04 | 26JAN04 | 26JAN04 | 26JAN04 | . | . | |
Mile 9 | Mile 10 | . | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | . | . | ||
Mile 10 | . | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | 29JAN04 | . | . | |||
Task 11 | Mile 12 | . | . | 26JAN04 | 27JAN04 | 26JAN04 | 27JAN04 | . | . | ||
Mile 12 | Mile 13 | FS_1 | 28JAN04 | SGE | 28JAN04 | 28JAN04 | 28JAN04 | 27JAN04 | 27JAN04 | . | 1 |
Mile 13 | . | 29JAN04 | 29JAN04 | 29JAN04 | 28JAN04 | 28JAN04 | . | 1 |
The interpretation of the start and finish times for a milestone depends on whether it is a start milestone or a finish milestone. By default, all milestones are start milestones and are assumed to be scheduled at the beginning of the date specified in the start or finish time variable. As such, PROC GANTT displays these milestones at the start of the corresponding days on the Gantt chart. However, if a milestone is a finish milestone then it may not be displayed correctly on the Gantt chart, depending on the scale of the display.
In this example, PROC GANTT is used to display the schedule produced in Output 4.28.4. Recall that the schedule is saved in the data set out2
. First, PROC GANTT is invoked without any modifications to the schedule data set. The resulting Gantt chart is displayed
in Output 4.28.5. The finish milestones (with values of EFINMILE
= '1') are not plotted correctly. For example, 'Mile 6' is plotted at the beginning instead of the end of the schedule bar for the predecessor activity, 'Act 5'. To correct this problem, you can adjust the schedule variables
for the finish milestones and plot the new values, as illustrated by the second invocation of PROC GANTT. The corrected Gantt
chart is displayed in Output 4.28.6.
title h=1.5 'Schedule with option SETFINISHMILESTONE and ALIGNDATE'; title2 'Gantt Chart of Early Schedule without adjustment'; proc gantt data=out2(drop=l_:); chart / compress act=act succ=succ lag=lag scale=7 height=1.7 cprec=cyan cmile=magenta caxis=black dur=dur nojobnum nolegend; id act succ lag e_start efinmile; run;
/* Save adjusted E_START and E_FINISH times for finish milestones */ data temp; set out2; format estart efinish date7.; estart = e_start; efinish = e_finish; if efinmile then do; estart=estart+1; efinish=efinish+1; end; run;
/* Plot the adjusted start and finish times for the early schedule */ title h=1.5 'Schedule with option SETFINISHMILESTONE and ALIGNDATE'; title2 'Gantt Chart of Early Schedule after adjustment'; proc gantt data=temp(drop=l_:); chart / compress act=act succ=succ lag=lag scale=7 height=1.7 es=estart ef=efinish cprec=cyan cmile=magenta caxis=black dur=dur nojobnum nolegend; id act succ lag e_start efinmile; run;