Skip to content

RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-7: keep, off by default; exact amplification; schedules; the demo; one math path on every build) - #82

Merged
BitmapAsset merged 21 commits into
feat/probbit-persona-cratefrom
research/rfc0011-amplitude-register
Oct 29, 2026

Conversation

@BitmapAsset

@BitmapAsset BitmapAsset commented Oct 27, 2026 •

Copy link
Copy Markdown
Owner

A register of q qubits (q ≤ 16 on the host, q ≤ 12 on a small microcontroller) simulated exactly on a CPU as a state
vector of 2^q complex amplitudes: unitary gates with phase, interference between basis states, measurement by the Born rule,
every step logged so the strand replays byte for byte. It is a simulation of a tiny quantum system and nothing else: no
quantum hardware, no speedup claim, no scaling past what 2^q amplitudes allow (10 qubits 16 KB, 16 qubits 1 MB, 20 qubits
16 MB; a microcontroller with 8 MB of PSRAM reaches about 16; a laptop about 25-28). Sampling a thermal distribution cannot
produce this behaviour (amplitudes carry signs and phases that probabilities do not); the register gets it by paying 2^q
memory and time, which is fine for the programs probbit actually solves (tens of two-valued variables, most of them not
coupled all at once).

Round 2: multi-level traits (draft, research; nothing here is merged or released)

