An Alternate Approach to Hammock Tasks in Microsoft Project

This entry describes the basis for hammock-type summary tasks and introduces an alternate method (and UpdateHammocks macro) for creating and maintaining such tasks in Microsoft Project (MSP) schedules.

Hammocks and LOE Tasks

“Hammock”* and “Level of Effort” (LOE) tasks in project schedules provide two similar approaches to summarizing and reporting the overall time consumed by a collection of other tasks.  Typically, hammock or LOE tasks are used to represent the indirect management and other support activities associated with the primary tasks, and they are often loaded with management and other indirect resources.  Hammock and LOE tasks are essentially the same, though minor differences exist in the implementation by different software.  Since hammocks and LOE tasks do not possess any driving logic, they should be excluded from any formal definition of the Critical Path for the project.

* The “hammock” name refers to the simple method of suspending a sleeping net or cloth (i.e. the hammock) between two trees.  When first described in hand-drawn activity-on-arrow (AOA) network diagrams, the time-summarizing activity took the shape of a simple curved line slung between two nodes – i.e. a hammock.

Hammocks in Primavera

Primavera scheduling tools have long provided explicit activity types for specifying hammock or LOE activities.  Primavera Project Planner (P3) and Primavera SureTrak Project Manager, for example, both included specific hammock activity types that would be specially treated in the schedule calculations.  The start dates for a hammock were defined by its Start-Start predecessors; finish dates came from its Finish-Finish successors; the same activity could not be included in both groups.  Oracle’s Primavera P6, a newer application, allows for LOE activities that inherit their dates from the primary tasks that are included in their “predecessors” and “successors” lists.  They are substantially more flexible than P3’s hammocks.  In most respects the scheduling aspects of these LOE activities are similar to the scheduling of summary bars in P6 schedules (and summary tasks in MSP), with the key difference being that there is no need for common hierarchical structure or activity coding of the related primary activities.

Hammocks in Other Tools

Most other major project scheduling tools also have special-purpose hammock task types.  For example, Phoenix Project Manager, Spider Project, and Deltek Open Plan all provide traditional hammock activity types, whose start and finish are defined by specific logical relationships.  Asta PowerProject also includes a “hammock” task whose construction is more like that of an independent summary activity.  That is, it is not necessary to indicate start/finish relationships.  In general, the number of activities being summarized by the hammocks (or LOEs in P6) are not practically limited.

OLE Hammocks in MSP

MSP has never included an explicit Hammock or LOE task type, and since summary tasks do not provide the needed solution in many cases, a subtle method for constructing simple hammock tasks was created.  As described here, the method involves copying the start/finish dates from two primary tasks and using a paste-special command to link these dates to the dates of the “hammock” task.  The resulting “links” – based on common Windows OLE (object linking and embedding) technology rather than explicit logical schedule relationships – remain essentially hidden and cannot be easily described or audited in an MSP schedule.

MSP’s response to changes in the linked dates is similar to its response when dates are entered manually: i.e. it sets an early constraint (SNET or FNET) and adjusts the task duration so that the task spans between the two linked dates.  Unfortunately, even if the links remain stable and updated (which is not guaranteed), the sources of these adjustments remain hidden.

MSP OLE Hammock Issues

In addition to the absence of auditable schedule information, regular users of linked hammocks may have noticed the following issues, which are present in MSP Professional 2010 and later releases:

  1. OLE hammocks are limited to summarizing only two tasks, one task providing the start date and the other providing the finish.  This limitation seems most consistent with the original description of hammocks in AOA networks, but it doesn’t exist in other modern software.  Often the activities being summarized are potentially concurrent, and it is preferred to allow the software to select dates from the group.
  2. MSP does not prevent the assignment of additional logical links or other constraints that may conflict with the OLE links.
  3. Creating new linked hammocks by copying and modifying existing linked hammocks – say as part of a fragnet replication – doesn’t work well. The resulting links may be subject to corruption and won’t update reliably.  The only reliable way to create such links is to copy and paste-link them one-at-a-time.
  4. Even “automatic” updating of links sometimes fails, with repeated pounding of the F9 key having no affect. In these cases, it’s useful to open the Links window, select all the links, and force an update. (To open the window, the “Edit Links” command needs to be available on one of the ribbons.  It can be added through the “customize the ribbon” dialog.)  This tool is absolutely necessary to make OLE hammocks even slightly bearable.
  5. Resource leveling of linked hammocks can result in unintended consequences. Although most of these can be corrected by a forced update of the links, some changes require that the hammock task be reconstructed.  E.g. removing leveling splits.  The safest course is to assign a priority of 1000 to all linked hammock tasks, thereby exempting them from any leveling actions.

MSP Alternate Hammocks

An alternate approach to hammocks in MSP involves the following steps:

  1. Create the proposed hammock task as either a Fixed Units or Fixed Work task, depending on the nature of the resource loading required.
  2. Specify two predecessors to the proposed hammock task: one Start-to-Start and one Finish-to-Finish, without lags. (These are the same tasks that would otherwise be the sources of the Start and Finish paste-links. Here they are visible and auditable. Do Not paste links.)
  3. Avoid specifying any successors to the hammock.
  4. Create a custom flag field named “Hammock,” and assign a value of “Yes” to the Hammock flag for this task.
  5. Adjust the duration of the task such that it spans between the associated start and finish predecessor dates. (This is done automatically with the macro code below.)
  6. Ensure that the task is assigned a Priority of 1000, which prevents it from being resource-leveled. (This is done automatically with the macro code below.)
  7. Load indirect resources to the task as appropriate.

This alternate approach has the key benefit of presenting an explicit logical basis for the hammock task’s schedule dates, which can be easily checked and modified if necessary.  It also supports the use of Fixed-Work hammocks for allocation of fixed contract costs.  While this alternate approach is no more robust than OLE hammocks when summarizing tasks with potential concurrency, it is far easier to review, modify, and update the associated hammock links when the controlling activities change.

The macro/vba code below is intended to automatically update the durations of all hammock tasks in the active project.  It also automatically removes constraints on hammocks and assigns a priority of 1000 to prevent resource leveling.

This macro/vba code comprises a subroutine and a custom function that should be pasted together into a single module in the Visual Basic Editor.  The “UpdateHammocks” macro may then be assigned to a “hotkey” or ribbon command as appropriate.

[Edit March 2018.  Our MSP add-in, BPC Logic Filter, excludes Hammocks constructed using this method from Longest-Path and Near-Longest-Path reports.  This satisfies the requirement that such tasks not be included in any calculations of the project’s Critical Path.  Since some users have reported inadvertent introduction of splits into hammock tasks during cost updating, I added a little mini-procedure to close all such splits that are 100% in the future, prior to updating the hammock duration.  I also updated the duration calculator to accommodate an assigned resource with a non-standard calendar.  ]

Sub UpdateHammocks()
'15Sep'17 coded by TM Boyle, PSP.
'A code to routinely update the Durations of unlinked, user-managed "hammock" tasks in Microsoft Project.
'A "hammock" task is an indirect/support task that may be resource loaded.  Its schedule
'depends solely on the tasks that it supports/summarizes.
'For this code to work:
'   - All hammock tasks are coded using a custom Flag field (named "Hammock"); Alternately Flag1 is assumed.
'   - Each hammock task has exactly one or two predecessors:
'       - The "Start" predecessor has a Start-to-Start relationship with no lag
'       - The "Finish" predecessor has a Finish-to-Finish relationship with no lag
'       - If there is only one predecessor, then both start and finish of the hammock will come from it.
'   - Each hammock should have NO successors, although this condition is not enforced.
'       - Successors on the hammock can synthetically lengthen the backward path to its "Start" predecessor,
'           thereby reducing Total Slack in that predecessor and its driving chain.
'[21Mar'18 added code to remove splits in hammocks.]
'[22Mar'18 added code for hammock scheduling using a single resource calendar.]


Dim t As Task
Dim d As TaskDependency
Dim StartH As Date
Dim FinishH As Date
Dim i As Integer 'Added 21Mar'18
        
If Not HammockFieldExists Then
    MsgBox ("Couldn't find a Hammock Flag. Aborting")
    Exit Sub
Else
    'Proceed
End If


