Macro for Filtering based on “Task Path” in Microsoft Project

Here in the TaskPathFilters module, I provide five simple macros for applying a filter (or table highlighting) that corresponds to Task Path bar highlighting output.

For users of Microsoft Project 2013+, including the desktop versions of Project for Office 365, the Task Path bar styles provide a useful method for highlighting logical connections between tasks.  Four different sets of bar styles can be created, corresponding to the Predecessors, Driving Predecessors, Successors, and Driven Successors of the selected task.  Unfortunately, the “show for…” criteria used to apply the bar styles are not available for creating a filtered display of tasks – say the driving path to a key milestone – while hiding the non-driving tasks.

[The “driving” and “driven” Task Paths are defined (by MSP) using the task StartDriver object, the same as in the Task Inspector.  As shown here, StartDriver has proven unreliable in identifying driving logic in the presence of non-FS relationships, actual progress, splits, and resource leveling.

In another blog entry here, you can find a set of macros for duplicating the results of the Task Path bars, with the added benefit of being able to re-sort tasks according to logic flow, so concurrent logic paths are easily separated.  Those macros use the same underlying data as Task Paths, so their results should be identical to these.  Unlike these, they can be used in versions of MSP prior to 2013.]

Here’s the code (requires MSP 2013+).

Note, for real logic analysis, have a look at BPC Logic Filter.

'TaskPathFilters Module
'This module includes four procedures to mark tasks according to their TaskPath
'characteristics.  A fifth procedure applies a filter to display only the marked tasks.
'The module is intended only for users of Microsoft Project 2013+, which incorporates TaskPath
'formatting of task bars.  If the applicable TaskPath formatting has not been applied,
'then no filter will be created.  VBA code developed by TMBoyle, 14Sep'18
'   1. Install all code into a new module, with "TaskPathFilters Module" above as the top line.
'   2. Assign buttons or hotkeys to the first four procedures only (the other one is called by these):
        'a. AllTaskPathFilter() - Filters all the marked task paths.
        'b. TaskPathPredecessorFilter() - Filters the marked "predecessors" of the selected task.
        'c. TaskPathDrivingPredecessorFilter() - Filters the marked "driving predecessors" of the selected task.
        'd. TaskPathSuccessorFilter() - Filters the marked "successors" of the selected task.
        'e. TaskPathDrivenSuccessorFilter() - Filters the marked "driven successors" of the selected task.
'
Public MsgBase As String, Tsel As Task
Sub AllTaskPathFilter()
    Dim t As Task
    Dim Apply As Boolean
    
    Set Tsel = ActiveCell.Task
    For Each t In ActiveProject.Tasks
        If Not t Is Nothing Then
            If (t.PathPredecessor = True) Or (t.PathDrivingPredecessor = True) Or _
                (t.PathSuccessor = True) Or (t.PathDrivenSuccessor = True) Then
                t.Marked = True
                Apply = True
            Else
                t.Marked = False
            End If
        End If
    Next t
    Tsel.Marked = "Yes"
    If Apply Then
        MarkedFilter
        MsgBox (MsgBase & "All Selected for task " & vbCrLf & _
            Tsel.ID & " - " & Tsel.Name)
    Else
        MsgBox "No Filter Applied."
    End If
End Sub
Sub TaskPathPredecessorFilter()
    Dim t As Task
    Dim Apply As Boolean
    
    Set Tsel = ActiveCell.Task
    For Each t In ActiveProject.Tasks
        If Not t Is Nothing Then
            If t.PathPredecessor = True Then
                t.Marked = True
                Apply = True
            Else
                t.Marked = False
            End If
        End If
    Next t
    Tsel.Marked = "Yes"
    If Apply Then
        MarkedFilter
        MsgBox (MsgBase & "Predecessors of task " & vbCrLf & _
            Tsel.ID & " - " & Tsel.Name)
    Else
        MsgBox "No Filter Applied."
    End If
End Sub

Sub TaskPathDrivingPredecessorFilter()
    Dim t As Task
    Dim Apply As Boolean
    
    Set Tsel = ActiveCell.Task
    For Each t In ActiveProject.Tasks
        If Not t Is Nothing Then
            If t.PathDrivingPredecessor = True Then
                t.Marked = True
                Apply = True
            Else
                t.Marked = False
            End If
        End If
    Next t
    Tsel.Marked = "Yes"
    If Apply Then
        MarkedFilter
        MsgBox (MsgBase & "Driving Predecessors of task " & vbCrLf & _
            Tsel.ID & " - " & Tsel.Name)
    Else
        MsgBox "No Filter Applied."
    End If
End Sub

Sub TaskPathSuccessorFilter()
    Dim t As Task
    Dim Apply As Boolean
    
    Set Tsel = ActiveCell.Task
    For Each t In ActiveProject.Tasks
        If Not t Is Nothing Then
            If t.PathSuccessor = True Then
                t.Marked = True
                Apply = True
            Else
                t.Marked = False
            End If
        End If
    Next t
    Tsel.Marked = "Yes"
    If Apply Then
        MarkedFilter
        MsgBox (MsgBase & "Successors of task " & vbCrLf & _
            Tsel.ID & " - " & Tsel.Name)
    Else
        MsgBox "No Filter Applied."
    End If
End Sub

Sub TaskPathDrivenSuccessorFilter()
    Dim t As Task
    Dim Apply As Boolean
    
    Set Tsel = ActiveCell.Task
    For Each t In ActiveProject.Tasks
        If Not t Is Nothing Then
            If t.PathDrivenSuccessor = True Then
                t.Marked = True
                Apply = True
            Else
                t.Marked = False
            End If
        End If
    Next t
    Tsel.Marked = "Yes"
    If Apply Then
        MarkedFilter
        MsgBox (MsgBase & "Driven Successors of task " & vbCrLf & _
            Tsel.ID & " - " & Tsel.Name)
    Else
        MsgBox "No Filter Applied."
    End If
End Sub

Sub MarkedFilter()
Dim HL As Boolean

    If MsgBox("Apply Highlighting Only?", vbYesNo) = vbYes Then
        HL = True
        MsgBase = "Highlighting TaskPath "
    Else
        MsgBase = "Filtered for TaskPath "
    End If
    On Error Resume Next
    FilterApply Name:="Marked Tasks", Highlight:=HL
    If Err.Number <> 0 Then
        FilterEdit Name:="Marked Tasks", TaskFilter:=True, Create:=True, OverwriteExisting:=True, _
           FieldName:="Marked", Test:="equals", Value:="Yes", ShowInMenu:=True, ShowSummaryTasks:=True
        FilterApply Name:="Marked Tasks", Highlight:=HL
    End If
    EditGoTo ID:=Tsel.ID
End Sub


Why I Left LinkedIn Groups

LinkedIn Groups are dead to me.  Today I removed my membership in all 22 Groups that I had joined since creating my LinkedIn account nearly 13 years ago.  For a long while during those 13 years, Groups seemed to provide the main forums for interesting discussions on project management topics, and a few web boards that had previously hosted those discussions became comparatively barren as a result.  Over the last several years, however, Groups have transformed from discussion forums into bazaars crowded with hawkers.  They’ve now become too noisy to stay and listen.

Here is a list of Groups’ problems that I’ve been compiling over the last 12 months or so:

  1. Barrage Marketing. I.e. >90% of thread initiators in some groups are links to external content, and there are few good discussions.  (One notable exception is the FIDIC Contracts group, which has a lot of active participants and seems to be extraordinarily well curated.  I’ll miss that one.)
  2. No retention of information. (Short memory and no search).  If you stumble upon or participate in a particularly edifying Group discussion – one that you may want to refer to later – don’t expect LinkedIn to archive it for you.  If it’s worth saving, copy and save it yourself.
  3. Classic Silos / Fragmentation of Discussion on common topics.  Whether asking a new and interesting question, sharing a Pulse article, or looking to drive traffic to an external website, thread-starters routinely cross-post the same entry to multiple groups.  (One day I encountered the same entry in eight or nine different groups.)  The scattered and disjointed comments that result can hardly be called discussions.
  4. Sloppy/repetitive discourse.  This is on the users.  E.g. ignoring all previous comments while simply repeating them.  Failure to “listen” before speaking. (There is no rational motivation for this.)
  5. Comments hierarchy.  The organization (i.e. grouping and sorting) of LinkedIn comments seems to vary depending on the client platform (e.g. mobile or desktop) and LinkedIn source (e.g. Group discussion, Pulse article, or Share).  Most of my interactions have been in Group discussions on a computer, where comments have been arranged (until recently) in flat chronological order.
  6. It’s difficult or impossible to filter views to see only “new” comments (i.e. since my last visit) or even “recent” comments (i.e. within the last day).  The “New conversations” control is not valid.
  7. Outright deletion of valid content by LI – e.g. truncation of discussions (while still leaving them open for further comments).  Deja vu!
  8. The last straw: it seems the September 2018 update to Groups has simply amplified all the negatives above.  Clicking a “Group” today reveals a simple stream of graphics-heavy linked content and ads for my consumption, hardly distinguishable from a Facebook or Twitter feed.  LinkedIn Groups is no longer a place to converse.  I’m done.

Relationship Free Float and Float Paths in Multi-Calendar Projects (P6 MFP Free Float Option)

This is a short article about the calculation and use of Relationship Free Float in Oracle Primavera P6, a project scheduling tool.  [It amends my previous entry on Total Float and Free Float Options in P6’s Multiple Float Path Analysis]

[The following few paragraphs are cribbed (with some edits to reflect improved understanding) from my own contribution to a discussion on Planning Planet a few years ago.]

Traditional notions of Total Float and Free Float are tied to the activities in the network, but they are not sufficient for evaluating logical float paths in complex CPM schedules, especially when variable calendars and/or late constraints are imposed.  Relationship floats are needed for identifying near-driving relationships and for multiple-float-path analyses.

Documentation seems very sketchy, but based on my own observations I believe relationship floats in P6 are calculated similarly to activity floats – that is

  1. The early and late dates of relationships are computed by treating them as activities (with single FS+0 links at each end) in the forward and backward passes through the network (Duration equals lag, normally zero).
  2. Relationship total float (RelTF) = relationship late finish (RelLF)  –  relationship early finish (RelEF); 
  3. Relationship free float (RelFF) = (Early Date of Relationship Successor Activity, ES for “FS” and “SS” links, EF for “FF” and “SF” links) – RelEF