Every recorded persona has three-level traits, so round 1's tier (two-valued variables only) could not answer them. Round 2,
simulated exactly on a CPU:

  • Encoding. A variable with d allowed values takes ⌈log2 d⌉ qubits; a three-level trait takes two (codes 00, 01, 10), its
    fourth code is unused and keeps amplitude exactly 0 (checked after every layer, never renormalised). The start is the
    uniform superposition over the valid codes.
  • Mixer complete-graph: per variable exp(i t (J − I)) on its valid codes, the identity on the unused ones (for two values
    this is exp(i t X), round 1's mixer exactly).
  • Phase layer. One general diagonal layer exp(−iγE), E = −log w per basis state: pair tables between three-level traits
    (3- and 4-body terms in qubits) need no decomposition. Round 1's Walsh transform, its decline and the RZ/RZZ cost layer are gone.
  • Components. The repository's example personas need 52-70 encoded qubits as one register but at most 10-15 in their
    largest connected component, so the tier runs one register per component (exact: the state is the product of the
    components' states); engine.q_max bounds the largest component.
  • Receipt: engine.qubits (encoded), new engine.components, engine.encoding, engine.mixer.
bar measured result
B1 exactness 220 programs mixing two- and three-level variables (20 designed) against an independent mixed-radix reference: max |Δ marginal| per level 2.7e-13 (bar 1e-9); unused-code mass after every layer 0 (bar 1e-15); mixer unitarity 8.9e-16 (bar 1e-12) PASS
B2 replay 100 strands of the tutor example with the tier (60 encoded qubits in 12 components): recorded twice byte-equal, verify on x86_64 and on the no_std build, re-written byte-equal, all 100/100; 0 floats past 6 decimals; the base branch and 0.13.0 exit 5 (unsupported) on 100/100, no false divergence PASS
B3 cost sweep + marginals at q 8/12/16 encoded: 42 µs / 0.82 ms / 16.3 ms (three-level), 97 µs / 2.1 ms / 43 ms (two-valued); the general phase layer 4-6x faster than the RZ/RZZ layer per layer; the whole two-valued sweep at q 12 2.4 % slower than round 1's (it runs the unused-code check); stack 2,016 B at q 8 and 12; silicon not measured PASS
B6 the language every public line swept PASS
flag off the 653-output corpus 0 differ; 726/726 recorded strands verify with documents equal to the base; demo weeks and the dispatch example byte-equal to the base PASS
B4 first pass the corpus's replay set (96 replays, 8,310 programs compared, 0 declined): 96.46 % of 90,456 trait decisions agree with the exact default tier; the differing cases sit where the default tier's own odds are below 0.5 (median 0.417). No verdict: round 3 owns it, and B5 first pass

Gate at 2047655: cargo test --workspace 0 failed; no_std check on xtensa-esp32s3-none-elf for core, ir, decide, persona and persona+decide 5/5; wasm build, 4/4 branches equal to native on three puzzles, boundaries passed. The tier stays off by default: without engine.tier no byte of any stance or strand changes. Simulated exactly on a CPU; no quantum hardware, no speedup claim.

Round 3: the verdict (research; nothing here is merged or released)

Verdict: KEEP as an optional tier (research; off by default), by the registered rule (B4 ≥ 90 %). The RFC's status is now
"accepted as optional tier". No code change in this round; simulated exactly on a CPU.

bar measured result
B4 agreement every program the recorded corpus's 653 outputs solve on the default tiers (replay, live, init, lint, prove, fuzz, the continuation), solved again by the tier at q_max 16: 338,567 exact solves, 0 declined; the level per trait agrees in 2,095,627 of 2,176,371 decisions = 96.29 % (stance path alone 96.52 %, distinct programs 95.94 %; worst traits valence 81.8 %, emoji 86.6 %, arousal 89.7 %); the corpus stays byte-identical with the comparison beside it PASS
B4 where they differ 80,744 cases, each with both odds: where the default tier's own level holds ≥ 0.60, 99.97 % agree; 91 % of the differing cases are where it holds < 0.5 (a plurality, not a majority); 99.1 % sit in components where most of the Born mass already obeys the rules, so not a projection artefact stated
feasible mass the receipt's product is < 1e-2 on 36.7 % of solves, per component on 0.04 % (min 2.6e-04): the product multiplies up to 12 components. A rule-penalty term lifts every component above 7e-03 but drops B4 to 83.44 %: not adopted; the projection stays measured
B5 interference three designed two-path programs, predicted by an independent reference before the engine ran: register vs thermal odds at the node 0.748 vs 1.000, 0.744 vs 0.990, 0.697 vs 0.969 (gaps 0.25-0.27; ≈ 0 when the two paths carry equal energy); engine vs reference 1.4e-14 PASS
B5 bound the bound harness (7 personas, seeds 0-9) with the tier: 0 of 4,100 cases above a certificate computed with the tier (largest ratio 1.000); 1,598 above a certificate computed without it (largest 1.46), so the certificate must be computed with the tier on (docs say so); tightness fails on one fixture with the tier (0.85 < 0.9) PASS (caveat stated)
B6 the language every public line swept PASS

Not verified: silicon cost and replay on a chip. The tier stays off by default: without engine.tier no byte of any stance
or strand changes.

Round 4: exact amplitude amplification in place of the projection (research; nothing here is merged or released)

engine.amplify: true (needs the tier; off by default, so every stance and strand without it is byte-identical to round 3).
Each component's swept state is rotated onto the plans that obey the rules by exact amplitude amplification, simulated exactly
on a CPU: the rules are the oracle, the diffusion is about the stored swept state, k = ⌊π/(4θ) − 1/2⌋ standard iterations
(θ = asin √a₀, a₀ the feasible mass) and one final iteration with matched phases land on the feasible part exactly. Every step
stays in the plane of the swept state's feasible and infeasible parts, so the result is the normalised feasible part: the
projection's distribution, reached by a unitary evolution. The receipt adds engine.amplify (iterations and final phases per
component, mass before and after) and feasible_mass becomes 1.

The invariance prediction: proved, and measured.

bar measured result
B1 invariance 220 programs (200 random mixed two-/three-level + 20 designed, one rule each, a₀ 1.7e-06 to 1, 0-611 iterations): max |Δ marginal| vs the projection 1.1e-12 (bar 1e-9), feasible mass after ≥ 1 − 3.3e-13 (bar 1 − 1e-12) on 220/220, the same plan 220/220. On the recorded corpus (every exact solve run both ways): plans equal on 339,389 / 339,389, max |Δ| 2.1e-13, B4 2,095,627 / 2,176,371 = 96.29 %, round 3's to the decision. A 287-event recorded day of a 52-qubit persona: the same stance line 287/287 (vs the thermal tier still 44 differ, as round 3) PASS
B2 replay 100 lives with amplify (tutor example, 20 events): recorded twice byte-equal 100/100, verify 100/100, no_std build verify 100/100 and re-write byte-equal 100/100, 0 floats past 6 decimals in 2,100 lines and 2,000 documents, feasible_mass 1 on 2,000/2,000; the base engine and the released 0.13.0 exit 5 (unsupported by this engine: engine.tier) on 100/100 PASS
B3 cost the recorded day: 1.19 vs 1.17 ms per event (1.02×, bar 3×); a 16-qubit component at a₀ = 0.022: 17.6 vs 16.7 ms (1.06×, 5 iterations); no_std stack high-water 2,016 B at q 8 and 12 (bar 8 KB) PASS
B6 the language every public line swept (diff, commit messages, this body) PASS (0 hits)
flag off recorded corpus 653 outputs / 0 differ; strands-A 726/726 verify, documents equal to the base engine's 726/726; demo weeks sha-equal to base; dispatch without the flag byte-equal 5/5; amplify: false = absent 20/20; the no_std proxy pair soft = plat PASS
gate cargo test --workspace 0 failed; xtensa no_std check 5/5; wasm build, 4/4 branches equal to native on 3 puzzles, boundaries passed PASS

What it buys: a register that itself holds feasible mass 1 and a receipt that logs how it got there. It does not buy a
different stance; the interference question (where the register decides and the thermal tier averages) is the next rounds'.

Round 5: schedules and the indifferent set (research; nothing here is merged or released)

engine.schedule: <name> (needs the tier; absent = the default sweep, so every stance and strand without it is
byte-identical to round 4): tf-linear-16x4 (default), tf-linear-64x16 (the same transverse-field sweep, four times the
layers), qaoa-p2 (two QAOA layers; angles γ 0.500000 β 0.500000, γ 1.500000 β 0.250000, fixed by a grid search on a held-out
third of the recorded corpus's programs, then frozen). The receipt names the schedule; an unknown name is refused. The register
is simulated exactly on a CPU.

The question: where the thermal tier is indifferent (its top two levels within 0.05), does the register separate them, and
at what cost in agreement elsewhere? Answer: the long sweep does, and it agrees more.

bar measured result
B1 the study recorded corpus: 339,389 exact solves, 130,088 distinct programs, 2,183,612 trait decisions; indifferent 234,004 = 10.72 % (thermal gap median 0.028). On the two thirds the grid did not see, the register's top-two gap: default median 0.048628 (> 0.10 on 9.5 %), long sweep 0.151709 (> 0.10 on 64.6 %, > 0.25 on 16.0 %), qaoa-p2 0.094292; agreement on the non-indifferent decisions 97.58 / 98.17 / 92.99 % (bar 90 %); noise band (two disjoint samples) 0.000697. Choice by the rule: tf-linear-64x16 (margin 0.103 ≈ 150× the band). On the indifferent decisions it takes the thermal plurality 78.5 %, the runner-up 20.1 %, a third level 1.4 % PASS
B2 replay 100 lives per schedule (tutor example + tier + amplify, 20 events, x86_64): recorded, recorded twice byte-equal, verify on the recording build 100/100 each; 0 floats past 6 decimals (2,100 lines, 2,000 documents each); the base engine and the released 0.13.0 exit 5 on 300/300; the key absent = the previous head byte for byte (20/20 lives, the recorded day both lanes). no_std build re-verify: default 100/100, tf-linear-64x16 0/100, qaoa-p2 98/100 (last-bit math differences; over four times the layers a 6-decimal odd flips) FAIL for the two non-default schedules on no_std (PASS for the default)
B3 cost the recorded 287-event day (52-qubit persona, x86_64): default 1.20/1.21 ms per event, long 1.52× / 1.51×, qaoa-p2 0.81× / 0.79×; key absent vs the previous head 1.02× / 1.03× (noise); tutor life long 1.83×, qaoa-p2 0.73×; a lone component (q 8 / 12): long 3.28× / 3.32×, qaoa-p2 0.33× / 0.28×; no_std stack 2,016-2,944 B on every schedule (bar 8 KB) PASS (long ≤ 5×, qaoa-p2 ≤ 2×)
B6 the language every public line swept (diff, commit messages, this body) PASS (0 hits)
flag off key absent: recorded corpus 653 outputs / 0 differ (also through the study's tap); strands-A 726/726 verify, documents equal to the base engine's 726/726; demo weeks sha-equal; dispatch 5/5; proxy pair soft = plat PASS
gate x86_64 node at the code head: cargo test --workspace 1 failure, run_deadline_ms_bounds_the_whole_call (a 900 ms wall-clock test, the named flake of round 3); the arm64 run: 0 failed; xtensa no_std check 5/5; wasm build, 4/4 branches equal to native on 3 puzzles, boundaries passed; CI on the head: see below PASS (named flake)

Found and fixed on the way: with amplification on, the long sweep leaves 165 of the 130,088 programs at a component mass near
5e-5, and after 100+ iterations rounding leaves the landing about 1e-12 short of its bar, which panicked the turn; it now
declines to the default tiers (amplification missed its 1 - 1e-12 landing; 0.12 % of decisions; 0 with the other schedules).

What it buys a decision: a slower sweep keeps more amplitude on the most probable plans, so the register commits where the
thermal answer is a near tie and keeps the thermal choice where there is one. It does not create a preference the weights do
not hold.

Round 6: the demo (research; nothing here is merged or released)

One decision where the thermal tier is a near tie, shown end to end on the recording (std) build, simulated exactly on a CPU.
No engine change in this round: three commits add the demo files and docs.

  • The corpus program, regenerated from the recorded corpus (the tutor fixture, seed 1, script 2, its 58th exact solve):
    a7fae99b114ea2d2, humour thermal playful 0.452774 vs light 0.442258 (gap 0.010516), default sweep gap 0.080846, long
    sweep playful 0.975625 (gap 0.951467), round 5's numbers to 6 decimals. Runner-up 07d909f824f224e4: thermal gap 0.019545,
    long sweep 0.945965 (the register takes the thermal runner-up there).
  • examples/persona/demo/: a fictional tutor reduced to its humour component, praise pulling humour up and criticism (a
    correction) pulling it down; register.yaml (engine: {tier: amplitude, amplify: true, schedule: tf-linear-64x16}) and
    thermal.yaml (no engine block: amplify and schedule need the tier); a 17-event life; both recorded strands; a README.
  • Event 9 (line 10 of both strands, the same program): thermal humour 0.059462 / 0.466563 / 0.473975 (none / light /
    playful; gap 0.007412); the register with the long sweep 0.007171 / 0.249010 / 0.743818 (gap 0.494808); the default sweep,
    for comparison, leans to light by 0.145481. Receipts: schedule_name tf-linear-64x16, amplify iterations [10, 1], mass
    before 0.006196 and after 1, feasible_mass 1, the state digest. Events 2 and 11 are near ties of the same kind; at event 14
    the register is the less decisive face (0.009221 vs thermal 0.072051).
  • The two faces: the Mood Monitor on each strand at event 9 (docs/rfc/0011-demo-thermal.png, 0011-demo-register.png):
    "playful, slightly" at 47.4 % vs "playful, clearly" at 74.4 %, both "replay verified".
  • The sentence: on one recorded decision of a fictional tutor, the default solver's odds for its two leading humour levels
    sit 0.007412 apart; the same program, solved by a qubit register simulated exactly on a CPU, separates them by 0.494808.
    Caveat: the long sweep replays on the recording (std) build only; the default schedule stays for every recorded strand.

Bars (x86_64 node at 677c770):

bar number result
B1 the exhibit a7fae99b114ea2d2 regenerated: 0.010516 / 0.080846 / 0.951467 (thermal / default / long gap), long l2 0.975625; both demo lives verify (17 events); event 9 thermal gap 0.007412 < 0.05, register gap 0.494808 >= 0.4, same program digest PASS
B2 replay both strands re-recorded twice = the committed bytes; branch verify ok; 0 floats past 6 decimals; 0.13.0 on the register strand exit 5 (unsupported by this engine: engine.tier); the thermal strand verifies on 1b29481 and on the 0.13.0 release binary (exit 0); both also re-verify on the no_std proxy (this short life only; round 5's 0/100 stands) PASS
B3 cost microseconds per event (340 events, best of 5): thermal 2,184, register long sweep 1,822 (0.83x the thermal copy), register default sweep 913 (long / default 2.00x); the expected ~1.5x vs the thermal copy is not what this five-variable persona shows (its thermal copy enumerates) PASS (measured, stated)
B6 the law 0 hits on the diff, the three commit messages, the demo files, this PR text PASS
flag off P0 653 / 0 differ; strands-A 726 / 726, documents equal to the base engine's 726 / 726; demo weeks sha-equal to base; dispatch 5 / 5; P0-b proxy pair soft = plat PASS
gate cargo test --workspace 444 passed, 0 failed, 4 ignored; xtensa no_std check 5 / 5; wasm build, 4 / 4 branches equal to native on 3 puzzles, boundaries passed PASS
CI not run: this PR conflicts with its base since the base's CHANGELOG reshape (already at 9570435, before this round), and pull_request workflows do not start on a conflicting PR. Resolving it means bringing the base into this branch, which waits for the 0.14.0 cut not met

Round 7: one math path, the tier replays on every build (research; nothing here is merged or released)

What an optional tier needs, made and measured: the simulated register, exact on a CPU, now evaluates cos, sin, sqrt, asin,
acos, atan2 and floor through the libm crate on the std and the no_std build alike (3481909), and its amplification
renormalises the swept state once before the standard iterations (ac1f76b, with two fixes CI found: f132e5a keeps the receipt's
mass before, 38b63f4 renormalises only when there are iterations and declines on a mass that is not a number). Docs: 1301fce.

schedule (100 fresh lives each, recorded on std, x86_64) verify on the no_std build no_std re-write = std bytes = the round-6 engine's strand
tf-linear-16x4 (default) 100/100 (round 5: 100/100) 100/100 100/100
tf-linear-64x16 100/100 (round 5: 0/100) 100/100 0/100 (moved)
qaoa-p2 100/100 (round 5: 98/100) 100/100 98/100

The default schedule's register strands did not move, and both demo strands re-record byte for byte (event 9: thermal gap
0.007412, register gap 0.494808, as in round 6). The arm64 leg is not measured. 0 floats past 6 decimals.

Round 5's study re-run on this tree (P0 corpus, 130,088 distinct programs, amplify on): 0 programs decline under any schedule
(round 5: 165 under the long sweep), 0 panics; long sweep median top-two gap on the indifferent decisions 0.151709 (round 5:
0.151709), agreement on the others 0.981671 (0.981717; now over the formerly declined decisions too); the default's and
qaoa-p2's rows unchanged to 6 decimals; band 0.000697. Cost per event on a 52-qubit recorded day: long 1.50x the default (round 5:
1.52x), this tree vs the round-6 engine 0.95-1.00x; no_std stack 2,016-2,944 B on every schedule. Tier off: P0 653 outputs / 0
differ, strands-A 726/726, weeks, dispatch 5/5, the proxy pair: byte-identical. Printed as found: that recorded day's
default-schedule register strands moved in the last bits (the tutor's and the demo's did not; no shipped fixture moved).
Gate: CI 20/20 on the code head 38b63f4 (two bugs CI caught on the way are fixed there), xtensa no_std check 5/5. Open before a
merge: the arm64 replay leg, the merge into the moved 0.14.0 branch and the identity re-check on the merged tree.

…d qubit register on a CPU, as an optional solver tier behind a persona flag

probbit-decide::amp (std and no_std + alloc; the state vector on the heap, 16 * 2^q bytes, q <= 16 on the host): gates H, X, Z,
RX, RZ, CNOT, CZ, RZZ; evolve_ising (a Trotterised transverse-field sweep, fixed step count); qaoa; exact marginals; measure (the
Born rule with Philox4x32); digest (sha256 of the state at 6 decimals). run::amplitude: a program whose variables have at most two
allowed values and at most q_max two-valued ones is written exactly as an Ising program (Walsh transform; a term past pairwise
declines), run on the register under the fixed default schedule tf-linear-16x4, and the rules are a projection onto the plans
that obey them. The persona flag engine.tier: amplitude (off when absent; engine.q_max default 12) uses it for the turn's solves;
otherwise the default tiers answer and engine.amplitude says why. Receipt in the stance document: engine.qubits, circuit,
schedule, schedule_name, state, feasible_mass. Without the flag no byte of any stance or strand changes; an engine without the
tier reads a strand that uses it as unsupported by this engine: engine.tier (exit 5). No quantum hardware, no speedup claim.
Docs: docs/rfc/0011-amplitude-register.md (draft, round 1), docs/persona.md 2.7, CHANGELOG (Research).
…th its line endings normalised (a Windows checkout has CRLF, so the flag was never inserted there)
…ster, an exact simulated qubit register on a CPU

A variable with d allowed values takes ceil(log2 d) qubits (a three-level trait two, its fourth code unused and kept at
amplitude 0, checked after every layer, never renormalised). The start is the uniform superposition over the valid codes; the
mixer is the complete-graph mixer per variable (the identity on unused codes; exp(i t X) for two values, round 1's mixer
exactly); the cost is one general diagonal phase layer exp(-i g E), E = -log w per basis state, so pair tables between
three-level traits need no decomposition: round 1's Walsh transform, its residual decline and the RZ/RZZ cost layer are gone
(the general layer measured 4-6x faster per layer). The tier runs one register per connected component of the program (exact:
the state is the product of the components' states); engine.q_max bounds the largest component. Receipt: engine.qubits counts
encoded qubits; new engine.components, engine.encoding, engine.mixer.

Measured: 220 multi-level programs against an independent mixed-radix reference, max |delta marginal| 2.7e-13; 100 tutor
strands with the tier replay byte for byte on x86_64 and the no_std build; an engine without the tier exits 5. Off by default:
every recorded corpus is byte-identical. Simulated exactly on a CPU; no quantum hardware, no speedup claim.
@BitmapAsset BitmapAsset changed the title RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, round 1) RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-2) Oct 27, 2026
… as an optional tier, an exact simulated qubit register on a CPU

Measured on every program the recorded corpus's 653 outputs solve on the default tiers (338,567 exact
solves, 0 declined, the corpus byte-identical with the comparison running beside it): the exact simulated
register picks the same level as the exact default tier in 2,095,627 of 2,176,371 trait decisions
(96.29 %, registered bar 90 %). The differing cases sit where the default tier's own level holds less than
half the mass (91 % of them), and 99.1 % of them in components where most of the Born mass already obeys
the rules, so they are not an artefact of the projection.