For Each t In ActiveProject.Tasks
    If Not t Is Nothing Then
        
        StartH = 0
        FinishH = 0
        If t.GetField(FieldNameToFieldConstant("Hammock")) = "Yes" Then
        'If t.Flag1 = True Then 'Flag1 is used to designate Hammock Activities
        
            'Added 21Mar'18
            'First Close Splits if any
            On Error GoTo 0
            If "Proceed" = "Proceed" Then '(change second "Proceed" to another word to bypass for troubleshooting)
                Do While t.SplitParts.Count > 1
                    i = t.SplitParts.Count
                    'Don't remove any splits that begin in the past
                    If ActiveProject.StatusDate < ActiveProject.ProjectFinish Then 'StatusDate Exists
                        If t.SplitParts(i - 1).Finish < ActiveProject.StatusDate Then Exit Do
                    Else ' Use now date
                        If t.SplitParts(i - 1).Finish < Now() Then Exit Do
                    End If
                        t.SplitParts(i).Start = t.SplitParts(i - 1).Finish
                Loop
            End If
            
            If t.PredecessorTasks.Count = 2 Or t.PredecessorTasks.Count = 1 Then
                For Each d In t.TaskDependencies
                    If d.To = t Then
                        If d.Type = pjFinishToStart Or d.Type = pjStartToFinish Then
                            MsgBox ("Hammocks may only have SS or FF predecessors (Check predecessors): " & t.ID & " " & t.Name)
                        Else
                            If d.Type = pjStartToStart Then StartH = d.From.Start
                            If d.Type = pjFinishToFinish Then FinishH = d.From.Finish
                            If t.PredecessorTasks.Count = 1 Then
                                If StartH = 0 Then StartH = d.From.Start
                                If FinishH = 0 Then FinishH = d.From.Finish
                            End If
                            If d.Lag <> 0 Then MsgBox ("Hammocks should not have lag (Check lag): " & t.ID & " " & t.Name)
                        End If
                    Else
                        MsgBox ("Hammocks should not have successors (Check successors): " & t.ID & " " & t.Name)
                    End If
                Next d
            
                    On Error Resume Next
                        t.Duration = Application.DateDifference(StartH, FinishH, t.CalendarObject)
                        If Err.Number <> 0 Then
                            Err.Clear
                            'Added 22Mar'18 - allow for resource calendar controlling task schedule
                            t.Duration = Application.DateDifference(StartH, FinishH, t.Assignments(1).Resource.Calendar)
                            If Err.Number <> 0 Then
                                Err.Clear
                                t.Duration = Application.DateDifference(StartH, FinishH)
                                If Err.Number <> 0 Then
                                    MsgBox ("Failed to update Hammock (Check predecessors): " & t.ID & " " & t.Name)
                                End If
                            End If
                        End If
                        If Err.Number = 0 Then
                            t.Priority = 1000
                            t.ConstraintType = 0
                        End If
            Else
                MsgBox ("There must be 1 or 2 predecessors for this hammock activity. Not Updating: " & t.ID & " " & t.Name)
                
            End If
        End If
    End If
Next t
Application.CalculateProject


End Sub


Function HammockFieldExists() As Boolean
    Dim StrTest As String
    Dim FlagTemp As String

    StrTest = "Hammock"
    On Error Resume Next
        FlagTemp = ActiveProject.ProjectSummaryTask.GetField(FieldNameToFieldConstant(StrTest))
    If Err.Number = 0 Then 'The fieldname exists and will be used
        HammockFieldExists = True
    Else
        HammockFieldExists = False
    End If
End Function

How to Find Multiple Critical Paths in a Single CPM Schedule

In complex project schedules, multiple critical paths can exist between the project’s start and finish milestones.  Additionally, integrated projects with multiple phased scopes of delivery often have several distinct, contractually-mandated deliverables and corresponding delivery dates.   Each possesses its own critical/driving path.

[Note to searchers: This article has a slight mention of Microsoft Project’s Advanced Calculation Option – “Calculate Multiple Critical Paths.”  It’s near the end, in the section called A Note About Open Ends.] 

A key tenet of the original Critical Path Method (CPM) of project scheduling is that each project has one and only one “Critical Path” (CP) that extends continuously from the project start milestone to the project finish milestone.  The CP is defined by the collection of activities that determine the finish date of the project, such that a delay of any one of them will delay the project.  Traditional methods identify the CP based on Total Slack/Float.  For an elementary review, have a look at The Ultimate Guide to the Critical Path Method over at projectmanager.com.

[As demonstrated in this heavier article of mine, the CP is in many cases not actually defined by the collection of “Critical” activities from the software.]

Single Finish Milestone w/ Parallel Drivers

It is possible for the “critical path” between the start milestone and the finish milestone to have several parallel branches of equivalent length.  These can be described as “multiple critical paths.”

Depending on the details of the schedule model, it is not uncommon to have at least a few activities that are both concurrent and critical.  That is, they comprise parallel branches of a common logic path that drives the completion of the project.  For example, the construction schedule for a residential building may include one activity for “plumbing rough-ins” and another activity for “electrical rough-ins” (where “rough-in” is another term for “first fix” work.)  The two activities have the same driving predecessors (e.g. structural framing) and driven successors (e.g. wall finishes), and they take the same amount of time to complete.  If the wall finishes are on the driving path to project completion, then the two rough-in activities form parallel branches of the “Critical Path” for the project.  Such parallel branches might be repeated for each floor of a multi-story building.  In practice, instances of parallelism/concurrency that comprise only a few activities like those described here seem rarely, if ever, to be identified as “multiple critical paths.”  This is because a) the parallel activities are seen as closely related; and b)traditional methods of identifying and depicting critical activities do not differentiate between the associated logic paths, typically sorting by dates and filtering primarily on the software’s “critical” flag and/or Total Slack/Float.

Multiple critical paths are also created by efforts to accelerate the project completion, such as crashing or fast-tracking exercises, after the initial development of the schedule.  For example, a large scale construction project must be accelerated by 40 days to meet contract commitments.  The critical path of the initial project schedule runs through building construction, while underground utility development activities possess 30 days of Total Float.

Additional resources (and costs) may be applied to compress the building construction activities by 30 days and yield a corresponding acceleration of the project completion.  At that point, the building construction and utility development activities must both be compressed by an additional 10 days (and at additional cost) to obtain the necessary 40-day acceleration of the project.  After the exercise, the building construction and utility development activities are equally driving the project completion, and the schedule possesses two critical paths.

Further crashing or fast-tracking exercises may add more critical paths.  The associated activities all possess the same total float/slack, and all are marked as “critical.”  Differentiating between the various paths requires a method for separately tracing and coding driving logic, either analytically or by visual inspection.  Such methods are explored later in this article.

In practice, multiple critical paths are also created during project execution, as float is completely consumed by unplanned delays in activities that were previously non-critical.  Exploration of such delays will have to wait for another article.  (Notions of the “Critical Path” are sometimes suspended in the late stages of major/mega projects, as virtually every incomplete activity may delay the ultimate completion of the project and is therefore “Critical”.)

Ultimately, all three of these instances of multiple critical paths can be traced to a certain simplification (or presumed simplification) of resource utilization in the project.  In the first example, plumbing and electrical crews are presumed to have exactly the same productivity, resulting in the same duration for both activities.  In fact, one of the crews may be capable of completing the work sooner but paces its effort in order to match the scheduled duration.  In the second example, it is presumed that the building construction activities and utility development activities may be compressed by exactly 40 days and 10 days, respectively.  In fact, optimum resource usage often follows a step-wise rather than linear (or even continuous) function; consistent with adding discrete crews or substituting higher-capacity equipment.  Thus, the building construction may be optimally compressed by 35 days or 45 days (not 40 days), and the utility development may be optimally compressed by 9 days or 12 days (not 10 days).  As a result, the project completion is optimally accelerated by 42 days (not 40 days), with the critical path being governed by utility development.  The crashed building construction activities get 3 days of float.

When taken to this level of detail, a single critical path may indeed be re-established.  Depending on the needs of the project, such detail may or may not be justified in light of various project uncertainties and the increased management effort involved.

Multiple Delivery Milestones

When a project involves the parallel or interim delivery of multiple scopes of work, each delivery may be construed to have its own “critical path”  – i.e. the sequence of activities and relationships determining the delivery date for the particular scope of work.  More importantly, any particular activity in the project schedule may be expected to participate in more than one of these multiple critical paths.  Examples include design, setup, or testing activities that may be common to several deliveries.

Here is a simple example project comprising six “phases” of inter-related tasks in a Microsoft Project (MSP) schedule.

