liveBook · Manning

Critical path method

As explained in Statistics Every Programmer Needs

A critical path is the sequence of project activities with zero scheduling slack that determines the shortest possible project completion time.

The critical path method (CPM) finds the longest sequence of dependent activities in a project plan. Its length is the shortest possible completion time under the planned durations and dependencies. A delay on that path delays the project; activities off the path may have scheduling flexibility. Use CPM to decide which work needs the closest attention and which activities could shorten the schedule if accelerated. section 13.3

Start with a work breakdown structure that identifies activities and their predecessors, then assign each activity an estimated duration. Calculate four times for every activity:

  • Forward pass: earliest start (ES) is zero when there are no predecessors; otherwise it is the greatest predecessor earliest finish. Earliest finish (EF) = ES + duration. section 13.3.1
  • Backward pass: begin at the project finish. Latest finish (LF) is the smallest latest start among immediate successors; latest start (LS) = LF − duration. section 13.3.2
  • Slack = LS − ES, equivalently LF − EF. Zero-slack activities are critical; positive slack indicates how far an activity can move without delaying project completion. section 13.3.3

Automated reporting tool: 29 weeks

The plan contains 12 activities whose expected durations sum to 39 weeks, but some work can proceed in parallel. CPM gives a 29-week project duration and the critical sequence A → B → C → D → E → G → J → K → L. Activities F and H each have five weeks of slack; I has nine. A small Python implementation can calculate the schedule from activities entered in dependency order: ```python tasks = { 'A': (3, []), 'B': (2, ['A']), 'C': (3, ['A','B']), 'D': (5, ['C']), 'E': (3, ['D']), 'F': (4, ['C']), 'G': (4, ['E']), 'H': (3, ['F']), 'I': (3, ['F']), 'J': (4, ['G','H']), 'K': (3, ['I','J']), 'L': (2, ['K']) } es, ef = {}, {} for task, (duration, predecessors) in tasks.items(): es[task] = max((ef[p] for p in predecessors), default=0) ef[task] = es[task] + duration finish = max(ef.values()) successors = {task: [] for task in tasks} for task, (_, predecessors) in tasks.items(): for predecessor in predecessors: successors[predecessor].append(task) ls, lf = {}, {} for task in reversed(tasks): lf[task] = min((ls[s] for s in successors[task]), default=finish) ls[task] = lf[task] - tasks[task][0] critical = [task for task in tasks if ls[task] == es[task]] print(finish, critical) # 29 ['A', 'B', 'C', 'D', 'E', 'G', 'J', 'K', 'L'] ``` The input order matters here: every predecessor must appear before its dependent activity. Check that ordering and the estimates before relying on the result. section 13.1 section 13.3.3 section 13.3.4

Table 13.3 CPM results for the automated reporting tool project. Activities in any project have slack or no slack, which is derived by subtracting the earliest start from the latest start or, alternatively, by subtracting the earliest finish from the latest finish (it doesn’t matter). Activities with no slack are on the critical path, whereas activities with slack are not.
Activity
Earliest start (ES)
Earliest finish (EF)
Latest start (LS)
Latest finish (LF)
Slack (LS – ES)
Critical path?
A
0
3
0
3
0
Yes
B
3
5
3
5
0
Yes
C
5
8
5
8
0
Yes
D
8
13
8
13
0
Yes
E
13
16
13
16
0
Yes
F
8
12
13
17
5
No
G
16
20
16
20
0
Yes
H
12
15
17
20
5
No
I
12
15
21
24
9
No
J
20
24
20
24
0
Yes
K
24
27
24
27
0
Yes
L
27
29
27
29
0
Yes

Compare each activity’s earliest and latest times to see exactly which activities have zero slack and which can move within the 29-week schedule. section 13.3.3

A 29-week schedule is an estimate, not a guarantee of finishing in 29 weeks: activity durations vary. Deadline-probability analysis uses variance estimates for critical activities. To shorten the planned schedule, examine critical activities rather than spending money accelerating noncritical ones, and recalculate the path when durations change. section 13.4 section 13.5

How Statistics Every Programmer Needs covers it

How deep it goes
Works through forward and backward passes, slack, and Python automation; treats deadline probability and crashing as subsequent analyses.
Examples
Calculates a 29-week reporting-tool schedule across 12 activities, including five-week slack for F and H and nine-week slack for I.
What it assumes
Builds on activity dependencies and estimated durations while defining earliest times, latest times, and slack before automation.
What you can do after
Build it from scratch to identify critical activities, calculate scheduling flexibility, and reevaluate a plan when activity durations change.
How it connects
Links work breakdown structures and PERT duration estimates to slack, deadline-probability analysis, and project crashing.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Statistics Every Programmer Needs. The section links point to the parts of the book it draws on.