biota is a distributed quality-diversity search platform for Flow-Lenia. Two subsystems share the same vectorized PyTorch runtime and the same Ray cluster: a MAP-Elites search that fills a behavioral archive, and an ecosystem dispatch that runs selected archive creatures on shared canvases. Both run on consumer-grade hardware — a 3-node RTX 5060 Ti cluster with Thunderbolt OCuLink GPU attach.
MAP-Elites runs a loop: sample parameters, simulate a creature, measure its behavior, insert it into the matching archive cell if it beats whatever is already there. After thousands of rollouts the archive fills with creatures covering the behavioral space as broadly as possible — not optimizing toward one solution, but toward diversity.
The archive is a three-dimensional behavioral grid. Each axis holds one descriptor chosen from a library of fifteen, all normalized to [0, 1] and empirically calibrated against real cluster runs. Each cell holds the highest-quality creature found with that behavioral fingerprint.
The driver owns the archive and the search loop. Each Ray task evaluates B creatures as a single (B, H, W) vectorized forward pass on one GPU. Workers are stateless; nothing persistent lives on the cluster between tasks. --workers N controls how many batches are in flight simultaneously: one means synchronous MAP-Elites with a maximally fresh archive, higher values trade freshness for throughput.
Once the archive is populated, biota ecosystem takes specific archive cells and runs them on a shared grid to see how creatures interact. A homogeneous run spawns N copies of one species. A heterogeneous run mixes two or more species, each with its own full parameter set — kernel radii, growth windows, weights — using species-indexed LocalizedFlowLenia: per-cell species ownership tracks which lineage owns the local mass, blends growth fields by ownership, and advects with the flow.
Ecosystem dispatch is Ray-correct in both directions: each experiment is a self-contained payload. The driver loads creatures from its local archive and ships them as part of the task input; workers simulate and render to bytes; the driver materializes outputs to its own local filesystem. No shared filesystem is assumed at any step, so experiments run correctly on real multi-node clusters without NFS or rsync setup.
Three scalars measured from each rollout index the archive's three axes. The active set is chosen per run — any three from the built-in library of fifteen.
biota searches the parameter space of Flow-Lenia — a continuous cellular automaton where matter is conserved by construction. Rather than finding a single best creature, it fills a behavioral grid where each cell holds the most compact creature with a particular phenotypic fingerprint. The result is a structured catalog of qualitatively distinct life-forms.
Each creature is a soliton: a stable, self-maintaining pattern that persists indefinitely given the right parameters. Mass conservation is what makes them viable across a wide parameter range — without it, most settings produce explosion or collapse within a few steps.
biota started as a side project to get hands-on with PyTorch and Ray without doing yet another deep learning thing, and grew into a full Flow-Lenia research platform with behavioral search, heterogeneous ecosystem simulation, and this static atlas. It runs on consumer-grade hardware in a home lab — nothing about the approach requires a data center.
If any of it is useful to you, or you want to point out something I got wrong, feel free to open an issue on GitHub.
biota is a self-contained CLI tool. You can run it on a laptop for quick iteration or across a Ray cluster for full-scale searches. The only hard dependencies are Python 3.12, PyTorch, and Ray.
# Clone and install git clone https://github.com/rkv0id/biota cd biota uv sync
uv run biota search --preset dev --budget 200
python scripts/build_index.py open runs/index.html
On Apple Silicon pass --device mps --batch-size 32 for a meaningful speedup. On a CUDA cluster, use --batch-size 64 --workers N where N is the number of nodes. The standard preset (192×192, 300 steps) at B=64 on an RTX 5060 Ti cluster runs 500 rollouts in about 97 seconds.
# Apple Silicon uv run biota search --preset standard --budget 500 \ --device mps --batch-size 32 # Single CUDA GPU, no Ray uv run biota search --preset standard --budget 500 \ --device cuda --batch-size 64 # Multi-node Ray cluster, custom descriptor axes uv run biota search --ray-address head:6379 \ --preset standard --budget 2000 \ --device cuda --batch-size 64 --workers 3 \ --descriptors oscillation,compactness,png_compressibility
Pass --descriptors with three comma-separated names to control which behavioral axes the archive uses. With 9 built-ins there are 84 possible configurations. You can also supply your own via --descriptor-module path/to/file.py — the file must define a list named DESCRIPTORS containing Descriptor objects.
# Default axes uv run biota search --descriptors velocity,gyradius,spectral_entropy # Shape and complexity axes uv run biota search --descriptors oscillation,compactness,png_compressibility