HHL rotation angle

The HHL rotation angle θ = arcsin(1/(2x)), approximated piece by piece. The discovered circuit chooses pieces that the input's own bits can name, so it can afford 345 pieces instead of 35, and each piece needs less arithmetic.

In brief

The baseline (Häner et al., 2018) fits a cubic on each of 35 intervals and finds the interval by comparing x with every boundary.

The discovered circuit puts piece boundaries on powers of two. A walk down a binary tree of the leading bits of x finds the piece, at about one Toffoli per piece. Cheap pieces mean many short pieces, packed where the curve bends. On short pieces a quadratic is accurate enough, and its products stay narrow.

TQ = 2·10⁵TQ = 5·10⁵TQ = 10⁶TQ = 2·10⁶2003001,0003,00010⁴peak qubits Q →Toffoli count T →Discovered circuitHäner et al. (2018)Live qubits as Toffolis execute16k1.3k300115
Narrow coordinates make the products small in gates and in width.
1

The leaf table and the registers

init

The input is a 21-bit integer X with x = X/216 ∈ [1, 32). The circuit adds the angle round(232 arcsin(215/X)) to a 33-bit accumulator k and leaves X unchanged (the two registers). The error must stay within 429 output units, below 10−7 radians, on every input.

The domain is cut into 345 pieces, called leaves. Each leaf is a dyadic interval [L, L + 2b) with L a multiple of 2b, and its width runs from 28 to 215. The table LSET maps each leaf to four integers: intercept g0, slope g1, curvature g2, and a rotation amount sh.

tree_from_leafset rebuilds the binary tree over the bits of X: a node splits on one bit until it reaches a stored leaf. One subtree per octave covers 216 to 221. Leaves are narrow near x = 1, where the curve bends, and wide where it is flat. A uniform partition at the finest width would need 7,936 pieces.

1248163200.5θ (radians)x = X / 2¹⁶ (log scale) →121 leaves86544737
The 345 table leaves under the angle curve, one subtree per octave.
LSET = {
(int(lo), int(bb)): (int(g0), int(g1), int(g2), int(sh))
for lo, bb, g0, g1, g2, sh in zip(
TAB["lo"], TAB["bb"], TAB["g0"], TAB["g1"], TAB["g2"], TAB["sh"]
)
}
def tree_from_leafset(lset):
def go(lo, bb):
if (lo, bb) in lset:
return Leaf(lo, bb, lset[(lo, bb)])
assert bb > 7, "frozen table is not a dyadic partition"
h = 1 << (bb - 1)
return Node(bb - 1, go(lo, bb - 1), go(lo + h, bb - 1))
Ts = [go(1 << (16 + e), 16 + e) for e in range(5)]
return Node(20, Node(19, Node(18, Node(17, Ts[0], Ts[1]), Ts[2]), Ts[3]), Ts[4])
def collect(nd, out=None):
if out is None:
out = []
if isinstance(nd, Leaf):
out.append(nd)
else:
collect(nd.left, out)
collect(nd.right, out)
return out
ROOT = tree_from_leafset(LSET)
LEAVES = collect(ROOT)
# ---------------------------------------------------------------------------
# Builder-native measurement-based erasure: b.hmr(w) demolishes a wire into
# an Outcome handle and b.cz(a, c, cond=m) hosts the deferred phase fixup.
# The Booth rows' [GID]-prefix dial reads the *current* live count against
# the frozen live-qubit cap through b.active_qubits. That accounting is
# load-bearing: the prefix schedule is part of the certified stream, so
# any change to what counts as live moves the emitted bytes.
# ---------------------------------------------------------------------------
def build(): # noqa: C901, PLR0915 - straight-line circuit emitter
"""Build the discovered circuit on a fresh Builder; return (b, regs).
Circuit helpers are closures over ``b``. Registers come first, so
Builder qubit ids 0..53 are the persistent I/O wires. build() is
also the entry point of tools/occupancy_profile.py, which replays
the ownership wire-set log fail-closed and charts the occupancy.
"""
b = Builder()
_r = declare_registers(b, [("X", 21), ("k", 33)]) # |X> preserved; |k> acc
XQ, KQ = _r["X"], _r["k"]
b.claim("X", XQ)
b.claim("k", KQ)
2

Look up the leaf's coefficients

lookup

A dyadic leaf of width 2b is fixed by the leading 21 − b bits of X. The circuit therefore finds the leaf by walking the tree, with no comparison against an arbitrary boundary. At each leaf, visit1 writes the set bits of the four stored words with CNOTs controlled by the leaf's flag. Table width therefore adds no Toffolis.

The words are a 26-bit intercept, a 16-bit biased slope, a five-bit curvature, and a three-bit rotation amount. The walk visits the octaves in order. The lookup costs 343 Toffolis, about one per leaf.

