A Rust reimplementation of the primordial-soup simulation from Computational Life: How Well-formed, Self-replicating Programs Emerge from Simple Interaction (Agüera y Arcas et al., 2024, arXiv:2406.19108), plus a handful of extensions the original paper leaves on the table.
The pitch in one sentence: take a pool of random byte strings, let them interpret each other as programs in a Brainfuck-ish language called BFF, sprinkle in a bit of mutation, and watch self-replicators show up on their own.
A Rust workspace with a handful of crates, a web frontend, and some scripts:
bff-core,bff-interp: the BFF instruction set and a CPU + GPU interpreter. GPU path goes through CubeCL so the same Rust compiles to WGSL, Metal, and CUDA. CPU and GPU are byte-for-byte deterministic against each other, which was surprisingly annoying to get right (SplitMix64 on u32-pairs, no 64-bit atomics on WGSL).bff-soup: the well-mixed soup itself. Fisher-Yates pairing, three-phase mutation, metrics pipeline.bff-spatial: a 2D grid variant with a Chebyshev interaction neighborhood. Not in the paper.bff-history: epoch-level zstd-compressed diffs with periodic checkpoints, so you can scrub backward and forward through a run.bff-analysis: Shannon entropy, higher-order entropy, and a brotli-q2 Kolmogorov approximation (matching the paper's choice).bff-db: SQLite persistence for run metadata, lineage, and identified replicator families.bff-server: Axum, WebSockets per simulation mode.web/: React + TypeScript (Bun), CodeMirror with vim bindings, dashboards for each mode.modal/: Modal deployment script for A100 parameter sweeps.scripts/optuna_search.py: hyperparameter search over soup configs via PyO3 bindings.
- Spatial soup. 2D toroidal grid, local interactions only. Phase transition still shows up but with visibly different dynamics than well-mixed.
- Run history. Bidirectional epoch-diff storage, so you can rewind a run and inspect how a replicator family emerged without rerunning from the seed.
- Taxonomy / lineage. Automatic classification of replicators into families based on their byte patterns, tracked over time.
- Variable-length tapes. Experimental mode where programs can grow and shrink, which changes the emergence dynamics noticeably.
- Optuna hyperparameter search over mutation rate, program count, grid size, and so on, optimizing for time-to-phase-transition.
-
The paper's phase transition reproduces cleanly. Starting from uniform random tapes, higher-order entropy crashes from the maximum-entropy baseline and compressibility spikes, on the same kind of timescale the paper reports (thousands of epochs at 128k programs, A100). A sample trace from
modal/results/seed_0.csv:epoch higher_entropy brotli_bpb 0 -0.00 8.00 (uniform random, maximum entropy) 128 2.74 4.30 (structure emerging) 1024 1.82 4.58 (replicators dominating) 3584 1.41 5.00 (stable ecosystem) -
GPU vs CPU determinism holds. The soup sim runs identically on CPU and GPU across all mutation phases, for any seed. Worth the pain: it means you can debug on CPU and scale on GPU without second-guessing the results.
-
GPU batching matters a lot. Moving Fisher-Yates onto the device and keeping state resident between epochs was the biggest single throughput win, roughly 10x over a naive host-device roundtrip per epoch.
-
Spatial soup transitions more slowly but more robustly. In well-mixed runs a single lucky replicator can dominate the pool quickly. On a grid, multiple lineages coexist longer before any one takes over, which is the sort of thing you'd expect but it was nice to see it fall out of the implementation.
-
CubeCL had sharp edges. No
continue, noreturn, dead branches still get const-evaluated soshift - 32upanics even when unreachable. Documented in the commit history if you're going down the same road.
Backend:
cargo run -p bff-server --releaseGPU features ship on by default. If your machine doesn't have a usable GPU, the soup runner falls back to CPU.
Frontend (use Bun, not npm):
cd web
bun install
bun run devThen open the URL it prints. The different simulation modes live under different routes.
A single soup run from a config:
cargo run -p bff-soup --example batch_sweep --release --features gpu-cuda -- \
--seeds 0 --max-epochs 50000 --num-programs 131072This is a personal research repo, not a maintained project. It reached the point where I wanted to look at it from the outside, so here it is. Code is MIT licensed. Issues and questions are welcome but I'm not promising I'll get to them.
- Agüera y Arcas, Alakuijala, Evans, Laurie, Mordvintsev, Niklasson, Randazzo, Versari. Computational Life. 2024. arXiv:2406.19108
- The paper's reference CuBFF implementation, which this project used for cross-checks.