actualcauses is a Python package to identify actual causes (Halpern–Pearl style) in deterministic or stochastic systems.
It implements approximate algorithms with adjustable precision introduced in the paper:
Searching for actual causes: approximate algorithms with adjustable precision (Reyd, Diaconescu, Dessalles).
Preprint: arXiv:2507.07857
The package is designed for explainability and causal analysis of autonomous / AI-based systems: given a system model, a context, and a target consequence, it searches for exact or approximate actual causes.
pip install actualcausesFor local development:
git clone https://github.com/SamuelReyd/ActualCausesIdentification
cd ActualCausesIdentification
python -m pip install -e ".[dev]"An SCM object represents a Structural Causal Model:
- V: endogenous variables (names)
- U: exogenous variables (names)
- D: variable domains
- u: a context (values for exogenous variables)
- dag: optional causal graph (for algorithms that exploit structure)
- model: a system model (see
SystemModelclass) used to evaluate interventions
Once created, you call:
scm.find_causes(...)
scm.show_identification_result()A system model defines how the system responds to interventions.
For simple Python models, subclass SystemModel and implement call(u, e).
For accelerated / vectorized evaluation, subclass BaseNumpyModel (and optionally its stochastic variants).
The package provides a ready-to-run example SCM:
from actualcauses import suzzy_example_scm
# Identify causes with two algorithms (Beam Search / ISI)
suzzy_example_scm.find_causes(ISI=False, max_steps=5, beam_size=20, epsilon=0.05, early_stop=False, verbose=2)
suzzy_example_scm.show_identification_result()
suzzy_example_scm.find_causes(ISI=True, max_steps=5, beam_size=20, epsilon=0.05, early_stop=False, verbose=2)
suzzy_example_scm.show_identification_result()A complete runnable version is in examples/quickstart.py.
See the examples/ folder for additional scenarios and advanced usage.
This mirrors examples/custom_scm.py (forest fire scenario). The important part is implementing a SystemModel and passing it to SCM.
from actualcauses import SCM, SystemModel
class ForestFireModel(SystemModel):
def __init__(self, disjunctive=True):
super().__init__(
phi=lambda s: s[-1], # consequence predicate (example: last variable)
psi=lambda s: sum(s), # heuristic used by search
)
self.disjunctive = disjunctive
def __call__(self, u, e):
md, l = u
e = dict(e)
MD = e.get("MD", md)
L = e.get("L", l)
if self.disjunctive:
FF = e.get("FF", int(L or MD))
else:
FF = e.get("FF", int(L and MD))
self.n_calls += 1
return [MD, L, FF]
scm = SCM(
V=("MD", "L", "FF"),
U=("md", "l"),
D=(0, 1),
u=(1, 1),
model=ForestFireModel(disjunctive=True),
dag={"MD": [], "L": [], "FF": ["MD", "L"]},
)
scm.find_causes()
scm.show_identification_result()The package provides:
-
Beam-search style identification for (approximate) actual causes.
-
ISI (Iterative Subinstance Identification) that can exploit a DAG to restrict search to relevant ancestors.
-
LUCB-based estimation for stochastic models, to allocate samples adaptively.
Exact knobs/parameters are exposed via SCM.find_causes(...). Notable usefull parameters include beam_size (integer), ISI (boolean), max_steps(integer), and early_stop (boolean). Algorithm have 3 level of verbosity (accessible via verbose=...).
The examples/ folder contains scripts intended to be read and modified:
- quickstart.py — Minimal end-to-end run using suzzy_example_scm.
- custom_scm.py — Implement a custom basic SCM and identify actual causes.
- custom_heuristic.py — Use different heuristics (psi) with a fixed system model and SCM.
- vectorized_system_model.py — Use BaseNumpyModel to accelerate identification by vectorizing intervention evaluation.
- stochastic_system_model.py — Stochastic evaluation with a naive average estimator and the LUCB estimator.
Run any example from the repository root, e.g.:
python examples/quickstart.pyMIT License. See LICENSE.
If you use this software in academic work, please cite:
Reyd, S., Diaconescu, A., & Dessalles, J. (2025). Searching for actual causes: Approximate algorithms with adjustable precision. arXiv:2507.07857.
@misc{reyd2025searchingactualcausesapproximate,
title = {Searching for actual causes: Approximate algorithms with adjustable precision},
author = {Samuel Reyd and Ada Diaconescu and Jean-Louis Dessalles},
year = {2025},
eprint = {2507.07857},
archivePrefix= {arXiv},
primaryClass = {cs.AI},
url = {https://arxiv.org/abs/2507.07857}
}