37Software Engineering Patterns for Causal-Dynamical Modelling
Status: Draft
v0.4
37.1 Introduction
This appendix covers layout and practice: how the bookβs Julia stack is organised, how a thin application wires identification to estimation, and how tests and dependency pins keep work reproducible. It is not a substitute for the conceptual chapters, and it is not the package manuals. Principles transfer to other languages; the concrete layout uses Julia.
37.2 Working stack
In these pages the working stack is CausalDynamics.jl (graphs, identification, SCMs / CDMs), CausalTargeted.jl (cross-fitted LMTP and interventional mediation), and DAGMakie.jl (DAG figures). Exported names match the literature (identify, do_intervention, run_lmtp_grid, dagplot, β¦). Process vocabulary belongs in this book (Chapter 9; Table 8); package manuals stay Pearl / targeted-learning facing (CausalTargeted methods).
LMTP / mediation grids, positivity, MC stability, sensitivity helpers
Cohort loaders, DAG string parsers
Application repos
Data, registries, concordance
Re-implementing EIF estimators
When extending the book or the packages, keep API names stable, add process gloss only in book prose where it clarifies, and update Table 8 if you introduce new central mappings. For manuals and changelogs, use the repositories, not this chapter as API documentation.
Continuous ODEs compose via optional SciML helpers (using OrdinaryDiffEq β solve_cdm), not a solver hard-dependency in core. Deferred continuous-time / filter modules are listed on the package Scope page.
CausalTargeted.jl is the estimation companion (not nested inside CausalDynamics):
Dual-stack synthetic recovery vs R lives in the book repo under scripts/synthetic_benchmark/ (treat single-draw wins as provisional).
Layout principles: separate graphs, identification, static SCM, and discrete CDMs; keep estimation out of CausalDynamics; prefer weakdep extensions over hard dependencies for optional backends.
37.4 End-to-end: identify β LMTP
A thin application should identify on a DAG, then estimate with CausalTargeted, without baking nuisance fitting into CausalDynamics:
Chapter 28 builds models with this type and calls simulate / counterfactual. Prefer package tests as the template: unit tests for a single mechanism, integration tests that intervene and replay shared noise, and synthetic recovery checks with known truth in CausalTargeted / the book benchmark scripts. Do not invent parallel APIs in application code that duplicate DoIntervention, DoSequence, or LMTP grids already exported by the packages.
37.6 Reproducibility
Pin Julia and major dependencies in Project.toml / Manifest.toml (this book targets Julia 1.12+ for CausalDynamics and CausalTargeted). Document which packages must be developed from path or Git URL versus General (DAGMakie is on General; see the package READMEs for the others). Examples in this book load dependencies via scripts/ensure_packages.jl.
37.7 Summary
The working stack separates identify (CausalDynamics), estimate (CausalTargeted), and display (DAGMakie). Application repositories should stay thin: data and concordance, not reimplemented estimators. Layout, weakdep extensions, and shared-\(U\) tests are the practices that keep that separation honest.
the generative head is (or can be reduced to) a conjugate / factorised model after residualisation (e.g. CausalDynamics infer_backdoor_effect on demeaned \((y,x)\))
\(N\) is large and you need a fast posterior summary for a scalar effect \(\tau\) or a low-dimensional latent
you already sit on an AgeSCM-style pipeline: encoder β αΊ β GraphPPL head
Prefer Turing (NUTS or other MCMC) when:
the likelihood is non-conjugate, hierarchical, or otherwise awkward for the current GraphPPL factors (abduction soft likelihoods, partial pooling, experimental-design comparisons)
you need a joint posterior over several parameters, or a small-\(n\) check against a VI mean
you want posterior predictive replicates drawn from full MCMC (Ch. 21)
Also in the stack (not a PPL choice): for latent trajectories, prefer filters / smoothers / StateSpaceDynamics Laplace before either PPL; use Turing only on short series or for parameter blocks once the path is handled.
Rule of thumb: conjugate tabular ATE and belief updates β RxInfer; flexible or pedagogical continuous models β Turing; long dynamical latent paths β SSM tooling first. Local timings live in scripts/bayesian_benchmarks.jl.
Design rule:αΊ is the PPL observation interface; TMLE-style propensity supports transport-weighted training. Resolve Graphs β€1.13 with RxInfer 5.x (DataStructures 0.18) in AgeSCM Project.toml, see AgeSCM docs/RXINFER_DEPS.md.
37.9.1 Live wiring: CausalDynamics β RxInfer
The book environment now ships GraphPPL and RxInfer. A confounded Gaussian table recovers \(\tau\approx 2\) in a fraction of a second:
AgeSCM replaces raw spectra by an encoder αΊ before this head; the identification and VI steps stay the same. Timings: scripts/bayesian_benchmarks.jl.
Cinelli, Carlos, and Chad Hazlett. 2020. βMaking Sense of Sensitivity: Extending Omitted Variable Bias.βJournal of the Royal Statistical Society: Series B (Statistical Methodology) 82 (1): 39β67. https://doi.org/10.1111/rssb.12348.
DΓaz, IvΓ‘n, Nicholas Williams, Katherine L. Hoffman, and Edward J. Schenck. 2023. βNonparametric Causal Effects Based on Longitudinal Modified Treatment Policies.βJournal of the American Statistical Association 118 (542): 846β57. https://doi.org/10.1080/01621459.2021.1955691.
Laan, Mark J. van der, and Sherri Rose. 2011. Targeted Learning: Causal Inference for Observational and Experimental Data. Springer Series in Statistics. Springer.
Liu, Richard, Nicholas T. Williams, Kara E. Rudolph, and IvΓ‘n DΓaz. 2024. General Targeted Machine Learning for Modern Causal Mediation Analysis. https://doi.org/10.48550/arXiv.2408.14620.
Petersen, Maya L., Kristin E. Porter, Susan Gruber, Yue Wang, and Mark J. van der Laan. 2012. βDiagnosing and Responding to Violations in the Positivity Assumption.βStatistical Methods in Medical Research 21 (1): 31β54. https://doi.org/10.1177/0962280210386207.