13  Cyclic Causal Structures

Status: Draft

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.

   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 msQuartoNotebookWorkerMakieExt (serial)
  1 dependency successfully precompiled in 7 seconds
Precompiling packages...
   4984.9 msQuartoNotebookWorkerCairoMakieExt (serial)
  1 dependency successfully precompiled in 5 seconds
Precompiling packages...
   6071.2 msGraphMakie
   5503.7 msDAGMakie
  2 dependencies successfully precompiled in 12 seconds. 270 already precompiled.
(a) A simple cyclic causal graph: \(X\) and \(Y\) mutually influence each other, forming a feedback loop.
Figure 13.1: A simple cyclic causal graph: X and Y mutually influence each other, forming a feedback loop.

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.

NoteCyclic vs Unrolled Structure

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 msEnzymeCore
   1001.9 msFastGaussQuadrature
    607.2 msADTypes → ADTypesEnzymeCoreExt
    610.8 msEnzymeCore → AdaptExt
   2738.7 msForwardDiff
   2851.7 msRecursiveArrayTools
    776.5 msFastPower → FastPowerForwardDiffExt
    780.9 msPreallocationTools → PreallocationToolsForwardDiffExt
    920.7 msForwardDiff → ForwardDiffStaticArraysExt
   1050.2 msRecursiveArrayTools → RecursiveArrayToolsStatisticsExt
   1050.0 msRecursiveArrayTools → RecursiveArrayToolsSparseArraysExt
   1131.6 msRecursiveArrayTools → RecursiveArrayToolsForwardDiffExt
   1166.2 msRecursiveArrayTools → RecursiveArrayToolsFastBroadcastExt
   1541.4 msDifferentiationInterface → DifferentiationInterfaceForwardDiffExt
    903.6 msNLSolversBase
   1655.9 msLineSearches
   8140.8 msSciMLBase
   1161.3 msSciMLBase → SciMLBaseDifferentiationInterfaceExt
   1518.7 msSciMLBase → SciMLBaseForwardDiffExt
   2657.3 msSciMLJacobianOperators
   6017.1 msLinearSolve
   3291.1 msLineSearch
   2389.5 msLinearSolve → LinearSolveForwardDiffExt
   1517.5 msLineSearch → LineSearchLineSearchesExt
   3079.4 msLinearSolve → LinearSolveSparseArraysExt
   5271.6 msNonlinearSolveBase
   1324.9 msNonlinearSolveBase → NonlinearSolveBaseLineSearchExt
   1350.4 msNonlinearSolveBase → NonlinearSolveBaseSparseMatrixColoringsExt
   1360.7 msNonlinearSolveBase → NonlinearSolveBaseSparseArraysExt
   1475.7 msNonlinearSolveBase → NonlinearSolveBaseForwardDiffExt
   1725.0 msLinearSolve → LinearSolveEnzymeExt
   1863.6 msNonlinearSolveBase → NonlinearSolveBaseLinearSolveExt
   3069.7 msBracketingNonlinearSolve
   1557.8 msBracketingNonlinearSolve → BracketingNonlinearSolveForwardDiffExt
   2528.6 msDiffEqBase
   5250.7 msNonlinearSolveSpectralMethods
   1548.2 msDiffEqBase → DiffEqBaseSparseArraysExt
   1408.6 msNonlinearSolveSpectralMethods → NonlinearSolveSpectralMethodsForwardDiffExt
   3123.0 msOrdinaryDiffEqCore
   3307.4 msDiffEqBase → DiffEqBaseForwardDiffExt
   1377.0 msOrdinaryDiffEqCore → OrdinaryDiffEqCoreEnzymeCoreExt
   6031.1 msSimpleNonlinearSolve
   9848.7 msNonlinearSolveQuasiNewton
   2512.2 msOrdinaryDiffEqFunctionMap
   2746.2 msOrdinaryDiffEqExplicitRK
   2830.2 msOrdinaryDiffEqPRK
   3251.3 msOrdinaryDiffEqStabilizedRK
   3024.6 msOrdinaryDiffEqSSPRK
   3918.9 msOrdinaryDiffEqLinear
   2821.2 msOrdinaryDiffEqRKN
   2328.9 msOrdinaryDiffEqQPRK
   2393.8 msOrdinaryDiffEqSymplecticRK
   2487.6 msOrdinaryDiffEqHighOrderRK
   5613.0 msOrdinaryDiffEqTsit5
   2366.1 msOrdinaryDiffEqFeagin
   3596.1 msOrdinaryDiffEqLowOrderRK
   2867.5 msOrdinaryDiffEqLowStorageRK
   2151.4 msNonlinearSolveQuasiNewton → NonlinearSolveQuasiNewtonForwardDiffExt
   2495.3 msOrdinaryDiffEqNordsieck
   2260.2 msOrdinaryDiffEqAdamsBashforthMoulton
  18508.3 msNonlinearSolveFirstOrder
   5516.4 msOrdinaryDiffEqDifferentiation
   2061.9 msOrdinaryDiffEqDifferentiation → OrdinaryDiffEqDifferentiationSparseArraysExt
   3336.8 msOrdinaryDiffEqExponentialRK
   4124.5 msOrdinaryDiffEqExtrapolation
   9207.7 msNonlinearSolve
  16640.9 msOrdinaryDiffEqVerner
   3302.0 msOrdinaryDiffEqNonlinearSolve
  12862.8 msOrdinaryDiffEqRosenbrock
   3485.2 msOrdinaryDiffEqIMEXMultistep
   3868.9 msOrdinaryDiffEqStabilizedIRK
   3957.3 msOrdinaryDiffEqPDIRK
   4673.8 msOrdinaryDiffEqSDIRK
   7376.5 msOrdinaryDiffEqBDF
  12760.0 msOrdinaryDiffEqFIRK
  17888.4 msOrdinaryDiffEqDefault
   9703.3 msOrdinaryDiffEq
  77 dependencies successfully precompiled in 94 seconds. 146 already precompiled.
