Use this file to discover all available pages before exploring further.
Terraform uses directed acyclic graphs (DAGs) to model dependencies and execute operations. This document covers the graph data structure, algorithms, and concurrent execution model.
// internal/dag/tarjan.gofunc StronglyConnected(g *Graph) [][]Vertex { acct := sccAcct{ NextIndex: 1, VertexIndex: make(map[Vertex]int), } for _, v := range g.Vertices() { if acct.VertexIndex[v] == 0 { stronglyConnected(&acct, g, v) } } return acct.SCC}func stronglyConnected(acct *sccAcct, g *Graph, v Vertex) int { // Assign index and push to stack index := acct.visit(v) minIdx := index // Visit all successors for _, target := range g.downEdgesNoCopy(v) { targetIdx := acct.VertexIndex[target] if targetIdx == 0 { // Recurse on unvisited minIdx = min(minIdx, stronglyConnected(acct, g, target)) } else if acct.inStack(target) { // Back edge to vertex in stack minIdx = min(minIdx, targetIdx) } } // If this is a root, pop the SCC if index == minIdx { var scc []Vertex for { v2 := acct.pop() scc = append(scc, v2) if v2 == v { break } } acct.SCC = append(acct.SCC, scc) } return minIdx}
Algorithm properties:
Time complexity: O(V + E)
Space complexity: O(V) for stack
Single pass: Visits each vertex once
Finds all cycles: Returns strongly connected components
Strongly connected component = group of vertices with paths to each other.
// internal/dag/dag.go:208func (g *AcyclicGraph) TransitiveReduction() { // For each vertex u for _, u := range g.Vertices() { uTargets := g.downEdgesNoCopy(u) // DFS from each direct descendant v of u g.DepthFirstWalk(g.downEdgesNoCopy(u), func(v Vertex, d int) error { // Find vertices reachable from both u and v shared := uTargets.Intersection(g.downEdgesNoCopy(v)) // Remove direct edges from u to those vertices for _, vPrime := range shared { g.RemoveEdge(BasicEdge(u, vPrime)) } return nil }) }}
Algorithm explanation:
For each vertex u
For each direct descendant v of u
Find vertices reachable from v
Remove direct edges from u to those vertices
Why it works:If u→v and v→w both exist, then u→w is redundant (path exists via v).Complexity: O(V(V+E)) or O(VE)See: internal/dag/dag.go:208
func (g *AcyclicGraph) walk( order walkType, test bool, start Set, f DepthWalkFunc,) error { seen := make(map[Vertex]struct{}) frontier := []vertexAtDepth{} for _, v := range start { frontier = append(frontier, vertexAtDepth{v, 0}) } for len(frontier) > 0 { var current vertexAtDepth if order&depthFirst != 0 { // Pop from end (stack) current = frontier[len(frontier)-1] frontier = frontier[:len(frontier)-1] } else { // Pop from beginning (queue) current = frontier[0] frontier = frontier[1:] } if _, ok := seen[current.Vertex]; ok { continue } seen[current.Vertex] = struct{}{} // Visit vertex if err := f(current.Vertex, current.Depth); err != nil { return err } // Add descendants to frontier edges := g.downEdgesNoCopy(current.Vertex) for _, v := range edges { frontier = append(frontier, vertexAtDepth{v, current.Depth + 1}) } } return nil}
// Get all ancestors (dependencies, transitively)func (g *AcyclicGraph) Ancestors(vs ...Vertex) Set { s := make(Set) start := make(Set) for _, v := range vs { for _, dep := range g.downEdgesNoCopy(v) { start.Add(dep) } } g.DepthFirstWalk(start, func(v Vertex, d int) error { s.Add(v) return nil }) return s}// Get all descendants (dependents, transitively) func (g *AcyclicGraph) Descendants(v Vertex) Set { s := make(Set) start := make(Set) for _, dep := range g.upEdgesNoCopy(v) { start.Add(dep) } g.ReverseDepthFirstWalk(start, func(v Vertex, d int) error { s.Add(v) return nil }) return s}