Resolving package versions... Updating `~/Documents/Work/CDCS/Project.toml` [d4a9c1e2] + DAGMakie v0.1.0 `~/Documents/Work/CDCS/packages/DAGMakie.jl` Updating `~/Documents/Work/CDCS/Manifest.toml` [d4a9c1e2] + DAGMakie v0.1.0 `~/Documents/Work/CDCS/packages/DAGMakie.jl` Precompiling packages... 6255.2 ms ✓ QuartoNotebookWorkerMakieExt (serial) 1 dependency successfully precompiled in 7 seconds Precompiling packages... 4984.9 ms ✓ QuartoNotebookWorkerCairoMakieExt (serial) 1 dependency successfully precompiled in 5 seconds Precompiling packages... 6071.2 ms ✓ GraphMakie 5503.7 ms ✓ DAGMakie 2 dependencies successfully precompiled in 12 seconds. 270 already precompiled.
13 Cyclic Causal Structures
v0.1
13.1 Learning Objectives
After reading this chapter, you will be able to:
- Understand why acyclicity is limiting for dynamical systems and biological feedback
- Interpret structural equation models with cycles via equilibrium semantics
- Apply the sigma calculus (σ-separation, σ-do) for cyclic causal reasoning
- Connect cyclic graphs to ODEs through the DAG-to-ODE bridge
- Distinguish sustained vs point interventions in cyclic systems
13.2 Beyond Acyclicity
The causal models we have developed thus far—directed acyclic graphs (DAGs) and their associated structural causal models (SCMs)—assume acyclicity: no variable may be its own ancestor. This assumption is mathematically convenient: it permits a unique topological ordering, ensures well-defined recursive evaluation, and underpins d-separation and the do-calculus (Pearl 2009). Yet real biological and physical systems are replete with feedback loops.
Consider homeostasis: blood glucose is regulated by insulin, which is secreted in response to glucose—a classic negative feedback loop. Signalling cascades in gene regulatory networks exhibit mutual regulation: transcription factors activate or repress each other’s expression. Ecological dynamics feature predator-prey cycles where each population influences the other. Immune responses involve cytokine feedback that amplifies or dampens inflammation. In each case, the causal structure is cyclic, not acyclic.
This creates a fundamental tension. The structural world, as formalised by Pearl and colleagues (Pearl 2009; Peters et al. 2017), privileges DAGs because they support clean intervention semantics and identification theory. The dynamical world, as captured by differential equations and state-space models, naturally describes feedback through coupled equations that evolve over time. The same system can be viewed as a cyclic graph (instantaneous mutual causation) or as a temporal process (causation unrolled in time). This chapter develops the machinery to reconcile these views: cyclic structural models, the sigma calculus for reasoning about them, and the DAG-to-ODE bridge that connects cyclic graphs to ordinary differential equations.
13.3 Directed Cyclic Graphs and Equilibrium Models
A directed cyclic graph (DCG) allows directed cycles: paths from a variable back to itself. In such a graph, we cannot assign values recursively in a single pass. Instead, we interpret the structural equations as a simultaneous system solved at equilibrium.
The graph in Figure 13.1 illustrates the simplest non-trivial cycle: two variables, each a parent of the other. No topological ordering exists; the equations must be solved jointly.
13.3.1 Equilibrium Semantics
An SCM with cycles is defined by structural equations:
\[ X_i = f_i(\mathbf{X}_{\mathrm{Pa}(i)}, U_i) \quad \text{for all } i \]
where \(\mathrm{Pa}(i)\) denotes the parents of \(X_i\) in the graph. In the acyclic case, we evaluate these equations in topological order. With cycles, no such order exists. We instead require that the equations hold simultaneously: the vector \(\mathbf{X} = (X_1, \ldots, X_n)\) must satisfy
\[ \mathbf{X} = \mathbf{f}(\mathbf{X}, \mathbf{U}) \]
for the given exogenous variables \(\mathbf{U}\). This is a fixed-point equation: \(\mathbf{X}\) is a fixed point of the map \(\mathbf{x} \mapsto \mathbf{f}(\mathbf{x}, \mathbf{U})\).
13.3.2 Existence and Uniqueness
Under suitable conditions on the functions \(f_i\) (e.g., contractivity in an appropriate norm), Banach’s fixed-point theorem guarantees a unique solution (Bongers et al. 2021). When the system is linear, \(\mathbf{X} = A\mathbf{X} + \mathbf{U}\), we require that \(I - A\) be invertible, which holds when the spectral radius of \(A\) is less than one. The equilibrium interpretation thus gives precise mathematical content to cyclic SCMs: they are fixed-point models, and the “output” of the model is the (unique) equilibrium configuration given the exogenous inputs.
Multiple equilibria can arise when the fixed-point map is not contractive; bifurcation theory then becomes relevant. For the purposes of causal reasoning, we typically assume uniqueness so that interventions yield well-defined counterfactual outcomes.
13.4 The Sigma Calculus
Bongers et al. (Bongers et al. 2021) developed the sigma calculus (σ-calculus) to extend causal reasoning from DAGs to directed graphs that may contain cycles. The key innovation is σ-separation, a graphical criterion that generalises d-separation to cyclic structures.
13.4.1 σ-Separation
In a DAG, d-separation characterises conditional independence: \(X ⫫ Y \mid Z\) holds in all SCMs compatible with the graph if and only if \(Z\) d-separates \(X\) and \(Y\). For cyclic graphs, d-separation is not sufficient—cycles can create dependencies that d-separation does not capture. σ-separation provides the correct generalisation.
Informally, a path between \(X\) and \(Y\) is σ-blocked by \(Z\) if it contains a collider not in \(Z\), or a non-collider in \(Z\), with appropriate handling of cycles. The formal definition involves the augmented graph and a refined notion of blocking that accounts for the equilibrium structure. We say \(Z\) σ-separates \(X\) and \(Y\) if every path between \(X\) and \(Y\) is σ-blocked by \(Z\). Then \(X ⫫ Y \mid Z\) holds in the equilibrium distribution of any SCM compatible with the graph.
13.4.2 The σ-do Operator
Interventions in cyclic models are formalised by the σ-do operator. The intervention \(do(X_i = x_i)\) replaces the structural equation for \(X_i\) with the constant assignment \(X_i := x_i\), breaking all incoming edges to \(X_i\). The system is then solved at the new equilibrium. This mirrors the do-operator for DAGs (Pearl 2009) but applies in the cyclic setting.
13.4.3 Identification in Cyclic Models
Identification—determining whether a causal effect can be expressed as a function of the observational distribution—becomes more complex with cycles. The sigma calculus provides rules analogous to the do-calculus for establishing identifiability in cyclic graphs. The key difference is that σ-separation, not d-separation, governs which conditional independencies hold.
13.5 The DAG-to-ODE Bridge
A profound insight connects cyclic structural models to dynamical systems: unrolling cycles in time converts a cyclic graph into a (time-indexed) DAG. This is the DAG-to-ODE bridge.
The cyclic graph \(X \leftrightarrow Y\) represents instantaneous mutual causation. When we index by time, the same structure becomes a chain: \(X_t \to Y_{t+1} \to X_{t+2} \to \cdots\). Causation is no longer simultaneous but sequential—and the graph is acyclic.
13.5.1 The Core Idea
Consider a simple feedback loop: \(X \leftrightarrow Y\). In the structural view, \(X\) causes \(Y\) and \(Y\) causes \(X\)—a cycle. In the dynamical view, we introduce time: \(X\) at time \(t\) influences \(Y\) at time \(t + \Delta t\), and \(Y\) at time \(t\) influences \(X\) at time \(t + \Delta t\). The unrolled graph is:
\[ X_t \to Y_{t+\Delta t} \to X_{t+2\Delta t} \to Y_{t+3\Delta t} \to \cdots \]
This is a DAG: each time slice has a unique temporal ordering. No variable is its own ancestor when we index by time.
13.5.2 The Continuous-Time Limit
As \(\Delta t \to 0\), the discrete-time unrolling becomes a continuous-time dynamical system. The cyclic structural equations
\[ X = f_X(Y, U_X), \quad Y = f_Y(X, U_Y) \]
translate to an ODE system:
\[ \dot{X} = f(X, Y), \quad \dot{Y} = g(X, Y) \]
where the equilibrium of the ODE (when \(\dot{X} = \dot{Y} = 0\)) corresponds to the solution of the cyclic SCM. The instantaneous causation in the cyclic graph becomes infinitesimal causation in the ODE: each variable’s rate of change depends on the current values of the others.
13.5.3 What the Bridge Connects
The DAG-to-ODE bridge establishes a concrete link between:
- Structural world: Cyclic causal graphs with equilibrium semantics and σ-separation
- Dynamical world: ODE (or SDE) systems arising from temporal unrolling
- Instantaneous causation (in the graph) ↔︎ Continuous-time dynamics (in the ODE)
This is a concrete realisation of the Structural → Dynamical transition in the three-worlds framework: the cyclic graph is the structural form; the ODE is its temporal embodiment.
13.6 Interventions in Cyclic Systems
Intervening on a variable in a feedback loop has distinctive features. The intervention \(do(X = x)\) breaks the loop: \(X\) no longer depends on its parents (including \(Y\)), so the feedback from \(Y\) to \(X\) is severed. The system reaches a new equilibrium with \(X\) fixed at \(x\).
13.6.1 Sustained vs Point Interventions
In continuous time, we distinguish:
- Sustained intervention: \(do(X(t) = x)\) for all \(t \geq t_0\). The variable is held constant; the system evolves to a new steady state.
- Point intervention: A brief perturbation at \(t = t_0\); the system then evolves according to its natural dynamics. This is closer to an impulse or initial condition change.
Control theory’s set-point control is a sustained intervention: the controller holds a variable at a target value, effectively performing \(do(X = x^*)\) continuously.
13.7 Practical Implementation
The following Julia code illustrates the DAG-to-ODE bridge with a simple two-variable feedback system. We define the ODE, show how it corresponds to a cyclic graph, and apply an intervention by breaking the loop. The linear system
\[ \frac{dX}{dt} = -\alpha X + \beta Y, \quad \frac{dY}{dt} = -\gamma Y + \delta X \]
has equilibrium when both derivatives vanish; solving \(-\alpha X + \beta Y = 0\) and \(-\gamma Y + \delta X = 0\) yields the fixed point. The intervention \(do(X = 2)\) sets \(dX/dt = 0\) and replaces \(X\) with the constant 2 in the \(Y\) equation, so \(Y\) evolves toward \(\delta \cdot 2 / \gamma\).
# Simple feedback system: X and Y mutually influence each other
# Cyclic graph: X ↔ Y
# ODE form: dX/dt = f(X,Y), dY/dt = g(X,Y)
# Find project root and include ensure_packages.jl
project_root = let
current = pwd()
while !isfile(joinpath(current, "Project.toml")) && !isfile(joinpath(current, "_quarto.yml"))
parent = dirname(current)
parent == current && break
current = parent
end
current
end
include(joinpath(project_root, "scripts", "ensure_packages.jl"))
@auto_using OrdinaryDiffEq
# Parameters
α = 0.5 # X's self-damping
β = 0.3 # Y's influence on X
γ = 0.4 # Y's self-damping
δ = 0.2 # X's influence on Y
# Original (cyclic) system: equilibrium when dX/dt = dY/dt = 0
function feedback_system!(du, u, p, t)
X, Y = u
du[1] = -α * X + β * Y # dX/dt
du[2] = -γ * Y + δ * X # dY/dt
end
u0 = [1.0, 1.0]
tspan = (0.0, 10.0)
prob = ODEProblem(feedback_system!, u0, tspan)
sol = solve(prob, Tsit5())
# Intervention: do(X = 2) — break X's dependence on Y, hold X fixed
# In ODE terms: remove dX/dt equation, set X(t) = 2
function intervened_system!(du, u, p, t)
X, Y = u
x_intervention = 2.0
du[1] = 0.0 # X held constant (loop broken)
du[2] = -γ * Y + δ * x_intervention # Y still depends on X
end
prob_do = ODEProblem(intervened_system!, u0, tspan)
sol_do = solve(prob_do, Tsit5())Precompiling packages... 492.4 ms ✓ EnzymeCore 1001.9 ms ✓ FastGaussQuadrature 607.2 ms ✓ ADTypes → ADTypesEnzymeCoreExt 610.8 ms ✓ EnzymeCore → AdaptExt 2738.7 ms ✓ ForwardDiff 2851.7 ms ✓ RecursiveArrayTools 776.5 ms ✓ FastPower → FastPowerForwardDiffExt 780.9 ms ✓ PreallocationTools → PreallocationToolsForwardDiffExt 920.7 ms ✓ ForwardDiff → ForwardDiffStaticArraysExt 1050.2 ms ✓ RecursiveArrayTools → RecursiveArrayToolsStatisticsExt 1050.0 ms ✓ RecursiveArrayTools → RecursiveArrayToolsSparseArraysExt 1131.6 ms ✓ RecursiveArrayTools → RecursiveArrayToolsForwardDiffExt 1166.2 ms ✓ RecursiveArrayTools → RecursiveArrayToolsFastBroadcastExt 1541.4 ms ✓ DifferentiationInterface → DifferentiationInterfaceForwardDiffExt 903.6 ms ✓ NLSolversBase 1655.9 ms ✓ LineSearches 8140.8 ms ✓ SciMLBase 1161.3 ms ✓ SciMLBase → SciMLBaseDifferentiationInterfaceExt 1518.7 ms ✓ SciMLBase → SciMLBaseForwardDiffExt 2657.3 ms ✓ SciMLJacobianOperators 6017.1 ms ✓ LinearSolve 3291.1 ms ✓ LineSearch 2389.5 ms ✓ LinearSolve → LinearSolveForwardDiffExt 1517.5 ms ✓ LineSearch → LineSearchLineSearchesExt 3079.4 ms ✓ LinearSolve → LinearSolveSparseArraysExt 5271.6 ms ✓ NonlinearSolveBase 1324.9 ms ✓ NonlinearSolveBase → NonlinearSolveBaseLineSearchExt 1350.4 ms ✓ NonlinearSolveBase → NonlinearSolveBaseSparseMatrixColoringsExt 1360.7 ms ✓ NonlinearSolveBase → NonlinearSolveBaseSparseArraysExt 1475.7 ms ✓ NonlinearSolveBase → NonlinearSolveBaseForwardDiffExt 1725.0 ms ✓ LinearSolve → LinearSolveEnzymeExt 1863.6 ms ✓ NonlinearSolveBase → NonlinearSolveBaseLinearSolveExt 3069.7 ms ✓ BracketingNonlinearSolve 1557.8 ms ✓ BracketingNonlinearSolve → BracketingNonlinearSolveForwardDiffExt 2528.6 ms ✓ DiffEqBase 5250.7 ms ✓ NonlinearSolveSpectralMethods 1548.2 ms ✓ DiffEqBase → DiffEqBaseSparseArraysExt 1408.6 ms ✓ NonlinearSolveSpectralMethods → NonlinearSolveSpectralMethodsForwardDiffExt 3123.0 ms ✓ OrdinaryDiffEqCore 3307.4 ms ✓ DiffEqBase → DiffEqBaseForwardDiffExt 1377.0 ms ✓ OrdinaryDiffEqCore → OrdinaryDiffEqCoreEnzymeCoreExt 6031.1 ms ✓ SimpleNonlinearSolve 9848.7 ms ✓ NonlinearSolveQuasiNewton 2512.2 ms ✓ OrdinaryDiffEqFunctionMap 2746.2 ms ✓ OrdinaryDiffEqExplicitRK 2830.2 ms ✓ OrdinaryDiffEqPRK 3251.3 ms ✓ OrdinaryDiffEqStabilizedRK 3024.6 ms ✓ OrdinaryDiffEqSSPRK 3918.9 ms ✓ OrdinaryDiffEqLinear 2821.2 ms ✓ OrdinaryDiffEqRKN 2328.9 ms ✓ OrdinaryDiffEqQPRK 2393.8 ms ✓ OrdinaryDiffEqSymplecticRK 2487.6 ms ✓ OrdinaryDiffEqHighOrderRK 5613.0 ms ✓ OrdinaryDiffEqTsit5 2366.1 ms ✓ OrdinaryDiffEqFeagin 3596.1 ms ✓ OrdinaryDiffEqLowOrderRK 2867.5 ms ✓ OrdinaryDiffEqLowStorageRK 2151.4 ms ✓ NonlinearSolveQuasiNewton → NonlinearSolveQuasiNewtonForwardDiffExt 2495.3 ms ✓ OrdinaryDiffEqNordsieck 2260.2 ms ✓ OrdinaryDiffEqAdamsBashforthMoulton 18508.3 ms ✓ NonlinearSolveFirstOrder 5516.4 ms ✓ OrdinaryDiffEqDifferentiation 2061.9 ms ✓ OrdinaryDiffEqDifferentiation → OrdinaryDiffEqDifferentiationSparseArraysExt 3336.8 ms ✓ OrdinaryDiffEqExponentialRK 4124.5 ms ✓ OrdinaryDiffEqExtrapolation 9207.7 ms ✓ NonlinearSolve 16640.9 ms ✓ OrdinaryDiffEqVerner 3302.0 ms ✓ OrdinaryDiffEqNonlinearSolve 12862.8 ms ✓ OrdinaryDiffEqRosenbrock 3485.2 ms ✓ OrdinaryDiffEqIMEXMultistep 3868.9 ms ✓ OrdinaryDiffEqStabilizedIRK 3957.3 ms ✓ OrdinaryDiffEqPDIRK 4673.8 ms ✓ OrdinaryDiffEqSDIRK 7376.5 ms ✓ OrdinaryDiffEqBDF 12760.0 ms ✓ OrdinaryDiffEqFIRK 17888.4 ms ✓ OrdinaryDiffEqDefault 9703.3 ms ✓ OrdinaryDiffEq 77 dependencies successfully precompiled in 94 seconds. 146 already precompiled. Precompiling packages... 433.9 ms ✓ RecursiveArrayTools → RecursiveArrayToolsTablesExt 456.7 ms ✓ RecursiveArrayTools → RecursiveArrayToolsStructArraysExt 2 dependencies successfully precompiled in 1 seconds. 40 already precompiled. Precompiling packages... 1138.8 ms ✓ SciMLBase → SciMLBaseDistributionsExt 1 dependency successfully precompiled in 2 seconds. 98 already precompiled. Precompiling packages... 812.9 ms ✓ SciMLBase → SciMLBaseChainRulesCoreExt 1 dependency successfully precompiled in 1 seconds. 62 already precompiled. Precompiling packages... 5120.0 ms ✓ SciMLBase → SciMLBaseMakieExt 1 dependency successfully precompiled in 6 seconds. 310 already precompiled. Precompiling packages... 361.7 ms ✓ EnzymeCore → EnzymeCoreChainRulesCoreExt 1 dependency successfully precompiled in 1 seconds. 9 already precompiled. Precompiling packages... 789.2 ms ✓ NonlinearSolveBase → NonlinearSolveBaseChainRulesCoreExt 1 dependency successfully precompiled in 1 seconds. 79 already precompiled. Precompiling packages... 884.4 ms ✓ BracketingNonlinearSolve → BracketingNonlinearSolveChainRulesCoreExt 1 dependency successfully precompiled in 1 seconds. 102 already precompiled. Precompiling packages... 963.5 ms ✓ DiffEqBase → DiffEqBaseUnitfulExt 1 dependency successfully precompiled in 1 seconds. 101 already precompiled. Precompiling packages... 881.3 ms ✓ DiffEqBase → DiffEqBaseChainRulesCoreExt 1 dependency successfully precompiled in 1 seconds. 103 already precompiled. Precompiling packages... 407.9 ms ✓ DispatchDoctor → DispatchDoctorEnzymeCoreExt 427.8 ms ✓ LuxCore → EnzymeCoreExt 576.5 ms ✓ Unitful → ForwardDiffExt 660.7 ms ✓ KernelAbstractions → EnzymeExt 727.1 ms ✓ NNlib → NNlibSpecialFunctionsExt 752.5 ms ✓ NNlib → NNlibForwardDiffExt 756.4 ms ✓ NNlib → NNlibEnzymeCoreExt 4098.9 ms ✓ LuxLib 1257.1 ms ✓ LuxLib → ForwardDiffExt 9 dependencies successfully precompiled in 6 seconds. 80 already precompiled. Precompiling packages... 737.3 ms ✓ Interpolations → InterpolationsForwardDiffExt 1 dependency successfully precompiled in 1 seconds. 47 already precompiled. Precompiling packages... 1083.7 ms ✓ IntervalArithmetic → IntervalArithmeticForwardDiffExt 1 dependency successfully precompiled in 1 seconds. 48 already precompiled. Precompiling packages... 1001.7 ms ✓ LinearSolve → LinearSolveChainRulesCoreExt 1 dependency successfully precompiled in 1 seconds. 99 already precompiled. Precompiling packages... 938.3 ms ✓ SimpleNonlinearSolve → SimpleNonlinearSolveChainRulesCoreExt 1 dependency successfully precompiled in 1 seconds. 108 already precompiled.
retcode: Success
Interpolation: specialized 4th order "free" interpolation
t: 7-element Vector{Float64}:
0.0
9.999999999999999e-5
0.0010999999999999998
0.011099999999999997
0.11109999999999996
1.1110999999999995
10.0
u: 7-element Vector{Vector{Float64}}:
[1.0, 1.0]
[1.0, 1.0]
[1.0, 1.0]
[1.0, 1.0]
[1.0, 1.0]
[1.0, 1.0]
[1.0, 1.0]
13.8 Connection to the Three Worlds
The cyclic structures and DAG-to-ODE bridge fit neatly into the three-worlds ontology:
Structural world: Cyclic graphs with equilibrium semantics, σ-separation, and the σ-do operator. The graph encodes invariant causal structure—who influences whom—without explicit time.
Dynamical world: ODEs and SDEs arising from temporal unrolling. Time enters; the cyclic graph becomes a DAG over time-indexed variables; the equilibrium of the dynamics corresponds to the structural equilibrium.
Observable world: Equilibrium observations from cyclic systems—the steady-state values we might measure when a feedback system has settled. These observations are generated by the dynamical process, which is in turn determined by the structural graph.
The DAG-to-ODE bridge is thus a concrete realisation of the Structural → Dynamical transition: the cyclic graph (structural form) is dynamised by unrolling in time, yielding the ODE (dynamical process) whose trajectories and equilibria constitute the observable phenomena.
13.9 Key Takeaways
Real systems have cycles: Homeostasis, gene regulation, ecology, and immune feedback all involve cyclic causation; DAGs are limiting for such systems.
Equilibrium semantics: Cyclic SCMs are interpreted as simultaneous equations; solutions are fixed points of the structural map.
Sigma calculus: σ-separation and the σ-do operator extend d-separation and the do-operator to cyclic graphs (Bongers et al. 2021).
DAG-to-ODE bridge: Unrolling cycles in time converts cyclic graphs to time-indexed DAGs; the continuous limit yields ODEs. Instantaneous causation becomes continuous-time dynamics.
Interventions break loops: \(do(X = x)\) severs \(X\)’s dependence on its parents; the system reaches a new equilibrium.
Three worlds: Cyclic graphs (Structural) → ODEs (Dynamical) → equilibrium observations (Observable). The bridge embodies the Structural → Dynamical transition.
13.10 Further Reading
- Pearl (2009): Foundational treatment of DAGs, d-separation, and the do-calculus
- Bongers et al. (2021): Sigma calculus for cyclic SCMs; σ-separation and identification
- Peters et al. (2017): Elements of causal inference; connects to the present framework
- See Deterministic Dynamics for ODEs as causal processes
- See From Structure to Time for the broader Structural → Dynamical transition