Here I review some impacts of “hard constraints” on the calculation of total float (or total slack) in logic-driven schedules.
A recent discussion on technet raised the issue of slack/float calculation for tasks with hard constraints – in this case Project’s “Must Start On” (MSO) constraint. A novice user of Microsoft Project (MSP), was puzzled by MSP’s calculation of non-zero total slack for an MSO-constrained task who’s early and late dates were the same. That is, the expected definition of Total Slack as “Late Finish minus Early Finish” [*] was clearly NOT being followed.
*[The traditional CPM definition of Total Slack/Float is TS=LF-ES-Dur. When Duration is a constant (as in MSP and P6) this simplifies to:
TS=(LF-Dur)-ES ==> TS=LS-ES, and
TS=LF-(ES+Dur) ==> TS=LF-EF.]
Consider the simple example comprising a three-task schedule with an MSO constraint on the second task and a deadline (a soft late constraint) on the third task, which I’ve shown below.
There are two basic issues about MSO (and MFO) constraints in Microsoft Project that come into play:
- Under typical default conditions, Project sets both the early start and late start equal to the MSO constraint date. This completely blocks logic flow through the task, and TS is zero. I’ve illustrated this in the first chart below, where I’ve set a lenient MSO constraint on task t2 but imposed a deadline on the completion task t3 to create some negative slack. Clearly the first task t1 should have negative slack, but the backward pass calculations don’t show it.
- If the early start imposed by the MSO constraint precedes the early start derived from the forward pass (i.e. the logic), then a logical conflict is created. If the “Tasks will always honor their constraint dates” box is checked in the Schedule options (the default condition), then Project keeps the imposed early and late starts – violating the CPM logic – and “resolves the conflict” by over-writing Total Slack with a negative value. This case is presented in the middle chart below. If the checkbox is not checked, then the Early Start is allowed to slip with the logic while the Late Start is retained. I’ve shown this on the bottom chart.
The example presented is a “Mandatory Constraint,” which is strongly discouraged in general and is explicitly prohibited in many contexts. Unchecking the “Tasks will always honor their constraint dates” box softens the impact of the constraint, but logic flow through the task is still interrupted. Because of these issues, users of MSP would be well advised to avoid MSO or MFO constraints in any context where scheduling logic (and Total Slack) are important.
MSP/Primavera P6 Comparison
With the checkbox checked (i.e. default conditions), Microsoft’s “Must Start On” constraint seems to behave almost identically to P6’s “Mandatory Start” constraint.
- Like Project’s MSO, P6’s Mandatory Start constraint over-writes early AND late dates, thereby imposing a null Total Float and interrupting logic flow through the schedule.
- In the absence of a logical conflict, Mandatory Start (in P6) results in the same dates AND Total Float (null-value) as MSO in MSP.
- There is one minor difference. Whereas Project separately computes and imposes negative Total Slack (on the constrained task only) to highlight a logical conflict, P6 preserves the CPM-defined Total Float of zero on the constrained activity. (This was the basis for the original question on technet.) Both constraints impose negative slack/float on the predecessors of the constrained task/activity based on the logical conflict alone; negative slack/float from a more stringent constraint later in the project will be blocked.
With the checkbox un-checked, the resulting MSP schedule appears similar at first to P6’s schedule when using a (softer) constraint like “Start-On”. This should not be misinterpreted. As shown in the next chart, MSP continues to over-write the late date with the constraint date, even when the CPM-based late date is more restrictive. Resulting predecessor slack values may be incorrect. P6’s “Start On” constraint, on the other hand, results in a correct float calculation for the imposed conditions.