quchip.engine.bands

Band decomposition by excitation-change weight.

This module splits an operator O, written in a number-basis product representation, into disjoint bands that connect Fock states with a fixed excitation difference. Let |m⟩ denote a single-mode number state. The entry O_{nm} = ⟨n|O|m⟩ contributes to the band with weight

\[w \;=\; m - n \;=\; \text{col} - \text{row}.\]

For a bilinear two-body operator on modes a and b the weight is the pair (Δa, Δb).

Physics use

  • In a rotating frame, assembly attaches a carrier exp(−i w ω t) to each band of a drive or coupling operator, and the RWA drops the counter-rotating bands (Jaynes & Cummings 1963). For the structured cQED treatment, see Gambetta et al., PRA 74, 042318 (2006). For cross-resonance specifically, see Rigetti & Devoret, PRB 81, 134507 (2010), and Magesan & Gambetta, PRA 101, 052308 (2020).

  • Observable reconstruction uses the same weights to demodulate expectations back into the control frame.

Implementation

The canonical entry points keep sparse layouts (CSR / DIA) when their structural metadata is concrete. Differentiable values can stay JAX-traced, because the declared indices and offsets keep the sparsity pattern statically known under jit. Dense traced payloads keep every candidate band, because they carry no equivalent structural declaration.

Functions

canonical_to_coo(canonical)

Flatten a canonical payload to (rows, cols, values) COO arrays.

canonical_to_dense_array(canonical)

Materialize canonical densely, preserving its array namespace (JAX-safe).

decompose_bands(op_matrix, dim)

Decompose a single-mode dense operator by weight w = col − row.

decompose_canonical_bands(canonical, dim, *)

Decompose a canonical single-mode operator by weight w = col − row.

decompose_two_body_canonical_bands(...[, ...])

Decompose a canonical two-body operator by (Δa, Δb) per-subsystem change.

embed_on_support(backend, op, support, dims)

Embed a component-local operator into the full space by support arity.

local_mode_bands(backend, local_op, *, dim, ...)

Decompose local_op into ascending excitation-change bands.

prune_zero_diagonals(canonical)

Drop concretely all-zero stored diagonals from a DIA canonical operator.

quchip.engine.bands.decompose_bands(op_matrix, dim)[source]

Decompose a single-mode dense operator by weight w = col − row.

Returns a dict keyed by integer weight w ∈ [−(dim−1), dim−1]. Each value is a full dim×dim matrix that holds only the entries on that diagonal band, with zeros elsewhere. Concrete arrays drop zero-norm bands. JAX-traced arrays keep every band, so the set of keys is statically known across traces.

quchip.engine.bands.decompose_canonical_bands(canonical, dim, *, semantic_to_solver=None, total_changes=None)[source]

Decompose a canonical single-mode operator by weight w = col − row.

Chooses the most compact representation for each band:

  • Sparse payloads with concrete structure (CSR/DIA) go through the COO path and emit sparse bands, including when their values are traced.

  • Dense payloads, or sparse payloads with traced structure, take decompose_bands() and emit dense bands.

Copies the subsystem metadata (dims, basis, subsystem_labels, tag) onto every band, so downstream engine operations can still find each band’s subsystem. total_changes optionally declares the weights the operator can carry, and the function skips other weights as structural zeros.

quchip.engine.bands.decompose_two_body_canonical_bands(canonical, dims, *, semantic_to_solver=None)[source]

Decompose a canonical two-body operator by (Δa, Δb) per-subsystem change.

canonical is in the product basis |i_a⟩ ⊗ |i_b⟩, with mode b as the fast index. dims is [d_a, d_b]. Each band has a definite excitation change on each mode, so assembly attaches the carrier exp(−i (Δa · ω_a + Δb · ω_b) t). This is the standard rotating-frame form for a bilinear coupling (see e.g. Magesan & Gambetta, PRA 101, 052308 (2020), Eq. (2)).

quchip.engine.bands.canonical_to_coo(canonical)[source]

Flatten a canonical payload to (rows, cols, values) COO arrays.

Dispatches on layout. Concrete dense and DIA payloads drop only exactly-zero entries (value != 0, no tolerance).

CSR is already explicitly sparse and keeps its stored nnz. Traced payloads keep their layout-native sparsity (CSR through indices/indptr, DIA through offsets), so the COO size stays static under jit. The fanout-everything fallback fires only when the layout’s structural metadata is traced, or for dense, which has no structural metadata.

quchip.engine.bands.canonical_to_dense_array(canonical)[source]

Materialize canonical densely, preserving its array namespace (JAX-safe).

Alias for CanonicalOperator.to_dense().

quchip.engine.bands.local_mode_bands(backend, local_op, *, dim, label, semantic_to_solver=None)[source]

Decompose local_op into ascending excitation-change bands.

Returns [(weight, band_op), ...] ordered by ascending weight. Each band_op is a backend operator on the local dim-sized space. It is not embedded into the full chip space and is without the 2π factor, so callers add their own embedding / scaling / wrapping.

quchip.engine.bands.prune_zero_diagonals(canonical)[source]

Drop concretely all-zero stored diagonals from a DIA canonical operator.

Operator algebra that cancels terms exactly keeps the union of the operands’ diagonal offsets, so the cancelled diagonals stay stored as explicit zeros. The solver applies these dead zeros at every integration step, and this function drops them from concrete (tracer-free) payloads. Traced payloads pass through unchanged, so the stored structure stays statically known under jit.

Non-DIA layouts pass through unchanged. CSR structure is the layout’s sparsity declaration, and dense has no structural metadata to prune. If every diagonal is zero, the function keeps the first one, so the operator stays constructible.