quchip.chip.sw¶
Schrieffer-Wolff reduction kernels (2nd order) on bare chip blocks.
All functions are pure, jax.numpy-only on the value path, and traced-safe:
no float(), no Python branch on a traced value. H is the chip’s bare
Hamiltonian in the C-order product basis, ordinary GHz; block masks are static
NumPy booleans (dims are static). The caller (the elimination handlers in
quchip.chip.transformations) owns cloning, folding, and control-plane
concerns.
The partition eliminates one mode: P = the mode in its ground state, Q =
everything else. The generator solves the Sylvester condition
[S, H₀] = -V_offdiag on the P↔Q blocks, giving the standard 2nd-order
effective Hamiltonian H_eff = P (H + ½[S, V]) P.
References: Bravyi, DiVincenzo & Loss, Ann. Phys. 326, 2793 (2011) (Schrieffer-Wolff); F. Yan et al., Phys. Rev. Applied 10, 054062 (2018) (tunable-coupler exchange J); Koch et al., PRA 76, 042319 (2007), §IV (dispersive shift); Krantz et al., Appl. Phys. Rev. 6, 021318 (2019), §V (Purcell decay, dispersive readout).
Functions
|
Full bare Hamiltonian as a dense |
|
Full bare product-basis index for the ground state, or one label's |
|
Row within the P-block ordering for the ground state, or one label's |
|
Exact-from-dressing reduction: labeled dressed energies instead of perturbation theory. |
|
|
|
Read survivor parameters from the P-block matrix. |
|
|
|
|
|
Virtual-state attribution for one |
|
|
|
Generator |
|
|
- quchip.chip.sw.bare_hamiltonian(chip, backend)[source]¶
Full bare Hamiltonian as a dense
jnparray in GHz, with labels and dims.Delegates assembly to
Chip.hamiltonian()— devices plus couplings at the chip’s RWA policy, pre-2π — and converts dense once viabackend.to_array. This is an analysis kernel, not a solver path; the dense conversion is the point, not a cost to avoid.
- quchip.chip.sw.mode_blocks(dims, labels, mode_label)[source]¶
(p_mask, q_mask)boolean arrays over the product basis.P is the eliminated mode in its ground state, Q everything else. The masks are static NumPy arrays (dims are static), so they can index and slice without touching the trace.
- quchip.chip.sw.sylvester_generator(h, p_mask)[source]¶
Generator
Ssolving the P↔Q Sylvester condition, plus the block-gap diagnostic.E = diag(H)are the bare energies andV = H − diag(E);S_ij = V_ij / (E_i − E_j)on the cross blocks only. The division is double-whereguarded so an exactly degenerate cross pair with no matrix element between it contributes zero — with a finite gradient, not aNaNpropagated backward through the unselected branch.
- quchip.chip.sw.h_effective_second_order(h, s, p_mask)[source]¶
H_eff = P (H + ½[S, V]) Prestricted to the P block (dense, GHz).
- quchip.chip.sw.basis_row(p_index, labels, dims, excited_label=None)[source]¶
Row within the P-block ordering for the ground state, or one label’s
n=1occupation.Shared basis bookkeeping between
extract_pair_parameters()and any caller reading out a matching row of a separately transformed P-block operator (e.g. a collapse operator carried throughtransform_collapse()).
- quchip.chip.sw.bare_index(labels, dims, excited_label=None)[source]¶
Full bare product-basis index for the ground state, or one label’s
n=1occupation.
- quchip.chip.sw.extract_pair_parameters(h_eff, p_index, labels, dims, mode_label)[source]¶
Read survivor parameters from the P-block matrix. Pure indexing, no physics choices.
Returns
{survivor: {"freq_after": E(1_s) − E(0)}}for every survivor, plus("J", a, b): h_eff[<1_a|, |1_b>]for every survivor pair — the effective exchange between the two single-excitation states.
- quchip.chip.sw.transform_collapse(c_full, s, p_mask)[source]¶
c_eff = P (c + [S, c]) P— the 2nd-order jump-operator transform (dense).The same rotation that block-diagonalizes
Hcarries the jump operators into the reduced frame; truncating at first order inSmatches the Hamiltonian’s 2nd-order accuracy. The projection is exact for the spectrum but approximate for dissipation — the caller records that honesty note (spec §6.2). Pass the unit jump operator and fold the rate back in viapurcell_rate_from().
- quchip.chip.sw.purcell_rate_from(c_eff_survivor_lowering_amplitude, kappa)[source]¶
rate = |amplitude|² · κ— the mediated decay a survivor inherits.amplitudeis the survivor-lowering matrix element of the transformed unit jump operator (dimensionless,≈ g/Δin the dispersive case);κis the eliminated mode’s own rate in 1/ns, so the result is Lindblad-ready without any further unit conversion.
- quchip.chip.sw.exact_reduction(chip, mode_label, survivor_labels)[source]¶
Exact-from-dressing reduction: labeled dressed energies instead of perturbation theory.
Diagonalizes once through the chip’s traced-safe array path and reads the reduced parameters off the labeled spectrum, so kept-block energies are exact to all orders — which is what ZZ needs. This is the des-Cloizeaux caveat in reverse: energies are exact, but the effective basis is the overlap-projected one, not the canonical SW rotation, so off-diagonal reads (
J) agree with the perturbative route only through 2nd order.Returns the same parameter shape as the perturbative extraction —
{survivor: {"freq_after": E(1_s) − E(0)}}and("J", a, b)— plus("zz", a, b) = E₁₁ − E₁₀ − E₀₁ + E₀₀per survivor pair (identical convention toChip.dispersive_shift()).- Raises:
ValueError – When two kept computational labels are assigned the same dressed state (concrete path only; under tracing the guard is skipped — labeling indices are best-effort diagnostics there, never a traced branch).
- Parameters:
- Return type:
- quchip.chip.sw.exact_transform_collapse(c_full, evecs, kept_dressed_indices)[source]¶
c_eff = P U† c U PwithUthe labeled eigenvector matrix (dense).Rotates the jump operator into the dressed basis and keeps the rows and columns of the kept block’s assigned dressed states. Exact counterpart of
transform_collapse(); the spectrum-vs-dissipation honesty note is the caller’s to record either way.
- quchip.chip.sw.pathway_attribution(h, s, p_mask, i_idx, j_idx)[source]¶
Virtual-state attribution for one
H_effmatrix element.The contribution of intermediate
|k⟩to(½[S, V])_ijis½ V_ik V_kj (1/(E_i − E_k) + 1/(E_j − E_k)), with the same double-whereguard as the generator. Returns(k, amount)pairs for the Q-block states carrying a nonzero path at working precision; under tracing the nonzero filter cannot run, so every Q state is returned (diagnostics remain complete either way — extra entries are exact zeros).