Critical path and slack analysis (CPM) of the current plan.
A backward pass computes, for each schedulable task, the latest dates it can have without delaying its successors or the end of the project:
- total slack - how much the task can slip without delaying the
project end (
late start - start) - free slack - how much the task can slip without delaying any successor
- a task is critical when its total slack is zero (or negative, when the plan already breaks a dependency); a project is critical when one of its descendants is
- a link is critical when it joins two critical tasks and drives the successor (the successor starts exactly when the link allows)
Slack is expressed in the duration unit of the store and honors calendars.
iex> store = GanttEx.Store.new!(
...> [
...> %{id: 1, text: "Design", start_date: ~D[2025-01-06], duration: 2},
...> %{id: 2, text: "Build", start_date: ~D[2025-01-08], duration: 3},
...> %{id: 3, text: "Docs", start_date: ~D[2025-01-08], duration: 1},
...> %{id: 4, text: "Launch", start_date: ~D[2025-01-11], type: :milestone}
...> ],
...> [
...> %{id: 1, source: 1, target: 2},
...> %{id: 2, source: 1, target: 3},
...> %{id: 3, source: 2, target: 4},
...> %{id: 4, source: 3, target: 4}
...> ]
...> )
iex> analysis = GanttEx.CriticalPath.analyze(store)
iex> for id <- 1..4, do: {id, analysis.tasks[id].critical, analysis.tasks[id].total_slack}
[{1, true, 0}, {2, true, 0}, {3, false, 2}, {4, true, 0}]
iex> analysis.tasks[3].free_slack
2
iex> analysis.links |> Enum.sort()
[1, 3]
Summary
Functions
Analyzes the store. Projects with children get critical (and the slack
of their most critical descendant).
Types
@type t() :: %{ tasks: %{required(GanttEx.Task.id()) => task_result()}, links: MapSet.t(GanttEx.Task.id()), project_end: NaiveDateTime.t() | nil }
@type task_result() :: %{ critical: boolean(), total_slack: integer(), free_slack: integer(), late_start: NaiveDateTime.t(), late_finish: NaiveDateTime.t() }
Analysis of one task.
Functions
@spec analyze(GanttEx.Store.t()) :: t()
Analyzes the store. Projects with children get critical (and the slack
of their most critical descendant).