Skip to Content
ToolchainLeviathan Engine

Leviathan Engine

High-performance C++ simulation core for large swarms. Leviathan advances agent states using physics and environment models, accepts actions from Gossamer, and logs outputs for Maneuver.Map to orchestrate, visualize, and analyze experiments.

At a glance

  • Integrators: semi-implicit Euler (default), RK4, velocity-Verlet.
  • Communication: bandwidth-limited, loss-prone, delay-buffered channel.
  • Collisions: sphere-sphere elastic resolution with configurable restitution.
  • Scale: demonstrated at 10⁶ agents on a single CPU node; OpenMP parallel.
  • Reproducibility: checkpoints carry serialized RNG state.

Minimal Python example

from leviathan import Simulation sim = Simulation({ "dt": "0.1", "num_agents": "1000", "integrator": "velocity_verlet", "collision_radius": "0.5", "comm_range": "10.0", "comm_bw_kbps": "8.0", "seed": "42", }) # Advance 100 steps with zero action (agents drift under their initial vels) for _ in range(100): sim.step() print(sim.metrics())

For MARL rollouts against PettingZoo, use leviathan_marl.env.LeviathanParallelEnv; it skips HTTP and runs the physics in-process. The MARL package is named leviathan_marl so it doesn’t shadow the pybind11 leviathan extension on sys.path.

Cite this tool