B5: three designed two-path programs differ from the thermal odds by 0.252, 0.246 and 0.272 at the node
(engine vs an independent reference within 1.4e-14). The bound harness with the tier on: 0 of 4,100
cases above a certificate computed with the tier, 1,598 above one computed without it, so the
certificate must be computed with the tier (docs/persona.md).

A rule-penalty term was measured and not adopted: it lifts the feasible mass but drops agreement to
83.44 %. No code change in this round; the tier stays off by default, so no recorded document moves.
Simulated exactly on a CPU; no quantum hardware, no speedup claim.
@BitmapAsset BitmapAsset changed the title RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-2) RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-3: keep, off by default) Oct 27, 2026
…f the projection, an exact simulated qubit register on a CPU

probbit-decide::amp: Register::oracle (a phase on the plans marked good) and Register::diffuse (the diffusion about a stored
state), logged as `oracle <phi>` / `diffuse <phi>` ops; amplify_exact(register, good): with the good mass a0 and
theta = asin(sqrt(a0)), k = floor(pi / (4 theta) - 1/2) standard iterations and one phase-matched final iteration land the
register on its normalised good part exactly (mass after asserted >= 1 - 1e-12). Every step stays in the plane of the good
and bad parts of the swept state, so the Born probabilities on the feasible plans are the projection's.