MSP identifies the CP for the project on the basis of Total Slack (TS<=0), and it colors the associated bars red.  The table includes six columns identifying the critical/driving tasks for each of the phase-completion milestones (CP1 through CP6).  For example, the critical/driving tasks for the Phase 1 Completion (ID #6) are flagged “yes” and highlighted yellow in the CP1 column.  This path comprises the following sequence, which is easily verified by inspection: 1->13->14->5->6.  Interestingly, the first Phase 1 task — ID #3 – “1A” —  is marked “critical” for the overall project but is not critical for the Phase 1 Completion.  A delay of this task would delay the project but would not immediately delay Phase 1.  Coincidentally, since Phase 6 is the last phase to finish, its critical path (column CP6) corresponds to the critical path for the overall project – i.e. the red bars and TS=0.

The project is scheduled identically using Oracle Primavera P6 (P6).

As a result of the modest number of inter-phase relationships, the critical/driving paths for five of the six phases include activities from other phases.  The exception, Phase 3, is essentially self-contained, although several of its tasks are also driving the completion of Phase 1.

So, how are these six different critical paths identified?

Identifying Multiple Critical Paths

There is in fact no way to simultaneously define the critical paths to each of the six phase completion milestones of the example project using Total Slack alone without manipulation.  The paths must be identified individually and directly reported (in the manner of BPC Logic Filter) or manually marked.

Deadlines / Late Constraints

It is common to apply deadlines (or late constraints in P6) to key completion milestones that are contractually defined – typically with financial consequences for delay.  Deadlines have the potential to reduce Total Slack/Float, which MSP and P6 use to identify Critical tasks.  When deadlines are applied to tasks and milestones that – together with their predecessor chains – are logically and organizationally separate, then Total Slack/Float can provide a reasonable indication of the driving path to each “deadlined” task or milestone.  This is a rare circumstance.  With only a single deadline applied, the Total Slack/Float for any task will be potentially influenced by the Project Completion date and by the deadline date, with the more “urgent” of the two forcing a lower Total Slack/Float value.  With more deadlines and intersecting logic paths, the issue is multiplied.

In the present example, each phase completion task has been given a deadline corresponding to its current finish date.  Consequently, all except two tasks in the entire project are given a Total Slack value of Zero and marked “Critical.”  The delay of any of these tasks is certain to violate at least one of the deadlines, although the deadlines to be violated are not obvious without the table.  The actual driving path to each phase completion remains obscured.  Although not completely reliable for defining individual driving paths, deadlines (and late constraints in P6) remain useful for flagging those tasks whose delay could affect (or already have affected) a contractually significant milestone.

If the project already includes multiple deadlines (for contractually significant milestones), then the critical/driving path for each milestone can be identified (one at a time) by forcing the milestone onto the MOST critical path, i.e.:

  • Temporarily accelerating the deadline date to the point that it becomes the most “urgent” deadline in the schedule network for all affected tasks.  The Total Slack of the milestone and its driving predecessors is then easily distinguished from that of other tasks; and then
  • Marking the tasks identified by the lowest Total Slack value.  Here, the deadline for the Phase 1 completion was accelerated by 9 work days, resulting in a Total Slack of -9 days for the completion task and its driving predecessors.  The CP1 custom flag field could then be marked accordingly.

As shown here, a nearly-identical process (using an accelerated Finish-on-or-before constraint) can be used for a P6 project schedule with multiple late constraints.

A similar approach can be used by adding a deadline or late constraint (in P6) if the project has none.

In fact this is the “Constraint Method” that was recognized by the Defense Contract Management Agency (DCMA) as the only valid method for defining a program critical path as part of its 14-point schedule assessment.

As shown above, using deadlines or constraints to generate negative slack/float is an effective way to identify multiple critical paths.  In Microsoft Project, however, these paths are difficult to distinguish on the Gantt charts because their red bars are not uniquely differentiated from others.  Both MSP and P6 can set the “Critical” flag – resulting in the red bars – for any tasks whose Total Slack/Float is below a certain user-specified threshold.  Unlike P6, MSP does not permit this threshold to be less than zero.  Consequently, all tasks with negative Total Slack – even those which are not driving anything – are flagged as “Critical” and given the red bar in MSP.

Trailing Dummy

An alternate approach to overcome this limitation for presentation purposes uses a “super-long trailing dummy” task.  In this approach, all deadlines and late constraints in the project must be removed (at least temporarily).  Then a “trailing dummy” task is assigned as a successor to the first key completion milestone, forcing the milestone onto the critical path.  The duration of the trailing dummy must be long enough to extend the completion of the project, creating positive Total Slack for all tasks that are not part of the dummy’s driving predecessor chain.  As shown in the following two figures, adding the 100-day Trailing Dummy task as a successor to the Phase 1 completion milestone effectively creates a new critical path for the project – one which is easily recognized as the Phase 1 critical path on the Gantt chart.  Moving the trailing dummy successor from phase to phase – one at a time – reveals the unique critical path for each phase.  

So far all of these approaches rely on temporary manipulation of Total Slack or Total Float, and it is important that such temporary changes be reversed prior to sharing or distributing schedule files.  Obviously, these approaches can be labor-intensive and error-prone, making them impractical when the schedule status (and logic) is in flux – as during regular weekly/monthly updating.  Even when the complications of multiple deadlines or late constraints are removed, Total Slack also becomes unreliable as an indicator of critical/driving relationships whenever multiple task/resource calendars or resource leveling are applied.

Driving Logic Tracing

The “Longest Path” algorithm in P6 defines the project’s Critical Path by automatically tracing driving logic backward from project completion.  This avoids the complications that late constraints and multiple calendars introduce to the interpretation of Total Float, and it is the preferred calculation method when these factors exist.  (It is unfortunate that P6 seems to be the only mainstream project scheduling tool to implement it.)  Since the algorithm always begins the backward trace with the project completion activity, using it with the trailing dummy method above is useful for identifying multiple critical paths on the basis of driving logic.  Driving logic can also be traced in other ways.

Driving Path Trace / Filter (P6)

P6 automatically identifies driving and non-driving relationships in the task details.  It also allows users to automatically add activities to existing filters by simply selecting them.  The combination of these two features allows users to manually construct a filtered view of the critical path to any completion milestone by simply clicking backward through the driving relationships.

The first step is to construct a custom filter to isolate the completion milestone of interest.  Here we are focusing on the Phase 1 completion milestone.

Next, the chain of driving activities (i.e. the driving path) is added to the view by stepping backward through the driving relationships using the “GoTo” button in the predecessors pane.  Here is the view after taking the first backward step.

Here is the view after tracing the network all the way back to the first driving relationship.  This is the driving (i.e. “critical”) path for the Phase 1 completion milestone. 

This click-tracing technique can become tedious when the project schedule is complex and there are numerous branches to the logic paths.  For example, if an activity along the driving path has two driving predecessors, then the analyst must make a note to return to the second one after the first is fully explored.  In addition, P6 routinely marks all links to Level-of-Effort (LOE) activities and links to ALAP-constrained predecessors as driving.  The LOE activities must be ignored during the trace, and the ALAP constrained activities need to be evaluated separately.  Finally, near-driving logic paths can be identified by the “relationship free float” field in the predecessors table, but isolating driving and near-driving paths involves creating and marking a number of new activity fields.

Fortunately, P6 includes an advanced scheduling option for calculating multiple float paths, which I’ve previously written about here.  This option effectively automates the click-tracing technique.

Combined with a view/layout/filter that depicts the “Float Path” field, this option provides a robust and repeatable method for defining the driving and near driving paths to each phase completion milestone in a P6 schedule.  (The “free float” option must be used.)  Float Path number 1 identifies the (first) driving path.  Higher Float Path numbers identify any parallel driving paths and near-driving paths.  Like the click-tracing technique, Multiple-Float Path analysis works without modifying the schedule network, so reversing temporary changes is not a concern prior to sharing the schedule.  Neither of these techniques affects P6’s assignment of the “critical” flag, however, so red-bars on the Gantt charts are not meaningful.

Task Path (MSP)

If you are using a recent version of Microsoft Project (2013+), then the driving path to each phase completion milestone can be visually identified and highlighted on the bar chart using the “Task Path” function with the “driving predecessors” switch selected.  (Task ID6 is selected, and the tasks in its “Driving Predecessors” Task Path are highlighted orange.)  The user can then manually enter a code (like the custom flag fields shown above) to mark the highlighted tasks.  It is fairly straightforward to automate the generation of a task path filter using a macro, and some macro snippets have been published.  (E.g. here.)  Unfortunately, Task Path’s “Driving Predecessors” are not reliable for most complex projects (e.g. when non-Finish-to-Start links, in-progress tasks, or manually-scheduled tasks are present.)  Those issues are discussed in my other blog entry here.

Logic-Tracing Add-ins

BPC Logic Filter (an MSP add-in) was developed in part to offset the absence of the Longest Path and multiple float path analysis in MSP.  The chart below shows driving and near-driving paths to Phase 1 completion – depicted by altering the bar chart.  The driving path is indicated by dark red bars with the zero indicating zero relative float.  Consistent with the trailing-dummy results, the two non-driving tasks that are part of Phase 1 are depicted as having 2 days and 3 days, respectively, of float relative to the Phase 1 completion milestone.  That is, they could slip 2 or 3 days before affecting the milestone.  Similar depictions of the driving and near-driving paths for the other five phases, and for the project as a whole, are made possible with a few clicks.  Since the schedule network is not manipulated in any way, Total Slack remains unchanged, and there is no need to reverse any analysis-based modifications prior to sharing the data file.

[See also Multiple Critical Paths – Revisited with BPC Logic Filter]

A Note About Open Ends

Some experts have suggested using open-ended logic along with a built-in software calculation setting to automatically mark multiple critical paths.  The proposal is as follows:

  1.  Ensure that each of the Phase completion milestones is sequenced so that a) it is a logical successor to all the activities in the phase, and b) it has no successors.
  2. Enable a calculation setting that forces activities with no successors to have zero total float.  In P6, this setting is the “Make open-ended activities critical” schedule option.  In MSP, the setting is the “Calculate multiple critical paths” advanced calculation option.

Effectively, this is the same as assigning a deadline to each completion milestone at a date that exactly equals its early finish date – an example of which was already explored above.  It is subject to the same drawbacks of that approach, but with none of the advantages.  I.e. If there are intersecting logic paths between phases (as shown in the example), then which activities are driving which milestone cannot be determined based on total float alone.  One merely sees a bunch of zero-float activities in all the phases.  Moreover, the basic technique of accelerating the milestone’s deadline/late-constraint date to reveal its driving predecessor path (through negative float) is not available when no deadline or late constraints have been applied.  Between this and other failings, I just don’t see any advantages to this open-ends approach.

Recap

A project schedule can possess multiple critical paths for one of two primary reasons:

  1. There is a single key completion milestone at the end of the project, and multiple, concurrent, parallel driving paths to that milestone exist.  In this case, the multiple critical paths often reflect a schedule model that is simpler than the actual execution of the project.  Correctly accounting for productivity of the assigned resources may remove the apparent concurrency and restore the single Critical Path, but the increased overhead of developing and managing a more detailed schedule would need to be justified.
  2.  The project possesses multiple key completion milestones, each with its own legitimate driving/critical path.  In this case, the correct identification and status reporting for the multiple Critical Paths is often beyond the capabilities of the scheduling software.  Then specialized logic tracing techniques are required.

These factors can also be combined in some project schedules.

Inspecting Task Resource Drivers with BPC Logic Filter for Microsoft Project

BPC Logic Filter – an add-in for Microsoft Project (desktop) – includes an advanced Logic Inspector feature to greatly simplify the examination and navigation of resource-leveled, logic-driven schedule activities.

The resource leveling feature in Microsoft Project (MSP) offers an effective method for management of resource-constrained projects, but most project managers don’t appreciate its impact on Total Slack, the Critical flag, and the resulting “critical path.”  Specifically, all of those terms become unreliable or misleading in the presence of resource leveling.  I first wrote about those issues here.

With some improvements to BPC Logic Filter – we were able to identify resource-driving links and include them in The Resource-Constrained Critical Path and in other logical path analyses.

Analyzing logical paths in schedules requires detailed examination of each task’s dependencies and (for leveled schedules) resource assignments. It’s helpful to have the results of such examinations at hand while reviewing (and confirming) the logical path analyses, so recent versions include a task Logic Inspector for Inspecting Task Links with BPC Logic Filter.

Logic Inspector also includes inferred resource-driving links if desired by the user.  Consider this simple resource-leveled schedule from the earlier articles.

With resource-checking disabled (and no calendars or constraints to confuse things), BPC Logic Filter computes relative float and identifies driving predecessors in a way that is consistent with MSP’s calculation of total slack.  For the A2 Structures task (ID 11), this means that the driving predecessor is the only predecessor — ID10: A2 Civil — even though it finishes two weeks before A2 Structures starts.  It also means that A2 Structures is logically driving all three of its successors.

Adding the late-relative float (LRF) column identifies the one successor relationship with bi-directional driving logic.  Thus, ID14: A2 Electrical Change Order 1 is highlighted red as the successor relationship with the most effect on the total slack of the selected activity. 

While this method is useful for understanding how MSP computes slack in resource leveled schedules, it does not help in understanding the actual resource limitations that drive the schedule of a task.  To gain that understanding, we first visit the Tracing Preferences tab in the Settings and ensure that Resource Checking is enabled.

Now Logic Inspector shows us the true picture of the schedule of the A2 Structures task.  Namely:

1. A new predecessor — the true driving predecessor for the task — is identified: the A1 Structures task in Area 1 must finish (and release its resources) before the A2 Structures task can start.  The only explicit logical predecessor of the A2 Structures task — ID10: A2 Civil — has 10 days of relative float.  That is, it could slip two weeks according to the standard calendar before THIS RELATIONSHIP starts to drive the A2 Structures task.

2. A new “driven successor” is identified in that the A3 Structures task may not start until the structural resources are finished with A2 Structures.

3. The A2 Electrical Change Order 1 task (ID14) is actually 40 days (8 weeks) away from being driven by its relationship to the current task.  (It is in fact driven by other resource constraints.)

4. Tasks 10 and 14 remain highlighted as late-date drivers.  With no direct impact on the scheduled dates for the selected task, they illustrate MSP’s basis for total slack calculations.

The JUMP button — which allows on-the-fly exploration of the schedule through logic links — treats the (implicit) resource driving links the same as explicit logical relationships.  Consequently, it is just as easy to hop through the logic of most resource-leveled schedules as it is to hop through one with no resources at all.

Dangling Logic in Project Schedules

Logic Driven project schedules can suffer from two kinds of open-ended or Dangling Logic, which makes the resulting schedule unreliable for dates or float analysis.

Project schedules need robust logical bases to reach two primary objectives:

  1. A schedule that accurately represents a true and achievable plan for executing the work – including technological and resource constraints.
  2. A schedule that supports accurate forecasting of consequences when the work does not proceed as originally planned – for example when activities fail to start or finish on time.

Dangling Activities – CPM

Logic-driven scheduling – often generically identified as “Critical Path Method” (CPM) scheduling – determines schedule dates by enforcing stringent logical sequential relationships between tasks from the start to the finish of the project.  The definition of adequate scheduling logic depends on the details of the project.  Logic is clearly inadequate, however, if any activity in the schedule is left logically disconnected from either the project start or the project finish – i.e. the activity is left “dangling.”  In the simple network diagram shown below, four activities are shown with no predecessors, while one activity is shown with no successors.  These cases typically represent omission of legitimate logical relationships with other (latent predecessor/successor) activities.  As a consequence, the early and late dates – and the Total Float – of all potentially-connected activities are not reliable.  The objectives of the logic-driven schedule can’t be met.  As a general rule, every activity in any CPM schedule – except the start and finish milestones – must have at least one predecessor and at least one successor.  Dangling activities not meeting this rule – also known as open-ended activities, “hanging activities”, or simply “hangers” – indicate inadequate schedule logic.

Dangling activities that are missing predecessors and/or successors are relatively easy to isolate in project scheduling tools – including Microsoft Project (MSP) and Oracle Primavera P6 (P6) – by using an activity filter that searches for empty “predecessors” or “successors” fields.  It is common for experienced schedulers to routinely tie such dangling activities to general-purpose milestones such as “notice to proceed” (as a predecessor) or “substantial completion” (as a successor).  Such an approach removes the obvious indication of inadequate logic.  Close review of the relationships at such “merge points” in the schedule may still be necessary to identify activities whose true predecessors and successors are not sufficiently defined.

Dangling Activities – PDM

Most modern scheduling software implements a variation of CPM scheduling called the Precedence Diagramming Method (PDM).  In addition to the “Finish-to-Start” relationship of basic CPM scheduling, PDM allows “Start-to-Start,” “Finish-to-Finish,” and “Start-to-Finish” relationships, all with or without lags.  While PDM software allows more realistic and more efficient modeling of real-world project schedules, it is possible for activities to have both predecessors and successors yet still suffer from dangling – hence inadequate – schedule logic.  These cases – generally categorized as dangling finish and dangling start – are also known as “orphan relationships.”

Dangling Finish

Consider the following three activities taken from a conceptual schedule for a civil construction project.  The project will take place on land that has been intentionally surcharged (pre-loaded with piles of soil) to strengthen the underlying materials.  The conceptual plan for the three activities is simple: 1) Push/roll-off the surcharge material to adjacent areas; 2) Perform grading and quality-assurance testing of the ground; 3) Construct concrete foundations for the buildings.

 

Because these activities are spread over a large area, it is possible to start the grading before completing the roll-over and to start the foundations before completing the grading.  The scheduler has modeled these relationships (in MSP) as SS+50% – that is the successor may start only after the predecessor has started, but with an additional lag of 50% of the predecessor’s duration (computed according to the successor’s calendar).  These activities, relationships, and the resulting (early) scheduled dates seem to reflect a true and achievable plan for prosecuting the work, meeting the first objective of a logic-driven schedule.

If the activities fail to progress as initially planned, however, then the schedule may not accurately forecast the consequences.  If the Roll-Over takes longer than expected, then this delay may in fact affect completion of the Rough-grading task and, eventually, the foundation construction and its successors.  The schedule model fails to account for these extended finishes, however, and may forecast outcomes that are physically impossible – such as building foundations being constructed in areas where the surcharge material has not yet been removed.

When the indefinite delay of an activity’s finish has no logical consequences for any other activity, then the activity has a “dangling finish” – representing incomplete logical development of the schedule.  In a PDM schedule, any activity with ONLY SS or SF successors has a dangling finish.  Such dangling finishes are called “open finishes” in Acumen Fuse, a 3rd party diagnostic tool.

Dangling Start

The same three activities could be modeled instead using Finish-to-Finish relationships to arrive at identical dates.

If subsequent schedule developments lead to longer durations for successor activities, the schedule model will respond by having them start earlier.  As a consequence, some schedule dates may occur at times that are physically impossible – such as starting rough grading before the first shovel of surcharge has been removed or (again) building foundations being constructed in areas where the surcharge material has not yet been removed.

When the indefinite acceleration of an activity’s start may be implemented without logical restraint from any other activity, then the activity has a “dangling start” – representing incomplete logical development of the schedule.  In a PDM schedule, any activity with ONLY FF or SF predecessors has a dangling start.  Such dangling starts are called “open starts” in Acumen Fuse.

Correction of Dangling Starts/Finishes

The examples shown are typical of overlapping activities with progressive feed relationships.  In such cases, it is common to implement a “ladder logic” scheduling model, where multiple parallel Start-to-Start and Finish-to-Finish relationships are imposed between related activities.  Such a model is easy to implement in P6.  In MSP – which prohibits parallel relationships between tasks – then dummy milestones are needed.

In a schedule model incorporating ladder logic, one of the two parallel relationships will drive the successor’s dates, depending on the relative durations and lags.  In the example below, the Rough grading activity is driven by its Start-to-Start relationship with Roll-over.  Because Rough grading has been extended, however, the subsequent Foundations construction is delayed (and driven) by the Finish-to-Finish relationship from Rough grading.  This represents robust logic development between the activities.

