Hyperbolic PolyStep · Explainer 6 · Phase 2

The Browser Core

hyperbolic_core.js is the Python reference ported to JavaScript, function for function. It is trusted because it reproduces the reference’s traces, and this page checks that live, in your browser, every time it loads.

Live parity check Run three channels What is in the core
parity: checking… 7 trace files · 0 dependencies
Contents
  1. Where this sits
  2. Live parity check
  3. How two languages agree
  4. Run three channels
  5. What is in the core
  6. Using it
  7. Limits
01

Where this sits

The core takes the Python reference (through its traces) and the four arithmetic tracks, and feeds the simulation page.

02

Live parity check

This page fetches the reference’s seven trace files and replays every one through the core loaded on this page. Exact fields must match exactly; floats within \(10^{-12}\) relative; Sinkhorn plans within \(10^{-5}\), since both sides stop at a convergence threshold.

Parity in this browser
Loading traces…
Every line of the report
    TraceWhat is replayedMatch
    prng.jsonThe published xoshiro128** vector, splitmix32 seeding, floats (bit for bit), bounded draws, a sample, rationals, an exact Cayley rotationExact
    geometry.jsonGhost map, exp at a point, distance, Klein chart on 12 cases; exact ghost points and boostsExact and \(10^{-12}\)
    step_b1.json24 steps of one channel on a 9-vertex 3-colouring: block, exact rotation, exact corners, costs, snapped states, Helix B; weightsExact and \(10^{-12}\)
    channels_b1.jsonThree channels for two registers with the membrane: 60 zero-point memory words with their SHA-256 chain, both registers’ pump identity, all final exact statesExact
    maxsat.jsonpolystep’s own MAX-SAT generator, rebuilt through a port of Python’s Mersenne Twister, and the shared-generator variantExact
    tree.json40 norm-5 tree words: quaternions, right-division, anchored decodingExact
    sinkhorn.jsonFour Sinkhorn plans from polystep’s solver\(10^{-5}\)
    Does the check catch anything?

    Yes. Each fault below was injected into a copy of the core, and the check failed exactly where it should:

    • a Cayley map with its sign flipped failed 85 of 169 lines;
    • a softmax temperature off by one part in \(10^7\) failed 25 (the snapped states move);
    • one changed character in the memory hash’s format failed 60.

    Rounding halves to even instead of up changed nothing. That is expected: the two rules differ only on an exact tie, and none occurs in these traces.

    03

    How two languages agree

    Python and JavaScript both use IEEE doubles, but agreeing to the last bit, and exactly on every rational, takes a few rules. Both implementations follow them.

    RuleWhy
    Exact to float is correctly rounded. Q.toNumber divides with a 65-bit quotient and a sticky bit, then rounds once.Python’s float(Fraction) rounds once. Dividing two rounded numbers, the obvious way, can be one unit off, and every float the search sees comes from an exact point.
    Float to exact is exact. Q.fromDouble reads the double’s bits.The snap measures its residual against Fraction(float), which is exact.
    Halves round up, floor(x + 1/2): in the snap, the exact step length t and B1’s edge count.Python’s round rounds halves to even; JavaScript’s Math.round rounds them up. The reference was changed to match (Amendment 1).
    One generator, written twice: xoshiro128** with splitmix32 seeding, plus a port of Python’s Mersenne Twister for polystep’s own instance generator.Neither torch’s nor the browser’s generator can be reproduced in the other language.
    Sums run left to right, in the order the reference writes them.Floating-point addition is not associative.
    The traced path avoids transcendental functions. It uses rational step lengths and exact Cayley rotations.exp, cosh and their kin may differ in the last bit between maths libraries. Where they remain (the weights), a tolerance is stated.
    04

    Run three channels

    The core running on its own in this browser: three channels on the zero-point clock attack a planted 3-colouring (B1), with Helix B certifying at every zero point. The settings are untuned, so this shows that the core runs; it is not a benchmark.

    Three channels, B1
    Press run.
    05

    What is in the core

    One file with no dependencies. It loads as window.HPCore in a page and through require in Node. Each part mirrors a Python module.

    PartMirrorsTrackNames
    Exact rationalsfractions.FractionBQ: add sub mul div cmp toNumber fromDouble parse
    Generatorsprng.py, Python’s random—Rng (xoshiro128**), PyRandom (Mersenne Twister)
    Exact geometryexact.pyB, CX.cayley ghost boost pointAt snap displacement pump pumpHolds
    Float geometryhyperbolic.pyAH.lorentz dist expAt logOrigin lorentzCentroid toKlein
    The stepstep.pyA, B, CPolyStepH, stepConfig, softmaxWeights, sinkhornWeights
    Problemsproblems.pyA, BThreeColouring MaxSat TreeAddress HardThresholdNet
    Channelschannels.pyA, BTriChannel, ON, OFF, scheduleFacts, memoryWord (SHA-256)
    06

    Using it

    <script src="hyperbolic_core.js"></script>
    // or in Node: const HPCore = require('./hyperbolic_core.js')
    const { Rng, ThreeColouring, PolyStepH, TriChannel, objective } = HPCore;
    const prob = new ThreeColouring(60, 4.4, new Rng(1000));
    const solvers = [], states = [];
    for (let j = 0; j < 3; j++) {
        const s = new PolyStepH(objective(prob), prob.m, 2, { epsilon: 0.5, stepRadius: 0.6, block: 8 }, new Rng(10 + j));
        states.push(s.initState(prob.initPoints(new Rng(20 + j), 4))); solvers.push(s);
    }
    const tc = new TriChannel(solvers, states, prob, { clutch: 'membrane', mu: 0.3 }).run({ budget: 24000 });
    console.log(tc.memory.at(-1));       // { F, costs, Y, best, hash }
    # the same parity check, in Node, from the Hyperbolic PolyStep folder
    node tests/parity.cjs                # prints each file's count and the total; -v prints every line
    07

    Limits

    What the core does not do
    • No Haar rotations. polystep’s Haar rotations come from torch’s generator and LAPACK, which the browser cannot reproduce. The core uses Cayley rotations from the shared generator, float or exact. The reference offers both.
    • Sinkhorn agrees only approximately (within \(10^{-5}\)). Both sides iterate to a threshold, and the softmax solver is the one traced exactly.
    • B4’s data are not traced. They come from Box–Muller, whose logarithms and cosines may differ in the last bit. The browser’s B4 runs are its own, and benchmark decisions come from the reference.
    • It is not fast. Exact arithmetic is BigInt and the search is plain JavaScript, so it suits the sizes the simulation page shows (tens to hundreds of variables), not the reference’s largest cells.