probbit-persona: `engine.amplify: true` (needs `tier: amplitude`; default false, so every stance and strand without it is
byte-identical to round 3): run::amplitude rotates each component's register instead of projecting, reads plan and
marginals from its Born probabilities, and the receipt adds `engine.amplify` (iterations and the final phases per component,
the mass before and after; `feasible_mass` is the mass after). probbit-nostd: asin, acos, atan2 for the no_std build.
Tests: amplification equals the projection to 1e-12 on 18 rules; the tutor example with amplify gives the projection's
stances, logs the amplification, verifies its strand; amplify without the tier is refused.
… numbers, an exact simulated qubit register on a CPU

docs/rfc/0011-amplitude-register.md: the amplification design bullet and section 5 "Amplification (round 4)": why exact
amplification lands on the projection's distribution (every step stays in the plane of the swept state's feasible and
infeasible parts; the matched final step lands on the feasible part), measured: marginals equal to 1.1e-12 on 220 programs,
the same plan on 220/220 and on all 339,389 solves of the recorded corpus (B4 unchanged, 96.29 %), 287/287 stance lines on a
recorded day, cost 1.02x, no_std stack 2,016 B, 100 lives replay byte for byte. docs/persona.md: the `engine.amplify` key.
CHANGELOG Research entry. Simulated exactly on a CPU; no quantum hardware, no speedup claim.
…s simulated on a CPU

The engine.amplify sentence now names it as what it is: exact amplitude amplification of a simulated qubit register, run on a
CPU. Docs only.
@BitmapAsset BitmapAsset changed the title RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-3: keep, off by default) RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-4: keep, off by default; exact amplification) Oct 28, 2026
…n, an exact simulated qubit register on a CPU

probbit-decide::amp: `Evolution` (a transverse-field sweep or QAOA layers) with `named`, `run`, `text`, `name`; three names
in SCHEDULE_NAMES: tf-linear-16x4 (DEFAULT_SCHEDULE, unchanged), tf-linear-64x16 (LONG_SCHEDULE: 4x the steps and the time,
about 4x the layers) and qaoa-p2 (QAOA_P2: two layers, gamma 0.500000 beta 0.500000, gamma 1.500000 beta 0.250000, fixed by a
grid search on a held-out third of the recorded corpus's programs, then frozen). A sweep's schedule text and name are
Schedule's, so the default's receipt is unchanged.

probbit-persona: `engine.schedule: <name>` (needs `tier: amplitude`; an unknown name is refused like every other bad key);
absent or `tf-linear-16x4` = the default sweep, byte for byte; run::amplitude_with(prog, q_max, amplify, evolution), and
run::amplitude is it with the default. The receipt's `schedule` digest and `schedule_name` name the evolution.
Tests: the named evolutions run what they name; the default name equals the absent key; the other two name themselves in the
receipt, keep feasible mass 1 with amplify and their strands verify; an unknown name and the key without the tier are refused.
…instead of panicking, simulated exactly on a CPU

amp::amplify_exact returned its result after asserting the mass after >= 1 - 1e-12; with the long sweep (tf-linear-64x16) a
few components of the recorded corpus's programs reach a tiny feasible mass (a0 ~ 5e-5) and 100+ iterations, where rounding
drift leaves the mass after about 1e-12 short and the assert panicked a persona turn (165 of 130,088 distinct programs in the
round-5 study; 0 with the default schedule and 0 with qaoa-p2). It now returns None there, and the tier declines to the
default tiers with `component <c>: amplification missed its 1 - 1e-12 landing` in the receipt (a component with no feasible
weight keeps its old message). Nothing changes where the landing meets the bar, which is every solve of round 4.
… an exact simulated qubit register on a CPU

docs/rfc/0011-amplitude-register.md, "Schedules and the indifferent set": on the recorded corpus the thermal tier is
indifferent (top two levels within 0.05) on 10.72 % of 2,183,612 trait decisions; there the simulated register's top-two gap
has median 0.048628 with the default sweep, 0.151709 with tf-linear-64x16 and 0.094292 with qaoa-p2 (measured on the two
thirds of programs the angle search did not see; noise 0.000697), and agreement on the other decisions is 97.58 / 98.17 /
92.99 %. The registered rule picks the long sweep; the default stays tf-linear-16x4. What it buys and what it does not, the
cost (1.5x per event on a recorded day), the missed-landing decline, and an arm64 replay note. docs/persona.md: the
`engine.schedule` key. CHANGELOG: Research entry.
…chedules fails and says so, simulated exactly on a CPU

Measured on x86_64: the no_std build re-verifies 100 lives of the default schedule 100/100, of tf-linear-64x16 0/100 and of
qaoa-p2 98/100 (the recording build verifies all 300, an engine without the tier exits 5 on all). The platform's math
functions and the no_std library differ in the last bits and over four times the layers a 6-decimal odd flips. The RFC,
docs/persona.md and the CHANGELOG entry now state it: the long sweep is the study's answer, not yet a schedule to record
strands with. On arm64 the default fails the same way on round 4's own path (not new).
@BitmapAsset BitmapAsset changed the title RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-4: keep, off by default; exact amplification) RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-5: keep, off by default; exact amplification; schedules) Oct 28, 2026
… humour component, simulated exactly on a CPU

examples/persona/demo/register.yaml: a fictional tutor reduced to the humour component (warmth, humour, formality, emoji,
the valence mood, their couplings and the two habits that bind them) and the two opposed drives that pull humour: praise
raises it, criticism (a correction) lowers it. engine: {tier: amplitude, amplify: true, schedule: tf-linear-64x16}: each
turn is solved by an exact simulated qubit register on a CPU with the long sweep and exact amplification. No names, no ids.

examples/persona/demo/thermal.yaml: the same persona on the default tiers (the thermal face). The engine block is absent as a
whole: engine.amplify and engine.schedule need engine.tier (a persona error, exit 2, without it), so removing the tier
removes all three. Every engine since 0.13.0 runs this copy.

README.md: the decision the demo shows (event 9: thermal top-two gap 0.007412, register gap 0.494808 on the same program),
how to record and check the lives, the receipts, and the caveat: the long sweep replays on the recording (std) build only
for now; the default schedule stays the one for every recorded strand. Simulated, exact, on a CPU; no quantum hardware.
…ter strands, simulated exactly on a CPU

examples/persona/demo/life.jsonl: 17 events (seed 1, fixed clock): a run of corrections, then at event 9 praise and a
correction together, then praise, and corrections again. thermal.strand and register.strand: the life recorded on each
copy; both verify (live verify ok, 17 events), record twice byte for byte, and carry 0 floats past 6 decimals. Event 9 is
line 10 of both strands; the two documents solve the same program (the same program digest).

Event 9, humour (none / light / playful): thermal 0.059462 / 0.466563 / 0.473975 (top-two gap 0.007412, a near tie);
the register, an exact simulated qubit register on a CPU with the long sweep, 0.007171 / 0.249010 / 0.743818 (gap 0.494808).
Receipts of that document: tier amplitude, schedule_name tf-linear-64x16, amplify iterations [10, 1] with mass before
0.006196 and after 1, feasible_mass 1, the state digest of the final amplitudes at 6 decimals. 0.13.0 refuses the register
strand (unsupported by this engine: engine.tier) and verifies the thermal one. Simulated, exact, on a CPU.
…es, an exact simulated qubit register on a CPU

docs/rfc/0011-amplitude-register.md, section 5 "The demo": the corpus program a7fae99b114ea2d2 regenerated (thermal humour
gap 0.010516, default sweep 0.080846, long sweep 0.951467) and the runner-up 07d909f824f224e4 (long sweep 0.945965, the
thermal runner-up taken); the demo persona and its 17-event life; event 9 on both strands (thermal gap 0.007412, register
gap 0.494808, default sweep 0.145481 for comparison) with the register document's receipts; the Mood Monitor's two faces at
that event (0011-demo-thermal.png, 0011-demo-register.png: "playful, slightly" at 47.4 % vs "playful, clearly" at 74.4 %);
one sentence for the launch pack and its caveat (recording build only; the default schedule stays for every recorded
strand); the cost on x86_64 (thermal 2,184, register long 1,822, register default 913 microseconds per event).
CHANGELOG Research: round 6. No engine change. Simulated, exact, on a CPU; no quantum hardware, no speedup claim.
@BitmapAsset BitmapAsset changed the title RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-5: keep, off by default; exact amplification; schedules) RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-6: keep, off by default; exact amplification; schedules; the demo) Oct 29, 2026
…) into research/rfc0011-amplitude-register: the Research bullets kept verbatim under the reshaped Unreleased; no code change in the resolution
… on every build

The amplitude register, an exact simulation on a CPU, now evaluates every function past + - * / (cos, sin, sqrt, asin,
acos, atan2, floor) through the libm crate on the std and the no_std build alike: pure Rust, the same code and evaluation
order on every target, no platform math library, no fused multiply-add. Round 5 measured the cost of two libraries: strands
recorded with the long sweep re-verified 0/100 on the no_std build (qaoa-p2 98/100) because the platform's cos/sin and
libm's differ in the last bits and over four times the layers a 6-decimal odd flips. libm becomes a direct dependency of
probbit-decide (already in the lock through probbit-nostd, 0.2.16). Tier off: no code path changes.
…ands on the long sweep too