The calendars used for the calculations seem to be as follows:

  • Early dates use predecessor calendar (from the forward pass)
  • Late dates use successor calendar (from the backward pass)
  • Relationship free float and total float use the predecessor calendar.

[Apr’19 Edit: Relationship Successor Total Float and Relationship Successor Free Float are derived from the same relationship dates, but using the successor calendar rather than the predecessor calendar.  (Figures now show both measures of relationship free float.)]

With multiple calendars, the driving and near driving paths revealed by Multiple Float Path (MFP) analysis are only partly correlated to the Relationship Free Float (and Relationship Successor Free Float) values displayed by P6.  These may require careful scrutiny to avoid misinterpretation in complex, multi-calendar projects, for the following reasons:

a) A relationship is “driving” when the successor activity possesses zero working time between the lag-adjusted predecessor and successor dates.  That is, the Relationship Free Float – according to the SUCCESSOR’s calendar (“Relationship Successor Free Float”) – is zero.

b) The Relationship Free Float that P6 displays (and that P6 appears to use as the primary path-allocation parameter for Float Paths >1, using the “Free Float” option) is computed according to the PREDECESSOR’s calendar.

Consider the simple schedule illustrated below, wherein the “Assembly” activity has three predecessors whose calendars differ from Assembly’s.  Assembly utilizes a standard 5-day calendar, while Machining 1 and Machining 2 are performed using automated equipment on a 7×24 calendar.  The Assembly Plan must be prepared during a weekly resource coordination meeting that only happens on Thursdays.

As the figure shows, the Longest Path (red bars) is comprised of the two Machining activities (finishing 12 hours apart) followed by Assembly.  As expected, both machining activities are marked as driving predecessors (there is zero relationship free float for either one according to Assembly’s calendar), and the Assembly Plan predecessor relationship is marked as non-driving.

P6’s MFP algorithm (Free Float option) allocates the three predecessors of the Assembly activity to three different Float Paths:

Float Path 1 (“most critical path”):  Machining 2, a driving predecessor, with Relationship Free Float (according to its own calendar) of 1.5 days.

Float Path 2 (“1st sub-critical path”): Assembly Plan, a non-driving predecessor, with Relationship Free Float (according to its own calendar) of 0.0 days.

Float Path 3 (“2nd sub-critical path”): Machining 1, a driving predecessor, with Relationship Free Float (according to its own calendar) of 2.0 days.

This is what the P6 Help file says for the MFP Free Float option.

Free Float – Choose this option to define critical float paths based on longest path. The most critical path will be identical to the critical path that is derived when you choose to define critical activities as Longest Path in the General tab. In a multicalendar project, the longest path is calculated by identifying the activities that have an early finish equal to the latest calculated early finish for the project and tracing all driving relationships for those activities back to the project start date. After the most critical path is identified, the module will calculate the remaining sub-critical paths.

Unfortunately, the underlined portion is not consistent with the observed behavior, where the Longest Path (i.e. the driving path to project completion) is divided between Float Paths 1 and 3.

Now we modify the schedule to give both machining activities exactly the same duration (2.5 days on a 7×24 calendar), so they both finish at 8:00 PM on Saturday.  They remain driving activities for Assembly and also have exactly the same Relationship Free Float (1.5d).  But now they trade Float Paths: Machining 1 is now on Float Path 1, while Machining 2 is on Float Path 3.

After restoring the original machining schedule (finishing 12 hours apart on Saturday), now we assign a different calendar to the one that finishes first – Machining 1 is now on a 6×24 calendar, with Sunday no longer a workday.  Consequently, the Machining 1 relationship now possesses only 1.0 days of Relationship Free Float, 0.5 days less than the Machining 2 relationship.  Nevertheless, Machining 2 stays on Float Path 1, while Machining 1 is still relegated to Float Path 3.

Several tentative conclusions seem apparent from these observations:

  1. For Float Path 1 only, the Float Path is allocated to the driving predecessor which is satisfied the latest of all the driving predecessors – without regard to Relationship Free Float.  Each of the remaining predecessors will be allocated to a new (higher-numbered) Float Path.
  2. If two or more driving predecessors finish at exactly the same time, then only one of them – selected by Activity ID, Activity Name, or some other non-logic-related criteria [Early Start, then Activity ID according to others] – will be assigned to Float Path 1.
  3. For Float Paths >1, the current Float Path is allocated to the remaining predecessor (driving or not) with the lowest Relationship Free Float of all remaining predecessors.  Each of the other remaining predecessors will be allocated to a new (higher-numbered) Float Path.  As  a consequence, legitimate members of the project’s Longest Path may be relegated to non-contiguous float paths far from the “most critical” Float Path 1.   (The fact that driving predecessors are NOT prioritized is an unfortunate weakness, in my opinion, of an otherwise robust logic analysis method.)

I’ve reviewed a number of P6 schedule submittals that seem to confirm these observations in addition to a few more:

  1. For Float Paths >1, if the remaining predecessors are driving AND have the same Relationship Free Float, then the current Float Path is allocated to the remaining predecessor that finishes latest.  Each of the other remaining predecessors will be allocated to a new (higher-numbered) Float Path.
  2. Consequently, in case of parallel driving paths, FF predecessors will be preferred (i.e. be allocated to lower-numbered Float Paths) over FS predecessors.
  3. [According to a paper first presented by Mssrs Roger Nelson and Patrick Kelly at the 2018 Annual Meeting of AACE International, and later presented at the AACE SoCal chapter meeting on 19Apr’19, the next two “tie-breakers” for path assignment are the latest Early Start date and, finally, the Activity ID.]
  4. In most cases, an ALAP-constrained predecessor automatically creates a parallel (and false) driving path with Relationship Free Float = 0.  Extensive use of ALAP constraints can lead to a proliferation of false Float Paths in the MFP results.

How to Filter for Leads and Lags in Microsoft Project

Here are two macro procedures – LagFilter and LeadFilter – for creating and applying a filter to show only tasks with leads or lags above a certain threshold value.

Using Lags and/or Leads (i.e. negative lags) in Project Scheduling is discouraged for good reasons.  In most project scheduling software it is easy to identify violations by creating a filter to show only tasks with Lags (or Leads) in their predecessor relationships.

In Microsoft Project, lags are indicated by the presence of a “+” character in the task’s predecessors field.  Here is the corresponding filter specification.

You can augment the filter to show tasks on both sides of the lags:

Leads are indicated (in MSP) by the presence of a “-” character in the task’s predecessors field.  Here is the corresponding filter specification (showing both sides of the leads).

Unfortunately, these simple filters don’t help to differentiate high-lag/lead relationships from low-lag/lead relationships.  All of them are lumped together in the same filter.  It is possible to create filters for only the highest lead/lag values using a number of custom fields with complex formulas.  It is far simpler, however, to create the necessary filters using vba/macros.

Here are two macro procedures – LagFilter and LeadFilter – for creating and applying a filter to show only tasks with leads or lags above a certain threshold value.  Choosing a zero-value threshold leads to the same results as the simple filters above.  These procedures work by examining the lag of each predecessor relationship of every task in the active project, comparing it to the specified threshold value.  If the lag is high enough, then the Flag6 field of the task will be set to “yes”.  At the end, a new filter is made and applied.  Note that these macros will overwrite any values in the Flag6 field of your project, unless Flag6 is already controlled by a formula.  (In that case, the macros will crash with an error.)  You may need to edit the macros to select a different Flag field.

[I’ve edited these macros… a) to allow the user to select whether to show both sides or only one side (the successor) of each lead/lag; b) to avoid null filters (i.e. blank screens) by applying the filter only when leads or lags matching the criterion are found; and c) to allow work-time, elapsed-time, or percentage-based lead/lag criteria.]

To apply these, simply copy and paste them into a new module in your Project Visual Basic editor (VBE).  (I typically keep these modules in the global.mpt file, though that practice is not always recommended.)  You can then run them directly from the VBE or from custom buttons that you link to the macros through the  “Customize the Ribbon” dialog.

