Skip to content

tacio/esper

Repository files navigation

Esper: Neuro-Symbolic Reasoning Engine

A bare-metal, pure-Mojo reasoning engine that learns a grid→grid transformation from a handful of demonstration pairs — fitting a small operator in-context with a derivative-free Evolution Strategy (no backprop, no neural-net framework) — and then applies it to an unseen input.

Esper generalizing a learned flip to a held-out grid: test input, Esper's prediction, and the truth, side by side.

Test input · Esper's prediction · truth. Esper never saw this grid during the fit; it learned flip_h from the task's other demo pairs and generalized. The panels are rendered straight from arc_solve --trace output — nothing is hand-drawn. ▶ Open the interactive version (marimo run tools/viz/esper_viz.py — see Reproduce).

What this is, in 60 seconds

The number that matters is held-out exact match: fit the operator on a task's train pairs, then score the test pair the model never saw. It is uncheatable by memorization — and on synthetic transforms like flip_h, Esper scores 1.00.

Under the hood is Nested Learning (the HOPE architecture):

  1. Slow Weights — a meta-learned prior over operators (a Reptile outer loop).
  2. Fast Weights (Continuum Memory System) — the operator itself, fit during the forward pass by an annealed, antithetic, SIMD/FMA Evolution Strategy — no gradients, no DSL, no target memorization.
  3. HopeArena — a strictly move-only, zero-overhead bump-pointer allocator hosting the POD nodes and their weight slices.

The engine learns the transformation; it is never handed a symbolic DSL. Geometric, colour, and count transforms emerge as fitted operator parameters.

Watch it work

Learning a transform in-context. The operator starts at the identity prior and is fitted by the ES on the demo pairs. Below is its prediction on the held-out input converging over 4 000 iterations — from the identity, through noise, to an exact flip_h:

Esper's held-out prediction converging from identity to an exact horizontal flip over ES iterations.

A learned open-ended behaviour. Esper's reward-free MAP-Elites repertoire illuminates a space of sandbox behaviours through the unchanged ES core. One elite's policy, rolled out under the sandbox's gravity, paints the world floor-up:

A repertoire policy painting the sandbox world, its paint settling under gravity over 64 ticks.

…and the repertoire's coverage of that behaviour space — the avatar-final-position illumination map (left) and the mean paint field (right):

MAP-Elites illumination: coverage of avatar-position behaviour space, and the repertoire's mean paint field.

Every frame is rendered offline from a --trace / .rep dump by a dependency-free renderer (numpy + stdlib only) — nothing is hand-drawn. See Reproduce.

Results (honest, including the negatives)

The evidence trail is the currency here. Everything is fit on train pairs and scored held-out, always quoted with its ES budget.

What Result Notes
Held-out flip_h (synthetic) 1.00 exact match fit on train pairs, scored on the unseen test pair
Same-shape synth corpus 0.806 train / 0.778 eval (mean) emergent composed memories
ARC-AGI-2 train 41 / 1000 v4 measure, in-context per task
ARC-AGI-2 eval (real) 0 / 120 full 30×30 ARC scale; full-budget fits are compute-prohibitive
Gate 001 — world-model prior transfer PARTIAL the repertoire's index transfers; flat weight priors do not
Gate 002 — prior rollout STOP all three STOP conditions triggered (3-seed)
Gate 003 — transferability proxy NOT-TESTABLE N_dec = 5 < 6 under the frozen threshold
Gate 004 — CBR retain STOP measured, full budget

Negative results are kept and documented in docs/gates/ — they are what steer the roadmap. The current horizon is the Gauntlet: a family of worlds built to share recombinable sub-goals, scored on the cross-world transfer curve.

Learn

New to the project? docs/course/ is a self-contained, undergrad-level course — the Nested Learning/HOPE theory, Evolution Strategies, the core architecture, the emergent memory zoo, the Vision-B open-endedness ladder, and the current cross-world-transfer frontier, with diagrams throughout. Open docs/course/index.html directly in a browser, or serve it via GitHub Pages.

Status & Roadmap

docs/ROADMAP.md is the canonical direction — mission, vision, objectives, and the full status ledger. Snapshot (2026-07-21):

  • The learning spine works and is proven held-out. Fast weights are a learned in-context memory fit by ES on each task's demonstration pairs, anchored to meta-learned slow weights. No hand-coded DSL, no target memorization, no backprop anywhere.
  • Open-ended mastery (Vision B) — complete: a five-rung reward-free ladder over a pure-Mojo sandbox — novelty search, a persistent MAP-Elites repertoire, exact empowerment, a learned world model with noisy-TV-immune learning progress, and an ACCEL-style emergent curriculum — all through the unchanged ES core.
  • Cross-world transfer (the active axis): what carries from world N to world N+1, measured warm vs cold at equal budget, held-out (see the results table above).

See docs/JOURNAL.md for the development narrative and docs/NL-summary.md for the architecture's theoretical basis.

Reproduce

Everything below is one command from a bootstrapped shell (see Development Environment).

The hero image, end-to-end (Mojo fit → trace → PNG):

./esper run src/arc_solve.mojo --report --trace /tmp/trace.jsonl <a synth .task bundle>
python tools/viz/render_hero.py /tmp/trace.jsonl --out docs/assets/hero.png

--trace writes one JSON object per task ({task, mem, held_out, train_fit, input, pred, true, …}) after each fit — never inside the ES hot loop. The renderer is dependency-free (numpy + stdlib zlib only).

The "watch it learn" animation (per-K-iter held-out prediction → GIF + filmstrip):

./esper run src/main.mojo --learn-trace /tmp/learn.jsonl
python tools/viz/render_learn.py /tmp/learn.jsonl   # -> docs/assets/learn.{gif,png}

A repertoire rollout + illumination map (needs a .rep under build/, produced by the repertoire tests or a MAP-Elites run — build/ is gitignored):

./esper run src/sandbox_trace.mojo build/b_poc_4.rep /tmp/rollout.jsonl
python tools/viz/render_rollout.py /tmp/rollout.jsonl      # -> docs/assets/rollout.{gif,png}
python tools/viz/render_repertoire.py build/b_poc_4.rep    # -> docs/assets/repertoire.png

The animated GIFs come from a self-contained GIF89a/LZW encoder in tools/viz/gifpng.py — still numpy + stdlib only, no Pillow.

The interactive triptych (marimo + anywidget, decoupled from the engine):

uv pip install marimo anywidget      # viz-only deps; the engine needs none of them
marimo run tools/viz/esper_viz.py    # opens in a browser; scrub between tasks

To ship it as a self-contained WASM page: marimo export html-wasm tools/viz/esper_viz.py -o site --mode run (serve the site/ dir over HTTP).

The ARC-AGI-2 number: clone the ARC-AGI-2 corpus (not vendored), then

python tools/arc_compiler.py <corpus>/data/evaluation data_bin/arc2_eval
./eval_parallel.sh data_bin/arc2_eval scratch/arc2_eval.txt 16 64 1500

The trailing pair is the documented corpus ES budget --fit N ITERS; the corpus number is always quoted together with its budget.

Constraints & Requirements

This project enforces a strict, bare-metal systems engineering ethos — for the learning engine (src/). The offline viz/tooling layer (tools/viz/) is fully decoupled and free to use a normal Python stack.

  • Language: Pure Mojo, targeting Mojo 1.0.0b2 (1.0 beta).
  • Dependencies: Zero external ML libraries in src/ (No PyTorch, No TensorFlow).
  • Execution Loop: No Python fallbacks or dynamic bindings in the core execution or inference passes. Python is isolated strictly to the offline toolchain (data compilation, analysis, visualization).
  • Hardware Utilization: Fast weight updates mandate simd_width_of vectorization and Fused Multiply-Add (FMA) instructions.

Development Environment

Infrastructure is strictly defined via Nix and uv. Mojo is installed from PyPI (the 1.0 beta is a prerelease).

Initialization

nix develop                                          # shellHook bootstraps the steps below
uv venv --python 3.12
source .venv/bin/activate
uv pip install "mojo==1.0.0b2" --prerelease allow
uv pip install numpy

Testing

./esper fast     # quick local gate (~2 min)
./esper suite    # full suite (~10 min; what CI runs)

run_tests.sh generates sample fixtures, runs every tier's tests/test_*.mojo (with -I src), runs the src/main.mojo driver, and finally runs the src/arc_solve.mojo held-out generalization driver over freshly generated .task bundles.

About

Bare-metal neuro-symbolic reasoning engine in Mojo exploring Nested Learning, evolution strategies, ARC-AGI, and beyond

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages