Skip to content

Make two-qubit gate leakage suppression and seepage pair-local in the general noise model - #671

Open
ciaranra wants to merge 1 commit into
devfrom
fix/pair-local-p2-leakage
Open

Make two-qubit gate leakage suppression and seepage pair-local in the general noise model#671
ciaranra wants to merge 1 commit into
devfrom
fix/pair-local-p2-leakage

Conversation

@ciaranra

@ciaranra ciaranra commented Sep 2, 2026

Copy link
Copy Markdown
Member

Summary

GeneralNoiseModel::apply_tq_faults processes a batched two-qubit gate pair by pair, but two decisions inside that loop looked at the whole gate instead of the current pair:

  • the leaked-input check scanned every qubit of the batched gate, so one leaked qubit anywhere suppressed the ideal gate and ordinary p2 sampling for every pair;
  • the seepage loop in the emission branch also walked every qubit of the batched gate, so seepage was attempted for the same leaked qubit once per pair, drawing RNG repeatedly.

Both are now scoped to the pair being processed. For a gate with a single pair, behavior and RNG consumption are unchanged.

Behavior change

Seeded output changes for batched two-qubit gates (more than one pair in one gate) when at least one qubit is leaked: unaffected pairs now execute and sample noise as they would as standalone gates, and each leaked qubit gets exactly one seepage attempt at its own pair site. Single-pair gates reproduce their previous byte stream, pinned by a captured-bytes test.

Tests

  • tq_leakage_only_removes_the_affected_pair: a leaked qubit in pair [0, 1] no longer suppresses the CZ on [2, 3].
  • tq_emission_and_seepage_are_pair_local: the batched call reproduces the operations and the subsequent RNG stream of driving the same seeded model pair by pair.
  • tq_seepage_scan_is_pair_local: with leaked qubits in both pairs, each gets one seepage attempt; reverting only the seepage loop makes this test fail on the RNG stream.
  • single_pair_tq_leakage_keeps_captured_legacy_bytes: single-pair output is byte-identical to the previous implementation.

The first three fail on the previous code; the fourth passes on both by design.

Verification

  • cargo test -p pecos-engines
  • cargo clippy -p pecos-engines --all-targets --all-features -- -D warnings
  • cargo fmt -p pecos-engines -- --check

Context

First of the separable changes ahead of the state-transition noise channel work; that work's compatibility fixture will be captured after this lands.

@ciaranra

ciaranra commented Sep 8, 2026

Copy link
Copy Markdown
Member Author

Reviewed. No objection; it needs a dev refresh (43 behind) but nothing I checked depends on that.

The fix is two lines and they are the right two

apply_tq_faults iterates a batched two-qubit gate pair by pair, but the leaked-input check and the seepage loop both read gate.qubits rather than the current pair's qubits. So one leaked qubit anywhere suppressed the ideal gate for every pair, and seepage was attempted for that qubit once per pair, consuming RNG each time. Both now read the pair. That is the whole change.

This is a good example of a defect that reads as correct: gate.qubits is a perfectly sensible-looking expression inside a loop over that gate, and nothing about it is obviously wrong until you notice the loop body is meant to be pair-scoped.

The claims about the tests are true, and I checked the finer one

The description says three of the four tests fail on the previous code and the fourth passes on both by design. Reverting both lines:

  • tq_leakage_only_removes_the_affected_pair FAILED
  • tq_emission_and_seepage_are_pair_local FAILED
  • tq_seepage_scan_is_pair_local FAILED
  • single_pair_tq_leakage_keeps_captured_legacy_bytes passed, as intended, since single-pair behaviour is unchanged

The finer claim is the one worth having verified. Reverting only the seepage loop failed only tq_seepage_scan_is_pair_local, with the other three passing. So the two tests are individually targeted at the two distinct defects rather than both merely reacting to the change as a whole. That is what stops a future partial regression from slipping through, and it is not something I could have concluded by reading.

Comparing the batched call against the same model driven pair by pair, and then comparing the following 16 RNG draws, is the right shape for the seepage claim specifically: matching operations alone would not establish that each leaked qubit gets exactly one seepage attempt, since a duplicated attempt that happens to draw the same outcome would still emit the same gates. The RNG stream is what makes that observable.

Verification

  • cargo test -p pecos-engines: 353 passed, zero failed.
  • cargo clippy --locked -p pecos-engines --all-targets --all-features -- -D warnings: clean.

Note on the behaviour change

Seeded output does change for batched two-qubit gates with a leaked qubit, which is correct: the previous behaviour was the bug. The captured-bytes test pinning single-pair output is the right way to bound the blast radius, since single-pair gates are the common case and their streams must not move. Worth being explicit in the release notes that batched multi-pair seeded runs will not reproduce byte-for-byte across this change.

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