Sub LagFilter()
'Copyright 15August2018 by T.Boyle PE, PSP
'This macro collects user input and filters the active project to display only tasks
'with dependency lags that are less than the user-specified threshold.  The threshold
'may be specified in units of working time, elapsed time, or percentage.  The filter
'is applied using the Flag6 custom field.
'FLAG6 WILL BE OVER-WRITTEN, IF POSSIBLE,OR THIS MACRO WILL CRASH.

    Dim t As Task
    Dim d As TaskDependency
    Dim LagUnits As String
    Dim ElapsedUnits As Boolean
    Dim LagThreshold As Double
    Dim LagLimit As String
    Dim SuccsOnly As Boolean
    Dim Filtername As String
    Dim Found As Boolean
    
    Found = False
    'Get lag units from user
    LagUnits = (InputBox("Enter lag units (m,h,d,w,mo,em,eh,ed,ew,emo,%):"))
    'Validate units
    Select Case LagUnits
        Case "m", "h", "d", "w", "mo", "em", "eh", "ed", "ew", "emo", "%"
            'Get the filter limit from user
            LagThreshold = (InputBox("Enter lag threshold (" & LagUnits & "):"))
            LagLimit = LagThreshold & " " & LagUnits
            If Left(LagUnits, 1) = "e" Then ElapsedUnits = True
        Case Else
            MsgBox ("Invalid lag units entered (case-sensitive). Aborting.")
            Exit Sub
    End Select
    'Convert units
    Select Case LagUnits
        Case "m"
            'proceed
        Case "h"
            LagThreshold = LagThreshold * 60
        Case "d"
            LagThreshold = LagThreshold * 60 * ActiveProject.HoursPerDay
        Case "w"
            LagThreshold = LagThreshold * 60 * ActiveProject.HoursPerWeek
        Case "mo"
            LagThreshold = LagThreshold * 60 * ActiveProject.HoursPerDay * ActiveProject.DaysPerMonth
        Case "em"
            'proceed
        Case "eh"
            LagThreshold = LagThreshold * 60
        Case "ed"
            LagThreshold = LagThreshold * 60 * 24
        Case "ew"
            LagThreshold = LagThreshold * 60 * 24 * 7
        Case "emo"
            LagThreshold = LagThreshold * 60 * 24 * 30
        Case "%"
            'proceed
    End Select
    
    If MsgBox("Display both Predecessors and Successors?" & vbCrLf & "(""Yes"" shows each lag twice. Default " _
            & "shows Successors Only)", vbQuestion + vbYesNo + vbDefaultButton2, "???") = vbYes Then
        SuccsOnly = False
        Filtername = "HasLagsAboveThreshold"
    Else
        SuccsOnly = True
        Filtername = "HasPredecessorLagsAboveThreshold"
    End If
    
    For Each t In ActiveProject.Tasks
        If Not t Is Nothing Then
            Call ClearT(t)
            For Each d In t.TaskDependencies
                If (d.To = t) Or (SuccsOnly = False) Then
                    If (d.Lag > 0 And LagThreshold = 0) Or (d.Lag >= LagThreshold And LagThreshold > 0) Then
                            If (d.LagType = 19 And LagUnits = "%") Then
                                Call MarkT(t, Found)
                            ElseIf (d.LagType Mod 2 = 1 And (Not ElapsedUnits) And (LagUnits <> "%")) Then
                                Call MarkT(t, Found)
                            ElseIf (d.LagType Mod 2 = 0 And ElapsedUnits) Then
                                Call MarkT(t, Found)
                            End If
                    End If
                End If
            Next d
        End If
    Next t
    
    If Found Then
        FilterEdit Name:=Filtername, TaskFilter:=True, Create:=True, OverwriteExisting:=True, FieldName:="Flag6", _
            Test:="equals", Value:="Yes", ShowInMenu:=True, ShowSummaryTasks:=True
        FilterApply Name:=Filtername
        MsgBox ("Filter applied: " & Filtername & vbCrLf & "Filter Threshold: " & LagLimit)
    Else
        MsgBox ("No lags found above threshold (" & LagLimit & "). No filter applied")
    End If

End Sub

Sub LeadFilter()
'Copyright 15August2018 by T.Boyle PE, PSP
'This macro collects user input and filters the active project to display only tasks
'with dependency leads (i.e. negative lags) that are less than the user-specified threshold.
'The threshold may be specified in units of working time, elapsed time, or percentage.
'The filter is applied using the Flag6 custom field.
'FLAG6 WILL BE OVER-WRITTEN, IF POSSIBLE,OR THIS MACRO WILL CRASH.

    Dim t As Task
    Dim d As TaskDependency
    Dim LeadUnits As String
    Dim ElapsedUnits As Boolean
    Dim LeadThreshold As Double
    Dim LeadLimit As String
    Dim SuccsOnly As Boolean
    Dim Filtername As String
    Dim Found As Boolean
    
    Found = False
    'Get Lead units from user
    LeadUnits = (InputBox("Enter Lead units (m,h,d,w,mo,em,eh,ed,ew,emo,%):"))
    'Validate units
    Select Case LeadUnits
        Case "m", "h", "d", "w", "mo", "em", "eh", "ed", "ew", "emo", "%"
            'Get the filter limit from user
            LeadThreshold = (InputBox("Enter Lead threshold (" & LeadUnits & "):"))
            LeadLimit = LeadThreshold & " " & LeadUnits
            If Left(LeadUnits, 1) = "e" Then ElapsedUnits = True
        Case Else
            MsgBox ("Invalid Lead units entered (case-sensitive). Aborting.")
            Exit Sub
    End Select
    'Convert units
    Select Case LeadUnits
        Case "m"
            'proceed
        Case "h"
            LeadThreshold = LeadThreshold * 60
        Case "d"
            LeadThreshold = LeadThreshold * 60 * ActiveProject.HoursPerDay
        Case "w"
            LeadThreshold = LeadThreshold * 60 * ActiveProject.HoursPerWeek
        Case "mo"
            LeadThreshold = LeadThreshold * 60 * ActiveProject.HoursPerDay * ActiveProject.DaysPerMonth
        Case "em"
            'proceed
        Case "eh"
            LeadThreshold = LeadThreshold * 60
        Case "ed"
            LeadThreshold = LeadThreshold * 60 * 24
        Case "ew"
            LeadThreshold = LeadThreshold * 60 * 24 * 7
        Case "emo"
            LeadThreshold = LeadThreshold * 60 * 24 * 30
        Case "%"
            'proceed
    End Select
    
    If MsgBox("Display both Predecessors and Successors?" & vbCrLf & "(""Yes"" shows each Lead twice. Default " _
            & "shows Successors Only)", vbQuestion + vbYesNo + vbDefaultButton2, "???") = vbYes Then
        SuccsOnly = False
        Filtername = "HasLeadsAboveThreshold"
    Else
        SuccsOnly = True
        Filtername = "HasPredecessorLeadsAboveThreshold"
    End If
    
    For Each t In ActiveProject.Tasks
        If Not t Is Nothing Then
            Call ClearT(t)
            For Each d In t.TaskDependencies
                If (d.To = t) Or (SuccsOnly = False) Then
                    If (d.Lag < 0 And LeadThreshold = 0) Or (d.Lag <= -1 * LeadThreshold And LeadThreshold > 0) Then
                            If (d.LagType = 19 And LeadUnits = "%") Then
                                Call MarkT(t, Found)
                            ElseIf (d.LagType Mod 2 = 1 And (Not ElapsedUnits) And (LeadUnits <> "%")) Then
                                Call MarkT(t, Found)
                            ElseIf (d.LagType Mod 2 = 0 And ElapsedUnits) Then
                                Call MarkT(t, Found)
                            End If
                    End If
                End If
            Next d
        End If
    Next t
    
    If Found Then
        FilterEdit Name:=Filtername, TaskFilter:=True, Create:=True, OverwriteExisting:=True, FieldName:="Flag6", _
            Test:="equals", Value:="Yes", ShowInMenu:=True, ShowSummaryTasks:=True
        FilterApply Name:=Filtername
        MsgBox ("Filter applied: " & Filtername & vbCrLf & "Filter Threshold: " & LeadLimit)
    Else
        MsgBox ("No Leads found above threshold (" & LeadLimit & "). No filter applied")
    End If

End Sub

Sub ClearT(t As Task)
    t.Flag6 = "No"
End Sub
Sub MarkT(ByRef t As Task, ByRef Found As Boolean)
    t.Flag6 = "Yes"
    Found = True
End Sub

Neither the simple filter nor the macro provided here implements the algorithm used by the Project Logic Checker in our BPC Logic Filter Add-In, which incorporates a slightly different premise.  That is: a relationship (or combination of relationships) with (positive or negative) lag may be the most effective and efficient method for modeling the true sequential restraints of the work, but only when the lag represents a relatively small proportion of the durations of the related tasks.  Thus, the Project Logic Checker flags tasks where the relationship lead/lag exceeds a certain percentage of the associated task durations.

BPC Logic Filter in Microsoft Project 2013/2016

During its development, we targeted BPC Logic Filter – our Add-In for analyzing project schedules – for use with Microsoft Project (MSP) 2010.  After all, we developed the Add-In essentially for our own use, and MSP 2010 has been a regular tool for us (in Windows 7 boxes) since its inception.  Our most recent computer purchase brought with it necessary upgrades to 2016 versions of MS Office and MSP, all running the 64-bit flavor on a Windows 10 Workstation.

Now that I’ve had a chance to directly test BPC Logic Filter in an MSP 2016 environment, I must apologize to those users of our software who have suffered in silence with their MSP 2016 (and also MSP 2013) installations.  My initial testing experience with the filter functions was horribly slow, and I was finally able to repeat some crashing behavior – not encountered in MSP 2010 – that had been reported by a lone user.  No wonder the representative feedback from users on MSP 2013 and 2016 has been, love the Task Logic Inspector! (but silent on the other stuff).

With recent updates, we’ve managed to speed up the filter functions while completely eliminating the particular crashing issue.  As a result, with bar-coloring disabled, the new machine can complete a comprehensive Near-Longest Path Filter of a typical ~1000-task schedule in under 8 seconds.  This compares to an 11-second analysis of the same schedule on the old machine; I attribute the improvement primarily to the increased processing speed of the new machine.

Bar-coloring, however, remains sub optimal.  This is already time-consuming – manipulating Gantt bars and bar styles using essentially “foreground” processes.   As a result, the time to generate our comprehensive Near-Longest Path Filter on the old (MSP 2010) machine increases from 11 seconds to 33 seconds when bar-coloring with auto-ranging is selected.  Such an increase is justified by the improved communication that bar coloring allows.  Unfortunately, the time to perform the same task on the new (MSP 2016) machine increased from 8 seconds to 46 seconds, even after our optimizations and adjustments.  I would expect users with slower computers to have much worse experience.  It seems that manipulating graphic display objects involves substantially more processing power in MSP 2016 than in MSP 2010.  This is ironic in light of the general degradation in graphical output beginning with MSP 2013.  Unfortunately, we have not yet found a way around this problem.

Finally, there seems to be a bug in MSP 2016’s handling of the GanttBarFormat method when a) the method originates in a VSTO (Visual Studio Tools for Office) Add-In rather rather than in a native VBA (Visual Basic for Applications) procedure; and b) there is actual progress on the task.  (The GanttBarFormat method is used to apply format exceptions to a particular bar style of a particular task; like right-clicking on a bar and choosing “format bar”.)  Unfortunately, MSP 2016 ignores the selected bar style and applies the exception to the “Task Progress” bar if one exists.  This makes for some odd-looking outputs from our Add-In for schedules showing actual progress.  I’ll have to figure out a way to raise this issue and get it fixed.

Understand the Impact of Calendars on Schedule Slack Calculation in Microsoft Project

The most recent build of BPC Logic Filter includes improved calculation of relative floats for tasks whose Resource Calendars are substantially different from the effective Task and Project Calendars.  While reviewing those improvements, I compiled this summary of the three different Calendar types used in Microsoft Project (MSP) schedules – with particular attention to their use in logic-driven scheduling and Slack calculation.  The summary moves from the simplest (Project Calendar only) to the most complex (combined Task and Resource calendars) case.  The conclusions are based on my own (imperfect) testing in MSP Professional 2010 and 2016 environments, and I’d welcome any corrections.

Dale Howard of Sensei Project Solutions has provided an excellent general examination of Calendars in Microsoft Project.  It may prove useful to review his post before proceeding.

A. Project Calendar

  1. The Project Calendar is used to schedule all tasks in a project IN THE ABSENCE OF OTHER CALENDARS.  When present, Task Calendars supersede all of the Project Calendar’s functions, and Resource Calendars supersede some – but not all – of the Project Calendar’s functions.
  2. Without Task or Resource Calendars, each task’s early start date occurs when all logic constraints have been satisfied and the Project Calendar makes work time available.  The task’s early finish occurs when the assigned duration has been fully expended according to the Project calendar.
  3. Relationship lags are computed according to the Project Calendar.
  4. Start Slack, Finish Slack, and Total Slack are computed using the Project Calendar.
  5. The default calendar for ProjDateAdd, ProjDateSub, and ProjDateDiff functions is the Project Calendar.*
  6. Because only a single calendar is involved in all schedule calculations, Total Slack may be a reliable indicator of Critical Path within a single project schedule.
  7. If two projects with different project calendars are joined together with inter-project dependencies, then the interaction of working periods between linked tasks can cause Total Slack to vary along a single driving logic path.

B. Project Calendar PLUS Resource Calendars

  1. Each Resource possesses a unique Resource Calendar, which is comprised of a Base Calendar with specific modifications/exceptions.  For example, the Base Calendar for all resources in a particular country may include standard weekends and holidays for that country.  These are inherited by the Resource Calendar, while exceptions may be applied for specific Resource vacations.  By default, the Base Calendar is the Project Calendar at the time the resource is created.  An alternate Base Calendar can be assigned afterward.  The Resource Calendar has the same name as the Resource.
  2. When one or more resources are assigned to a task, the task is scheduled according to a) predecessor and successor logic, including lags; and b) the available working times in the Resource Calendars.  The task’s early start date occurs when all logic constraints have been satisfied and at least one assigned resource has available work-time.  The task’s early finish date occurs when the last resource assignment is completed – AND for Fixed-duration tasks with positive duration, the specified duration has been expended.  For tasks that are not of type “Fixed Duration,” the Duration is the sum of all the intervals (from start to finish) during which at least one resource is working.  Thus, a task with multiple resources (each with a unique calendar) may have a Duration and Start/Finish dates that do not directly correspond to ANY single defined Calendar.  For Fixed-Duration tasks, the Duration is the difference between the early start and early finish as computed using the Project Calendar.  Thus, a Fixed-Duration task with 12-hours of work by a night-shift resource can have a Duration of Zero, based on the Project’s Standard calendar.  Moreover, a Fixed-Duration task with a specified duration of 2 days and 16 hours of work by a weekend-working resource may start on Saturday (when the resource is available) and not be completed until Tuesday evening, when its specified duration has been expended according to the project calendar.  During the backward pass, Late dates are established similarly, based on (resource) working-time calendars.
  3. Relationship lags are computed using the Project Calendar.
  4. Start Slack, Finish Slack, and Total Slack are computed using the Project Calendar.
  5. The default calendar for ProjDateAdd, ProjDateSub, and ProjDateDiff functions used in custom Task fields remains the Project Calendar.  When used in custom Resource fields, the default calendar for these functions is the Resource’s Base Calendar, which is often the Project Calendar.*
  6. Since a resource calendar may delay a task from starting work during an available work period as defined in the Project Calendar, the task’s driving predecessor may possess slack.  Thus, Total Slack can vary along a single driving logic path.

C. Project Calendar PLUS Task Calendars (No Resource Calendars OR “Ignore Resource Calendars” Selected)

  1. A task calendar may be created and assigned to multiple tasks.  Each Task Calendar is a Base Calendar that may be created by copying and modifying an existing Base Calendar.  (Because it is a base calendar itself, a task calendar does not inherit information from other calendars.)
  2. Task Calendars may be used to refine schedule constraints based on the nature of the tasks being performed.  E.g. seasonal or environmental limitations.  Task Calendars may also be used to represent resource restrictions when no resources have been assigned (e.g. a year-end non-work period for certain tasks in a master/summary schedule.)  When “Ignore Resource Calendars” is checked, then assigned Resources will be compelled to work exactly according to the Task Calendar, possibly violating their own work time availability.
  3. Without effective Resource restrictions, the task’s early start date occurs when all logic constraints have been satisfied and the Task Calendar makes work time available.  The task’s early finish occurs when the assigned duration has been fully expended according to the Task Calendar.
  4. Relationship lags are computed according to the Task Calendar of the successor task, if it has one, or the Project Calendar.
  5. Start Slack, Finish Slack, and Total Slack for each task are computed using the Task Calendar, if it has one, or the Project Calendar.
  6. The default calendar for ProjDateAdd, ProjDateSub, and ProjDateDiff functions used in custom Task fields is the Task Calendar, if one exists, or the Project Calendar.*
  7. The interval between a driving predecessor and a driven successor may possess work time according to the predecessor’s calendar but not the successor’s.  The driving predecessor may possess slack.  Thus, Total Slack can vary along a single driving logic path.

D. Elapsed-Durations

  1. For most practical purposes, specifying a task duration using an “elapsed” unit (edays, for example), is essentially the same as: a) Applying a 24-hour task calendar with “ignore resource calendars” selected; AND b) Assigning a duration value that accounts for the project’s hours-per-day, hours-per-week, and days-per-month settings.  For example, 1 elapsed day is the same as 24 hours or 3 “days” (8-hours each) applied to a 24-hour working calendar.  (Since mixing duration “days” with 24-hour calendars routinely causes confusion, it is good practice to instead specify such durations in hours.)
  2. Any task with an elapsed duration will have the Task Calendar field disabled.  (A stored value may be visible, but it is inactive as long as the duration units are elapsed.)
  3. Since elapsed-duration tasks automatically ignore resource calendars, any assigned Resources will be compelled to work 100% without rest, possibly violating their own work time availability.  Consequently, it’s not a good idea to routinely apply elapsed durations together with resource loading.  Even machines need downtime for maintenance.
  4. Without effective Resource restrictions, the task’s early start date occurs when all logic constraints have been satisfied, period.  The task’s early finish occurs when the elapsed duration has been fully expended.
  5. Non-elapsed relationship lags are computed according to the Task Calendar of the successor task, if it has one, or the Project Calendar.
  6. Start Slack, Finish Slack, and Total Slack for each elapsed-duration task are computed on the basis of elapsed time.
  7. For tasks with elapsed durations, the default calendar for ProjDateAdd, ProjDateSub, and ProjDateDiff functions used in custom Task fields is the 24-Hour Calendar.*
  8. The interval between an elapsed-duration predecessor and its driven (non-elapsed) successor may possess non-working time according to the successor’s effective calendar (task, resource, or project).  The driving predecessor may possess slack.  Thus, Total Slack can vary along a single driving logic path.

E. Project Calendar PLUS Task Calendars PLUS Resource Calendars (NOT “Ignored”)

If the task’s “Ignore Resource Calendars” box is NOT checked, then:

  1. Each task is scheduled only during work time that is available in BOTH the Task Calendar and the applicable Resource Calendar for each assignment.
  2. The task’s early start date occurs when all logic constraints have been satisfied,  the Task Calendar makes work time available, AND at least one assigned resource has available work time.  The task’s early finish occurs when the last assignment is completed within the combined work time restrictions.
  3. Relationship lags are computed according to the Task Calendar of the successor task, if it has one, or the Project Calendar.
  4. Start Slack, Finish Slack, and Total Slack are computed using the Task Calendar, if any, or the Project Calendar.
  5. The default calendar for ProjDateAdd, ProjDateSub, and ProjDateDiff functions used in custom Task fields remains the Task Calendar, if one exists, or the Project Calendar.  When used in custom Resource fields, the default calendar for these functions remains the Resource’s Base Calendar.*
  6. As a result of either resource-delays or task calendar mismatches, Total Slack can vary along a single driving logic path.

*  Note: The comparable Project VBA functions (Application.) DateAdd, DateSubtract, and DateDifference always default to the Project Calendar of the ActiveProject.

F. Slack and Calendars Re-Cap

In general, the Project Calendar of a fully resource-loaded project schedule plays no direct role in the calculation of the Early and Late dates, but it plays a primary role in MSP’s subsequent calculation of Slack based on those dates.  Conversely, although resource calendars can fundamentally alter the logic-driven dates of a typical resource-loaded task, MSP ignores them in the Slack calculation.  As a consequence, both the calculation and interpretation of Total Slack in a resource-loaded schedule become greatly simplified, if sometimes misleading.

Alternately, whenever a task calendar is applied (with or without resource-loading), that same calendar is used to calculate the Dates AND the Slack.  Consequently, the calculation of Total Slack seems to be more correct and can be equally simple to calculate (using a Task- rather than Project-Calendar), but its interpretation can be confusing.

For example, the chart below illustrates two alternate methods for modeling a calendar-restricted Board-approval activity in a project schedule.  The Board meets on the third Wednesday of each month for, among other items, approving key project commitments.  If the project team fails to prepare the necessary documents in sufficient time for the meeting, then the approvals (and follow-on tasks) will be delayed by a month.  (This is exactly how project governance works in some organizations.)  For this example, the board-approval, preparation, and follow-up activities are not on the Critical Path for the project, finishing up about a month before the project’s finish milestone.

In the first case, the restraint on the Board Approval task is modeled by applying a Task Calendar with only the third Wednesday of each month as a working day.  In the second case, the restraint is modeled by loading a “Board Availability” resource whose Base Calendar is exactly the same as the Task Calendar applied above.  Early Dates and Late Dates for all tasks are identical for both cases, and the only difference is the Total Slack of the Board Approval task.  This value is computed as the difference between the task’s Late Finish (17Apr’19) and its Early Finish (20Mar’19).  When the restraint is applied using the Task Calendar, the Total Slack of 1 day reflects the fact that one Board Meeting/availability day exists between the two dates.  With the restraint applied using a resource calendar, the Project Calendar applies, and Total Slack of 20 days reflects the twenty weekdays between the two dates.

In either case, the example also illustrates the difficulty of identifying logic paths using Total Slack alone.

G. A Note on the Resource Availability Grid

The Resource Availability Grid (part of the Resource Information dialog window) is sometimes seen as an alternate/supplemental method for specifying resource working time.  Unlike the Resource Calendar, however, Resource Availability entries do not participate in the working-time definitions that drive the scheduling calculations.  Rather, they serve as a time-phased version of the Max Units property for identifying over-allocation of resources.  Once flagged, MSP can attempt to resolve these over-allocations through automatic resource-leveling.  This is distinct from logic-driven scheduling.

 

Extract the Logic Plan Inside Your Schedule – Project Virtual Conference 2018

In June 2018 I had the privilege of speaking at the Project Virtual Conference 2018.  The event was very well done and was supported by a number of key sponsors in the Microsoft Project consulting world.  (Surprisingly, Microsoft was not among them.)  I hope to have a chance to return in future years.  My session focused on using BPC Logic Filter to examine schedule plans.  The 55-minute session was recorded (link below).

There are a few lines I’d like to have back, especially the repeated reference to DCMA (the Defense Contract Management Agency) as the Defense Contract Management Association.  Maybe I conflated DCMA with the NDIA (the National Defense Industry Association) to create this new fiction….  Both have issued comprehensive guides related to project schedule quality, and the Planning and Scheduling Excellence Guide (PASEG) from NDIA is one of the better ones out there.

Don’t Confuse Critical Tasks with Critical Paths in Project Schedules

The “critical” activity flags in modern project schedules often do not correctly identify the true critical paths.  Blind acceptance of such “critical” flags to identify the critical path inhibits proper understanding, communication, and management of project schedule performance – and gives CPM a bad rap.

Basic CPM Concepts (in General):

The “critical path method” (CPM) – a ~60-year-old algorithm of fairly straightforward arithmetic – lies at the core of most modern project scheduling tools, and most project managers worthy of the name have been exposed to at least the basic CPM concepts.  Any discussion of the critical path must address the underlying conceptual basis:

  1. A CPM project schedule is comprised of all the activities necessary to complete the project’s scope of work.
  2. Activity durations are estimated, and required/planned sequential restraints between activities are identified: e.g. Predecessor task “A” must finish before successor task “B” can start, and predecessor task “C” must finish before successor task “D” can start.  The combination of activities and relationships forms a schedule logic network.  Below is a diagram of a simple schedule logic network, with activities as nodes (blocks) and relationships as arrows.
  3. Logic Relationships.  A logic relationship represents a simple (i.e. one-sided) schedule constraint that is imposed on the successor by the predecessor.  Thus, a finish-to-start (FS) relationship between activities A and B dictates only that the start of activity B may NOT occur before the finish of activity A.  (It does not REQUIRE that B start immediately after A finishes.)  Other relationship types – SS, FF, SF, which were added as part of the precedence diagramming method (PDM) extension of traditional CPM – are similarly interpreted.  E.g. A–>(SS)–>B dictates only that the start of B may not occur before the start of A.  Activities with multiple predecessor relationships must be scheduled to satisfy ALL of them.
  4. Logic Paths. A continuous route through the activities and relationships of the network – connecting an earlier activity to a later one – is called a “logic path.”  Logic paths can be displayed – together or in isolation – to show the sequential plans for executing selected portions of the project.  The simple network shown has only two logic paths between the start and finish milestones: Path 1 = (StartProject) <<A><B>> (FinishProject); and Path 2 = (StartProject) <<C><D>> (FinishProject).  [Experimenting with some shorthand logic notation: “<” = logic connection to activity’s Start; “>” = logic connection to activity’s Finish.]
  5. Schedule Calculations. Schedule dates are calculated using three essential steps:
    • During the forward pass, the earliest possible start and finish dates of each activity are computed by considering the aggregated durations of its predecessor paths, beginning from the project start milestone and working forward in time.
    • Assuming an implicit requirement to finish the project as soon as possible, the early finish of the project completion milestone is adopted as its latest allowable finish date. This can be called the finish reflection.  (Most CPM summaries ignore this step.  I include it because it is the basis for important concepts and complications to be introduced later.)
    • During the backward pass, the latest allowable start and finish dates of each activity are computed by considering the aggregated durations of its successor paths, beginning from the project completion milestone and working backward in time.
  6. Driving and Non-Driving Logic. A logic relationship may be categorized as “driving” or “non-driving” depending on its influence over the early dates of the successor activity – as calculated during the forward pass.  A driving relationship controls the early start/finish of the successor; a non-driving relationship does not.  In other words, a “driving” relationship prevents the successor activity from being scheduled any sooner than it is.  A logic path (or path segment) may be categorized as “driving” (to its terminal activity) when all of its relationships are driving.  [Such a path is sometimes called a “string.”]
  7. Total Float. In simplified terms, the difference between the early start/finish and late start/finish of each activity is termed the activity’s “total float” (or “total slack”).  A positive value denotes a finite range of time over which the activity may be allowed to slip without delaying “the project.”  A zero value (i.e. TF=0) indicates that the activity’s early dates and late dates are exactly equal, and any delay from the early dates may delay “the project.”  It is important to remember that total float/slack is nominally computed as a property of each individual activity, not of a particular logic path nor of the project schedule as a whole.  [While computed individually for each activity, the float is not possessed solely by that activity and is in fact shared among all the activities within a driving logic path.  In the absence of certain complicating factors, it is common to refer to a shared float value as a property of that path.]
  8. Critical Path. A project’s critical path is the path (i.e. the unique sequence of logically-connected activities and relationships) that determines the earliest possible completion of “the project.”  I prefer to call this the “driving path to project completion.”  Other logic paths through the schedule are considered “near-critical paths” if they are at risk of becoming the critical path – possibly extending the project – at some time during project execution.  In our simple project shown below, the critical path is Path 1, whose total duration of 4 weeks (20 days on a standard 5dx8h calendar) controls the early finish of the completion milestone.

    In unconstrained schedule models incorporating only a single calendar (and without other complicating factors), the finish reflection causes the activities on the critical path to have late dates equal to their early dates; i.e. TF = 0.  Consequently, any delay of a critical-path activity cascades directly to delay of the project completion.  The near-critical paths are then defined as those paths whose activities have TF more than zero but less than some threshold.  In traditional “critical path management,” activities that are NOT on or near the critical path may be allowed to slip, while management attention and resources are devoted to protecting those activities that are on or near the critical path.  More importantly, acceleration of the project completion (or recovery from a prior delay) may only be accomplished by first addressing the activities and relationships on the critical path.

[Note: The definition of “critical path” has evolved with the introduction of new concepts and scheduling methods over the years.  The earliest definitions – based on robust schedule networks containing only finish-to-start relationships, with no constraints, no lags, and no calendars – were characterized by the following common elements:

  • It contained those activities that determined the overall duration of the project (i.e. the “driving path to project completion.”)
  • It contained those activities that, if allowed to slip, would extend the duration of the project (hence the word “critical”).
  • A delay of any of its activities would be directly transmitted to an equal (matching) delay of the project completion.
  • Its activities comprised the “longest path” through the schedule network. That is, the arithmetic sum of their durations was greater than the corresponding sum for any other path in the network.
  • After completion of the forward and backward passes, its activities could be readily identified by a shared total float value of zero.  Thus TF=0 became the primary criterion for identifying the critical path.

With the incorporation of non-FS relationships, early and late constraints, lags, and calendars in modern project scheduling software, these observations are no longer consistent with each other nor sometimes with a single logic path.  Some of these inconsistencies are addressed later in this article.  Only the first of these defining elements (“driving path to project completion”) has been generally retained in recent scheduling standards and guidance publications, though implied equivalence of the others continues to persist among some professionals.]

Software – the Critical Activities / Critical Tasks:

The basic element of modern project schedules is the activity or task.  In most scheduling tools, logic paths are not explicitly defined.  Nevertheless, the obvious importance of the critical path dictates that software packages attempt to identify it – indirectly– by marking activities that meet certain criteria with the “critical” flag.  Activities with the “critical” flag are called “critical activities” (or “critical tasks”) and are typically highlighted red in network and bar-chart graphics.

Applying Critical Flags using Default Total Float Criteria

The simplest criterion for flagging a task as “critical” is TF=0.  This is the primary method that most new schedulers seem familiar with, and it is the default criterion for some software packages.  As noted earlier, this criterion is applicable to schedules with no constraints and only a single calendar.  In Microsoft Project (MSP) and Oracle Primavera P6 (P6), the default “critical” flag criterion is TF<=0, and the threshold value of “0” can be adjusted.  The differences between these criteria and the simpler TF=0 criterion are justified by four primary concerns:

  1. Risk Management. Due to the inherent uncertainty of activity duration estimates, the critical path of a real-world project schedule – as ultimately executed – often includes an unpredictable mix of activities from the as-scheduled critical path and near-critical paths.  In the absence of quantitative schedule risk assessment, it is reasonable to consider all such (potentially-critical-path) activities equally when evaluating project schedule risks.  This purpose is easily served by applying the “critical” flag to all activities whose TF value is less than or equal to some near-critical threshold.
  2. Late Constraints. Overall project completion priorities (and contractual requirements) often lead to the imposition of deadlines (in MSP), late-finish constraints (in MSP and P6), or project constraints (in P6).  Such constraints can override the finish reflection and cause the late dates of some activities to be earlier or later than they would be in the absence of the constraints.  As a result, total float can vary among the activities on the driving path to project completion.   In a project with multiple constrained milestones, the driving path to only one of them (the most “urgent”) can be expected to have a constant total float value (i.e. the lowest total float.)  Due to intersecting logic paths, total float can vary along the driving paths to other constrained milestones.   Applying the “critical” flag to activities with total float less than or equal to the project’s lowest total float marks those activities that are on the driving path to the most urgent constrained milestone in the project.  If a project constraint (in P6 only) is applied, the lowest total float value may be greater than zero; without a more urgent constraint, the marked activities then denote the driving path to the final activity in the project.
  3. Negative Float. Late constraints can cause late dates to precede early dates for certain activities.  This results in negative values for total float/slack (i.e. TF<0).    In practically all cases, negative total float indicates that the activity cannot be scheduled in time to satisfy one or more of the deadlines or constraints (though which one of these is violated may not be clear); and some corrective action is necessary.  [*The concept of negative float – and the constraints that create it – were not included in the foundations of CPM and PDM.  Negative float is not universally accepted among scheduling professionals today, and not all scheduling software supports its calculation.]

    Applying the “critical” flag to all activities with total float less than or equal to zero then marks all activities that:

      • Are on the driving path to an unconstrained project completion (i.e. TF=0, controlled by the project’s finish reflection); or
      • Are on the driving path to a constrained project completion or intermediate milestone that is just barely met (i.e. TF=0, controlled by deadline/constraint); or
      • Are on the driving path to project completion where an explicit project completion milestone is violated (i.e. TF<0, controlled by project deadline/constraint); OR
      • Are on the driving path to some intermediate activity whose constraint is violated (i.e. TF<0, controlled by intermediate deadline/constraint); or
      • Are on any number of non/near-driving paths to one or more constrained project completion or intermediate milestones, (i.e. TF<0). Though non-driving, these paths must still be shortened (in addition to shortening the driving and nearer-driving paths) to meet the milestones.

     

  4. Working-Time Calendar Effects. When activities with different calendars are logically connected in a schedule network, the interval between the finish of a predecessor task and the start of its successor may sometimes contain working time for the predecessor but not for the successor.  If this occurs, then a driving logic relationship exists, but the predecessor still has room to slip without delaying any other tasks or the project (i.e. it possesses float.)  Thus, total float may vary along a single driving logic path, including the critical path.  The amount of this variation depends on the size of potential offsets between calendars: from a few hours (for shift calendar offsets) to a few days (for 5-day and 7-day weekly calendars offsets) to a few months (for seasonal-shutdown calendar offsets).

    Applying the “critical” flag to all activities with total float less than or equal to the largest calendar-related offset will mark all activities that:

    • Are on the driving path to project completion with TF<=0;
    • Are on the driving path to project completion but with TF>0 (and less than the specified offset);
    • Are NOT on the driving path to project completion but have TF less than the specified offset. These are false positives.  For these activities, total float could be controlled either by the finish reflection (TF>=0) or by some other constraint.

Critical Flags and Critical Paths

Unfortunately, applying the “critical” flag as noted for most of these considerations has one consistent result:  the continuous sequence of activities and relationships constituting a “critical path” often remains obscured.  It is disappointing that the majority of project schedulers – using MSP or P6 – continue to issue filtered lists of “critical” activities as “the critical path.”  Much of the time – especially in MSP – they are not.  Even among expert schedulers, there is a persistent habit of declaring total float as the sole attribute that defines the critical path rather than as a conditional indicator of an activity’s presence on that path.

When an activity is automatically marked “critical” based on total float/slack, the primary conclusion to be drawn is simply, “this activity has total float/slack that is at or below the threshold value.  That is, there is insufficient working time available between the early- and late- start/finish dates.”  If total float/slack is less than zero, then one might also conclude, “this activity is scheduled too late to meet one or more of the project’s deadlines/constraints.”  [If automatic resource leveling has been applied, then even these simple conclusions are probably incorrect.]  These are important facts, but a useful management response still requires knowledge of the driving logic path(s) to the specific activities/milestones whose deadlines/constraints are violated – knowledge that total float/slack and its associated “critical” flag do not always provide.

Workarounds for Total Float Criteria

P6 provides several features, not available out-of-the-box in MSP, for correctly identifying the critical path when total float criteria do not.  Specifically:

  1. For Risk Management. P6’s multiple-float path analysis (MFP) allows the identification of successive driving and near-driving paths to specified project completion milestones.  Monitoring progress on these paths is worthwhile for risk management.  I’ve previously written about MFP analysis HERE.  P6 does not support using float paths (the output of MFP analysis) as an explicit criterion for the “critical” activity flag.
  2. For Late Constraints and Negative Float. P6 allows a negative critical float threshold.  It is possible to set this threshold low enough so that only the “path of lowest total float” is marked as critical.  In the absence of working time calendar effects, this criterion can be effective in identifying the (most) critical path.  Thus it is possible to correctly identify the project’s critical path when: a) there is only a single constraint on the project; and b) that constraint coincides with the sole project completion milestone; and c) that constraint is violated (creating negative float).
    • MSP does not allow a negative critical float threshold, so correct identification of the critical path in a negative float scenario is not possible. All tasks with negative total slack are automatically and unavoidably flagged as “critical.”
    • If the P6 schedule has a project “must finish by” constraint, then the activities on the critical path may have positive total float. In that case, the lowest-float criterion may be applied (using a positive threshold) to correctly identify the critical path.
  3. For Working-Time Calendar Effects. Unlike other project scheduling software, P6 allows the “critical” activity flag to be assigned on the basis of some criterion other than total float – called Longest Path.  The name is misleading, as the method is based on driving logic rather than activity durations.  Any activity that is found on the driving logic path to project completion is flagged as “critical.”  (The algorithm tracks driving logic backward from the task(s) with the latest early finish in the project.)  The Longest Path criterion ignores the total float impacts of multiple calendars and constraints.  While it is effective in identifying the project’s critical (logic) path, Longest Path alone is not useful for identifying near-critical paths.  MFP analysis (noted above) is useful for this purpose.  “Longest path value ™,” a relative-float metric available in Schedule Analyzer Software (a P6 add-in) also helps to identify near-critical paths in these circumstances.  For a more detailed review, see What is the Longest Path in a Project Schedule?

MSP provides no out-of-the-box solutions to address these weaknesses in critical path identification.  Total float/slack remains the sole basis for applying the “critical” flag, yet the impacts of constraints, deadlines, and calendars remain unaddressed.  In MSP 2013 and later versions, the “task path” bar style modifier does provide a basis for graphically identifying the driving path to a selected completion activity, and this is helpful.  Nevertheless, a logic tracing add-in (like the BPC Logic Filter program that I helped to develop) is necessary to correctly identify the controlling schedule logic – including the true critical path – in a complex MSP schedule.

Definitions and Recommended Practices

Defense Contract Management Agency (DCMA – 2009)

DCMA’s in-house training course, Integrated Master Plan/Integrated Master Schedule Basic Analysis (Rev 21Nov09) is the source of the “14-Point Assessment” that – because its explicit “trigger” values are easily converted to pass/fail thresholds and red/yellow/green dashboards – is seen as a de-facto industry standard for schedule health assessment.  The course materials contain the following definitions:

(Slide 28) Critical Path ~ Sequence of discrete work packages that has the longest total duration through an end point.
~ has the least amount of total float
~ cannot be delayed without delaying the completion date of the contract (assuming zero float).
(Slide 98) Critical Path – Definition: a sequence of discrete tasks/activities in the network that has the longest total duration through the contract with the least amount of float.
~ A contract’s critical path is made up of those tasks in which a delay of one day on any task along the critical path will cause the project end date to be delayed one day (assuming zero float).
(Slide 99) The critical path is ‘broken’ whenever there is not a sequence of connected critical path tasks that goes from the first task of the schedule until the last task.  A broken Critical Path is indicative of a defective schedule. 

These definitions are mostly (though not entirely) consistent with each other.  They do share a common emphasis on the … “longest”… “sequence” … with “lowest total float” and direct transmission of delay from any critical-path task directly to the project’s completion.  Obviously, the reliance on total float makes them incompatible with any project schedule that incorporates multiple calendars, late constraints, or resource leveling.

(Slide 97) Critical Task:  Some tasks possess no float…they are known as critical tasks.
~Any delay to a critical task on the critical path will cause a delay to the project’s end date.

Unlike most of the later definitions, DCMA’s appears to contemplate the existence of critical tasks that are not on the critical path.  Obviously, the expectation that such critical tasks possess “no float” is not compatible with negative-float regimes, nor is it compatible with the positive-float regimes that accompany project “must finish by” constraints in P6.

AACE International (2010 & 2018)

AACE International (formerly the Association for the Advancement of Cost Engineering) maintains and regularly updates its Recommended Practice No. 10S-90: Cost Engineering Terminology.  The most recent issue of RP 10S-90 (June 2018) includes the following definitions:

CRITICAL PATH – The longest continuous chain of activities (may be more than one path) which establishes the minimum overall project duration. A slippage or delay in completion of any activity by one time period will extend final completion  correspondingly. The critical path by definition has no “float.” See also: LONGEST PATH (LP). (June 2007)

CRITICAL ACTIVITY – An activity on the project’s critical path. A delay to a critical activity causes a corresponding delay in the completion of the project. Although some activities are “critical,” in the dictionary sense, without being on the critical path, this meaning is seldom used in the project context. (June 2007)

Unfortunately, these definitions fall apart in the presence of multiple calendars, multiple late constraints, or negative total float – when the second and third clauses in both definitions no longer agree with the first.  They appear distinctly out of sync with modern project scheduling practices, and (according to AACE International’s Planning and Scheduling Subcommittee Chair) an update is pending.

AACE International’s RP No. 49R-06, Identifying the Critical Path (last revised in March 2010) instead defines the Critical Path as

…the longest logical path through the CPM network and consists of those activities that determine the shortest time for project completion.  Activities within this [group (sic)] or list form a series (or sequence) of logically connected activities that is called the critical path. 

Aside from the apparently inadvertent omission of a word, I don’t have any problem with this definition.  It is certainly better, in my opinion, than the first.

RP 49R-06 notes the existence of “several accepted methods for determining the critical path” and goes on to describe the four “most frequently used” methods:

  1. Lowest Total Float. This is as I described under Workarounds for Total Float Criteria, above.  Although this method is listed first, the RP spends four pages detailing the issues that make total float unreliable as a CP indicator.  As long as the CP is to be defined only with respect to the most urgent constraint in the schedule (including the finish reflection) – and there are no calendar issues –  then this method provides a useful result.
  2. Negative Total Float.  In apparent acquiescence to the limitations of MSP, the RP describes this method by first abandoning the fundamental definition of the critical path as a specific logic path.  It then allows the “critical” classification for any activity that must be accelerated in order to meet an applied deadline or constraint.  Ultimately, the RP attempts to justify this method based solely on certain legal/contractual considerations of concurrent delay.  It is not useful for those whose primary interest is timely completion of the project, or a particular part of the project, using critical path management principles.
  3. Longest Path.  This “driving path to project completion” algorithm, as I described above in Workarounds for Total Float Criteria, has been implemented in versions of (Oracle) Primavera software since P3 (2.0b).  It is the preferred method for P6 schedules with constraints and/or multiple activity calendars.  A similar algorithm is included in BPC Logic Filter, our add-in for Microsoft Project.  While the method is nominally aimed at finding the driving path(s) to the last activity(ies) in the schedule, it can be combined with other techniques (namely a super-long trailing dummy activity) to derive the driving path to any specific activity, e.g. a specific “substantial completion” or “sectional-completion” milestone.
  4. “Longest Path Value.”  This is an expanded method for identifying the driving and near-driving paths to project completion.  The method works by adding up relationship floats leading to a specific substantial completion milestone.  If the aggregate value of these floats along a specific logic path (i.e. “Longest Path Value”) is zero, then that path is identified as the critical path.  While the RP suggests that this method can be performed manually (presumably by “click-tracing” through the network of a P6 schedule), manual implementation in complex schedules is tedious and error prone.  As implemented in Schedule Analyzer Software, this method is essentially an improved version of  P6’s Longest Path method (except that the add-in cannot change the “critical” flag for activities.)  It is a preferred method in P6 for those possessing the Schedule Analyzer Software.  BPC Logic Filter performs similar analyses – using “path relative float” instead of “Longest Path Value” – for MSP schedules.

While not listed among the “most frequently used” methods, P6’s MFP analysis option is briefly addressed by the RP in the context of identifying near-critical paths.  BPC Logic Filter performs similar analyses for MSP schedules.

None of the four methods described are useful for identifying the resource critical path (or resource-constrained critical path) of a leveled schedule.

Project Management Institute (PMI-2011)

PMI’s Practice Standard for Scheduling (Second Edition, 2011) explicitly defines the critical path as…

Generally, but not always, the sequence of schedule activities determining the duration of the project.  Generally, it is the longest path through the project.  However, a critical path can end, as an example, on a schedule milestone that is in the middle of the schedule model and that has a finish-no-later-than imposed date schedule constraint.

Unlike the RP (49R-06) from AACE International, PMI’s Practice Standard provides no meaningful method for quantitatively identifying the activities of the critical path (or any logic paths) in a particular schedule model.  In fact, in its description of the precedence diagram method (PDM – the modern version of CPM used by most modern scheduling software) the Practice Standard acknowledges the complicating factors of constraints and multiple calendars but notes that “today’s computerized scheduling applications complete the additional calculations without problems.”  Then it concludes, “In most projects the critical path is no longer a zero float path, as it was in early CPM.”  The Practice Standard goes on to scrupulously avoid any explicit link between total float and the critical path.  The impact of all this is to just take the software’s word for what’s “critical” and what isn’t.  That’s not particularly helpful.

Finally, educating senior stakeholders on the subtle difference between “schedule critical” and “critical” is always one of the first issues faced when implementing systematic project management in non-project focused organizations.  The Practice Standard’s several conflicting definitions of critical activities tend to confuse rather than clarify this distinction.

U.S. Government Accountability Office (GAO-2015)

The GAO’s Schedule Assessment Guide: Best Practices for Project Schedules (GAO-16-89G, 2015) has been taken to supersede the earlier DCMA internal guidance in many formal uses.  (Nevertheless, the GAO’s decision to discard any formal trigger/threshold values – a good decision in my view – means that the DCMA-based assessments and dashboards remain popular.)  The GAO document contains the following formal definitions:

Critical path: The longest continuous sequence of activities in a schedule. Defines the program’s earliest completion date or minimum duration.

[With some minor reservations related to meaning of “longest,” I believe this is a good definition.]

Critical activity: An activity on the critical path. When the network is free of date constraints, critical activities have zero float, and therefore any delay in the critical activity causes the same day-for-day amount of delay in the program forecast finish date.

[Unfortunately, the caveats after the first clause are insufficient, ignoring the complicating effects of multiple calendars.]

For the most part – and despite the float-independent formal definition above – the Schedule Assessment Guide’s “Best Practices” tend to perpetuate continued reliance on total float as the sole indicator of the critical path.  In fact, “Best Practice 6: Confirming That the Critical Path Is Valid” does a good job of illustrating the complicating factors of late constraints and multiple calendars, but this review leads essentially to the differentiation of “critical path” (based on total float alone) from “longest path” (based on driving logic).  This is a direct contradiction of the formal definition above.  In general, the text appears to be written by a committee comprised of P6 users (with robust driving/Longest Path analysis tools) and MSP users (without such tools.)  Thus, for every “longest path is preferred,” there seems to be an equal and opposite, “the threshold for total float criticality may have to be raised.”  This is silly.

National Defense Industrial Association (NDIA-2016)

The NDIA’s Integrated Program Management Division has maintained a Planning & Scheduling Excellence Guide (PASEG), with Version 3.0 published in 2016.  The PASEG 3.0 includes the following key definitions:

Critical Path: The longest sequence of tasks from Timenow until the program end. If a task on the critical path slips, the forecasted program end date should slip.

Driving Path(s): The longest sequence of tasks from Timenow to an interim program milestone.  If a task on a Driving Path slips, the forecasted interim program milestone date should slip.

The second clause of each definition – which presumes a single calendar – is included in the Schedule Analysis chapter but is excluded from the formal definition in Appendix A.  Timenow is effectively the data/status date.  The PASEG does not define or mention critical task/activity as distinct from a “task on the critical path.”

The PASEG notes, “Some of the major schedule software tools have the ability to identify and display critical and driving paths. Additionally, there are many options available for add-in/bolt-on tools that work with the schedule software to assist in this analysis.”  [I suppose BPC Logic Filter would be one of the mentioned add-in tools for Microsoft Project.]

The PASEG also mentions some manual methods for identifying critical and driving paths, e.g.:

a. Imposing a temporary, super-aggressive late constraint and grouping/sorting the output (presumably by total float and early start.  Though not explicitly mentioned in the method description, total float is the key output affected by the imposed constraint.)  Obviously, this method isn’t reliable when more than one calendar is used.

b. Building a custom filter by manually “click-tracing” through driving logic and marking the activities.  This method is most reliable in P6, with some caveats.  It is reliable in MSP only under some fairly restrictive conditions.

In general, these methods are non-prescriptive, though the emphasis on driving logic paths (rather than total float) seems clear.

Guild of Project Controls (GPC, “The Guild” – 2018)

The Guild is a relatively young (~2013) international community of project controls practitioners – initially associated with the PlanningPlanet.com web site – whose founding members have assembled a Project Controls Compendium and Reference (GPCCaR).  The GPCCar takes the form (more or less) of an introductory training course on Project Controls, including Planning and Scheduling.  The GPCCaR includes no formal Glossary, Terminology, or Definitions section, so “critical path” and “critical path activities” accumulate several slightly varying definitions in the applicable Modules (07-01, 07-7, and 07-8).  In general, “zero total float” and “critical path” are used interchangeably, and the complications of multiple calendars and multiple constraints in P6 and MSP are ignored.  This is not a suitable reference for complex projects that are scheduled using these tools.

American Society of Civil Engineers (ASCE)

ASCE Standard ANSI/ASCE/CI 67-17 – Schedule Delay Analysis is one of the few documents with a clear and correct distinction between the critical path and the collection of critical activities:

Critical path—The series of logically connected tasks that define the minimum overall duration for completion of the project, also known as the longest path. There can be more than one critical path in the schedule.

Critical activities—Activities with zero or negative float in a schedule reflecting a current adjusted completion date, some of which may not be on the critical path.

Recap

  1. A full understanding of driving and non-driving schedule logic paths for major schedule activities is useful for managing and communicating a project execution plan.
  2. The most important logic path in the project schedule is the “critical path,” i.e. the driving path to project completion.  Overall acceleration (or recovery) of a project is only made possible by first shortening the critical path.  Acceleration of activities that are not on the critical path yields no corresponding project benefit to project completion.  Multiple critical paths may exist.
  3. Some traditional notions of critical path path attributes – e.g. critical path activities possess no float; slippage or acceleration of critical path activities always translates directly to project completion – are not reliable in modern project schedules.
  4. Total float remains a valuable indicator of an activity’s scheduling flexibility with respect to completion constraints of the project.  An activity with TF=0 may not be allowed to slip if all project completion constraints are to be met.  Activities with TF<0 must be accelerated if all the constraints are to be met.
  5. Project scheduling software typically defines individual activities as “critical” without fully accounting for common complicating factors like multiple constraints and calendars.  As a result, the collection of “critical” tasks/activities in a complex project schedule often fails to identify a true critical path.
  6. A critical task/activity is best defined (in my opinion) as either:
    1. An activity that resides on the critical path; or
    2. An activity whose delay will lead to unacceptable delay of the project completion; or
    3. An activity whose delay will lead to unacceptable delay of some other constrained activity or milestone.
    4. In general, these conditions are mutually exclusive, and different activities within a single project schedule may satisfy one or more of them.
  7. Professional project managers and schedulers should be careful not to automatically characterize “critical” tasks (i.e. those with low total float) as indicators of a project’s critical path when complicating factors are present.

 

Recent Improvements to BPC Logic Filter (Feb 2018)

We developed BPC Logic Filter – our Add-In for Microsoft Project – primarily for our own use, and we continue to make modifications mainly when we see the need.  This entry is intended to highlight several recent improvements that have been specifically made to serve the needs of other users.

Region and Language Adaptability (Jan’18)

As its name implies, BPC Logic Filter creates special views of the project schedule that rely on unique filters and formatting to highlight important, logic-related information.  Until recently, these unique filters and formatting were unavailable to Microsoft Project users with non-English display languages.  In response to specific requests from French-language users of the software, we made substantial changes to the underlying code and settings to account for the ways that filters, views, and Gantt bars work in different languages.  Subsequently, we systematically incorporated several other European languages.  As a result, BPC Logic Filter works without limitations in the default French, German, Italian, Spanish, and Portuguese (Brazilian) languages in addition to English.  [Mar’19 Edit: While the program interface is restricted to English, the group of usable language packs has been expanded to nine, including Russian and Hebrew.  Other Unicode-compliant language packs can be added if requested by specific users.]

User-Selectable Fields in Task Logic Inspector (Feb’18)

As shown in a previous post, the Task Logic Inspector provides a rich table of information concerning predecessor and successor tasks; including dates, progress, slack, calendar, and resources.  The default fields are shown below.  (The resources of the current task are highlighted because the task has been delayed by resource leveling.)

While task calendars and resources can be important for determining the basis of a task’s current schedule dates, they are not present in all schedules.  In most schedules, they provide no value in the table.

Recent versions of BPC Logic Filter have made these last two columns available as user-selectable, optional fields.  Thus, in cases where the Task Calendar or Resources are not important, the user may display other information from the related tasks.  Users can select the two option fields using the pull-down lists in the General Settings.  To keep things compact, the pull-down lists are restricted to the fields contained in the current task table.

Here, the Text3 field (used for a Responsibility code) and the task Work field have been selected.  Typically, this information may be useful for the analyst to evaluate the details of the relationship – or to guide further navigation through the network using the Jump button.

Jumping through Sub-Projects with Task Logic Inspector (Feb’18)

Unlike logic tracing within a standalone project schedule, logic tracing through inter-project links is problematic.  BPC Logic Filter was developed to trace such links as long as the connected projects are linked together in a master-subproject structure.

The vast majority of Microsoft Project schedules encountered in the world – including most projects that we work with from day to day – are in fact standalone, and the Task Logic Inspector was initially developed to meet that need.  When used within linked master-subproject structures, the initial release of Task Logic Inspector would correctly report the logical relationships, but the Jump button did not work across inter-project links.

Some users make extensive use of very large linked master-subproject structures, so recent releases have removed this limitation.  The Jump button now works as intended, selecting and activating the selected predecessor or successor (as long as it is visible in the current view).  Jumping across inter-project links can involve more number-crunching, however, especially if the two related tasks are many rows apart.

The example below is taken from the linked master-subproject structure described in the Introduction to BPC Logic Filter on our website.

 

The Right Way to Construct Level of Effort (LOE) Activities in Primavera P6

This short entry demonstrates why Level of Effort activities in Oracle Primavera P6 should be constructed using predecessor successor relationships only – especially when designating Critical activities using the Longest Path algorithm. 

P6 LOE Activities

Level-of-Effort (LOE) activities in Oracle Primavera P6 project scheduling software are useful for summarizing the schedule dates of other (primary) activities.  They are effectively a replacement for the “hammock” activities that existed in prior versions of Primavera products, including Primavera Project Planner (P3) and SureTrak Project Manager.

In prior software versions, hammocks were constructed by establishing a group of start-controlling activities as SS predecessors and a separate group of finish-controlling activities as FF successors.  To avoid circular logic, the same activity could not be included in both predecessor (i.e. Start) and successor (i.e. Finish) groups.

In P6, LOE activities can be constructed using practically any mix of predecessors and successors, and the help file implies that the two can be used almost interchangeably.  Although the same activity may not be included as both a predecessor and a successor, it MAY be included multiple times (e.g. as both an SS and FF predecessor) in either group.  This allows for more flexibility in modeling activities that are not strictly hammocks.

P6 Help – Level of effort activity

Here’s a portion of the LOE Help topic in P6, which seems indifferent to the types of relationships used in specifying primary activities.

A level of effort activity is similar to but different from a hammock activity.

  • A level of effort activity uses its assigned calendar to summarize its dates. Hammocks are not scheduled using their own calendar.
  • Any type of relationship can be assigned to a level of effort activity. Only a start-to-start and finish-to-finish relationship can be assigned to a hammock activity.
  • A level of effort activity’s duration is calculated from the earliest early start of its predecessors/successors (linked to the start end of the level of effort activity) to the latest early finish of its predecessors/successors (linked to the finish end of the level of effort activity).A hammock activity’s duration is calculated from the earliest early start of its predecessors to the latest early finish of its successor activities.

Problems with LOEs and Longest Path

Despite the increased flexibility afforded by LOE activities in P6 – and its implied indifference to predecessor or successor relationships – many users continue to use SS-predecessors and FF-successors when establishing LOE dates.  This can create issues when the project’s Critical Path is defined using the Longest Path option.

Here is a simple example project comprising a Critical Path of activities A-B-C-D-E-F-G with a side branch of associated activities A1-B1-C1-D1-E1-F1.  The side activities must be completed before the final activity G can start.  All activities are on the same calendar, and there are no constraints or resources.  The corresponding Critical Path, as determined by Total Float (TF=0), is highlighted red on the Gantt Chart.

Critical Path by Total Float

For this simple project, the Critical Path based on Total Float should be identical to the Critical Path based on “Longest Path” – i.e. the “driving path to project completion.”  Unfortunately, this is not the case, as activities A1 (TF=10) and B1 (TF=8) are now included – incorrectly – on the Longest Path.

Critical Path by Longest Path (Driving Logic)

This error is caused by the Level of Effort activity LOE-1, which summarizes the dates of the side activities in Branch 1.  Similar to P3 hammocks, this LOE activity is constructed using SS-predecessors to govern its start and FF-successors to govern its finish.  The resulting dates are correct, but two complications are introduced.

P3 Hammock-Type Relationships
  1. As a rule, P6 marks all relationships to and from LOE activities as “Driving,” even when the relationship does not control any of the LOE’s dates.
  2. The Longest Path algorithm, which traces driving logic backward from the project completion, does not differentiate LOE driving relationships from other driving relationships during the trace.

As a result of these complications, the Longest Path calculation traces driving logic backward from activity F1 through LOE-1 to its two driving predecessors A1 and B1.  The latter two – along with their entire chains of driving predecessor logic, if any – are now included on the Longest Path.  P6 automatically removes the LOE activity and its relationships from the Longest Path (after the backward pass), but the “Critical” flag on its “driving” predecessors remains.

Activities that are incorrectly included on the Longest Path may be identified by first noting those “Critical” activities whose successor relationships are NOT BOTH “Driving” and “Critical.”  Then their “driving” predecessors are traced until either 1) there are no more driving predecessors, or 2) an activity is reached that has a separate successor relationship that is BOTH “Driving” and “Critical,” provided that this successor does not ultimately lead to another incorrect LOE predecessor.  Such an examination can be tedious.

A quicker identification is obtained by re-calculating the schedule using Multiple Float Paths (Free Float option), with no End activity specified.  Unlike the erroneous LP algorithm, MFP analysis correctly truncates the backward trace at LOE activities.  Consequently, the true driving path to project completion (i.e. the correct Longest Path) of our simple project is identified as “Float Path 1,” and activities A1 and B1 are correctly relegated to Float Paths 6 and 5, respectively.

Multiple Float Path (FF)

When analyzing Multiple Float Paths under the Longest Path regime: if a “Critical” activity has a Float Path that is higher than the Float Path of even one non-critical activity (all computed using the Free Float option), then that “Critical” flag may be incorrect.*

[Edit:  Unfortunately, similar symptoms are produced by MFP analysis when P6 incorrectly assigns legitimate members of the Longest Path to much higher Float Path numbers.  See details in Relationship Free Float and Float Paths in Multi-Calendar Projects (P6 MFP Free Float Option).]

Avoiding the Problem

The simplest way to avoid this Longest Path LOE bug is to avoid including a mix of predecessors and successors when specifying the primary references for LOE activities.  That is, use ONLY predecessors or ONLY successors.  Since LOEs are technically inheriting their dates entirely from the primary activities, my initial preference was to use only predecessor relationships in the LOE.

Using Predecessor-Only Relationships

As shown here, the Longest Path of our simple example project is fixed by re-constructing LOE-1 logic using predecessors only.  The two activities that were formerly “FF” successors of the LOE are now “FF” predecessors of the same LOE.  The dates and float calculations are essentially unchanged, but the Longest Path is now correct.

Predecessor-Only Relationships – LOE-1

Sometimes we want to make an LOE activity whose finish corresponds to the finish date of the project.  Creating such an LOE using predecessor-only relationships doesn’t work as intended, however, because P6 picks the new LOE as the starting point of its Longest Path trace during the backward pass.  Thus, our intention to stop logic flow through the LOE is foiled.  In the next figure, this is shown by the new LOE-2 activity, whose finish is determined by the finish milestone (FM) of the project.  Since LOE-2 is the latest-finishing activity with no successors, P6 starts the backward pass with it, ultimately including its non-critical predecessors A1 and B1 (incorrectly) on the Longest Path.

Predecessor-Only Relationships – LOE-2

Using Successor-Only Relationships

In contrast, if LOE-2 is constructed using successor-only relationships, then P6 will never choose it as the starting point of the Longest Path trace.  Moreover, the absence of predecessors will ensure that when P6 does encounter such an LOE during the backward pass, the Longest Path trace will not continue past the LOE.  As shown below, constructing LOE-2 using successor-only relationships leads to dates, float calculations, and Longest Path calculation that are all correct.  This example suggests that successor-only relationships should be the preferred method for specifying LOE activities in P6.*

Successor-Only Relationships – LOE-2

*Thanks to astute reader A Lou Gonzalez, who pointed out the special issue with using predecessor-only relationships to define LOE activities at the project completion date.

Late Cost Curves for LOE Activities

While using predecessors-only to specify LOE activity dates seems to fix the logic-flow issues, it has no effect on another defect of LOE activities.  As Wail Menesi, has described in his LinkedIn Pulse entry,  P6 incorrectly computes the remaining late start dates of certain in-progress LOE activities.  As a consequence, the “Remaining Late” resource distribution for the affected activity is skewed to the left of the data date.  In other words, P6 indicates that certain incomplete work must be completed in the past to avoid delaying the project, even when there is no negative float.  That’s clearly incorrect.  Fortunately, the issue seems to be limited to LOE activities who’s start dates are determined by Finish-to-Start relationships – a relatively rare structure in practice.