Driving Logic in Backward Scheduled Projects (Microsoft Project)

In MSP, a “backward scheduling” mode – sometimes called backward planning, reverse scheduling, or reverse planning – can be invoked by scheduling the project from its finish rather than its start.  In the traditional language of Critical Path Method scheduling, it’s most simply described as a Late Dates schedule.  Backward planning is useful in several non-standard methodologies, including Critical Chain Project Management and the “Pull Planning” aspects of the Last Planner System.

The Mechanics of Backward Scheduling

When specified for the active project, this mode essentially does the following:

  1. Sets the default constraint type for all new tasks to As Late As Possible.
  2. Re-sets the constraint type for all existing Summary tasks to As Late As Possible.
  3. [Users choosing this mode in the middle of schedule development must manually re-set the constraint type for all existing non-Summary tasks to As Late As Possible.]
  4. Automatically sets “No Later Than” constraints when dates are manually entered into the Start or Finish fields of tasks.  [Such date entry in forward scheduling mode leads to “No Earlier Than” constraints, so users choosing this mode in the middle of schedule development should manually review, validate, and potentially re-set any previously-entered date constraints.]
  5. Performs the network scheduling calculations in reverse order, with the reflection point occurring at the project start rather than the project finish.  I.e. the Project Start Date (not the Finish, which is user-input) is determined by the logic.
  6. Sets the “Start” and “Finish” of automatically-scheduled tasks to their Late Dates rather than their Early Dates.  (This is the most important part.)
  7. Finally, the resource leveling engine resolves resource over-allocations by accelerating higher priority tasks from late dates rather than delaying lower priority tasks from early dates.  Thus, entries in the “leveling delay” field are negative.  This behavior creates a minor complication regarding use of Priority = 1000.  Just as in forward scheduling, a task with Priority=1000 is always exempted from any leveling action.  In backward scheduling, this means that Priority values of 1000 and 0 are essentially equivalent when considered in the leveling decisions.  The highest effective Priority for controlling leveling behavior then becomes 999, not 1000.

Logic relationships used in backward scheduling still have exactly the same meanings that they do in forward scheduling.  A Finish-to-Start relationship still means that the two tasks are logically connected such that the successor may not start before the predecessor finishes, and the rarely-applicable Start-to-Finish relationship still indicates that it is impossible for the successor to finish before the predecessor starts.  Some users seem to think that backward scheduling involves reversal of these two relationships in particular, but that’s not consistent with the rest of the backward scheduling mode.  Unfortunately, mixing of the two approaches seems to continue, though this typically amounts to invalid date manipulation in my view.

In normal (i.e. forward) scheduling, a task with an “As Late as Possible” constraint has the dubious distinction of corrupting its entire chain of successors – driving all of them to the critical path.  There are very few legitimate applications for this constraint.  In backward scheduling, the “As Soon as Possible” constraint plays a similar role, corrupting its chain of predecessors.  It needs to be avoided in backward scheduling.

When to Use Backward Scheduling

I’ve never used backward scheduling in a real project.  Others have recommended its use to determine the desired start date of a project when the desired completion date is already known.  It also seems consistent, when tasks are suitably buffered, with aspects of Critical Chain Project Management that require work to be scheduled as late as possible.

Ultimately, backward scheduling rests on the presumption that tasks can be accelerated (i.e. moved to the left on the bar chart) indefinitely as needed to meet the fixed end date for the project.  Thus, a task whose duration is extended can simply be re-scheduled to start sooner than previously planned.  And its predecessors can be similarly accelerated.  Similarly, a higher priority task can be started (and finished) earlier to avoid resource conflicts with a lower-priority task that demands the same resources.  The problem with this presumption is that time invariably marches forward, and as scheduled dates for incomplete work are overtaken by the vertical time-now line on the bar chart there is no chance for recovery.  Backward scheduling method seems pointless if the latest allowable Project Start Date has already been passed – e.g. the project is in progress.

Backward scheduling seems to be of primary value in determining the latest responsible date to start a project (or project segment) while still meeting the desired completion date.  After that, the project must be converted from backward-scheduled to forward-scheduled mode if it is to be used for updating and forecasting during project execution.  The original question – i.e. what is the latest responsible project start date? – is also easily answered by manipulating and examining the late dates of the forward scheduled project.  Thus, for a competent project scheduler, the use of backward scheduling seems largely to be an unproductive diversion.

Driving Logic Analysis

