Skip to content
← Writing

Why I rewrote RIES in Rust

Essay

Bringing Robert Munafo’s solver to the command line, Python, and the browser.

Give RIES 2.506628274631 and it returns √(2π) — or rather, it finds that equation among the candidates, ranks it, and shows its work. I liked Robert Munafo’s original solver enough to rewrite it in Rust.

I started ries-rs because I wanted that search in the tools I use: the command line, Python, and the browser. I also wanted runs I could repeat and output other programs could read. The original is a C program with terminal output — fine for trying a number, awkward for everything after.

What stayed the same

The search model is unchanged. The solver enumerates valid postfix expressions up to a complexity limit. Some of those expressions contain x; those become candidate left-hand sides. Others are constant-only expressions; those become candidate right-hand sides. The search then tries to solve equations of the form LHS(x) = RHS numerically and ranks the matches it finds.

The search is bounded by the chosen complexity limit and available symbols. A numerical match gives you a candidate relation to investigate; it does not prove an identity.

What Rust changed

The rewrite separates expression generation, matching, and ranking into modules, which made two other things practical: Python bindings and a WebAssembly build from the same engine. Native builds can spread generation across cores.

For scripting, searches print structured JSON and record run manifests, so a script can inspect results without scraping terminal formatting. Deterministic mode fixes the result ordering, so two runs can be compared directly.

Parallel generation only helped searches dominated by generating expressions. For searches dominated by matching and refinement it did almost nothing — which is what sent me to the profiler. The performance follow-up describes the ranking bug that turned up there, and the separate turbo mode for parallel matching.

Why the browser build mattered

The browser version runs the solver locally, compiled to WebAssembly. A reader can enter a number and try a search immediately, without installing the command-line tool.

That made it practical to put a number form on the project page and open the solver with the target already filled in. Shared URLs can carry the search settings too.

The browser build also surfaced every packaging detail: asset paths have to work below the site’s project URL, the interface has to wait for WebAssembly initialization, and its runtime dependencies have to be vendored. The browser uses the sequential solver; native turbo mode is a different execution path.

You can explore the project on the project page, try the live demo, or browse the source on GitHub.

Related Project

View all →