Metadata-Version: 2.4
Name: causal-automata
Version: 0.1.1
Summary: A blazing-fast, JAX-accelerated Cellular Automaton engine for causal discovery.
Author-email: Masakazu Yamagiwa <myamagiwa@gmail.com>
License: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: NOTICE
Requires-Dist: numpy>=1.26
Requires-Dist: networkx>=3.2
Requires-Dist: scikit-learn>=1.4
Provides-Extra: cuda
Requires-Dist: jax[cuda13]; extra == "cuda"
Requires-Dist: torch>=2.1; extra == "cuda"
Requires-Dist: gcastle>=1.0.4; extra == "cuda"
Provides-Extra: jax
Requires-Dist: jax>=0.4.30; extra == "jax"
Requires-Dist: jaxlib>=0.4.30; extra == "jax"
Provides-Extra: gcastle
Requires-Dist: gcastle>=1.0.4; extra == "gcastle"
Requires-Dist: torch>=2.1; extra == "gcastle"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=7.0; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
Requires-Dist: myst-parser>=2.0; extra == "docs"
Dynamic: license-file

# causal-automata

[![PyPI Version](https://img.shields.io/pypi/v/causal-automata.svg)](https://pypi.org/project/causal-automata/)
[![Python Versions](https://img.shields.io/pypi/pyversions/causal-automata.svg)](https://pypi.org/project/causal-automata/)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

A blazing-fast, JAX-accelerated Cellular Automaton engine for causal discovery.

## Installation

```bash
pip install causal-automata
```

With CPU JAX:

```bash
pip install "causal-automata[jax]"
```

With NVIDIA CUDA JAX (and the Colab-style stack):

```bash
pip install "causal-automata[cuda]"
```

Or using `uv`:

```bash
uv add "causal-automata[jax]"
```

## Benchmark — N=100 on Tesla T4

Final figures (Colab **Tesla T4**, GOLEM `num_iter=20000`):

| Algorithm | Skeleton F1 | Directed F1 | Wall Time (s) |
| --- | ---: | ---: | ---: |
| PC (gcastle) | 0.968 | 0.813 | 528.631 |
| GOLEM (gcastle) | 0.577 | 0.403 | 251.182 |
| Bayesian CA (JAX) | 0.812 | 0.483 | 0.323 |

Bayesian CA is ~**778×** faster than GOLEM and ~**1636×** faster than PC, while beating GOLEM on both skeleton (**0.812 vs 0.577**) and directed (**0.483 vs 0.403**) F1.

## Documentation

Full docs (theory, physics, API, CLI): https://causal-automata.readthedocs.io/en/latest/

## How it works — CA physics + V-well

State is a binary DAG adjacency `A`, node elevations `E ∈ [0,1]`, and a fixed empirical covariance `Cov` from continuous observations. Each tick is a local cellular update:

1. **Gravity** — keep only downhill edges (`E[parent] > E[child]`), then drift elevations toward the midpoint of parent/child means.
2. **V-structure gravity well** — absent undirected pairs that share neighbors and are marginally independent (`|ρ|` below the death threshold with empty conditioning set) mark shared neighbors as **colliders**. Those elevations are sunk (`E -= 2·lr`), so later birth prefers arrows into the collider — the classic V-structure `i → k ← j`.
3. **Death / birth** — kill weak edges and birth strong ones using partial correlations conditioned on the top-`k` union neighbors ranked by `|Cov|`. Birth orients by elevation after the `|ρ|` gate.

The NumPy prototype (`bayesian.step`) and the pure functional JAX port (`jax_core.step`, `@jax.jit`) share this physics.

## Run

```bash
# Synthetic DAG harness (NumPy default; use --backend jax for JIT)
python -m causal_automata.bayesian_synth --n 10
python -m causal_automata.bayesian_synth --n 50 --backend jax
python -m causal_automata.bayesian_synth --n 100

# Benchmark vs gCastle PC / GOLEM (default N=100)
python -m causal_automata.benchmark
python -m causal_automata.benchmark --n 100 --seed 0 --ticks 100
python -m causal_automata.benchmark --smoke   # device checks + GOLEM init only
```

Smoke the JAX compile:

```bash
python -c "from causal_automata import warmup; print(warmup())"
```

## Package layout

```
causal-automata/
├── causal_automata/
│   ├── __init__.py
│   ├── bayesian.py          # NumPy Bayesian CA step
│   ├── bayesian_synth.py    # Synthetic linear-DAG harness
│   ├── jax_core.py          # JAX @jit port of step
│   └── benchmark.py         # vs gCastle PC / GOLEM
├── docs/                    # Sphinx / Read the Docs
├── .readthedocs.yaml
├── pyproject.toml
├── README.md
└── NOTICE
```

## License / notice

See `NOTICE`. Copyright 2026 Masakazu Yamagiwa.