In general, dangling starts/finishes are avoided by explicit inclusion of all legitimate technological and/or resource constraints in the schedule model, even where the resulting relationships are not obviously driving successor activities.  This is, of course, the basis of all robust logic-driven scheduling practice.

Finding Dangling Starts/Finishes

Until recently, detecting and isolating dangling starts and finishes was not an easy process for users in either MSP or P6.  In both tools, the preferred approach is to specify an activity/task filter to show only those activities that:

  • For Dangling Starts –
    • Have some predecessors, and
    • Have NO FS or SS predecessors.
  • For Dangling Finishes –
    • Have some successors, and
    • Have NO FS or FF successors.

In MSP, each task includes a “predecessors” field listing the Task ID, relationship type, and lag for each predecessor relationship.  The task “successors” field lists the same information for successor relationships.  Unfortunately, the default relationship type – FS – is not explicitly listed in either field, and preparing a filter to exclude activities that contain FS relationships in one field or the other is not trivial, requiring several intermediate calculations.  Alternately, the user is left to manually inspect the predecessors and successors of each task, to export the project to Excel for analysis, or to use an add-in like Acumen Fuse or BPC Logic Filter to identify danglers.  [The add-ins examine the underlying relationship objects in the MSP database, which could also be done directly using a Project macro/vba.]

Similarly, each activity in a P6 schedule includes both “Predecessors” and “Successors” list fields, but these lists include only the IDs of the connected activities – relationship types are excluded.  P6 16.1 and later releases include two additional fields – Predecessor Details and Successor Details – that include relationship types and may be easily included in a filter specification using the above criteria.  Users who have not updated to P6 16.1 or later – and who do not have access to an add-in like Acumen Fuse or Steelray – may export the activity and relationship information to a spreadsheet for analysis.  (Spreadsheet analysis of the P6 data is generally more straightforward than for MSP.)

Consequences of Dangling Logic

The primary consequence of dangling logic in a project schedule is an initial/Baseline plan that is not reliable due to the omission of substantial sequential constraints.  For example, many fast-track design-build projects require the start of field work before the completion of engineering, and sometimes the final engineering works are either left dangling or are tied only to a generic project completion milestone.  The logical ties between certain engineering activities and the necessary quality assurance and commissioning activities may be inadvertently omitted.  Without complete logic, neither the early (CPM) dates nor the late dates for the project are reliable.  Total Float shown for the later engineering activities and for their latent/unlinked successors may be excessive.  Since Total Float and the Critical Path definition are unreliable as a result of missing logic, the Baseline project schedule does not provide a suitable basis for monitoring progress or for evaluating potential delays.

Many project schedules may appear acceptable at the time of Baseline review, but dangling starts and finishes can severely compromise their usefulness during the project execution.  This is ultimately because actual durations invariably differ from baseline durations, but the secondary relationships that are needed to ensure logic integrity are missing.  In other words, the schedule model fails to reflect the real consequences of activity delays that appear during schedule updates.  The flaws in the schedule logic become obvious, and credibility is lost.

Schedule Risk Analysis is aimed at quantifying, typically through simulation, the consequences of uncertainty in schedule durations.  Since the intent of a simulation is to repetitively reproduce the consequences of changed durations in the schedule, the model weaknesses that affect the schedule update process also affect the outcome of the simulation.  Therefore, risk simulation of a project schedule with dangling logic is not reliable.

Terminology for Dangling Logic

Dangling logic – and particularly dangling starts and finishes – have been identified as such in the literature for at least 10-15 years.  See http://www.projectrisk.com/white_papers/The_Problem_with_Dangling_Activities_in_Project_Schedules.pdf.

Although the two concepts of dangling logic described here (i.e. the CPM and PDM varieties) are fairly straightforward, there is not uniform agreement on the terminology.

The Practice Standard for Scheduling, Second Edition (2011), published by the Project Management Institute (PMI) limits its “dangling” logic discussion to the PDM variety.  It describes “dangling” activities as activities that don’t “have an FS or SS predecessor and an FS or FF successor.”  In this standard, “Open-Ended Activities” include those “lacking either a predecessor or a successor or both.”  Thus, while not explicitly stated, “Open-Ended Activities” are a subset of dangling activities.

PMI’s Scheduling Excellence Initiative Committee has described a dangling activity somewhat vaguely.  The Committee’s CPM Scheduling for Construction: Best Practices and Guidelines (published by PMI, 2014) provides the following definition – “Dangling Activity: An activity tied from only one end (start or finish). A dangling activity has only a predecessor(s) or successor(s), not both.”  This definition clearly combines the two concepts without distinguishing between them.  “Dangling” references in the text are limited to the CPM, or open-ends, concept.

CPM in Construction Management, Eighth Edition (2016), a graduate-level textbook and respected reference book for serious construction planners and schedulers, contains only a single reference to “dangling activities” as something to be precluded.  It does not otherwise describe or define them.  The book briefly discusses dangling starts/finishes as a problem unique to PDM schedules, but it uses the term “orphaned relationships” rather than “dangling”.

