Skip to content

Prototype: composable transition and Pauli-leakage noise channels - #518

Draft
qciaran wants to merge 3 commits into
devfrom
general-noise-transition-channels
Draft

Prototype: composable transition and Pauli-leakage noise channels#518
qciaran wants to merge 3 commits into
devfrom
general-noise-transition-channels

Conversation

@qciaran

@qciaran qciaran commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

[!IMPORTANT]\n> This PR is preserved as an exploratory implementation prototype. The public semantics and API are now under design review in RFC PR #591; this implementation is not intended to merge as-is before that RFC is resolved.\n\n## Summary

  • add reusable conditional state-transition channels over PECOS's effective {0, 1, L} state space
  • add complementary stochastic Pauli-plus-leakage channels over {I, X, Y, Z, L}
  • expose both channel families in Rust and Python, with matching GeneralNoiseModelBuilder hooks
  • support ordered channel stacks before and after one- and two-qubit gates without changing the existing gate-noise APIs
  • support independent per-leg or joint two-qubit channels, including joint labels such as 0L -> L0 and XL\n- support coherent *L / L* identity-wire rules that act on one gate leg without measuring or resolving the other
  • support tensor products of single-qubit dictionaries/channels to construct two-qubit models
  • reserve * for tensor products and replace the old p2 gate-replacement spelling with ~XX or :replace:XX

Channel model

Conditional state transitions

TransitionChannel(p, transitions) represents a stochastic population map. Rows are conditioned on the incoming effective state and each nonempty row is normalized independently:

TransitionChannel(
    0.01,
    {
        "0": {"0": 0.05, "1": 0.05, "L": 0.90},
        "1": {"0": 0.10, "1": 0.80, "L": 0.10},
        "L": {"0": 0.45, "1": 0.45, "L": 0.10},
    },
)

The outer p is the probability that the channel is considered. Conditional rows describe P(output | input) and therefore do not share one global relative-weight normalization. Missing input rows are identity rows. This naturally represents state-dependent leakage, seepage, bit-state transitions, and mixed recovery. PECOS consumes any internal population measurement; it is not returned as a program measurement.\n\nFor factorized two-qubit transition maps, * in the same source and destination position is a coherent identity wire. For example, \"*L\": {\"*0\": 0.45, \"*1\": 0.45, \"*L\": 0.10} acts only on the second leg. *L and L* rules may coexist and both apply to LL under the channel's shared outer coin; wildcard legs never become computational measurement dependencies.

Pauli plus leakage

PauliLeakageChannel(p, events) is the familiar overall-error-probability plus relative-event-weight model:

PauliLeakageChannel(0.001, {"X": 1.0, "Y": 1.0, "Z": 1.0, "L": 0.2})

The event weights are normalized as one conditional distribution and need not sum to one. Identity is implicit when the outer coin fails, so users do not need an I: 0.999 entry. L means any -> L; Paulis act only in the computational subspace. Joint two-qubit events such as IX, XL, and LL are supported.

Both families model fixed stochastic mixtures of trace-preserving component maps on the effective qutrit space, rather than exposing arbitrary Kraus operators. Leakage events use the existing leakage machinery and follow leakage_scale; channel outer probabilities follow the global and p1/p2 scale factors.

Composition and placement

Single-qubit dictionaries/channels use * for tensor products and @ for transition-channel composition. The p2 add_*_transition_channel_{before,after}_gate methods accept either a TransitionChannel (applied independently to both legs) or a TwoQubitTransitionChannel (applied jointly) directly. An explicit two-qubit step is only needed for different first/second-leg channels or mixed step lists. Multiple channels/steps can be installed at every hook and run in insertion order.

At a gate site the fixed cross-family order is:

  1. before-gate Pauli-plus-leakage channels
  2. before-gate transition channels
  3. ideal gate suppression/execution and existing p1/p2 noise
  4. after-gate Pauli-plus-leakage channels
  5. after-gate transition channels
  6. existing p2 idle noise

That ordering lets a transition channel recover leakage introduced by an earlier Pauli-plus-leakage channel at the same hook. Existing GeneralNoiseModel behavior is unchanged when the new channel lists are empty.

Python surface

The following are exported from both pecos and pecos_rslib.noise:

  • TransitionDict, TransitionChannel, TwoQubitTransitionChannel, P2TransitionStep
  • PauliLeakageDict, PauliLeakageChannel, TwoQubitPauliLeakageChannel, P2PauliLeakageStep

The Rust and Python builders provide matching with_* and add_* methods for before/after p1 and p2 sites. The user guide includes construction, conditional-probability, composition, and ordering examples.

QEC replacement-label syntax

Plain p2_weights labels such as XX remain post-gate Pauli branches. Replacement branches use either ~XX or the equivalent :replace:XX; ~II / :replace:II omits the ideal gate without applying a Pauli. The former *XX spelling is rejected with a migration hint, leaving * with the consistent tensor-product meaning in the new channel APIs.

Validation

  • just lint (full workspace strict Clippy and pre-commit checks)
  • cargo test -p pecos-engines (unit, integration, normal rustdoc, and compile-fail rustdoc tests)
  • cargo clippy -p pecos-engines -p pecos-rslib --all-targets -- -D warnings
  • focused Rust Pauli/leakage and channel tests
  • Python transition and Pauli/leakage suites: 9 passed
  • top-level pecos and pecos_rslib.noise export smoke tests
  • git diff --check

Follow-up

The Selene PECOS wrapper does not yet expose these GeneralNoiseModel channel stacks. Wrapper integration can follow after the core API is reviewed.

@qciaran
qciaran force-pushed the general-noise-transition-channels branch from e3c2276 to d0a346a Compare August 14, 2026 22:45
@qciaran qciaran changed the title Add two-qubit leakage transition channels Add reusable qubit leakage transition channels Aug 14, 2026
@ciaranra ciaranra self-assigned this Aug 15, 2026
@qciaran
qciaran force-pushed the general-noise-transition-channels branch from d0a346a to 4acff9e Compare August 17, 2026 15:58
@qciaran qciaran changed the title Add reusable qubit leakage transition channels Add composable qubit stochastic channels Aug 17, 2026
@qciaran
qciaran force-pushed the general-noise-transition-channels branch 4 times, most recently from 93db595 to 447257c Compare August 18, 2026 15:13
@qciaran qciaran changed the title Add composable qubit stochastic channels Add composable transition and Pauli-leakage noise channels Aug 18, 2026
@qciaran
qciaran force-pushed the general-noise-transition-channels branch from 447257c to 2a91c37 Compare August 20, 2026 01:52
@qciaran
qciaran force-pushed the general-noise-transition-channels branch from 2a91c37 to 3ee36aa Compare August 20, 2026 15:12
@qciaran qciaran changed the title Add composable transition and Pauli-leakage noise channels Prototype: composable transition and Pauli-leakage noise channels Aug 25, 2026
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.

2 participants