When the logic network is well constructed – and complicating factors like multiple calendars, (Early) constraints, and resource leveling are avoided – then the Critical Path may be reasonably identified by Total Slack = 0.  Other methods of driving logic analysis must be modified, however.

Under Backward Scheduling, any slack/float of a task exists on the side towards its predecessors, i.e. to its left on a bar chart.  A driving relationship exists when a successor prevents a predecessor from being scheduled any later than it is.  This means that there are Driving Successors and Driven Predecessors.  Consequently, the Longest Path in a backward scheduled project is the Driving (Successor) Path from the Project’s Start.

MSP includes two built-in methods for reviewing and analyzing driving logic: the Task Inspector and the Task Paths bar styles.  As I wrote in this article a few years ago, I’ve found these tools to be unreliable in complex real-world project schedules.   Under backward scheduling, they are essentially useless and/or misleading.

To start with, Task Inspector simply doesn’t work with backward scheduling.  Opening TI on a backward scheduled project yields the following message:  This project is set to Schedule from Finish.  We are unable to provide scheduling information.

Also under backward scheduling, the “Driving Predecessors” and “Driven Successors” bar styles are still derived from Early Dates, as they are in Forward Scheduling.  This makes them essentially useless for assessing the controlling logic of the displayed (Late Dates) schedule.  Consider the example below, where all four Task Path bar styles have been imposed, and Task 11 – A2 Structures – is selected.  (The automatic “Slack” bar style is also imposed, but it is invisible since Free Slack – formally defined by Early dates alone – is uniformly zero.) 

The selected task is in fact driving/controlling the displayed dates of both of its predecessors, but only one of them displays the correct bar style (the one that was the driving predecessor during the forward pass).  Of Task 11’s four successors, only the first (Task 13 – A2 Electrical) is directly driving/controlling Task 11’s schedule.  The tasks for two of the remaining three successor relationships are incorrectly highlighted, while the third (Task 14) is correctly highlighted only because it is driving/controlling Task 13 – a case of redundant logic.  (All four successors were driven successors during the forward pass.)  Thus in a backward scheduled project, the Task Path bar styles for Driving and Driven dependencies are meaningful (or “correct”) ONLY along the Longest/Critical path of the project, where Early dates and Late dates coincide.

BPC Logic Filter – my company’s Add-In for logic analysis of MSP schedules – identifies driving logic based on relationship free float, which we often call “relative float.”  In BPC Logic Filter, the Longest Path and near-longest paths of simple, backward-scheduled projects can be found using the Task Logic Tracer, starting from the project start milestone and using appropriate settings (i.e. driving relationships in successor direction).  As illustrated in the example project, this is fairly trivial since the results are 100% aligned with Total Slack. 

Other driving logic paths (not on the Critical Path) are not so trivial but are easily addressed using BPC Logic Filter, provided that the impact of multiple calendars is minimal.

Precision analysis of more complex, backward-scheduled projects would require some modest modifications to the algorithms.  If any BPC Logic Filter users see a need for such an improvement, please let me know in the comments, and I’ll pass it along.

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

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

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

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

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

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

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

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

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

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

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

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

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

On Manually Scheduled Tasks [Aug’18 Edit]

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

In Backward Scheduled Projects [Jan’19 Edit]

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

 

 

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

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

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

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

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

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

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

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

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

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

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


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

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

Tracing Near Longest Paths with BPC Logic Filter

This article highlights the creation of a new targeted report from BPC Logic Filter to identify the “Near Longest Paths” of a project.

While BPC Logic Filter was originally developed as a pure logic tracer, I added a few targeted reports early on to reflect some specific needs, including the “Longest Path Filter” and the “Local Network Filter.”  This article highlights the creation of a new targeted report to identify the “Near Longest Paths” of a project.

Often, when presented with a new project schedule in Microsoft Project, my first step (in concert with a logic health check) has been to run a Longest Path Filter analysis using BPC Logic Filter.  This report quickly and clearly identifies the driving path to project completion.  While the resulting filtered task list is useful for reporting, it rarely satisfies the needs of a serious analysis.  The second step, therefore, is to identify the associated near-longest-paths of the project by running a “Task Logic Tracer” predecessor analysis – with a positive relative float limit – for the project completion task.  The result is a clear description of the driving and near-driving paths to project completion.  The latest release of BPC Logic Filter adds a specific command to combine these two actions and generate a single “Near Longest Path Filter” for the project.

The mechanics are pretty simple.  As usual – with a Gantt view active in a project that contains logic – just open the Add-Ins ribbon [changed to the BPC ribbon in subsequent versions] and click on the button for “Near Longest Path Filter.”

bpclogicfilter-ribbongroup1611

The add-in will initialize, and the user is given a choice of modifying the default analysis parameters.  Some of the parameters are pre-set and can’t be changed here.  The key parameter for a formal Near-Longest-Path analysis is the Relative Float Limit, highlighted below.  Any related task with a Path Relative Float that is less than the specified limit will be included in the filter; all others will be ignored and considered unrelated.  The default value is 100 days away from the driving/longest path (which can be changed in the Settings).

bpclogicfilter-near-longest-path-window

The standard output for a simple project (using the parameters selected above) is provided here.  Selecting “Re-Color Bars” instructs the add-in to generate the custom output shown, including the header, the legend, and five different bar colors depending on proximity to the Longest Path.  Thresholds for applying these bar colors can be manually adjusted in the program settings or, if desired, automatically adjusted by the add-in.  nlp_tensixexampleltr

Here’s an alternate view showing the Near Longest Paths in-line in the context of an existing Outline/WBS organization.  In this analysis I reduced the Relative Float Limit from 100 to 20 days, and the three tasks at the bottom of the earlier figure were ignored.  Here they are given a green “BPC Unrelated Task” bar.

nlp_tensixexampleinlineltr

While I’ve always hated redundant work, this particular improvement to BPC Logic Filter was kick-started by my recent review of the draft of “Analyzing Near-Critical Paths,” a pending Recommended Practice from AACE International.  The new draft recommended practice is based largely on the previously-published (2010) Recommended Practice 49R-06 – Identifying the Critical Path.  According to both documents, Critical- and Near-Critical paths may be identified on the basis of total float/slack thresholds (in the absence of variable calendars, constraints, or other complicating factors) and – when total float/slack does not suffice – “closeness to the longest path.”  For the latter cases, 49R-06 suggests two methods of analysis:

  • Longest Path Value – a metric that appears similar to Path Relative Float (in BPC Logic Filter) for the project completion task. This metric has been applied as an add-on to Oracle Primavera scheduling tools: See Ron Winter’s Schedule Analyzer.
  • Multiple Float Path analysis. Like the Longest Path Value, Multiple Float Path analysis is primarily associated with Oracle’s Primavera scheduling tools – it is presented as an advanced scheduling option in P6.  As I’ve noted in Beyond the Critical Path – multiple float path analysis indicates closeness to the longest path without explicitly measuring and presenting it.  Detailed examination of the results, including relationship free floats, is necessary to determine the apparent relative float of each activity.

From its start, BPC Logic Filter has supported a similar analysis for Microsoft Project schedules through its Path Relative Float metric, Multiple-Float-Paths views, and other reporting.  The new “Near Longest Path Filter” offers a single-step approach to identifying and analyzing near-critical paths in the presence of variable calendars, constraints, and other complicating factors – when Total Slack becomes unreliable as an indicator of logical significance.

See also Video:

Video – Analyze the Near-Longest Paths in Microsoft Project using BPC Logic Filter

 

A Logic Tracing Example in Microsoft Project

This article uses BPC Logic Filter to present the progression of a single logic tracing example from a simple approach to a more focused analysis.

[If you came here looking for a simple logic tracing macro and are comfortable using Visual Basic for Applications (VBA), have a look at these two other entries: Macro for tracing filtering and sorting task paths in Microsoft Project and Simple Macro for Listing Driving Predecessor(s) in MS Project.  They may give you what you want as long as your project has simple logic.]

BPC Logic Filter is an excellent tool for defining and visualizing the Critical Path and Near-Critical Paths of a project when Total Slack proves inadequate – namely in the presence of constraints, variable calendars, and resource leveling.  As I’ve written elsewhere, however, the first version of BPC Logic Filter was prompted by a very different, though straightforward stakeholder request: “My people can’t see why they need to finish these tasks so soon. Isn’t there a report or something to show what other tasks (in other departments) are depending on them?”  In other words, couldn’t I group, filter, and sort tasks simply according to logical relationships – in addition to Work Breakdown Structure, responsible department, and other codes.  At its core, the resulting solution was a simple logic tracing routine for exploring, marking, and displaying logical relationships in an existing project schedule.

This article presents the progression of a single logic tracing example from a simple approach to a more focused analysis.

Consider the example of the small installation project presented below.  There is a deadline on the “Substantial Completion” milestone, and the project is 10-days behind schedule.  For unrelated reasons, the project manager has identified a need to trace the predecessors driving one task – “A3 Install Line D.”  The selected task is marked with the arrow in the figure.

lt-00

We can first examine the task’s predecessors using MSP’s Task Detail Form and the Task Inspector feature.  The form shows that the task has two finish-to-start predecessors but provides no other schedule information for them.  Task Inspector identifies the second one — ID 22 – A3 Install Line C — as the driving predecessor.  That is the predecessor whose logic is controlling the start date for our task.

The Logic Inspector in BPC Logic Filter presents a single consolidated view of the task’s driving and non-driving predecessors, including other relevant information like dates, task calendars, and resources.  Driving relationships are highlighted and listed at the top, while links to inactive predecessors are de-emphasized and listed at the bottom.  For logical significance, the RelFlt column indicates how far the predecessor relationship is from being a driving relationship, in days.  (Logic Inspector also provides a similar view of successor relationships.)

Using a simple “Trace” macro (like the the one linked above or one of the freeware settings in BPC Logic Filter), it is possible to identify the chain of predecessors and apply a filter to hide the tasks that are not related to the selected task.  As seen in the result shown below, however, the actual driving logic for the selected task is not apparent.  (And no, Total Slack does not define driving logic for this task.)

lt-01

With advanced logic analysis features, the relative float of all the predecessor task paths can be defined and displayed.  The following chart shows the entire project, with the predecessor paths of the selected task highlighted according to their path relative float in days.  (Path relative float indicates how much a particular task or path may be delayed before affecting the selected task; i.e. “days away from driving”.)  Path relative float is indicated numerically at the right side of each related bar.  Unrelated bars are de-emphasized and colored green.

lt-02

BPC Logic Filter allows one variation – bounded network analysis – to only show connections to a particular target task.  The figure below highlights the connections between the selected task, A3 Install Line D, and the target task, A2 Civil.

lt-03

The previous two figures displayed the related task paths in-line and within the context of the overall project view.  A more focused view of the driving and near-driving paths is provided by applying a filter to hide all unrelated tasks, as shown here.

lt-04

It is often useful to group and sort tasks to clearly display the chain of driving logic and associated near-driving paths.  The first group in the figure below – “BPC Relative Float (d): 0” – indicates the driving logical path for the selected activity.  The next two groups depict branching logical paths (one task each) that are 10- and 20-days away from driving the selected task.

lt-05

Finally, when attempting to accelerate a task by shortening its driving logical path, Drag quantifies the maximum acceleration that may be gained by shortening a particular task along that path.  Drag is limited by the existence of parallel paths, as clearly evidenced by Tasks 6 and 11 in the figure below.  For focused acceleration of complex projects, the Drag metric can assist in prioritizing actions.

lt-06

The examples shown here represent successively more powerful analyses of driving logic for an arbitrary task in a project schedule.  If that task were the final task or a key completion milestone for the project, then the resulting special case of the driving path would be the “Critical Path” for the project.

See a related video entry:

Video – Logic Tracing Example in Microsoft Project

 

Eddies and Checkdams: Odd Structures in CPM Logic Flow

In logic-driven project schedules, the scheduled start and finish of each activity is determined by a “driving path” of predecessor activities and relationships.  Driving logic is said to “flow” along this path from the earliest predecessor to the activity’s completion.  In simply-modeled projects, this driving logic flow is one-directional and continuous, such that any delay (or acceleration) of a predecessor task is directly translated to a corresponding delay (or acceleration) of its ultimately driven successors.  Thus, delaying a task on the “Critical Path” (the driving path to project completion) ultimately delays the project.  More complex schedule models – i.e. those using other than finish-to-start relationship links – allow the driving logic flow to be checked or even reversed, so delay or acceleration of a given task may not have the anticipated result on other tasks or on the project as a whole.  Such effects can be transient, appearing and disappearing in the course of a single progress update.

Some Cases

Last year I read a series of articles by Miklos Hajdu (Research Fellow at Budapest University of Technology and Economics) on the sometimes-unexpected consequences of certain relationships in logic-driven project schedules.  I encountered them again a few months ago during an extended Linked-In discussion that Hajdu started relating to Drag calculation.  (BPC Logic Filter is one of the few scheduling tools that actually sets out to compute drag, and we identified some areas needing standardization of definitions.)

Hajdu’s Articles laid out five basic cases where incrementally delaying or accelerating a particular Critical Path activity might not lead to the expected delay or acceleration of the overall project:

  • Normal Critical Activities (Expected Behavior – i.e. Lengthening task extends project; Shortening task shortens project.)
  • Neutral Critical Activities (Neither lengthening nor shortening the task has any impact on project completion.)
  • Bi-Critical Activities (Either lengthening or shortening the task always extends the project.)
  • Reverse Critical Activities (Lengthening the task shortens the project; Shortening the task extends the project.)
  • Increasing Neutral Decreasing Reverse Critical Activities (Lengthening the task has no impact on project completion; Shortening the task extends the project.)
  • Increasing Normal Decreasing Neutral Critical Activities ( Lengthening the task extends the project; Shortening the task has no impact.)

A more recent blog by consultant Pat Weaver, Critical confusion – when activities on the critical path don’t compute…… reviewed these cases and illustrated the consequences using time-scaled-logic diagrams rather than the simple fragnet blocks first used by Hajdu.  With graphical images especially, Weaver has done a great job of clarifying the underlying logic flow and emphasizing the consequences of careless planning.  His article is a good read. Unfortunately, his suggestion that competent planners should avoid creating any such constructs in their project schedules seems impractical for planners using P6 or Microsoft Project to schedule complex projects.

I had encountered all of these issues previously in various project schedules and and had focused on them quite a bit while developing the drag-associated parts of BPC Logic Filter – that’s where the “Negative, Positive, and Absolute” terminology below came from.

Driving Logic Flow of the Cases

At the start of a project (i.e. ignoring progress updates and Data Date), every activity is scheduled to be completed according to a path of driving logic (comprising predecessor activities AND relationships) extending from the project start milestone or some valid external constraint forward to the activity’s Finish. (For the particular case of the Project Completion activity, its driving path is synonymous with the “Critical Path” of the project.)

  • Identifying the “Driving Logic Flow” through any arbitrary activity along that path starts with the Relationship Free Float values of its predecessor and successor links.  A Relationship Free Float value of 0 indicates a driving relationship, while a value greater than zero indicates a non-driving relationship.
  • The activity’s duration “participates” in the driving logic flow if (and only if) there are “Driven” and “Driving” relationships at opposite ends of the activity. Various combinations of relationship float have the implications in the table below.
Relationship Float and Driving Logic Flow
Relationship Float and Driving Logic Flow

Keeping in mind that any changes to activity duration can immediately change the driving logic flow through the schedule and the associated relationship floats – such that an activity described by the first line of the table above may jump to the third line simply by adding a day to its duration – we can interpret the table as follows:

  • An activity with a Driven Start and a Driving Finish has a Positive duration participation, as the logic flows forward through the duration from Start to Finish.  This is “Normal” in Hajdu’s articles; lengthening the task extends the project, while shortening the task shortens the project.  This case seems to represent the vast majority of activities in typical schedules.  BPC Logic Filter computes a drag value corresponding to the activity duration, any applicable constraints, and parallel (i.e. near-critical) paths.

    Duration and Logic Flow1
    Positive Duration Participation in Logic Flow (“Normal Critical”)
  • An activity with a Driven Finish and a Driving Start, on the other hand, has a Negative duration participation, as the logic flows backward through the duration from Finish to Start.  This corresponds to Hajdu’s  “Reverse-Critical” case; lengthening the task and thereby allowing it to start sooner ends up shortening the project, while shortening the task and thereby forcing it to start later ends up extending the project.  BPC Logic Filter computes a negative drag value for these cases, partly to indicate the apparently perverse logic at work. While such tasks seem to be rare in baseline schedules, I have seen them arise during updating on fairly high-level integrated masters (i.e. not in construction).

    Duration and Logic Flow2
    Negative/Backward Driving Logic Flow through Duration – Starting Early and working slower Helps; Starting Later and working fast hurts.
  • For an activity with only a Driven Finish and Driving Finish (or Driven Start and Driving Start), then the duration is bypassed and has no participation in the driving logic flow.  This corresponds to Hajdu’s “Neutral Critical” case; neither lengthening nor shortening the task has any impact on project completion, and BPC Logic Filter computes a duration drag of zero for task B.  It should be noted that although “dangling starts” and “dangling finishes” are evident in the examples depicted below, they are unrelated to the zero-participation observed.  Adding non-driving start predecessors and/or finish successors to Activity B would not change the conclusions.
    Logic Flow Duration Bypass - Through Finish
    Logic Flow Duration Bypass – Through Finish

    Duration and Logic Flow3
    Logic Flow Duration Bypass – Through Start
  • An activity with both driving and driven relationships at both ends (i.e. minimum Relationship Float = 0 in all four columns of the table) represents four parallel driving logic paths:  1) through the Start only; 2) through the Finish only; 3) forward through the Start, the Duration, and the Finish; and 4) backward through the Finish, the Duration, and the Start.  In this case, the Duration Participation is “Absolute,” since any change to the activity duration (either positive or negative) results in positive (lengthening) of the overall path.  There is no chance to accelerate the project here, so BPC Logic Filter computes a duration drag of 0.  This case corresponds to Hajdu’s “Bi-Critical” case.  I’ve added an additional predecessor and successor to the illustration fragnets below – mainly to indicate that its occurrence is not limited to ladder-logic structures.  The combined “Positive” and “Negative” behaviors are obvious.

    Duration and Logic Flow5
    Absolute Participation = Positive/Normal on Lengthening, Negative/Reverse on Shortening
  • Finally, the four variations of “Limited” Duration Participation arise from the cases where three of the four “Relationship Float” columns are zero.  They essentially represent various combinations of “Positive,” “Negative,” and “None” cases above, and they correspond to Hajdu’s “Increasing Normal Decreasing Neutral” and “Increasing Neutral Decreasing Reverse” cases.   With any of these cases, it is only possible to Lengthen, never to Shorten, the overall length of the project by modifying the duration of Task B, so BPC Logic Filter computes a drag of zero.
    Duration and Logic Flow6
    Positive Limited Low Participation – Acceleration won’t help, but slippage will hurt.
    Duration and Logic Flow7
    Positive Limited Low Participation – Acceleration won’t help, but slippage will hurt.
    Duration and Logic Flow8
    Negative Limited High Participation – Starting early and working longer won’t help, but delaying start will hurt.
    Duration and Logic Flow9
    Negative Limited High Participation – Starting on-time and working slower won’t hurt, but starting later and working faster will hurt.

    Logic Flow Conclusions

Ultimately, these types of odd logic structures seem to arise from two contributory causes:

  1. The legitimate need for project planners to include in the project schedule no more detail than is necessary to plan and control the work (at the level reflected in the schedule).  In Primavera P6 and Microsoft Project scheduling software – based on the precedence diagramming version of the critical path method (i.e. PDM/CPM) – this need is partly satisfied by consolidating many single activities representing simple tasks (with only Finish-to-Start relationships) into longer activities representing more complex work, connected with relationships other than Finish-to-Start.  Common examples are Finish-to-Finish and Start-to-Start, often with time or volume lags. As a consequence, driving (controlling) predecessor logic can either “push” an activity (through its “Driven Start”) OR “pull” the activity (by its “Driven Finish”) – or both. Similarly, the activity may drive its logical successors through its “Driving Start” or its “Driving Finish.”
  2. The continuous-activity assumption in the prevailing PDM software packages like P6 and MSP.  That is, while the activity may be pushed and/or pulled by predecessor logic, the activity’s duration remains as a rigid connection from Start to Finish, neither stretching nor compressing (nor splitting into parts) in response to logical pressures alone.  Consequently, the activity’s duration will be scheduled at the earliest continuous interval that satisfies the most stringent of its start/finish predecessor relationships.  All other predecessor relationships will possess “relationship free float.”

Within P6 and MSP schedule models, using Ladder Logic to approximate progressive feeding of work volumes between largely parallel activities is a technique that effectively models the actual work interfaces.  Yet it seems virtually guaranteed for such paired-activity ladder structures to encounter at least “neutral-critical” and sometimes “bi-critical” driving logic flow during updating.  In my opinion this should be acceptable as long as the paired activities are effectively managed together.

Negative (“Reverse-Critical”) driving logic flow, however, reflects a case where the work being depicted is too complex to be represented by a single activity, and further breakdown is needed.  Since it also provides an opportunity for the scheduler to sequester or otherwise manipulate float, the underlying logic structure may be indirectly prohibited by scheduling specifications.  BPC Logic Filter presently flags reverse flows of driving logic (using negative drag) during the drag analysis.

The multiple cases where the driving logic flow effectively bypasses an activity’s duration (“Neutral-Critical”) appear to be a natural outcome of the scheduler’s intent.  In addition, they seem consistent with the actual work interfaces in some construction projects, particularly where there are substantial variations in the production rates of parallel activities.  While BPC Logic Filter doesn’t currently identify such cases, it seems reasonable to modify the Gantt-bar coloring routines in a future release.