The US’s Government Accounting Office (GAO) and Defense Contract Management Agency (DCMA) both align with the PMI practice standard, describing dangling activities according to the PDM concept.  From GAO-16-89G, Schedule Assessment Guide; Best Practices for Project Schedules (2015) – “Dangling activities: number of remaining detail activities and milestones with no predecessor on start date” and “Dangling activities: number of remaining detail activities and milestones with no successor off finish date.”    (As of the 21Nov’09 revision, DCMA’s 14-Point assessment guidelines provide comparable definitions and a “general rule to avoid Dangling Activities” under Metric #1: Logic.  They are NOT explicitly included in the metric, however.)  Open-ended logic (i.e. the CPM variety of dangling logic) is simply identified as “missing logic,” “missing predecessors,” or “missing successors.”  This is the source of DCMA’s Metric #1.

The Planning & Scheduling Excellence Guide (PASEG v3, 2016), published by the National Defense Industry Association,  includes a brief section on Open Ended Tasks among things to avoid in its chapter on Horizontal Traceability.  This section mentions “dangling logic” (specifically a dangling finish) as something to be avoided because it invalidates schedule risk assessment.  Neither term is formally defined in the guide.

AACE International (formerly the Association for the Advancement of Cost Engineering) publishes a number of recommended practices (RPs) related to project scheduling.  Unfortunately RP 10S-90: Cost Engineering Terminology (which is routinely updated to reflect the development of related standards and RPs) includes a definition for “Open-Ended Activities” only.  It ignores dangling logic of the PDM variety.

Dangling Logic in BPC Logic Filter

Users of BPC Logic Filter for Microsoft Project can execute the Project Logic Checker to isolate dangling logic and other issues affecting project schedule integrity.  The PMI/GAO definitions are used.  This figure shows the same schedule depicted in the network diagram at the beginning of this post – after running the Project Logic Checker.  The five “No Predecessors” and two “No Successors” tasks (including start and finish milestones) are clearly tagged and summarized, as are two dangling-finish tasks.

Video – Inspect and Step through Network Logic Links Using BPC Logic Filter

I’ve been using the JUMP buttons on the task logic inspector windows – a lot.  These are great complements to the rest of BPC Logic Filter.

[Dec’20:  Here’s a different demo of the Limited Logic Inspector – essentially the same inspection and jumping functionality, but without the extra logic analysis.]

 

 

How to Model Waiting Times in Microsoft Project

Mandatory waiting times between certain tasks are a common feature of many project schedules.  In construction, the typical example is concrete curing time.  That is the time interval (typically under a week) after a batch of concrete is placed but before it gains sufficient strength to remove/strip the formwork and continue working.  Similar wait times can be required in non-construction projects. Common features of such waiting times are:

  • The waiting time is not associated with productive work;
  • The waiting time is independent of any Project, Task, or Resource calendar.  That is, it takes place around the clock, independent of weekends and holidays.

Consider a 5-day curing time in a Microsoft Project (MSP) schedule using the default Standard calendar (i.e. 5dx8h Monday-Friday work week).  The curing process always occurs over a mix of working and non-working (night and weekend) time.  Since the number of workdays included in this period varies from three to five depending on the time and day of the week that the concrete placement finishes, it is not possible to specify a fixed curing duration (in Standard-calendar workdays) without introducing an unnecessary delay in the schedule.

Instead, there are four obvious modeling techniques to accurately schedule the curing and follow-on activities:

  1. Create a “cure” task with a “5-day” duration and assign a 7-day x 24-hour calendar to the task.
  2. Create a “cure” task and assign a duration of 5 “elapsed” days.
  3. Don’t create a “cure” task.  Instead model the curing time as a 5-elapsed-day lag between the “place concrete” and “strip forms” tasks.
  4. Create a “cure” task with a 5-day duration and assign a modified 7-day weekly calendar to the task.

As shown in the figures, all four techniques can be used to generate the same (early) schedule dates for the project.  Which technique to use depends on a few factors.

  •  Within MSP, a “day” is fundamentally defined according to the “hours per day” setting for the project, and any “day” entries are automatically converted to minutes using that setting.  With default settings, one “day” is 8 hours (i.e. 480 minutes).  This can lead to confusion when calendars are changed or assigned without taking the setting into account.  For example, when a 24-hour calendar is assigned to a 3-day-duration task in a project with default (i.e. 8 hours/day) settings, then the task will finish in 24 hours (i.e. 1 calendar day).   Under the same conditions, a curing time of 5 calendar days (i.e. 120 hours) would require a specified task “duration” of 120/8 = 15 days.  To minimize such confusion, it is a good practice to specify durations in hours when 24-hour calendars are applied, as shown in the figure.
  • For most purposes, assigning an “elapsed days” duration is functionally equivalent to applying a 24-hour calendar to the task and making the necessary duration adjustments.  This can reduce confusion associated with the hours per day setting.  The two techniques yield identical results in the example.
  •  Using an elapsed-lag instead of a dedicated task is functionally simple to implement, and many project schedulers routinely use this approach.  Nevertheless, lags are generally discouraged or prohibited by some scheduling specifications and recommended practices for good reasons.  Chiefly, lags can substantially affect schedule dates while remaining relatively invisible on typical schedule documents – this makes them easy to abuse for date-manipulation.  In addition, unlike tasks, lags are not easily incorporated into external algorithms for evaluation or manipulation of project schedules – e.g. for risk simulation. This can substantially degrade the value of such algorithms.
  • Total Slack calculations are substantially complicated by the impacts of multiple calendars (including the use of elapsed durations).  Since MSP relies solely on Total Slack to identify “Critical” tasks, the true Critical Path for the project can be inadequately described for any of these techniques.  For example, when the curing time finishes at the end of a workday in the middle of the work week, the “cure” task (on a 24-hour calendar) possesses 15 hours of Total Slack – MSP therefore excludes it from the Critical Path.  If instead of a 24-hour calendar, a modified (i.e. 7d x 8h, no-weekend) calendar is applied to the curing task, then the positive Total Slack is eliminated in this case, and the Critical Path is correct.  (This is shown at the top of the figure below.)  Unfortunately, the modified calendar is no better than the others if the curing time finishes on the weekend.  The 1 day of Total Slack causes the Critical Path to be truncated.  (See the lower half of the figure below.) 

Unfortunately, the only out-of-the-box method to ensure that the entire critical path is captured is to raise the Total Slack threshold from the default value (zero) to some number that is judged high enough to capture all the truly critical tasks. I have found such an approach unsatisfactory for a variety of reasons.  In any case, the true Critical Path – i.e. the driving logical path to project completion – remains obscured.

Fortunately, the Longest Path algorithm in BPC Logic Filter is indifferent to which modeling approach is used.  As shown in the figure below, the driving logical paths are correctly identified for each case.  (The number to the right of each bar is the task’s path relative float with respect to the project completion task – zero for the longest path.  BPC Logic Filter typically depicts logical driving paths with a dark red bar.)

Problems with Driving Logic in Task Inspector and Task Paths (Microsoft Project 2010-2016)

Neither the Task Inspector nor the “Task Path” bar highlighter is a reliable indicator of task driving logic in Microsoft Project in the presence of mixed-type predecessor relationships or Backward Scheduling. 

At first glance, the Task Inspector pane in Microsoft Project (MSP) seems to be a reasonable tool for revealing the logic that is largely hidden in project schedules.  After all, you just select a task, click “Inspect Task”, and MSP provides a hyperlinked list of “Predecessor Tasks” that are controlling the schedule dates of the selected task.  For simple (i.e. Finish-to-Start) relationships between tasks with no progress, this assumption seems generally correct.

Unfortunately, many times Task Inspector is just plain wrong. (The examples below are taken from a ~1000-task real-world project schedule with actual progress updates.  Task names were obfuscated for confidentiality).  Each example represents many more cases in the schedule.

1. Once an actual start is recorded, logical drivers constraining the finish are ignored.

2. In case of parallel FS and SS driving predecessors, the FS driver is ignored.

Here is the corresponding bar highlighting from Task Path’s Driving Predecessors (MSP 2016).  The noted red bar should be orange like the one below it.

3. In case of parallel FS and FF driving predecessors, the FF driver is ignored.

3. In some (but not all) cases, an FF predecessor with substantial relative float is identified as the driving predecessor, while the true FS driver is ignored.

In general, the issues are present mainly in tasks with multiple predecessors of different types.  In forward scheduled projects, they are not found in un-started tasks whose predecessors are all of type Finish-to-Start.

The “Driving Predecessors” bar highlighter of the Task Path tool in Microsoft Project Professional 2016 has the same issues as the Task Inspector results shown here.  They are both consistent with the StartDriver object for each task.  Any driving-logic tracer based on the StartDriver object – including those provided in my blog (Macro for Listing Driving Predecessors and QuickTrace Macros ) – has similar issues.

In the examples above, the task predecessors are displayed in Logic Inspector views from BPC Logic Filter (our MSP Add-in).  Predecessors are “driving” if their relative floats are zero; i.e. there is no working time between the corresponding predecessor and successor dates.  The driving predecessors identified in the examples are easily confirmed by examining the dates.  [Though illustrated mostly using Microsoft Project Professional 2010, all examples have been confirmed in Microsoft Project Professional 2016.]

Though not really highlighted here, it bears noting that MSP’s “driving logic” indicators are completely oblivious to resource-leveling decisions.  Thus, resource-driving logic is not addressed.  In contrast, BPC Logic Filter handles resource-driving logic quite well.

On Manually Scheduled Tasks [Aug’18 Edit]

If a manually scheduled task has predecessors, then MSP will identify one or more of them as the driving predecessor even when the manual scheduling has substantially delayed the task compared to the logic requirements.  This is one of the few factors differentiating a manually scheduled task from a normal (i.e. automatically scheduled) task with a mandatory constraint.  In this case, the Task Path “Driving Predecessors” bar highlighter ignores the delay and continues to trace “driving” logic through the identified start drivers.  (The Task Inspector suggests that the user either accelerate the task to remove the delay or convert the task to automatic scheduling.)  As a consequence, a schedule with manually scheduled tasks can have a driving path to project completion (according to Task Path) that is substantially different from the Critical Path that is based on Total Slack.

In Backward Scheduled Projects [Jan’19 Edit]

As pointed out in this recent article, neither the Task Inspector nor Task Path bar styles are useful in backward scheduled projects.

 

 

Inspecting Task Links with BPC Logic Filter for Microsoft Project

BPC Logic Filter – an add-in for Microsoft Project (desktop) – includes an advanced Logic Inspector feature to greatly simplify the examination and navigation of logic-driven schedule activities.

When building or managing a complex project schedule, it’s often necessary to examine the logical relationships between tasks for a variety of reasons.  Particular questions for any given task include:

  1. What other tasks must finish (or start) before this task may start (or finish)? (i.e. what are its predecessors and how are they related?)
  2. Of all the task’s predecessors, which ones are actually controlling the scheduled dates for this task? – i.e. what are its driving predecessors?
  3. For the task’s non-driving predecessors, how much may each be allowed to slip before it becomes driving (for this task)? – i.e. what is the relative float?
  4. a)What other tasks must wait for this task to finish (or start) before they can proceed? – i.e. what are its successors?  b)Which successors are driven? c)How much relative float exists?

For users of Microsoft Project (MSP), questions 1 and 4a are most easily answered using the “Predecessors and Successors” view of one of the Task Forms in the lower pane.  For simple schedules, question 2 can be answered by the “Predecessors” list of the Task Inspector pane.  For more complex schedules – and for all other questions – the user must visually cross-reference the scheduled dates of the various linked tasks from several views, estimating relative floats and identifying driving relationships.  This can be time consuming and error prone.  Beginning with the 2013 version, MSP provides “Task Path” bar styles, which visually identify driving and non-driving predecessor and successor paths (i.e. logically connected task chains) of any selected task on the bar chart.  These can be difficult to read, however, when the project logic is complex.

BPC Logic Filter has always answered these questions on the way to visualizing logic flow through a schedule, and several of the tracer analyses can be easily customized to examine only a single task and its links.  Since the tracers generally apply a custom filter to the schedule, however, the time to examine a single task could become unwieldy for a very large project.

The native MSP predecessor and successor tables provide only limited information: ID, Name, Type, and Lag – all sorted according to the order the links were initially created.  Here they are shown as part of the Task Details Form.  Further examination of any linked task can be achieved by double-clicking an entry in the Predecessor or Successor list to open the corresponding Task Information dialog.

In the LLI Edition of  BPC Logic Filter, clicking the Logic Inspector button creates two new floating windows that summarize logic-related information about the selected task as well as its predecessor and successor tasks.

Logic-related properties for the selected task – remaining duration, total slack, constraints, deadlines, scheduled dates, resources, and calendar – are included for reference above each table.  Colored highlighting and other indicators are used to emphasize properties with notable influence or relevance to the current schedule.  E.g. summary or inactive status, effective constraints, violated constraints and deadlines, actualized dates, and leveled resources.

In contrast to the native forms, Logic Inspector provides a richer relationship table, including scheduled dates (with Actual indicators), % complete, total slack, and two user-selected fields for each predecessor and successor task.  Inactive tasks (in MS Project Pro 2010+) are also highlighted gray.  The scroll and fix buttons allow dynamic resizing and other controls of window appearance.  In the LLI Edition, the predecessor and successor tasks are ordered the same as in the native lists, which generally reflect the sequence in which the relationships have been added to the model.

Most importantly, the JUMP button allows logic-based navigation forward and backward through the schedule network one task at a time.  Jumping to another task using the button automatically updates the predecessor and successor forms.  [See also Video – Inspect and Jump through Network Logic Links Using BPC Logic Filter – LLI Edition]

While the LLI (for Limited Logic Inspector) Edition of BPC Logic Filter is aimed at schedulers looking to quickly inspect and jump through relationships, the STD Edition adds robust analysis and reporting of driving logic in the schedule.  Thus, the Logic Inspector of the STD Edition also analyzes and sorts relationships on the basis of driving logic flow.

As a result, driving logic relationships are highlighted yellow and shown at the top of each list.  The first of these becomes the default target for the Jump button, allowing quick navigation through driving logic paths.  The relationships that are furthest from driving are shown at the bottom.  (As a corollary to this, Inactive tasks in MSP 2010 are relegated to the bottom of the list, while Inactive tasks in later versions may sometimes be shown as driving or near driving, depending on their dates.)  The Std Edition also allows display of MSP’s internal “driving/driven” flag for each relationship: the basis of the corresponding Task Path bar styles as well as the Predecessors portion of the Task Inspector pane.  These internal flags are sometimes incorrect, leading to a false “Driving Predecessors” Task Path.    Finally, several types of hierarchical driving logic can be added to the Logic Inspector Windows.

The Std Edition also adds the ability to Jump to and/or through tasks that are hidden in the current view and to build a custom task filter using Jump.

The Pro version adds extensive capabilities for analysis of relationship and path relative float.  Within the Logic Inspector, this means additional columns to display up to four different types of relative float for each relationship.  More importantly, late-driving and bi-directional-driving relationships are highlighted by default.  These are particularly useful for prioritizing multiple driven successors of a particular task.  In the example, this option leads to a re-sorting of the successor tasks, with one of the two driven successors from the Std Edition now being flagged and prioritized.  (This successor task, 1439, controls the late-dates of the selected task; the relationship is driving in both directions.)

Since implementation, I’ve found Logic Inspector to be an invaluable – and fast – complement to the rest of the features in BPC Logic Filter.  The two new windows are passive readers of existing project data; they are not for adding, removing, or modifying relationships.  MSP already provides a number of different approaches there.

Here’s another, older video showing an earlier, less-capable version of the feature in action.

Using Logic Inspector to examine resource drivers is addressed in another post.

Microsoft Project Schedule Health Checking and Fixing using BPC Logic Filter

Regular users of BPC Logic Filter will have noticed some modest changes with the recent release of version 1.2.  The ribbon has been slightly revised, and two new buttons have been added: “Project Logic Checker” and “Logic Quick Check”. The second is essentially an abbreviated version of the first.

The Project Logic Checker examines every task in the project and flags the following logic issues for closer review or action:

Task Definition Issues
  • Manually-scheduled tasks (By definition, these are incompatible with logic-driven scheduling.)
  • Inactive tasks (In MSP 2010, these are essentially ignored. In MSP 2013+ they are essentially included in the schedule calculations as zero-duration tasks.)
  • External tasks and external links (Scheduling of tasks with external links can change depending on whether the source schedules of the external tasks are available and open.)
  • (Hammock) tasks made with OLE links (OLE links typically impose persistent logic constraints.)
  • Summary tasks with Logic (Hierarchical logic can override precedence logic in the schedule calculations and cause confusion.)
  • Tasks with Logic on Parent Summaries  (These tasks may be controlled by non-precedence logic.)
  • Constraints and Deadlines (“Must Start/Finish On” constraints are “Hard” constraints since they can override logic.  In addition, “Start/Finish No Later Than” constraints are included as “Hard” constraints ONLY when “Tasks will always honor their constraint dates” is checked (i.e. the default value).  These are always “Hard” constraints according to 2009 DCMA 14-Point Assessment guidance.)
  • Duplicate Task Names (Duplicate task names force reliance on a task’s outline hierarchy for recognition of task scope.  Development and analysis of the project logic then becomes inefficient or impossible.)    
TASK Relationship ISSUES
  • Missing logic; that is “Open Ends,” including Dangling Starts and Finishes.  (Schedules with these conditions are unreliable.)
  • Relationship Lags and Leads (i.e. negative lags) that that are excessive with respect to the associated task durations (Ideally, logic driven schedules use explicit tasks for all time-consuming activities.  Substantial leads and lags are incompatible with schedule risk assessment and are generally considered poor practice.)
  • Relationships that are not Finish-to-Start (Some scheduling philosophies mandate only Finish-to-Start relationships.)
  • Relationships that are Start-to-Finish (These relationships are extremely rare in actual project schedules, but they are often used incorrectly.)
  • Merge Points in the schedule (i.e. tasks with a high number of immediate predecessors)
  • Reverse Logic Flow through the task’s duration; i.e. shortening the task delays the successor, and lengthening the task may accelerate the successor.  (See this entry).
  • Neutral Logic Flow through the task’s duration; i.e. shortening or lengthening the task has no impact on the successor.
  • Links to inactive tasks  (Depending on the MSP version being used, such links can alter the schedule unexpectedly.)
Task Update ISSUES
  • Invalid Dates, including incomplete work in the past and completed work in the future (with respect to the Status Date)
  • Splits
  • Out-of-sequence progress
  • Tasks that have missed their target/baseline finish date (as of the status date.)
Other TASK ISSUES
  • Overlong task durations
  • False Milestones (i.e. “Milestones” with non-zero durations)
  • Excessive or negative values for Total Slack

Users can include or exclude any desired checks from the analysis – or adjust associated thresholds – using the Checker Preferences.

The tool automatically restricts the view to show only tasks with logic issues, then it presents an output form that a) summarizes the analysis, and b) allows the user to dynamically modify the filter for pinpoint focus.

For example, here is a highly summarized, ~3300-task, proposed recovery schedule for a troubled international construction project. The Settings window confirms that the logic checker will examine most non-resource-related issues but will ignore the long-duration and high-slack checks for now.

Running the Project Logic Checker identifies and presents over 1500 tasks with logic issues (perhaps a hint to the source of the project’s “troubles.”) The user can then use the output form to reduce or expand the view.

Here’s a close-up of the output/filter form, slightly improved from the one shown in the other figures:

For example, by un-checking all but the Dangling Start box and then clicking filter, I can choose to see only the tasks with Dangling Starts, i.e. tasks with predecessors but without start-predecessors.

Then, I can check only the False Milestones box to see – and correct – the 17 tasks that are coded as milestones but possess a non-zero duration.

Of course, if I’m only interested in one issue – Logic on Summary Tasks for example, than I can begin by excluding all the other issues from the analysis. The result is a (slightly) less cluttered picture.  This one highlights the four summary tasks with logic and the forty-four subtasks that are (or may be) affected.

The dynamic re-filtering requires full data persistence (in the general settings), and the bar labeling only works if “Re-color Bars” is selected (in the bar settings).

For schedulers and schedule reviewers, the new Project Logic Checker provides an action-focused basic schedule health check functionality that can be leveraged off the various logic tracers included in the tool.  There is no fancy dashboard and no pass/fail metrics based on odd ratios.  For now I think I prefer it that way.

Macro for Tracing, Filtering, and Sorting Task Paths in Microsoft Project

Here are three macros (collectively called QuickTrace) to display the logical predecessors or successors (or both) of the selected task – filtering out all others – and sorted by logical path.  The filter can be limited to show all logic or only “driving” logic.  There is also a highlight-only option.

With the apparent demise of Mike Dahlgren’s site, masamiki.com, his “Trace” macro seems to no longer be generally available.  (It’s also a violation of his site’s terms of use to re-distribute code that was obtained there.)  My entry on Listing Driving Predecessors has been getting a lot of traffic from people who (I suspect) are trying to find a variation of Trace.  In response to a question over at MPUG today, I decided to write up something – what I call QuickTrace – to generate similar output for sharing.  It is after all less than a hundred lines of code.  [Note: The code here works for all modern – i.e. 2007 and later – versions of MSP.  If you are already using the “Task Path” bar styles in MSP 2013+ and are looking for a compatible filter, then have a look at my other article: Macro for Filtering based on “Task Path” in Microsoft Project.]

For determining driving relationships, QuickTrace relies on MSP’s “StartDriver” task object, the basis of the Task Inspector pane (and the “Task Path” Driving Predecessors and Driven Successors bar styles in MSP 2013+).  This is a substantial improvement over the original Trace macro, which used Free Slack as the driving indicator.  Still, I’ve found StartDriver to be unreliable in the presence of non-FS relationships (See here.)  BPC Logic Filter (our MSP Add-In) instead identifies driving relationships directly by computing and examining relationship free floats – quite a bit more involved.

[Jan’19 Edit: QuickTrace also relies on recursion (a sort of repeated self-cloning process), and this makes it susceptible to crashing if the path length (i.e. the number of tasks in sequence) is too long.  In MSP 2010, I’ve analyzed path lengths a bit over 4,000 tasks before crashing.  The same analysis in MSP 2016 leads to a crash after only 700 tasks.

Version 1.5 of BPC Logic Filter now includes a QuickTrace option.

This implements the same recursive tracing algorithm that I’ve included in the macro code.  It’s blazing fast, and its results are perfectly aligned with the Task Path bar styles of MSP 2013+, no matter how flawed.  It also handles much longer path lengths (just under 8,000 tasks in MSP 2016) before running out of memory.]

