Skip to content

boschresearch/CausalMan

Repository files navigation

CausalMan

A Causal simulator for manufacturing process systems. CausalMan generates synthetic observational and interventional datasets from complex production lines with known ground-truth causal graphs, enabling benchmarking of causal discovery, inference and RCA algorithms.

Overview

CausalMan implements an expert-defined SCM of a manufacturing production line. Parts flow through machines and parallel sections, and each path through the line has distinct properties and parameterizations. The whole SCM is specified by symbolic structural equations (SymPy). The simulator returns:

  • Observational data — sensor readings from the partially observable production process
  • Interventional data — data under hard do-calculus interventions on selected variables
  • Path data — per-part routing through parallel sections
  • Causal graph — the ground-truth DAG (and optionally its ADMG/MAG projections after marginalizing latent variables)

Project Structure

causal_simulator_to_release/
├── src/                    # Installable Python package
│   ├── causalman.py              # Main CausalMan simulator class
│   ├── fcm.py                    # FCM core: DAG construction, sampling, interventions. 
│   ├── node.py                   # Node model definitions
│   ├── sample_batch.py           # Per-batch sampling logic
│   ├── graph_plotter.py          # Interactive graph visualization (Pyvis)
│   ├── graph_projections.py      # ADMG/MAG latent variable projections
│   ├── marginalization.py        # Marginalization via R dagitty (optional)
│   ├── col_masking.py            # Filter datasets to observable columns
│   ├── FCM_Definitions/          # FCM equation templates for parallel sections
│   ├── line_structure/           # Production line hierarchy (line, section, machine)
│   ├── dataset_objects/          # Pre-computed simulation configurations (~7.6 GB)
│   ├── utils/
│   │   ├── sampling.py           # Sequential and parallel batch runners
│   │   ├── graph.py              # Graph manipulation and I/O utilities
│   │   ├── data.py               # DataFrame processing utilities
│   │   └── equation.py           # Sympy equation construction helpers
│   ├── output/                     # Generated simulation results
│   ├── example_observational.ipynb
│   └── interventions_example.ipynb
│   ├── causal_inference_data_generation.ipynb  # Generate CI benchmark datasets (notebook)
│   ├── rca_data_generation.ipynb               # Generate RCA benchmark datasets (notebook)
│   └── generate_causal_inference_data.py       # Generate CI benchmark datasets (CLI)
├── pyproject.toml
└── requirements.txt

Installation

Requirements: Python 3.9+

Clone the repository and install the package in one step:

git clone <repository-url>
cd causalman
pip install .

This installs the causalman package along with all required dependencies. The precomputed dataset objects (~7.6 GB of pickle files) are bundled inside the package and installed automatically — no separate download needed.

Note: Installation copies the full dataset_objects/ directory into your Python environment. Make sure you have at least 8 GB of free disk space before installing.

Optional extras — install only what you need:

pip install ".[graph-layout]"   # Graphviz-based graph layouts (pygraphviz)
pip install ".[png-export]"     # Export graphs to PNG via headless browser (playwright)
pip install ".[r-dagitty]"      # R dagitty marginalization bridge (rpy2)
pip install ".[all]"            # Everything above

After installing playwright, run:

playwright install chromium

After installing rpy2, ensure R is installed locally with the dagitty package.

Set the R_HOME environment variable to your R installation directory before importing causalman.marginalization:

# Linux / macOS
export R_HOME=/usr/lib/R          # typical system R
export R_HOME=/usr/local/lib/R    # Homebrew R on macOS

# Windows (PowerShell)
$env:R_HOME = "C:\Program Files\R\R-4.4.2"

# Windows (Command Prompt)
set R_HOME=C:\Program Files\R\R-4.4.2

You can also set it in Python before the import:

import os
os.environ["R_HOME"] = "/path/to/R"   # must be set before importing rpy2

from causalman.marginalization import marginalize_to_mag

To find your R home directory, run R.home() inside an R session.

Quick Start

from causalman import CausalMan

simulator = CausalMan(
    name="causalman_small",   # dataset variant
    seed=42,                  # random seed
    batch_multiplier=1,       # controls number of samples per batch
)

obs_df, int_table, path_df, causal_dag = simulator.sample()

Returned values

Variable Type Description
obs_df pd.DataFrame Observational sensor readings (partially observable)
int_table pd.DataFrame Binary indicator table of which variables were intervened on
path_df pd.DataFrame Path routing of each part through parallel sections
causal_dag nx.DiGraph Ground-truth causal DAG (level 2)

Dataset Variants

Name Description
causalman_micro Small production line with a single product. 24 Observable variables.
causalman_small Production line with ~50 observable variables. Multiple products.
causalman_medium Medium-size production line with ~180 observable variables.
causalman_large Large-size production line with >400 observable variables.

CausalMan Large simulates the whole production line, and the other variants instead simulate progressively smaller parts of it, with the goal of providing a simpler benchmarking scenario.

Configuration Options

CausalMan(
    name="causalman_small",   # one of: micro, small, medium, large
    seed=42,                  # reproducibility seed
    batch_multiplier=1,       # scale factor for number of samples
    parallelize=False,        # enable multi-process batch sampling
    max_workers=5,            # worker count when parallelize=True
    debug_mode=False,         # write debug outputs to disk
    save_path="output/run1",  # directory for CSV and graph outputs
)

Interventional Sampling

Specify a dictionary of hard interventions before calling sample():

simulator = CausalMan(name="causalman_small", seed=42)
simulator.intervention_dict = {"PF_M1_T1_sgrad": 18500}
obs_df, int_table, path_df, dag = simulator.sample()

The simulator mutates the causal graph and resamples downstream variables according to the intervention.

Working with Causal Graphs

The returned causal_dag is a NetworkX DiGraph. Observable and latent nodes are tracked as node attributes.

import networkx as nx

# List observable nodes
observable = [n for n, d in dag.nodes(data=True) if d.get("observable")]

# Export to GraphML
nx.write_graphml(dag, "causal_graph.graphml")

Latent Variable Projections

To compute the ADMG (Acyclic Mixed Graph) and MAG (Maximal Ancestral Graph) after marginalizing latent variables:

from causalman.graph_projections import get_latent_projection_single, admg2mag

admg = get_latent_projection_single(dag)
mag  = admg2mag(admg)

Graph Visualization

from causalman.graph_plotter import GraphPlotter

plotter = GraphPlotter(dag)
plotter.plot()  # opens interactive HTML in browser

Masking to Observable Columns

python -m causalman.col_masking \
    --graph output/run1/batch_data/batch_0/batch_graph.pkl \
    --csv   output/run1/merged.csv \
    --output_dir output/run1/observable/

Output Directory Layout

When save_path is provided:

output/run1/
├── batch_data/
│   └── batch_0/
│       ├── batch_graph.pkl          # Ground-truth causal DAG (pickled)
│       ├── batch_graph.graphml      # Graph in GraphML format
│       └── observed_nodes_list.txt  # List of observable node names
└── DEBUG/                           # Debug outputs (if debug_mode=True)

Parallel Processing

For large-scale sampling, enable multi-process execution:

simulator = CausalMan(
    name="causalman_medium",
    parallelize=True,
    max_workers=8,
)
obs_df, int_table, path_df, dag = simulator.sample()

Examples

Two tutorial notebooks are provided in causalman/:

  • example_observational.ipynb — basic FCM construction and observational sampling
  • interventions_example.ipynb — interventional sampling and comparison with observational distributions

Benchmark Data Generation

Two notebooks in src/ generate ready-to-use benchmark CSV datasets:

  • src/causal_inference_data_generation.ipynb — generates causal inference benchmark datasets. Set SCALE, SEEDS, and N_SAMPLES at the top of the notebook and run all cells. Produces for each (scale, seed) combination:

    • observational.csv — training data with no interventions
    • task1_force_ltl_control.csv / task1_force_ltl_treatment.csv — do(PF_M1_T1_Force_LTL = 15000/18000)
    • task2_force_control.csv / task2_force_treatment.csv — do(PF_M1_T1_Force = 16000/30000)
  • src/rca_data_generation.ipynb — generates root-cause analysis benchmark datasets across 4 tasks and multiple scales. Set SCALES, SEED, and N_SAMPLES at the top and run all cells.

A CLI equivalent of the causal inference notebook is also available:

# Basic usage (variant required)
python src/generate_causal_inference_data.py --variant small

# Full benchmark: 5 seeds, 10 000 rows per dataset
python src/generate_causal_inference_data.py --variant medium --seeds 4 6 42 66 90

# Custom output directory and sample count
python src/generate_causal_inference_data.py --variant large --samples 5000 --output my_output/
Argument Default Description
--variant (required) Scale variant: micro, small, medium, large
--seeds 42 One or more random seeds
--samples 10000 Rows to write per dataset
--output output/causalman_causal_inference Root output directory

Citation

If you use CausalMan in your research, please cite the associated work.

@misc{tagliapietra2025causalman,
      title={CausalMan: A physics-based simulator for large-scale causality}, 
      author={Nicholas Tagliapietra and Juergen Luettin and Lavdim Halilaj and Moritz Willig and Tim Pychynski and Kristian Kersting},
      year={2025},
      eprint={2502.12707},
      archivePrefix={arXiv},
      primaryClass={cs.LG},
      url={https://arxiv.org/abs/2502.12707},
      doi={10.48550/arXiv.2502.12707}
}

arXiv: https://arxiv.org/abs/2502.12707

License

CausalMan is open-sourced under the AGPL-3.0 license. See the LICENSE file for details.

For a list of other open source components included in CausalMan, see the file 3rd-party-licenses.txt.

About

No description or website provided.

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors