Repository navigation
Add alias sampling - #48
Conversation
7d82a46 to
334e160
Compare
smcardleQ
left a comment
There was a problem hiding this comment.
Minor comments on coherent alias sampling, otherwise looks good to merge. I have not checked the arithmetic primitives yet.
…M TODO Per smcardleQ's review of PR NVIDIA#48: - drop the instance-specific '~0.19' overlap figure from the garbage caveat - spell out the QROM-word packing convention (alias low bits, keep above) - rename terse offsets k0/r0/l0/c0 -> keep_off/ref_off/ladder_off/carry_off - add a TODO to expose the inverse QROM as an explicit qrom_inverse call, since measurement-based uncomputation makes the adjoint PREPARE cheaper No behavior change; alias-sampling suite 26/26. Signed-off-by: Scott Thornton <wsttiger@gmail.com>
Adds `cudaq_algorithms.primitives` reversible integer arithmetic device kernels — little-endian, in-place, with hand-written inverses (no `cudaq.adjoint`, per cuda-quantum#4897/#4898). **CDKM/Cuccaro ripple-carry** (arXiv:quant-ph/0410184): - `add_register` / `subtract_register` — `b ← (b ± a) mod 2ⁿ`, **2n−2** Toffolis (the unused top carry-out cancels; §4.1's 2n−3 not adopted). - `add_constant` / `subtract_constant` — constant loaded into a caller-provided `work`+`carry` register, 2n−2. - `cmp_ge_constant` — `out ^= (x ≥ K)`, restores `x`, **2n−1** Toffolis. - `cmp_ge_register` / `cmp_gt_register` — `out ^= (a ≥ b)` / `(a > b)` on equal-width unsigned registers, 2n−1, no n-qubit work register. **Draper QFT** (arXiv:quant-ph/0008033, no Toffolis — `r1` rotations only): - `add_constant_qft` / `subtract_constant_qft`. - `cmp_ge_constant_qft_shift` / `cmp_ge_constant_qft_shift_adj` — the compute half **leaves `x` shifted** by −K (for the #48 alias sampler); the adjoint restores it. `out` is XOR-loaded, with the argument order matching the CDKM comparators (`out` last). **Tests (100 passing; 2 version-gated skips):** operation-pinning harnesses — fixed-operand superposition for the register ops, basis-input truth tables for the constant ops, correlated-flag superposition for the comparators (over `out ∈ {0,1}` and `K ∈ 0..2ⁿ`, for both comparator families) — op-then-inverse identity checks, direct `qft`/`iqft` and large-`K` coverage, a public-API resolution check, and `estimate_resources` contracts against the documented per-kernel counts. **`cudaq.control`:** composition over these kernels was a 0.15.x specialization regression — correct on 0.14.2 and fixed on 0.16.0 (no upstream issue filed). A version-gated superposed-control test pins it on 0.16 and skips on 0.15.x. **Follow-ups:** ancilla-light constant adder (Häner, arXiv:1611.07995); Cuccaro §4.1's 2n−3 adder. --------- Signed-off-by: Scott Thornton <wsttiger@gmail.com>
AliasSamplingPrepare: the Babbush-style (arXiv:1805.03662, Sec. III.D) PREPARE-with-garbage whose index-register marginal realizes the integer-Vose table distribution exactly (per-bin discretization bound 1.5 / (K 2^mu), derived not assumed), with a hand-written adjoint. The (alias, keep) lookup is the variants QROM under variant="auto": the ladder slice inside the garbage register is qrom.num_ladder wide, so num_garbage = m + 2mu + 4 + qrom.num_ladder (the historical 2m + 2mu + 4 whenever the plain select walk wins the pricing). No variant is pinned - every variant restores its ladder and self-inverts on the clean-ladder sector, which is what the adjoint's second lookup uses. The new qrom property exposes the priced lookup. Tests pin the index marginal against an independent brute-force branch enumeration, the table distribution against the ideal within the derived bound, prepare-then-adjoint identity, degenerate weights and validation messages, plus compiler-pinned resource contracts: each PREPARE side costs exactly qrom.toffoli_count + 4 (mu + 1) Toffolis (the lookup at the QROM's own reported price plus the two CDKM comparator adders) and num_index Fredkins, adjoint == forward gate-for-gate. Review fixes: pass variant/block_size through to the QROM constructor as keyword-only parameters (they shape num_garbage via qrom.num_ladder; QROM validation errors propagate as-is) and pin the variant-agnostic claim with a forced select_swap test asserting the exact marginal, the prepare-then-adjoint identity and the Toffoli cost identity; reject bool mu explicitly while keeping integral numpy ints; document that the per-bin garbage vectors are not mutually orthogonal (only the index amplitude magnitudes are guaranteed - exactly the qubitization <0|PREP' SELECT PREP|0> contract); say "the available QROM variants" instead of naming constructions this base does not ship; version-scope the cudaq.control nested-call rejection (through CUDA-Q 0.15, lifted in 0.16); mark the h-count assertion as incidental and the toffoli_count cross-check as a deliberate bookkeeping-vs-compiler pin. Signed-off-by: Scott Thornton <wsttiger@gmail.com>
Bare |0...0> kets and the |table - ideal| absolute value in the AliasSamplingPrepare docstrings parse as unterminated RST substitution references and fail the warnings-as-errors docs build now that the class is on the API reference page. Same fix as the unary-iteration module received on the QROM PR. Signed-off-by: Scott Thornton <wsttiger@gmail.com>
Implements the reviewer-suggested consolidation: the PREPARE's keep-vs-reference conditional now calls the arithmetic family's cmp_ge_register (flag <- (ref >= keep) on the bare mu-bit operands) instead of the bespoke two-adder weave (subtract keep on a (mu+1)-bit extension, copy the borrow, negate, add back). - Toffoli count per PREPARE side drops from 4(mu+1) to 2mu: the cost identity is now qrom.toffoli_count + 2 mu Toffolis + num_index Fredkins, re-derived in the docstrings and re-pinned by the resource tests against cudaq.estimate_resources. - The (mu+1)-bit extension's two pad qubits (keep_pad, ref_pad) are gone: cmp_ge_register complements its second operand in place and needs only the one-qubit carry the layout already had. num_garbage shrinks by 2 to num_index + 2 mu + 2 + qrom.num_ladder, and ladder_offset moves down accordingly. - The hand-written adjoint stays the literal gate-reversal: cmp_ge_register is palindromic around its self-inverse flag copy, so re-applying it is the reversed gate sequence. All marginal/bound/identity tests pass unchanged; only the layout and cost accounting assertions are re-derived. Signed-off-by: Scott Thornton <wsttiger@gmail.com>
…M TODO Per smcardleQ's review of PR NVIDIA#48: - drop the instance-specific '~0.19' overlap figure from the garbage caveat - spell out the QROM-word packing convention (alias low bits, keep above) - rename terse offsets k0/r0/l0/c0 -> keep_off/ref_off/ladder_off/carry_off - add a TODO to expose the inverse QROM as an explicit qrom_inverse call, since measurement-based uncomputation makes the adjoint PREPARE cheaper No behavior change; alias-sampling suite 26/26. Signed-off-by: Scott Thornton <wsttiger@gmail.com>
PR NVIDIA#47 merged with the one-Toffoli comparator saving (cmp_ge_register is now 2n-1, not 2n). The alias-sampling PREPARE consumes that comparator, so its documented Toffoli cost drops by one: qrom.toffoli_count + 2*mu - 1 (was + 2*mu). Updates the sampler docstring and the resource tests; the 2*mu register widths/offsets are unchanged. Suite: 26 passed on 0.15.1/qpp-cpu. Signed-off-by: Scott Thornton <wsttiger@gmail.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1cc210b to
fd53593
Compare
|
Rebased onto One re-pricing followed from the merge: #47 landed with the one-Toffoli comparator saving ( Green: 26/26 |
Summary
Adds
AliasSamplingPrepare, an implementation of the PREPARE-with-garbage construction described by Babbush et al. in arXiv:1805.03662, Sec. III.D.Given nonnegative weights
w_k, the primitive prepares a state whose index-register measurement probabilities exactly match an integer-discretized alias table. This construction is a standard state-preparation component for qubitized quantum simulation.The implementation builds on the arithmetic primitives introduced earlier in this PR stack:
(alias, keep)pair associated with each bin.Exact, bounded discretization
The input weights are discretized to
mubits using an integer version of Vose's alias-table algorithm.The resulting quantum circuit realizes the discretized distribution exactly. Tests compare against exact rational probabilities rather than relying only on floating-point tolerances.
For
Kbins, the error for each probability is bounded by1.5 / (K * 2^mu).The module docstring derives this bound, including why the residual-redistribution cursor cannot wrap around. Zero-weight entries and bins introduced through power-of-two padding receive exactly zero probability.
Resource costs and register layout
The implementation exposes and tests the following resource contract:
Toffoli count:
qrom.toffoli_count + 4 * (mu + 1)Fredkin count:
num_indexThe resource tests validate these formulas against the compiled kernel using
cudaq.estimate_resources. They also cross-check the QROM object's reported costs against the compiled QROM circuit.The garbage-register layout is documented field by field. Its total width is
num_garbage = num_index + 2 * mu + 4 + qrom.num_ladder.Because
qrom.num_ladderdepends on the selected QROM implementation, the garbage width automatically reflects the chosen variant.The internal QROM accepts
variant=andblock_size=options. The default"auto"mode evaluates the available constructions and selects the lowest-cost option. Tests also force theselect_swapvariant to verify that both PREPARE and its adjoint are independent of the selected QROM implementation, including clean-ladder reuse during uncomputation.PREPARE-with-garbage contract
AliasSamplingPrepareguarantees the probability associated with each index value. It does not guarantee clean state preparation of the formsum_k sqrt(p_k) |k>|0>.Instead, the prepared state generally has the form
sum_k sqrt(p_k) |k>|G_k>,where the conditional garbage states
|G_k>need not be mutually orthogonal. Consequently, the reduced state of the index register is not necessarilydiag(p_k).This is sufficient for the qubitization identity
<0| PREP^dag SELECT PREP |0> = sum_k p_k U_k.Because
SELECTis diagonal in the index basis, index orthogonality eliminates cross terms regardless of overlaps between the garbage states. The class documentation states this contract explicitly so consumers do not assume clean amplitude preparation or a diagonal reduced index state.Validation
The test suite includes:
(bin, reference)branch and comparison with circuit results.exp(-18)throughexp(4).mu = 8.The adversarial sweep found no discretization-bound violations, and padded bins remained exactly zero.
At this branch tip:
Deferred work
The following extensions are deliberately left for future changes:
Both can be introduced behind the existing QROM interface when a consumer requires the associated resource tradeoff.