Precompiling packages...
    433.9 msRecursiveArrayTools → RecursiveArrayToolsTablesExt
    456.7 msRecursiveArrayTools → RecursiveArrayToolsStructArraysExt
  2 dependencies successfully precompiled in 1 seconds. 40 already precompiled.
Precompiling packages...
   1138.8 msSciMLBase → SciMLBaseDistributionsExt
  1 dependency successfully precompiled in 2 seconds. 98 already precompiled.
Precompiling packages...
    812.9 msSciMLBase → SciMLBaseChainRulesCoreExt
  1 dependency successfully precompiled in 1 seconds. 62 already precompiled.
Precompiling packages...
   5120.0 msSciMLBase → SciMLBaseMakieExt
  1 dependency successfully precompiled in 6 seconds. 310 already precompiled.
Precompiling packages...
    361.7 msEnzymeCore → EnzymeCoreChainRulesCoreExt
  1 dependency successfully precompiled in 1 seconds. 9 already precompiled.
Precompiling packages...
    789.2 msNonlinearSolveBase → NonlinearSolveBaseChainRulesCoreExt
  1 dependency successfully precompiled in 1 seconds. 79 already precompiled.
Precompiling packages...
    884.4 msBracketingNonlinearSolve → BracketingNonlinearSolveChainRulesCoreExt
  1 dependency successfully precompiled in 1 seconds. 102 already precompiled.
Precompiling packages...
    963.5 msDiffEqBase → DiffEqBaseUnitfulExt
  1 dependency successfully precompiled in 1 seconds. 101 already precompiled.
Precompiling packages...
    881.3 msDiffEqBase → DiffEqBaseChainRulesCoreExt
  1 dependency successfully precompiled in 1 seconds. 103 already precompiled.
Precompiling packages...
    407.9 msDispatchDoctor → DispatchDoctorEnzymeCoreExt
    427.8 msLuxCore → EnzymeCoreExt
    576.5 msUnitful → ForwardDiffExt
    660.7 msKernelAbstractions → EnzymeExt
    727.1 msNNlib → NNlibSpecialFunctionsExt
    752.5 msNNlib → NNlibForwardDiffExt
    756.4 msNNlib → NNlibEnzymeCoreExt
   4098.9 msLuxLib
   1257.1 msLuxLib → ForwardDiffExt
  9 dependencies successfully precompiled in 6 seconds. 80 already precompiled.
Precompiling packages...
    737.3 msInterpolations → InterpolationsForwardDiffExt
  1 dependency successfully precompiled in 1 seconds. 47 already precompiled.
Precompiling packages...
   1083.7 msIntervalArithmetic → IntervalArithmeticForwardDiffExt
  1 dependency successfully precompiled in 1 seconds. 48 already precompiled.
Precompiling packages...
   1001.7 msLinearSolve → LinearSolveChainRulesCoreExt
  1 dependency successfully precompiled in 1 seconds. 99 already precompiled.
Precompiling packages...
    938.3 msSimpleNonlinearSolve → 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]

Trajectories of the feedback system: original (cyclic) vs intervened (do(X=2)). The intervention breaks the loop and holds X constant.

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

  1. Real systems have cycles: Homeostasis, gene regulation, ecology, and immune feedback all involve cyclic causation; DAGs are limiting for such systems.

  2. Equilibrium semantics: Cyclic SCMs are interpreted as simultaneous equations; solutions are fixed points of the structural map.

  3. Sigma calculus: σ-separation and the σ-do operator extend d-separation and the do-operator to cyclic graphs (Bongers et al. 2021).

  4. 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.

  5. Interventions break loops: \(do(X = x)\) severs \(X\)’s dependence on its parents; the system reaches a new equilibrium.

  6. 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