CausalStructures.jl
CausalStructures.jl is a Julia package for causal graphs and causal inference. It provides graph representations for the structures used in causal inference, along with algorithms for graphical queries, causal identification, and transformations between graph classes.
Supported Graph Classes
Currently implemented classes form the following type hierarchy:
CausalGraph
├─ DAG Directed Acyclic Graph
├─ UG Undirected Graph
├─ AbstractPDAG All Partially Directed Acyclic Graphs
│ ├─ PDAG Partially Directed Acyclic Graph
│ ├─ CPDAG Completed Partially Directed Acyclic Graph
│ └─ MPDAG Maximally Oriented Partially Directed Acyclic Graph
├─ ADMG Acyclic Directed Mixed Graph
├─ AbstractAG All Ancestral Graphs
│ ├─ AG Ancestral Graph
│ └─ MAG Maximal Ancestral Graph
├─ PAG Partial Ancestral Graph
└─ UNKNOWN No structural constraintsUNKNOWN can be used for currently unsupported graph classes. The constraints each class imposes are validated on construction, and an error is thrown if the graph is invalid.
The following edge types exist:
directed(:A, :B)forA --> Bundirected(:A, :B)forA --- Bbidirected(:A, :B)forA <-> Bpartially_directed(:A, :B)forA o-> Bpartially_undirected(:A, :B)forA o-- Bpartial(:A, :B)forA o-o B
These same markers can alternatively be used as a string, passed directly to a graph type's constructor, see below.
Quick Start
Construct graphs by specifying edges and the desired graph class. The quickest way is to write edges directly as a string, using the markers above (+ fans a marker out to, or in from, several nodes at once):
using CausalStructures
dag = DAG("U --> X + Y, X --> Y")DAG with 3 nodes and 3 edges:
nodes: U, X, Y
edges:
U --> X, U --> Y, X --> Y
Edges can equivalently be built up from constructor calls, which is useful when composing edges programmatically:
dag = DAG(
directed(:U, :X),
directed(:U, :Y),
directed(:X, :Y)
)DAG with 3 nodes and 3 edges:
nodes: U, X, Y
edges:
U --> X, U --> Y, X --> Y
You can then run a variety of causal graph queries, transformations, and causal identification methods such as adjustment-set computations. For example, if U is unobserved, we can project it out to obtain an ADMG:
admg = latent_project(dag, :U)ADMG with 2 nodes and 2 edges:
nodes: X, Y
edges:
X --> Y, X <-> Y