Here’s the code. There are basically three front-end macros that you can assign buttons or hot keys to, one for predecessor chains, one for successor chains, and one for both.  (Using the last one can make the resulting path sort a little jumbled, so I made re-sorting optional.)    These call the other procedures to a) collect user input; b) clear existing values in the Flag4 and Number5 fields; c) recursively run through the chains of related tasks and and mark them using those fields; d) apply the filter and sort using those fields; and e) display a message box summarizing the filter/highlighting.  Note, this is provided as-is and is not supported by anyone.  I have not taken the time to accommodate every possible situation and won’t be doing so in the future.  If you are new to vba, please google around a bit before asking questions that are already answered somewhere else – that includes, “how do I install this and make it work?”  (Short answer: copy and paste the entire block into a new module in the visual basic editor.  Then add the three front-end macros to a custom group on one or more of your ribbon tabs.)

'QuickTrace Module
'Coded by T.Boyle, PE, PSP on 16Mar'17 [25Sep'18 edits - to allow highlighting, to provide a descriptive message box
'   after running, and to streamline the code.]  This Module is intended to trace logical paths from the selected task
'   to all of its predecessors or successors, then show only related tasks.  Tasks are sorted in the order of analysis,
'   which generally corresponds to identified logical "paths".
'CAVEATS:
'   1. This code WILL OVER-WRITE fields FLAG4 and NUMBER5.  Make sure these fields are not needed before running.  Otherwise,
'      edit the code to use different fields, as shown below.
'   2. This code relies on the StartDriver object for defining driving path logic.  It may not always be reliable for non FS
'      relationships.
'   3. Install all code into a new module, with "QuickTrace Module" above as the top line.
'   4. Assign buttons or hotkeys to the first three procedures only (the others are called by these three):
        'a. CallQTraceP() - Traces predecessors.
        'b. CallQTraceS() - Traces successors.
        'c. CallQTraceB() - Traces both predecessors and successors (Added 15Nov'17)
'
 
Option Explicit
Private Cnt As Long, Driv As Boolean, HL As Boolean, ShowSums As Boolean, Tsel As Task, DirGlob As String
 
Sub CallQTraceP()
    'This procedure finds, marks, filters, and sorts predecessors of the selected task.
    'Run this directly using a button or hot key
     
    Cnt = 0
    DirGlob = "P"
        
    ClearFields
    CollectInput
    'Run Trace from Selected cell
    Call QTrace(Tsel, "P")
    Call Filter("P")
 
End Sub
 
Sub CallQTraceS()
    'This procedure finds, marks, filters, and sorts successors of the selected task.
    'Run this directly using a button or hot key
     
    Cnt = 0
    DirGlob = "S"
        
    ClearFields
    CollectInput
    'Run Trace from Selected cell
    Call QTrace(Tsel, "S")
    Call Filter("S")
 
End Sub
 
Sub CallQTraceB()
    'This procedure finds, marks, filters, and sorts both predecessors and successors of the selected task.
    'Run this directly using a button or hot key
     
    Cnt = 0
    DirGlob = "B"
        
    ClearFields
    CollectInput
    'Run Trace from Selected cell
    Call QTrace(Tsel, "P")
    Call QTrace(Tsel, "S")
    Call Filter("P")
 
End Sub
 
Sub QTrace(ByRef t As Task, ByVal dir As String)
    'This procedure marks a task (as related) and calls itself for each related predecessor or successor.
    'This procedure is called by another procedure.
     
    Dim d As TaskDependency
    Dim ds As TaskDependency
     
    'Mark this task as related
    Cnt = Cnt + 1
    '''''''''''''''''''''''''''''''''''''''''''''Edit Fields Flag4 and Number5 as Needed'''''''''''''''''''''''''''''''''''''''''
    t.Flag4 = True
    t.Number5 = Cnt
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     
    'Recurse to next dependency
    If Driv Then
        If dir = "P" Then
            For Each d In t.StartDriver.PredecessorDrivers
                Call QTrace(d.From, "P")
            Next d
        Else 'i.e. dir="S"
            For Each ds In t.TaskDependencies
                If ds.From = t Then
                    For Each d In ds.To.StartDriver.PredecessorDrivers
                        If d.From = t Then Call QTrace(d.To, "S")
                    Next d
                End If
            Next ds
        End If
    Else
        For Each d In t.TaskDependencies
            If dir = "P" And d.To = t Then Call QTrace(d.From, "P")
            If dir = "S" And d.From = t Then Call QTrace(d.To, "S")
        Next d
    End If
End Sub
 
Sub CollectInput()
    'This procedure collects user input.
    'This procedure is called by another procedure.

    Driv = False
    HL = False
    ShowSums = False
    
    Set Tsel = ActiveCell.Task
    If MsgBox("Driving Path only?", vbYesNo) = vbYes Then Driv = True
    If MsgBox("Highlight only?", vbYesNo) = vbYes Then
        HL = True
    Else
        If MsgBox("Show Summary Tasks?", vbYesNo) = vbYes Then ShowSums = True
    End If

End Sub
Sub ClearFields()
    'This procedure runs through the tasks of the active project and clears two selected fields for use.
    'This procedure is called by another procedure.
     
    Dim t As Task
    'Clear Fields
    For Each t In ActiveProject.Tasks
        If Not t Is Nothing Then
    '''''''''''''''''''''''''''''''''''''''''''''Edit Fields Flag4 and Number5 as Needed'''''''''''''''''''''''''''''''''''''''''
            t.Flag4 = False
            t.Number5 = 0
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        End If
    Next t
End Sub
 
Sub Filter(ByVal dir As String)
    'This procedure creates and applies a filter to show only related tasks.
    'This procedure is called by another procedure.
     
            '''''''''''''''''''''''''''''''''''''''''''''Edit Field Flag4 as Needed'''''''''''''''''''''''''''''''''''''''''
            FilterEdit Name:="Flag4", TaskFilter:=True, Create:=True, _
                OverwriteExisting:=True, FieldName:="Flag4", Test:="equals", _
                Value:="Yes", ShowInMenu:=True, ShowSummaryTasks:=ShowSums
            FilterApply Name:="Flag4", Highlight:=HL
            '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
        
        If ShowSums Then '(HL is False)
            'Sort by path order
            If MsgBox("Resort to show paths?", vbYesNo) = vbYes Then
            '''''''''''''''''''''''''''''''''''''''''''''Edit Field Number5 as Needed'''''''''''''''''''''''''''''''''''''''''
                If dir = "P" Then Sort Key1:="Number5", Ascending1:=False, Renumber:=False, Outline:=True
                If dir = "S" Then Sort Key1:="Number5", Ascending1:=True, Renumber:=False, Outline:=True
            '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            End If
        Else '(ShowSums is False and HL may be true or false)
            If Not HL Then
            'Sort by path order
                If MsgBox("Resort to show paths?", vbYesNo) = vbYes Then
            '''''''''''''''''''''''''''''''''''''''''''''Edit Field Number5 as Needed'''''''''''''''''''''''''''''''''''''''''
                    If dir = "P" Then Sort Key1:="Number5", Ascending1:=False, Renumber:=False, Outline:=False
                    If dir = "S" Then Sort Key1:="Number5", Ascending1:=True, Renumber:=False, Outline:=False
            '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
                End If
            End If
        End If
        EditGoTo ID:=Tsel.ID
        FilterBox
End Sub
        
Sub FilterBox()
    'This procedure creates and displays a message box describing the filter/highlight basis.
    'This procedure is called by another procedure.
    Dim Msg As String
    
    If HL Then
        Msg = "Highlighting "
    Else
        Msg = "Filtering for "
    End If
    
    Select Case DirGlob
        Case "P"
            If Driv Then Msg = Msg & "driving "
            Msg = Msg & "predecessors "
        Case "S"
            If Driv Then Msg = Msg & "driven "
            Msg = Msg & "successors "
        Case "B"
            If Driv Then Msg = Msg & "driving & driven "
            Msg = Msg & "predecessors & successors "
    End Select
    
    Msg = Msg & "of task " & Tsel.ID & ": " & Tsel.Name & " (inclusive)"
    MsgBox Msg
    
End Sub


[Aug’18 Edit:] One of the commenters sent an example of a schedule where the macro includes in the driving path to project completion two tasks that are in fact neither critical nor driving .  As shown below, the Task Path functionality is used to highlight the “Driving Predecessors” to Task 13 (orange bars).

Tasks 21 and 22 are included in the Task Path highlighting, and they are also flagged as part of the Driving Path (to Task 13) by the QuickTrace macros.  This is because MSP has marked Task 22 as the StartDriver predecessor for Task 26.  As a manually-scheduled task, however, Task 26 really has NO StartDriver predecessor, and the reference to Task 22 is incorrect.  Neither the macro nor the Task Path function has been adapted to account for this.  (BPC Logic Filter correctly excludes these non-driving tasks, and MSP marks them as non-critical because they possess positive Total Slack.)