amplify_exact renormalises the swept state once before the iterations (its squared norm summed with Neumaier's
compensation). The diffusion about a state of squared norm 1 + eps is not unitary: |D v|^2 = |v|^2 + 4 eps |<psi|v>|^2, so
the error grows with every iteration, linearly in their number. The long sweep's four times the layers leave a larger eps,
and at a tiny good mass (hundreds of iterations) that left 165 corpus programs about 1e-12 short of the landing's bar
(round 5: they declined to the default tiers). A rotation in the 2-D plane would hide the cause; renormalising removes it
and keeps every iteration the same unitary step. Test: a state of squared norm 1 + 1e-12 and one good state of 2^14
(100 iterations) lands within 1e-12 of mass 1. Exact, simulated on a CPU; tier off: no code path changes.
…t state's

The previous commit reported the renormalised state's good mass as the amplification's mass before; it differs from the
swept state's in the last bits, which the unit test exact_amplification_lands_on_the_projection caught (1e-15 bar, CI on
ubuntu and macOS). The receipt keeps the swept state's mass, as since round 4; the rotation's angle uses the renormalised
state's. Exact, simulated on a CPU; tier off: no code path changes.
…ons; a non-finite mass declines

CI on the previous head (persona tests amplify_lands_on_the_projection_and_logs_it and the_schedule_key_names_the_evolution,
macOS) found the renormalisation's edge: a component whose plans are all feasible has a good mass a hair under 1, and after
renormalising its naive sum can round above 1, so asin(sqrt) is NaN and the turn panicked reading the plan. The swept state is
now renormalised only when there are standard iterations to drift over (k >= 1, so the good mass is at most 1/4); with none,
the one matched step is round 4's, unchanged. A mass after that is not a number now declines to the default tiers like a
missed landing, never a panic. Exact, simulated on a CPU; tier off: no code path changes.
…the std and the no_std build

The RFC gains "One math path (round 7)": 100 fresh lives per schedule recorded on the std build re-verify on the no_std build
100/100 for tf-linear-16x4, tf-linear-64x16 (round 5: 0/100) and qaoa-p2 (98/100) on x86_64, the default schedule's strands
byte-identical to the round-6 engine's, both demo strands re-recorded byte for byte, arm64 not measured; and the missed
landing's cause and fix. docs/persona.md's engine.schedule paragraph and the demo README replace "recording build only" with
that measured result; docs/persona.md section 5.8 now says the stance digest is the sha256 of /doc/N's JSON without the
trailing newline (checked on both demo strands). CHANGELOG Research: one bullet per item. Exact, simulated on a CPU.
@BitmapAsset BitmapAsset changed the title RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-6: keep, off by default; exact amplification; schedules; the demo) RFC 0011: amplitude register, an exact simulated qubit register as an optional solver tier (research, rounds 1-7: keep, off by default; exact amplification; schedules; the demo; one math path on every build) Oct 29, 2026
…ay result does not cover

The simulated register, exact on a CPU: round 5's study re-run on this tree declines 0 programs under any schedule (round 5:
165 under the long sweep); the long sweep's median gap 0.151709 and agreement 0.981671; cost 1.50x the default per event on a
52-qubit recorded day; no_std stack at most 2,944 B. The previous docs commit said the default schedule's strands are
byte-identical to before: true for the tutor lives and the demo, not for every persona (that recorded day's default strands
moved in the last bits). persona.md, the RFC and the CHANGELOG now say which.
@BitmapAsset
BitmapAsset marked this pull request as ready for review October 29, 2026 12:00
@BitmapAsset
BitmapAsset merged commit de7c630 into feat/probbit-persona-crate Oct 29, 2026
20 checks passed
@BitmapAsset
BitmapAsset deleted the research/rfc0011-amplitude-register branch October 29, 2026 12:03
@BitmapAsset
BitmapAsset restored the research/rfc0011-amplitude-register branch October 29, 2026 12:04
BitmapAsset added a commit that referenced this pull request Oct 31, 2026
…y crate (std + no_std) (#78)

The 0.14.0 development line. probbit-persona becomes a library crate (features std and nostd; no_std + alloc checked on xtensa-esp32s3-none-elf) that probbit-cli uses unchanged; setup, the turn and resume return boxed values (one event's stack high-water on the host proxy 31,824 -> 13,808 B); strands resume from a checkpoint and seal into segments. The expectation keeps an exact cache. The self layer (RFCs 0013-0016: reflection, integrity, the rest pass, curiosity), each part opt-in and recomputed by probbit live verify. A simulated amplitude register as an optional tier (RFC 0011, #82), off by default. A persona that declares none of the new keys gets byte-for-byte 0.13.0 output (P0 corpus 653 recorded outputs, 0 differ). The individual commits stay on refs/pull/78/head.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant