Repository navigation
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Contributor
|
Contributor
☂️ Code Coverage
Overall Coverage
New Files
Modified Files
|
rafaelha
force-pushed
the
statevector-sampler
branch
from
October 12, 2026 13:13
3721934 to
37fb756
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A float32 uniform draw is a multiple of 2^-23, so any p1 below 2^-23 gave outcome 1 with probability 2^-23: deterministic outcomes, whose p1 rounds to ~1e-15 instead of 0, fired at ~1.2e-7 per measurement under complex64. Compare two uint32 draws with p1·2^32 instead, independent of the dtype. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
p1 = (nu - <P>)/(2 nu) cancels catastrophically (p1 ~ 1e-7 instead of ~1e-15 on eigenstates under complex64), and renormalizing by 1 - p1 loses the relative precision of a small p0. Sum each outcome's weight directly (|psi +- P psi|^2 / 4, or the even and odd parity halves) and renormalize by the selected weight. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 1e-5 threshold was built for stabilizer-rank arithmetic. Under complex64 each rotation adds ~1e-7 relative drift, which is harmless because every probability is normalized by the measured weights, so warn above 1e-3 for complex64 and 1e-9 for complex128. Stabilizer-rank components keep 1e-5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The per-shot estimate counted only the amplitudes; peak memory was up to 2.7x higher, and the memory-derived batches (millions of lanes) were also slower. Count the f-params and records on host and device, cap the automatic batch at 2^16 lanes, and require one lane to fit in the same 50% budget that sizes batches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hand-built ops reach a dormant measurement of Y (S_DAG on the pivot), a forgotten dormant measurement that no later op depends on, and a diagonal measurement on two active axes. Running a tape as [0, k) then [k, A) reproduces running [0, A) field by field. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All five acceptances still agree with Clifft 0.10.0 and no norm warning is printed. Write zero logical-error counts as upper bounds, and note that the previous logical-error section could not resolve the ~1e-7 sampling floor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add benchmark_clifft.py, which runs Clifft on the five clifft-bench workloads the way clifft-bench does, and workloads.py, which both benchmark scripts share. benchmark.py now reports the cores kept busy in the timed window and takes --seed; NPROC=1 pins JAX to one thread. results.md compares Tsim with Clifft 0.11.0 on one thread and on all threads of the same machine, lists both libraries' active widths, and checks the logical-error rates against Clifft and SymFT. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zx_param is now zxparam: rename the imports in the statevector modules, their tests and the test helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Read every output off the final symbols instead of carrying records through the tape: an output is the measurement's sign, XOR its branch bit when the measurement is random. This removes the Record action, the RECORD kernel, slots, the scratch record column and the sign of measurement actions. - Dispatch on the component type in sample_component and give each component type its own norm-warning threshold, so sample_program is the loop it is on main. - Pick the per-component compiler once in compile_program and reuse its output indices and f-bit selection in ComponentLayout.of. - Share one anticommute helper across heisenberg, schedule and plan, and one elimination step between StabilizerGroup.rotate and measure. - Derive num_lines, num_f, num_words, num_outputs and num_branches instead of storing them; drop the unused dtype option. - Gather once in the diagonal measurement kernel and jit sample_statevector_component as a whole. - Plan on ops in schedule order and emit each Rotate in one place. - Share test fixtures, merge duplicated tests and drop subsumed ones. - Default the benchmark circuits to a clifft-bench checkout next to the repository instead of a personal path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rafaelha
force-pushed
the
statevector-sampler
branch
from
October 13, 2026 15:51
d216963 to
ec8caf6
Compare
This was referenced Oct 14, 2026
rafaelha
added this pull request to stack #200
October 14, 2026 02:09
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
strategy="statevector"tocompile_samplerandcompile_detector_sampler. It builds on the zxparam migration (#194 and #195), which is now inmain.Every component of the reduced sampling graph that is not a single error-basis bit is simulated as a circuit on a dense state vector, in the style of Clifft:
zxparam.extract.extract_circuitturns the reduced component back into a circuit.statevector/heisenberg.pyrewrites the circuit as Pauli rotations and measurements in the Heisenberg frame. Noise only flips signs, so each op carries an affine GF(2) sign row over the error-basis bits, and commuting ops can be reordered freely.statevector/schedule.pyreorders commuting ops to keep the active width small. The width is n − dim S, where S is the Pauli group that stabilizes every trajectory up to sign. The scheduler runs measurements and non-widening rotations eagerly. Otherwise it runs the pending measurement with the fewest unrun rotations ahead of it.statevector/plan.pyplans the schedule on a fixed width W, tracking a Clifford frame.statevector/program.pylowers the plan to an action tape.statevector/execute.pyruns the tape in JAX as afori_loopover alax.switchof six kernels, on lanes × 2^W amplitudes.Details:
jax_enable_x64.choose_outcome(p1, count, key), which draws outcomes with 2^-64 resolution. Lanes carry acount, andrun(start, stop)can resume a tape, so trajectory sharing can be added later.mode="joint", and for components wider than 30 qubits or that zxparam cannot extract. The error suggestscat5.zx_param; the last commit ports them to zxparam.Active width
ActiveWidthSchedulePasspeak_active_widthfrom Clifft 0.11.0, compiled three ways: withhir_passes=None, with the default passes, and with the default passes plus the opt-inActiveWidthSchedulePass. The Clifft paper's table matches the no-pass column.convert_s_to_t.make_d5_end2end(0.001)from unitaryfoundation/clifft-paper.Performance (same machine, Apple M4 Pro)
Shots/s, postselecting every detector as clifft-bench does.
NPROC=1pins JAX to one thread.strategy="statevector"every clifft-bench circuit compiles in under 1 s.ChannelSampler.__init__and 32 s of ZX reduction.ChannelSampler.sample. The statevector part is no more expensive than without the escape stage.The performance numbers were measured before the rebase onto #195. The statevector code is unchanged since then, and the widths and action counts are identical on this branch. Full tables are in
scripts/statevector/results.md, produced byscripts/statevector/benchmark.pyandbenchmark_clifft.py.How this was verified
Test plan
pytest: 1478 passedpyright src test: 0 errorsKnown limitations, left for follow-ups:
ChannelSamplerdominates both build time and sampling time on the escape-stage circuit.🤖 Generated with Claude Code