_oct = None
# The open lookup/oct{o} phase block: an octave's phase runs from its
# first leaf to the next octave's first leaf, walk ANDs included.
octave = contextlib.ExitStack()
def visit1(ctrl, lf):
nonlocal _oct
o = lf.lo.bit_length() - 17
if o != _oct:
_oct = o
octave.close()
octave.enter_context(b.phase(f"lookup/oct{o}"))
for w, i in leaf_bits(lf):
bank, nm = ((g2q, "g2"), (shq, "shift"), (wsl, "wslope"), (c0q, "intercept"))[w]
b.cx(ctrl, _mat(bank, nm, i))
Tree lookup 343 Toffolis · peak 115 qubits
with b.phase("lookup/setup"), octave:
walk(visit1)
assert all(q is not None for bank in (g2q, shq, wsl, c0q) for q in bank), (
"coefficient bit never written by any leaf"
3

The tree walk

walk, leaf_bits

The walk is unary iteration. The top split uses the input bit itself: an X gate on the bit selects the left child and a second X selects the right one. Every other internal node computes one temporary AND of its parent flag and its bit. One CNOT repoints that AND from the left child to the right one, and the release erases it by measurement. A tree with 345 leaves has 344 internal nodes, so the walk costs 343 Toffolis.

leaf_bits lists the set bits of a leaf's words, in a fixed order. The lookup writes these bits, and the final phase repair reads the same list, so the two stay in step. A coefficient wire comes into existence at the first leaf that sets its bit.

The same function runs the phase repair at the end. With floor set, the walk stops descending below that tree level, and every leaf beneath fires with the node's own flag.

def leaf_bits(lf):
"""Return the 1-bits of a leaf's four stored words, as (word, bit) pairs
in emission order: g2, sh, W >> GUARD, g0 >> C0D. The single
source for the lookup writes (visit1) and the fixup kick list
(leaf_mbs) — the two sides must stay in exact lockstep or the
fixup mis-repairs the demolition kickback.
"""
g0, g1, g2, sh = lf.coef
# stored slope word: W >> GUARD = g1 + (BIAS >> GUARD)
for w, (word, width) in enumerate(
((g2, G2W), (sh, 3), (g1 + (BIAS >> GUARD), G1W), (g0 >> C0D, C0W))
):
for i in range(width):
if (word >> i) & 1:
yield w, i
⋯ 15 lines
def _mat(bank, name, i):
if bank[i] is None:
bank[i] = b.qubit()
b.claim(name, [bank[i]])
return bank[i]
⋯ 1 line
def walk(visit, floor=-1):
"""Unary-iteration tree walk: ``visit(ctrl, leaf)`` fires once per
leaf, with ``ctrl`` the wire that is 1 exactly on the leaf's X range
(None above the uncontrolled top split). One temporary AND per
internal node; the CX(ctrl, a) sibling flip reuses each AND for both
children. Internal nodes below tree level ``floor`` are not
descended: every leaf beneath fires with the node's own control (the
fixup hands those leaves to the one-hot bank); floor=-1 descends
everywhere. Runs both the lookup (stage 1) and the fixup re-walk
(stage 9).
local: gadgets.qrom.pruned_walk expresses the same adaptive depth
(uniform=) at the same 1 Toffoli + 1 AND per node, but visits the
right child first and re-points each AND with 2 CX per node; this
walk is left-first with the 1-CX sibling flip, and its visit order
is the certified stream's.
"""
def go(nd, ctrl):
if isinstance(nd, Leaf):
visit(ctrl, nd)
return
if nd.bit < floor:
for lf in collect(nd):
visit(ctrl, lf)
return
bq = XQ[nd.bit]
if ctrl is None:
b.x(bq)
go(nd.left, bq)
b.x(bq)
go(nd.right, bq)
else:
a = b.and_compute(ctrl, bq, pol=(True, False))
go(nd.left, a)
b.cx(ctrl, a)
go(nd.right, a)
b.and_release(a, ctrl, bq)
go(ROOT, None)
4

Rotate the input into a shared coordinate

rotate

Every leaf feeds the same arithmetic, but leaves have different widths. Write X = L + δ with 0 ≤ δ < 2b. The table stores sh = 15 − b, and the circuit rotates the low 15 bits of X cyclically left by sh. The three bits of sh control rotations by 1, 2, and 4 places.

The varying bits of δ move to the top of the word. The bits that the leaf fixes wrap around to the bottom and form a constant cL, so the coordinate is dn = 215−bδ + cL. The offline fit absorbs cL into the coefficients, so no subtraction is needed. The coordinate lives on the X wires themselves; dqb names dn ≫ 3 there.

140bit of X00110011001100δ (b = 8)δX = L + δrotate left by 7dn = 27δ + cL001100δ (b = 12)δX = L + δrotate left by 3dn = 23δ + cL
The low 15 bits of X for a narrow leaf (b = 8) and a wide one (b = 12). Rotating left by 15 − b puts the varying bits δ at the top for every leaf width, so all leaves share one coordinate.
# ---- 2. rotate: align the leaf's varying bits into the coordinate dn ----
Rotate 42 Toffolis · peak 104 qubits
with b.phase("rotate/s1"):
crotl(shq[0], 1)
with b.phase("rotate/s2"):
crotl(shq[1], 2)
with b.phase("rotate/s4"):
crotl(shq[2], 4)
dqb = [XQ[TAU + t] for t in range(NDQ)] # dq = dn >> 3, on the X wires
5

One controlled rotation

crotl

A cyclic rotation is a permutation of qubits, so under a control it is a sequence of controlled swaps. The amounts 1, 2, and 4 are coprime to 15, so each rotation is one 15-cycle. The cycle needs 14 Fredkin gates, one Toffoli each.

The rotation allocates no register. The three forward rotations cost 42 Toffolis, and the three inverse rotations at the end cost another 42 and restore X exactly.

def crotl(ctrl, amt):
"""Rotate X[0..14] left by ``amt`` under ``ctrl``, as disjoint swap
cycles of Fredkins (Builder.cswap, 1 Toffoli per swapped pair; its
first swap operand is the CX pivot, and the operand order is
load-bearing — swapping it is semantically equal but moves the
certified stream): 14 Toffoli per rotation (gcd(15, amt) = 1,
asserted — one 15-cycle, 14 swapped pairs).
"""
n = NDN
amt = amt % n
if amt == 0:
return
assert math.gcd(n, amt) == 1
seen = [False] * n
for s in range(n):
if seen[s]:
continue
cyc = []
i = s
while not seen[i]:
seen[i] = True
cyc.append(i)
i = (i + amt) % n
for j in range(len(cyc) - 1, 0, -1):
b.cswap(ctrl, XQ[cyc[j - 1]], XQ[cyc[j]])
6

Add the intercept, then measure it away

c0add

The circuit evaluates each leaf's quadratic in nested form, g0 − dn(g1 − g2dn), with the intercept and the outer product accumulated into k. The intercept goes first: an in-place addition of the stored 26-bit word at bit 6 of k. Its lowest 11 carry positions use temporary ANDs that are erased by measurement; the higher positions use the majority/unmajority ripple of Cuccaro et al. This addition costs 41 Toffolis.

The intercept word is not needed again. demolish measures each wire in the X basis and frees it. An outcome of 1 leaves a sign that depends on the leaf. The circuit keeps the outcomes in mb_c0 and repairs those signs at the end, together with the signs of the other three words.

def demolish(rset, qs):
"""Demolish a coefficient word, top bit down: hmr + release + free
per wire. Returns the X-measurement bits, indexed like ``qs`` —
the fixup's kick list (leaf_mbs).
"""
mb = [None] * len(qs)
for i in range(len(qs) - 1, -1, -1):
mb[i] = b.hmr(qs[i])
b.release_recycle(rset, [qs[i]])
return mb
# ---- 3. c0add: k += g0; demolish the intercept word ----
# Gidney form with the carry chain truncated to gl=C0GL live AND
# wires; the prefix length is a searched dial (gen_constants.py). No
# carry-in wire exists in this form.
Add intercept 41 Toffolis · peak 115 qubits
with b.phase("c0add/add"):
add(b, KQ[C0D : C0D + len(c0q)], c0q, gl=C0GL, cout=KQ[C0D + len(c0q)])
with b.phase("c0add/c0erase"):
mb_c0 = demolish("intercept", c0q)
7

Signed digits, and the inner step

vcompute

Both products use signed radix-4 (Booth) digits. For the product, the multiplier is Y = dn ≫ 2, a 13-bit integer, and digit t is dt = y2t−1 + y2t − 2y2t+1 ∈ {−2, …, 2}. The sum Σ dt4t equals Y exactly, so seven rows replace thirteen. The five-bit curvature word becomes three digit rows over dn ≫ 3. prod_row_spec and q_row_spec name each digit's source wires; prod_pairs and q_pairs list the operand bits of each column.

The inner step forms v = W − Q(dn, g2) over the slope word, where W = (g1 ≪ 4) + 216. Four fresh guard wires sit below the stored slope word. Complementing the low 17 bits before and after the rows turns the signed additions into a subtraction.

Signed partial sums need not move monotonically, so a safe final value says nothing about the prefixes. An exhaustive check confirms that after every row, for every input, the window stays in [0, 217). No carry crosses bit 16, so each row's chain is 17 bits wide. The rows run highest digit first.

# ---- Booth digit row tables --------------------------------------------
# Product digits t = 0..6 recode Y = dn >> 2 (Y bits y_j live on
# XQ[j + J0]): d_t = y_{2t-1} + y_{2t} - 2 y_{2t+1}, boundary bits
# zero. After the in-place CXs, s1w holds the |d|=1 selector
# y_{2t-1} ^ y_{2t}, m1w holds y_{2t} ^ y_{2t+1}, and the untouched
# high source wire y_{2t+1} is the sign. The boundary rows carry no
# recode CX (t=0) and no sign (t=6: d_6 = y_11 + y_12 >= 0).
def prod_row_spec(t):
lo, mid, hi = XQ[2 * t + 1], XQ[2 * t + 2], XQ[2 * t + 3] if 2 * t + 3 <= NDN - 1 else None
if t == 0:
return [], mid, hi, hi
if hi is None:
return [(mid, lo)], lo, mid, None
return [(mid, lo), (hi, mid)], lo, mid, hi
def prod_pairs(t):
sig = SIG[t]
out = []
for c in range(VW - sig + 1):
va = vq[sig + c] if sig + c <= VW - 1 else None
vb = vq[sig - 1 + c]
out.append((va, vb))
return out
# Curvature digits s = 0..2 recode g2 (5 bits, VORD emission order):
# e_s = g2_{2s-1} + g2_{2s} - 2 g2_{2s+1}, boundary bits zero; row s
# adds e_s (dq << 2s) >> RQ into the 17-bit window, the |e|=2
# candidate one dq bit deeper.
def q_row_spec(s):
if s == 0:
return [], g2q[0], g2q[1], g2q[1]
if s == 2:
return [(g2q[4], g2q[3])], g2q[3], g2q[4], None
return [(g2q[2], g2q[1]), (g2q[3], g2q[2])], g2q[1], g2q[2], g2q[3]
def q_pairs(s):
out = []
for c in range(NDQ - RQ + 2 * s + 1):
ia, ib = c + RQ - 2 * s, c + RQ - 2 * s - 1
va = dqb[ia] if 0 <= ia <= NDQ - 1 else None
vb = dqb[ib] if 0 <= ib <= NDQ - 1 else None
out.append((va, vb))
return out
# ---- 4. vcompute: v = W - Q(dn) inside the 17-bit bias window ----
# The X sandwich turns the signed digit rows into a two's-complement
# subtract; the per-prefix window invariant (certified, frozen VORD
# order) guarantees no carry ever crosses bit 16, so only
# tgtv = vq[:17] is conjugated and every row chain is 17 bits wide.
Inner step 113 Toffolis · peak 112 qubits
with b.phase("vcompute/setup"):
guards = [b.qubit() for _ in range(GUARD)]
b.claim("guard", guards)
vq = list(guards) + list(wsl)
tgtv = vq[: QCAP + 1]
for q in tgtv:
b.x(q)
for s in VORD:
with b.phase(f"vcompute/s{s}"):
cxs, s1w, m1w, signw = q_row_spec(s)
brow(cxs, s1w, m1w, signw, q_pairs(s), tgtv, None)
with b.phase("vcompute/close"):
for q in tgtv:
b.x(q)
8

One Booth digit row

brow, row_gl

CNOTs recode the digit's three source wires in place and allocate nothing. Afterwards s1w marks |d| = 1, m1w holds the XOR of the high pair, and an intact source wire carries the sign. One AND forms m2, which marks |d| = 2; it is the row's only AND outside the columns.

booth_columns builds each addend column as (s1w AND va) XOR (m2 AND vb), where vb sits one bit deeper because doubling is a shift. The sign wire puts the columns in one's-complement form, and the adder's negate input supplies the carry that completes negation. Right after the addition, the column ANDs are erased by measurement, and two conditioned CZs on the still-live operand pair repair each sign.

The argument gl splits the carry chain. Each of the first gl carries is a measured AND: one Toffoli and one live wire. The rest use majority/unmajority carries: two Toffolis and no extra wire. row_gl gives the measured prefix whatever the live-qubit cap of 117 leaves, with two wires of headroom. A sweep over the whole circuit chose that cap by TQ-cost.

def brow(recode_cxs, s1w, m1w, signw, pairs, T, gl):
"""T += d * (operand row) — one signed Booth radix-4 digit row.
The digit's three source wires are recoded in place by
``recode_cxs`` (allocating nothing): ``s1w`` ends up holding the
|d|=1 selector (the XOR of the low source pair), ``m1w`` the XOR
of the high pair, and ``signw`` — a still-intact source wire —
the digit sign, fed to the adder's negate input. The |d|=2
selector m2 = (NOT s1w) AND m1w is the row's only non-column AND.
Each addend column is the pair-select (s1w AND v_a) XOR
(m2 AND v_b) — v_a, v_b the |d|=1 / |d|=2 candidate operand bits,
one shift apart — built X-sandwiched into one's-complement form
under the sign wire. Right after the adder returns, every column
AND is demolished by measurement and its phase kick repaired
inline by two conditioned CZs on the still-live operand pair.
``gl`` is the adder's [GID]-prefix length (the (qubits, Toffoli)
dial): prefix carries ride measured ANDs at 1 Toffoli + 1 live
wire, the rest of the addend span rides [CDKM] MAJ/UMA carries in
the column temps at 2 Toffoli + 0 wires, and the sign-extension
tail is always [GID].
"""
for u, v in recode_cxs:
b.cx(u, v)
m2 = b.and_compute(s1w, m1w, pol=(False, True))
cols, reps = booth_columns(b, s1w, m2, pairs, neg=signw)
add(b, T, cols, neg=signw, gl=gl)
booth_columns_release(b, cols, reps, neg=signw)
b.and_release(m2, s1w, m1w, pol=(False, True))
for u, v in reversed(recode_cxs):
b.cx(u, v)
⋯ 1 line
def row_gl(m, n):
"""[GID]-prefix length for a capped product row. At the chain
top, m column temps + the digit AND + the gl prefix carries + the
(n - 1 - m) sign-extension tail carries are all live above the
stage base (n live wires at gl = 0), so the prefix takes what the
frozen cap leaves, two wires of headroom kept under it.
"""
return max(0, min(m, PCAP - b.active_qubits - n - 2))
9

Multiply into the accumulator

product

The outer product goes straight into the accumulator: k ← k − P(dn, v). Complementing k before and after the seven rows turns their additions into a subtraction. No register holds the product or the finished angle.

Row t adds dt(v ≫ sigt)·2Bt, with B = [4, 5, 5, 5, 6, 6, 6] and sig = [13, 12, 10, 8, 7, 5, 3]. These shifts drop the low partial-product columns. The offline search fits the integer coefficients to this exact truncated computation, so truncation and rounding share one error budget. The exhaustive check finds a worst error of 427.15 output units, 9.95 × 10−8 radians.

# ---- 5. product: k -= P(dn, v), 7 signed Booth digit rows ----
Product into k 417 Toffolis · peak 115 qubits
with b.phase("product/setup"):
for q in KQ:
b.x(q)
for t in range(7):
with b.phase(f"product/t{t}"):
cxs, s1w, m1w, signw = prod_row_spec(t)
m, n = VW - SIG[t] + 1, 33 - B4[t]
brow(cxs, s1w, m1w, signw, prod_pairs(t), KQ[B4[t] :], row_gl(m, n))
with b.phase("product/close"):
for q in KQ:
b.x(q)
10

Cancel the bias, restore the slope

comp, vuncompute

The bias 216 inside W enters every product row. Because Σ dt4t = Y exactly, the row-wise bias terms add up to exactly 27Y. One carry-only addition of the 13 bits of Y removes them all. It costs 25 Toffolis, and its carry ANDs are erased by measurement.

The three curvature rows then run again in reverse order, without the complement, and add Q back, so v = W. The reverse order visits the same partial sums, so the same window check covers it. The low four bits of W are zero, so the guards hold |0⟩ and are freed without measurement.

# ---- 6. comp: cancel the bias, k += (dn >> 2) << 7 ----
# The Booth recode preserves sum d_t 4^t = dn >> 2 exactly, so every
# product row carries the bias term of its digit and one carry-only
# Gidney add removes them all exactly.
Bias correction 25 Toffolis · peak 107 qubits
with b.phase("comp"):
# gadgets.arith gidney_add: 13 addend bits against a 26-bit target,
# the zero tail rippling carry only — 25 Toffoli, every carry AND
# uncomputed for free.
gidney_add(b, [XQ[j] for j in range(J0, NDN)], KQ[QCAP - RPROD + J0 :])
# ---- 7. vuncompute: mirrored rows restore W ----
# No X sandwich: the same signed rows now add Q back. The row order
# is VORD reversed, so the uncompute prefixes revisit exactly the
# certified compute prefixes (the window invariant covers both
# directions with one frozen order).
for s in reversed(VORD):
Inner step reversed 113 Toffolis · peak 112 qubits
with b.phase(f"vuncompute/s{s}"):
cxs, s1w, m1w, signw = q_row_spec(s)
brow(cxs, s1w, m1w, signw, q_pairs(s), tgtv, None)
if s == VORD[0]:
# Guards end |0> without measurement: stage 7's mirror restored
# v = W exactly, and W mod 2^GUARD = 0 (asserted at werase below) —
# freed here, after the last mirrored row, at the end of their
# liveness window.
b.release_recycle("guard", guards)
11

Rotate back and measure the words

unrotate

The three inverse rotations restore the low bits of X. The slope, rotation, and curvature words now hold exactly their table values. The circuit measures the slope word, then the rotation and curvature words, in the X basis.

Reversing the lookup would clear these words with a second 343-Toffoli walk. Measurement clears them at no Toffoli cost. Each outcome leaves a sign that is a known function of the leaf, and the last stage repairs all of them.

# ---- 8. unrotate: restore X; demolish slope, shift, g2 words ----
Rotate back 42 Toffolis · peak 78 qubits
with b.phase("unrotate/s4"):
crotl(shq[2], NDN - 4)
with b.phase("unrotate/s2"):
crotl(shq[1], NDN - 2)
with b.phase("unrotate/s1"):
crotl(shq[0], NDN - 1)
with b.phase("unrotate/werase"):
mb_g1 = demolish("wslope", vq[GUARD:])
assert BIAS % (1 << GUARD) == 0 # W = (g1 << GUARD) + BIAS: W mod 2^GUARD = 0
with b.phase("unrotate/sherase"):
mb_sh = demolish("shift", shq)
with b.phase("unrotate/g2erase"):
mb_g2 = demolish("g2", g2q)
12

Where the repair walk stops

fixup

Measuring a wire that holds leaf bit b with outcome m multiplies the state by (−1)bm. For each recorded 1, the circuit rebuilds the leaf's flag and applies a CZ between the flag and a wire held at |1⟩. The CZ costs no Toffolis; rebuilding every flag with a full walk would cost 343.

The walk instead stops at a fixed tree level. Below it, a one-hot decode of input bits 7 and up serves all narrower leaves at once. fixup_cost adds the walk's ANDs above level m to 2m−7 − 2 for the decode. The loop keeps the cheapest level whose bank fits under the cap. It selects level 12: the upper walk costs 182 Toffolis, and the decode of bits 7 to 11 distinguishes 211 of the 345 leaves.

# ---- 9. fixup: one conditioned-CZ walk repairs all phase kickback ----
# Demolishing a coefficient wire that held bit b of the leaf's word kicks
# (-1)^b exactly when the measurement bit came up 1; the repair is a CZ
# between the leaf's path flag and a constant-|1> kick wire, conditioned
# on that classical bit. Below tree level BESTM the walk is replaced by a
# one-hot expansion of X[7..BESTM-1]: the unary wires serve every leaf
# of width < 2^BESTM at once, cheaper than descending their subtree
# nodes. BESTM minimizes walk-ANDs + one-hot cost subject to the
# one-hot bank fitting under the peak cap.
# local: gadgets.qrom.erase_register + phase_fixup serve one demolished
# word per fixed-depth window walk; this fixup serves all four words
# (g2, sh, W, g0) in a single adaptive floored walk.
def fixup_cost(m):
state = {"ands": 0, "stopped": False}
def go(nd, has):
if isinstance(nd, Leaf):
return
if nd.bit < m:
state["stopped"] = True
return
if has:
state["ands"] += 1
go(nd.left, True)
go(nd.right, True)
go(ROOT, False)
oh = max(0, (1 << (m - 7)) - 2) if state["stopped"] else 0
return state["ands"] + oh, state["stopped"]
BESTM, BESTC = 7, None
for m_try in range(7, 14):
cst, stp = fixup_cost(m_try)
if stp and 56 + (1 << (m_try - 7)) + (21 - m_try) > PCAP:
continue
if BESTC is None or cst < BESTC:
BESTM, BESTC = m_try, cst
13

Repair every sign in one walk

fixup

onehot_build grows the decode one input bit at a time, one AND per new wire. Thirty-two one-hot wires cost 25 − 2 = 30 Toffolis, so the walk and the decode cost 212 together. The bank stays live for the whole walk, so the four measured words share it.

The floored walk reaches each leaf with its flag. leaf_mbs gathers the outcomes of exactly the bits that the lookup wrote. A wide leaf gets one CZ with the kick wire per outcome, conditioned on its classical value. A narrow leaf gets CZs with its one-hot wires instead.

onehot_free erases the decode, and the kick wire returns to |0⟩. Only X and k remain, with k increased by the angle.

def onehot_build(bits):
"""One-hot bank over ``bits``: U[y] = [bits == y], grown one bit at a
time with 2^t ANDs at level t (2^j - 2 Toffoli total).
local: gadgets.qrom.phase_fixup routes its one-hot window by cswap
(2^j - 1 Toffoli) and consumes it inside one fixup call; this
AND-grown bank costs 2^j - 2 and stays claimed across the whole
floored walk.
"""
j = len(bits)
f1 = b.qubit()
b.cx(bits[0], f1)
f0 = b.qubit()
b.cx(bits[0], f0)
b.x(f0)
U = [None] * (1 << j)
U[0], U[1] = f0, f1
b.claim("onehot", [f0, f1])
for t in range(1, j):
for y in range(1 << t):
n = b.and_compute(U[y], bits[t])
b.cx(n, U[y])
U[y + (1 << t)] = n
b.claim("onehot", U[2:]) # the AND-grown bank wires, now long-lived
return U
def onehot_free(U, bits):
b.release("onehot", U)
j = len(bits)
for t in range(j - 1, 0, -1):
for y in range((1 << t) - 1, -1, -1):
n = U[y + (1 << t)]
b.cx(n, U[y])
b.and_release(n, U[y], bits[t])
b.x(U[0])
b.cx(bits[0], U[0])
b.recycle(U[0])
b.cx(bits[0], U[1])
b.recycle(U[1])
def leaf_mbs(lf):
"""Return the measurement bits recorded as 1-kicks for this leaf's words."""
return [(mb_g2, mb_sh, mb_g1, mb_c0)[w][i] for w, i in leaf_bits(lf)]
Phase repair 212 Toffolis · peak 95 qubits
with b.phase("fixup/kick"):
kick = b.qubit()
b.claim("kick", [kick])
b.x(kick)
with b.phase("fixup/onehot"):
ohbits = [XQ[t] for t in range(7, BESTM)]
U = onehot_build(ohbits)
def emit_leaf(ctrl, lf):
if lf.bb >= BESTM:
for cbit in leaf_mbs(lf):
b.cz(ctrl, kick, cond=cbit)
else:
mask = (1 << (BESTM - 7)) - 1
xb = (lf.lo >> 7) & mask
mbs = leaf_mbs(lf)
for xr in range(1 << (lf.bb - 7)):
u = U[xb + xr]
for cbit in mbs:
b.cz(ctrl, u, cond=cbit)
with b.phase("fixup/walk"):
walk(emit_leaf, floor=BESTM)
with b.phase("fixup/unhot"):
onehot_free(U, ohbits)
with b.phase("fixup/close"):
b.x(kick)
b.release_recycle("kick", [kick])
Start (init): 0 Toffolis, peak 54 qubitsTree lookup (lookup): 343 Toffolis, peak 115 qubitsRotate (rotate): 42 Toffolis, peak 104 qubitsAdd intercept (c0add): 41 Toffolis, peak 115 qubitsInner step (vcompute): 113 Toffolis, peak 112 qubitsProduct into k (product): 417 Toffolis, peak 115 qubitsBias correction (comp): 25 Toffolis, peak 107 qubitsInner step reversed (vuncompute): 113 Toffolis, peak 112 qubitsRotate back (unrotate): 42 Toffolis, peak 78 qubitsPhase repair (fixup): 212 Toffolis, peak 95 qubits11554peak live qubits per phase, above the 54 I/O qubits1,348 Toffolis →
LSET = {
(int(lo), int(bb)): (int(g0), int(g1), int(g2), int(sh))
for lo, bb, g0, g1, g2, sh in zip(
TAB["lo"], TAB["bb"], TAB["g0"], TAB["g1"], TAB["g2"], TAB["sh"]
)
}
def tree_from_leafset(lset):
def go(lo, bb):
if (lo, bb) in lset:
return Leaf(lo, bb, lset[(lo, bb)])
assert bb > 7, "frozen table is not a dyadic partition"
h = 1 << (bb - 1)
return Node(bb - 1, go(lo, bb - 1), go(lo + h, bb - 1))
Ts = [go(1 << (16 + e), 16 + e) for e in range(5)]
return Node(20, Node(19, Node(18, Node(17, Ts[0], Ts[1]), Ts[2]), Ts[3]), Ts[4])
def collect(nd, out=None):
if out is None:
out = []
if isinstance(nd, Leaf):
out.append(nd)
else:
collect(nd.left, out)
collect(nd.right, out)
return out
ROOT = tree_from_leafset(LSET)
LEAVES = collect(ROOT)
# ---------------------------------------------------------------------------
# Builder-native measurement-based erasure: b.hmr(w) demolishes a wire into
# an Outcome handle and b.cz(a, c, cond=m) hosts the deferred phase fixup.
# The Booth rows' [GID]-prefix dial reads the *current* live count against
# the frozen live-qubit cap through b.active_qubits. That accounting is
# load-bearing: the prefix schedule is part of the certified stream, so
# any change to what counts as live moves the emitted bytes.
# ---------------------------------------------------------------------------
def build(): # noqa: C901, PLR0915 - straight-line circuit emitter
"""Build the discovered circuit on a fresh Builder; return (b, regs).
Circuit helpers are closures over ``b``. Registers come first, so
Builder qubit ids 0..53 are the persistent I/O wires. build() is
also the entry point of tools/occupancy_profile.py, which replays
the ownership wire-set log fail-closed and charts the occupancy.
"""
b = Builder()
_r = declare_registers(b, [("X", 21), ("k", 33)]) # |X> preserved; |k> acc
XQ, KQ = _r["X"], _r["k"]
b.claim("X", XQ)
b.claim("k", KQ)
⋯ 159 lines
_oct = None
# The open lookup/oct{o} phase block: an octave's phase runs from its
# first leaf to the next octave's first leaf, walk ANDs included.
octave = contextlib.ExitStack()
def visit1(ctrl, lf):
nonlocal _oct
o = lf.lo.bit_length() - 17
if o != _oct:
_oct = o
octave.close()
octave.enter_context(b.phase(f"lookup/oct{o}"))
for w, i in leaf_bits(lf):
bank, nm = ((g2q, "g2"), (shq, "shift"), (wsl, "wslope"), (c0q, "intercept"))[w]
b.cx(ctrl, _mat(bank, nm, i))
Tree lookup 343 Toffolis · peak 115 qubits
with b.phase("lookup/setup"), octave:
walk(visit1)
assert all(q is not None for bank in (g2q, shq, wsl, c0q) for q in bank), (
"coefficient bit never written by any leaf"
)
# ---- 2. rotate: align the leaf's varying bits into the coordinate dn ----
Rotate 42 Toffolis · peak 104 qubits
with b.phase("rotate/s1"):
crotl(shq[0], 1)
with b.phase("rotate/s2"):
crotl(shq[1], 2)
with b.phase("rotate/s4"):
crotl(shq[2], 4)
dqb = [XQ[TAU + t] for t in range(NDQ)] # dq = dn >> 3, on the X wires
def demolish(rset, qs):
"""Demolish a coefficient word, top bit down: hmr + release + free
per wire. Returns the X-measurement bits, indexed like ``qs`` —
the fixup's kick list (leaf_mbs).
"""
mb = [None] * len(qs)
for i in range(len(qs) - 1, -1, -1):
mb[i] = b.hmr(qs[i])
b.release_recycle(rset, [qs[i]])
return mb
# ---- 3. c0add: k += g0; demolish the intercept word ----
# Gidney form with the carry chain truncated to gl=C0GL live AND
# wires; the prefix length is a searched dial (gen_constants.py). No
# carry-in wire exists in this form.
Add intercept 41 Toffolis · peak 115 qubits
with b.phase("c0add/add"):
add(b, KQ[C0D : C0D + len(c0q)], c0q, gl=C0GL, cout=KQ[C0D + len(c0q)])
with b.phase("c0add/c0erase"):
mb_c0 = demolish("intercept", c0q)
# ---- Booth digit row tables --------------------------------------------
# Product digits t = 0..6 recode Y = dn >> 2 (Y bits y_j live on
# XQ[j + J0]): d_t = y_{2t-1} + y_{2t} - 2 y_{2t+1}, boundary bits
# zero. After the in-place CXs, s1w holds the |d|=1 selector
# y_{2t-1} ^ y_{2t}, m1w holds y_{2t} ^ y_{2t+1}, and the untouched
# high source wire y_{2t+1} is the sign. The boundary rows carry no
# recode CX (t=0) and no sign (t=6: d_6 = y_11 + y_12 >= 0).
def prod_row_spec(t):
lo, mid, hi = XQ[2 * t + 1], XQ[2 * t + 2], XQ[2 * t + 3] if 2 * t + 3 <= NDN - 1 else None
if t == 0:
return [], mid, hi, hi
if hi is None:
return [(mid, lo)], lo, mid, None
return [(mid, lo), (hi, mid)], lo, mid, hi
def prod_pairs(t):
sig = SIG[t]
out = []
for c in range(VW - sig + 1):
va = vq[sig + c] if sig + c <= VW - 1 else None
vb = vq[sig - 1 + c]
out.append((va, vb))
return out
# Curvature digits s = 0..2 recode g2 (5 bits, VORD emission order):
# e_s = g2_{2s-1} + g2_{2s} - 2 g2_{2s+1}, boundary bits zero; row s
# adds e_s (dq << 2s) >> RQ into the 17-bit window, the |e|=2
# candidate one dq bit deeper.
def q_row_spec(s):
if s == 0:
return [], g2q[0], g2q[1], g2q[1]
if s == 2:
return [(g2q[4], g2q[3])], g2q[3], g2q[4], None
return [(g2q[2], g2q[1]), (g2q[3], g2q[2])], g2q[1], g2q[2], g2q[3]
def q_pairs(s):
out = []
for c in range(NDQ - RQ + 2 * s + 1):
ia, ib = c + RQ - 2 * s, c + RQ - 2 * s - 1
va = dqb[ia] if 0 <= ia <= NDQ - 1 else None
vb = dqb[ib] if 0 <= ib <= NDQ - 1 else None
out.append((va, vb))
return out
# ---- 4. vcompute: v = W - Q(dn) inside the 17-bit bias window ----
# The X sandwich turns the signed digit rows into a two's-complement
# subtract; the per-prefix window invariant (certified, frozen VORD
# order) guarantees no carry ever crosses bit 16, so only
# tgtv = vq[:17] is conjugated and every row chain is 17 bits wide.
Inner step 113 Toffolis · peak 112 qubits
with b.phase("vcompute/setup"):
guards = [b.qubit() for _ in range(GUARD)]
b.claim("guard", guards)
vq = list(guards) + list(wsl)
tgtv = vq[: QCAP + 1]
for q in tgtv:
b.x(q)
for s in VORD:
with b.phase(f"vcompute/s{s}"):
cxs, s1w, m1w, signw = q_row_spec(s)
brow(cxs, s1w, m1w, signw, q_pairs(s), tgtv, None)
with b.phase("vcompute/close"):
for q in tgtv:
b.x(q)
# ---- 5. product: k -= P(dn, v), 7 signed Booth digit rows ----
Product into k 417 Toffolis · peak 115 qubits
with b.phase("product/setup"):
for q in KQ:
b.x(q)
for t in range(7):
with b.phase(f"product/t{t}"):
cxs, s1w, m1w, signw = prod_row_spec(t)
m, n = VW - SIG[t] + 1, 33 - B4[t]
brow(cxs, s1w, m1w, signw, prod_pairs(t), KQ[B4[t] :], row_gl(m, n))
with b.phase("product/close"):
for q in KQ:
b.x(q)
# ---- 6. comp: cancel the bias, k += (dn >> 2) << 7 ----
# The Booth recode preserves sum d_t 4^t = dn >> 2 exactly, so every
# product row carries the bias term of its digit and one carry-only
# Gidney add removes them all exactly.
Bias correction 25 Toffolis · peak 107 qubits
with b.phase("comp"):
# gadgets.arith gidney_add: 13 addend bits against a 26-bit target,
# the zero tail rippling carry only — 25 Toffoli, every carry AND
# uncomputed for free.
gidney_add(b, [XQ[j] for j in range(J0, NDN)], KQ[QCAP - RPROD + J0 :])
# ---- 7. vuncompute: mirrored rows restore W ----
# No X sandwich: the same signed rows now add Q back. The row order
# is VORD reversed, so the uncompute prefixes revisit exactly the
# certified compute prefixes (the window invariant covers both
# directions with one frozen order).
for s in reversed(VORD):
Inner step reversed 113 Toffolis · peak 112 qubits
with b.phase(f"vuncompute/s{s}"):
cxs, s1w, m1w, signw = q_row_spec(s)
brow(cxs, s1w, m1w, signw, q_pairs(s), tgtv, None)
if s == VORD[0]:
# Guards end |0> without measurement: stage 7's mirror restored
# v = W exactly, and W mod 2^GUARD = 0 (asserted at werase below) —
# freed here, after the last mirrored row, at the end of their
# liveness window.
b.release_recycle("guard", guards)
# ---- 8. unrotate: restore X; demolish slope, shift, g2 words ----
Rotate back 42 Toffolis · peak 78 qubits
with b.phase("unrotate/s4"):
crotl(shq[2], NDN - 4)
with b.phase("unrotate/s2"):
crotl(shq[1], NDN - 2)
with b.phase("unrotate/s1"):
crotl(shq[0], NDN - 1)
with b.phase("unrotate/werase"):
mb_g1 = demolish("wslope", vq[GUARD:])
assert BIAS % (1 << GUARD) == 0 # W = (g1 << GUARD) + BIAS: W mod 2^GUARD = 0
with b.phase("unrotate/sherase"):
mb_sh = demolish("shift", shq)
with b.phase("unrotate/g2erase"):
mb_g2 = demolish("g2", g2q)
# ---- 9. fixup: one conditioned-CZ walk repairs all phase kickback ----
# Demolishing a coefficient wire that held bit b of the leaf's word kicks
# (-1)^b exactly when the measurement bit came up 1; the repair is a CZ
# between the leaf's path flag and a constant-|1> kick wire, conditioned
# on that classical bit. Below tree level BESTM the walk is replaced by a
# one-hot expansion of X[7..BESTM-1]: the unary wires serve every leaf
# of width < 2^BESTM at once, cheaper than descending their subtree
# nodes. BESTM minimizes walk-ANDs + one-hot cost subject to the
# one-hot bank fitting under the peak cap.
# local: gadgets.qrom.erase_register + phase_fixup serve one demolished
# word per fixed-depth window walk; this fixup serves all four words
# (g2, sh, W, g0) in a single adaptive floored walk.
def fixup_cost(m):
state = {"ands": 0, "stopped": False}
def go(nd, has):
if isinstance(nd, Leaf):
return
if nd.bit < m:
state["stopped"] = True
return
if has:
state["ands"] += 1
go(nd.left, True)
go(nd.right, True)
go(ROOT, False)
oh = max(0, (1 << (m - 7)) - 2) if state["stopped"] else 0
return state["ands"] + oh, state["stopped"]
BESTM, BESTC = 7, None
for m_try in range(7, 14):
cst, stp = fixup_cost(m_try)
if stp and 56 + (1 << (m_try - 7)) + (21 - m_try) > PCAP:
continue
if BESTC is None or cst < BESTC:
BESTM, BESTC = m_try, cst
def onehot_build(bits):
"""One-hot bank over ``bits``: U[y] = [bits == y], grown one bit at a
time with 2^t ANDs at level t (2^j - 2 Toffoli total).
local: gadgets.qrom.phase_fixup routes its one-hot window by cswap
(2^j - 1 Toffoli) and consumes it inside one fixup call; this
AND-grown bank costs 2^j - 2 and stays claimed across the whole
floored walk.
"""
j = len(bits)
f1 = b.qubit()
b.cx(bits[0], f1)
f0 = b.qubit()
b.cx(bits[0], f0)
b.x(f0)
U = [None] * (1 << j)
U[0], U[1] = f0, f1
b.claim("onehot", [f0, f1])
for t in range(1, j):
for y in range(1 << t):
n = b.and_compute(U[y], bits[t])
b.cx(n, U[y])
U[y + (1 << t)] = n
b.claim("onehot", U[2:]) # the AND-grown bank wires, now long-lived
return U
def onehot_free(U, bits):
b.release("onehot", U)
j = len(bits)
for t in range(j - 1, 0, -1):
for y in range((1 << t) - 1, -1, -1):
n = U[y + (1 << t)]
b.cx(n, U[y])
b.and_release(n, U[y], bits[t])
b.x(U[0])
b.cx(bits[0], U[0])
b.recycle(U[0])
b.cx(bits[0], U[1])
b.recycle(U[1])
def leaf_mbs(lf):
"""Return the measurement bits recorded as 1-kicks for this leaf's words."""
return [(mb_g2, mb_sh, mb_g1, mb_c0)[w][i] for w, i in leaf_bits(lf)]
Phase repair 212 Toffolis · peak 95 qubits
with b.phase("fixup/kick"):
kick = b.qubit()
b.claim("kick", [kick])
b.x(kick)
with b.phase("fixup/onehot"):
ohbits = [XQ[t] for t in range(7, BESTM)]
U = onehot_build(ohbits)
def emit_leaf(ctrl, lf):
if lf.bb >= BESTM:
for cbit in leaf_mbs(lf):
b.cz(ctrl, kick, cond=cbit)
else:
mask = (1 << (BESTM - 7)) - 1
xb = (lf.lo >> 7) & mask
mbs = leaf_mbs(lf)
for xr in range(1 << (lf.bb - 7)):
u = U[xb + xr]
for cbit in mbs:
b.cz(ctrl, u, cond=cbit)
with b.phase("fixup/walk"):
walk(emit_leaf, floor=BESTM)
with b.phase("fixup/unhot"):
onehot_free(U, ohbits)
with b.phase("fixup/close"):
b.x(kick)
b.release_recycle("kick", [kick])