@software{arboria2026leviathan, title = {Leviathan Engine: high-performance multi-agent physics simulation}, author = {{Arboria Labs}}, year = {2026}, url = {https://www.arborialabs.com/tools/leviathan_engine} }

How It Fits With Gossamer + Maneuver.Map

  • Leviathan: physics, environment, agent state, scalable stepping, logging.
  • Gossamer: provides action policies (e.g., flocking) and metrics; used via Python bindings.
  • Maneuver.Map: controls runs, tunes parameters, stores data (e.g., GCS), and serves 3D visualization and APIs.

Features

  • Selectable integrator — Euler (default), RK4, or velocity-Verlet (symplectic; correct default for orbital / long-horizon scenarios where Euler drifts >20% over 10⁵ steps).
  • Real C++ communication channel — bandwidth (comm_bw_kbps), per-link capacity, Bernoulli loss (comm_loss_prob), propagation delay (comm_latency_steps or derived from comm_latency_ms). No-op when none are set; zero performance regression for legacy callers. Aggregate counters (comm_attempted / delivered / dropped_loss / dropped_range / bytes_in_flight) surfaced in metrics().
  • Sphere-sphere collisionscollision_radius + collision_restitution (0 = stick-and-share, 1 = elastic). collisions_last_step reported in metrics().
  • OpenMP parallelism — over physics, environment-field, and collision loops (LEVIATHAN_WITH_OPENMP=ON by default; falls back to serial cleanly when OpenMP is unavailable).
  • Deterministic checkpointsSimulation::get_rng_state() / set_rng_state() serialize the std::mt19937 state so resumed runs are byte-identical to non-resumed runs. Exposed through pybind and the HTTP /checkpoint / /restore endpoints.
  • Environment fieldsnone, uniform vector, or central inverse-square (gravity-like).
  • Spatial hashing + neighbor-only physicsO(N)O(N) neighbor queries within a cutoff radius rather than all-to-all dynamics. Demonstrated at 10⁶ agents on a single CPU node.
  • PettingZoo ParallelEnv wrapperleviathan_marl.env.LeviathanParallelEnv for drop-in MARL training (RLlib, CleanRL, MARLlib, TorchRL). Sits on top of the in-process pybind module so no HTTP round-trip per step.
  • Differentiable JAX backend stubleviathan_diff_brax ports Euler and velocity-Verlet to pure JAX for gradient-based swarm-shaping research.
  • Python bindings — pybind11 module named leviathan with a Simulation class.

Build & Run (Local)

mkdir -p build && cd build cmake -Dpybind11_DIR="$(python3 -m pybind11 --cmakedir)" .. make -j"$(nproc)" python3 -c "import leviathan; from leviathan import Simulation; print('OK')"

Force-disable OpenMP (debugging or unsupported toolchains):

cmake -DLEVIATHAN_WITH_OPENMP=OFF -Dpybind11_DIR="$(python3 -m pybind11 --cmakedir)" ..

Output Schema

  • CSV columns: timestamp, agent_id, position_x, position_y, position_z. The Maneuver.Map runner extends this with optional per-algorithm columns (role, soc, aoi, density, pheromone) when relevant.
  • Parquet part files at <output_path>.parts/part-<step>.parquet — one per logged step. Maneuver.Map’s /frames API streams these via pyarrow.dataset with predicate pushdown on timestamp and column pruning.
  • CSV → Parquet conversion utility: python scripts/csv_to_parquet.py path/to/leviathan_output.csv.

Python Integration

  • Bindings module name: leviathan. The pybind11 extension exports a Simulation class with step(), metrics(), get_rng_state(), set_rng_state(), checkpoint(), and restore().
  • MARL wrapper: leviathan_marl.env.LeviathanParallelEnv (separate package name to avoid shadowing the extension on sys.path).
  • Differentiable backend: leviathan_diff_brax ports the kernel to JAX for gradient-based research; parity at 1k agents today, larger scales on the roadmap.
  • Used by Maneuver.Map’s runner via either HTTP (ENGINE_MODE=http) or in-process pybind (ENGINE_MODE=inprocess); the latter skips a full HTTP round-trip per step and is what we use for million-step rollouts.

Docker

  • See Dockerfile for a Cloud‑ready build of core + bindings. The Maneuver.Map Orchestrator image builds Leviathan and serves APIs.

Typical Research Workflow

  1. Define agent logic in Gossamer (policies, metrics).
  2. Configure Leviathan (environment, agents, output format and frequency).
  3. Run simulation locally or via orchestrator; log CSV/Parquet.
  4. Visualize and analyze in Maneuver.Map.

Configuration Reference

Leviathan reads a flat string-valued config map (HTTP body, pybind kwarg dict, or key: value file). Every key is optional; defaults are noted.

Core physics

  • dt (float, default 1.0) — simulation time step in seconds.
  • num_agents (int, default 10).
  • bound (float, default 100.0) — periodic-box half-extent.
  • integrator (string, default "euler") — "euler" | "rk4" | "velocity_verlet".
  • acc_min, acc_max (float) — random-action bounds for the legacy demo path; the Maneuver.Map runner always supplies actions from Gossamer and these are ignored.
  • seed (int) — deterministic agent-state initialization.

Environment field

  • field_type (string) — "none" | "uniform" | "central" (inverse-square, gravity-like toward origin).
  • field_vx, field_vy, field_vz (float) — components for "uniform" fields.
  • field_strength (float) — scalar strength for "central" or "uniform" fields.

Communication channel (no-op when all default)

  • comm_range (float, metres).
  • comm_bw_kbps (float) — shared per-link bandwidth cap.
  • comm_bundle_kb (float, default 0.1) — bundle size in KB.
  • comm_loss_prob (float, 0–1) — Bernoulli per-bundle drop probability.
  • comm_latency_steps or comm_latency_ms — fixed propagation delay; the latter is converted using dt.
  • comm_seed (int) — independent RNG for the comms layer.

Collisions (no-op when collision_radius == 0)

  • collision_radius (float, metres).
  • collision_restitution (float, 0–1) — 0 = stick-and-share, 1 = elastic.

Output (when invoked through the legacy CLI runner; the Maneuver.Map runner has its own writer)

  • output_path — CSV path; Parquet parts go to output_path + ".parts".
  • output_frequency (int) — write rows every N steps.
  • output_format"csv" (default) or "parquet" (requires Arrow/Parquet at build).

Output Details

  • CSV schema (engine default): timestamp,agent_id,position_x,position_y,position_z.
  • Parquet schema (if enabled): same columns as CSV; emitted in parts under <output_path>.parts/.
  • Maneuver.Map may extend the schema when orchestrating (CSV includes additional columns like role,soc,aoi,density,pheromone and emits Parquet parts by default). The viewer selects and streams only the columns it needs.

Performance Notes

  • Use higher output_frequency to reduce I/O when stepping many agents.
  • Prefer Parquet for downstream slicing/streaming in Maneuver.Map; predicate pushdown prunes time ranges and columns server‑side.
  • For very large num_agents, ensure the surrounding container has sufficient memory; simulation cost scales roughly linearly with agent count per step.
Last updated on