Algorithms Module
DAG-specific algorithms that leverage acyclicity guarantees.
These algorithms are optimized for DAGs and would be incorrect or inefficient on general graphs with cycles. The DAG property enables linear-time solutions for problems that are NP-hard on general graphs.
Algorithms Provided
Algorithm |
Complexity |
Use Case |
|---|---|---|
|
O(V+E) |
Task scheduling, dependency ordering |
|
O(V+E) |
Critical path analysis (PERT/CPM) |
|
O(V+E) |
Minimum cost path between nodes |
|
O(V²) |
Reachability queries, indirect dependencies |
|
O(V×E) |
Simplify graphs, remove implied edges |
|
O(V+E) |
Impact analysis, prerequisite counting |
|
O(V×(V+E)) |
Merge bases, shared dependencies |
Why DAGs Are Special
DAGs enable efficient algorithms for problems that are intractable on general graphs: - Longest Path: O(V+E) on DAGs vs NP-hard on general graphs - Topological Sort: Always succeeds on DAGs vs may fail with cycles - Shortest Path: O(V+E) on DAGs vs O((V+E) log V) with Dijkstra
References
Functions and values
| Function or value |
Description
|
||
|
Count total descendants or ancestors using set-based DP.
Parameters
Complexity
Example
Use Cases
val impact: obj
val prerequisites: obj
|
||
|
Finds the Longest Path (Critical Path) in O(V+E). In a DAG, the longest path problem is well-defined and solvable in linear time. This is useful for critical path analysis in project scheduling.
Type ConstraintEdge weights must be integers. Complexity
Example
Use Cases
val criticalPath: obj
val printfn: format: Printf.TextWriterFormat<'T> -> 'T
|
||
|
Finds the lowest common ancestors (LCAs) of two nodes. A common ancestor of nodes A and B is any node that has paths to both A and B. The "lowest" common ancestors are those that are not ancestors of any other common ancestor - they are the "closest" shared dependencies.
Parameters
Complexity
Example
Use Cases
val lcas: obj
|
||
|
Finds the shortest path between two specific nodes in a weighted DAG. Uses dynamic programming on the topologically sorted DAG to find the minimum
weight path from
Type ConstraintEdge weights must be integers. Complexity
Example
Use Cases
union case Option.Some: Value: 'T -> Option<'T>
val path: obj
val printfn: format: Printf.TextWriterFormat<'T> -> 'T
union case Option.None: Option<'T>
|
||
|
Topological sort guaranteed to succeed for the Dag type.
Complexity
NoteThis function cannot fail because the Dag type guarantees acyclicity. If it somehow encounters a cycle, it raises an exception (indicating a bug). Example
val order: obj seq
val node: obj
|
||
|
Transitive Closure: Reachability map with merged weights. Computes a new DAG where there's a direct edge from u to v if v is reachable from u in the original DAG. Edge weights are merged using the provided function.
Parameters
Complexity
Example
Use Cases
val closure: obj
val min: e1: 'T -> e2: 'T -> 'T (requires comparison)
|
||
|
Computes the transitive reduction of a DAG. The transitive reduction removes all edges that are redundant - i.e., edges u -> v where there exists an indirect path from u to v through other nodes. The result has the minimum number of edges while preserving all reachability relationships. This is the inverse of transitive closure.
Parameters
Complexity
Example
Use Cases
val minimal: obj
val min: e1: 'T -> e2: 'T -> 'T (requires comparison)
|