quchip.analysis

quchip.analysis — physics analysis tools.

Sub-modules

cross_resonance

analyze_cross_resonance() — extract the six CR effective Hamiltonian coefficients {IX, IY, IZ, ZX, ZY, ZZ} from Bloch-vector tomography data.

dispersive_readout

analyze_dispersive_readout() — closed-form steady-state readout figures of merit (pointer states, SNR, assignment error, measurement dephasing) from the χ/κ that eliminate() reports.

effective_hamiltonian

analyze_static_zz() — exact static ZZ between two devices plus its 2nd-order SW virtual-pathway attribution. effective_hamiltonian() — the des-Cloizeaux effective Hamiltonian on a labeled computational subspace, with eigenvalues exactly the labeled dressed energies. effective_hamiltonian_between_states() — the same construction specialized to exactly two explicit bare states (e.g. a static exchange rate between two single-excitation states).

class quchip.analysis.CRHamiltonianResult(IX, IY, IZ, ZX, ZY, ZZ, IX_err, IY_err, IZ_err, ZX_err, ZY_err, ZZ_err, params_ctrl0=None, params_ctrl1=None, cov_ctrl0=None, cov_ctrl1=None, cost_ctrl0=0.0, cost_ctrl1=0.0)[source]

Bases: object

Store the six CR effective Hamiltonian coefficients in GHz, with uncertainties.

All six quantities are ordinary frequency (not angular); multiply by 2π to convert to rad/ns. The convention matches Sheldon et al. (PRA 93, 060302(R), 2016):

H_eff = (I ⊗ A + Z ⊗ B) / 2

where A = ω_IX X + ω_IY Y + ω_IZ Z and B = ω_ZX X + ω_ZY Y + ω_ZZ Z.

params_ctrl0 / params_ctrl1 hold the raw per-control-state fit output [px, py, pz, td, bx, by, bz] and are diagnostics only: they are in the fit’s internal units (px/py/pz in Hz, td in seconds), not converted.

Parameters:
IX: float
IY: float
IZ: float
ZX: float
ZY: float
ZZ: float
IX_err: float
IY_err: float
IZ_err: float
ZX_err: float
ZY_err: float
ZZ_err: float
params_ctrl0: ndarray | None = None
params_ctrl1: ndarray | None = None
cov_ctrl0: ndarray | None = None
cov_ctrl1: ndarray | None = None
cost_ctrl0: float = 0.0
cost_ctrl1: float = 0.0
coeffs()[source]

Return {name: (value_ghz, err_ghz)} for all six coefficients.

Return type:

dict[str, tuple[float, float]]

summary()[source]

Print and return a formatted summary of all six coefficients.

Return type:

str

class quchip.analysis.CRSusceptibilityResult(m_control_0, m_control_1, IX_per_amplitude, ZX_per_amplitude, control, target, drive)[source]

Bases: object

Store weak-drive CR coefficients per unit programmed drive amplitude.

For control-state-conditioned target-transition matrix elements

\[m_z = \langle\widetilde{z_c,1_t}|D_c|\widetilde{z_c,0_t}\rangle,\]

the effective-Hamiltonian convention

\[H_\mathrm{eff} = \tfrac{1}{2}(IX\,I\!X + ZX\,Z\!X)\]

gives IX_per_amplitude = m_0 + m_1 and ZX_per_amplitude = m_0 - m_1. Values are backend-native complex scalars and remain JAX-traceable.

Parameters:
  • m_control_0 (Any)

  • m_control_1 (Any)

  • IX_per_amplitude (Any)

  • ZX_per_amplitude (Any)

  • control (str)

  • target (str)

  • drive (str)

m_control_0, m_control_1

Dressed target-transition matrix elements conditioned on the control occupying |0> and |1>.

IX_per_amplitude, ZX_per_amplitude

Weak-drive Pauli coefficients per unit signal amplitude.

control, target, drive

Resolved labels.

m_control_0: Any
m_control_1: Any
IX_per_amplitude: Any
ZX_per_amplitude: Any
control: str
target: str
drive: str
class quchip.analysis.DispersiveReadoutResult(pointer_states, photon_numbers, sigma, snr, assignment_error, dephasing_rate, chi_eff, validity, notes)[source]

Bases: object

Store steady-state dispersive-readout figures of merit.

All numeric fields stay in the array namespace of the inputs (JAX in, JAX out), so the whole result traces under jax.jit/grad. validity holds {"n_over_ncrit", "below_ncrit"} when n_crit was given — below_ncrit is then a traced boolean under jit/grad; read it outside the traced region or branch with jnp.where — and is empty otherwise. chi here is χ_pull (f_r|1 f_r|0, 2× the σ_z-convention χ).

Parameters:
pointer_states

Complex α_j in the IQ plane, shape (levels,).

Type:

Any

photon_numbers

Steady-state photons |α_j|², shape (levels,).

Type:

Any

sigma

Integrated vacuum-noise blob width 1/√(2κτ) (dimensionless, α-plane units).

Type:

Any

snr

|α₁ α₀|·√(2κτ).

Type:

Any

assignment_error

½·erfc(SNR/(2√2)) — optimal linear discriminant between two equal Gaussians.

Type:

Any

dephasing_rate

Measurement-induced dephasing Γ_m = κ·|α₁ α₀|²/2 in 1/ns.

Type:

Any

chi_eff

chi, or chi/(1 + n̄₀/n_crit) when n_crit was given (GHz).

Type:

Any

validity

See above.

Type:

dict[str, Any]

notes

Explicitly dropped physics.

Type:

list[str]

pointer_states: Any
photon_numbers: Any
sigma: Any
snr: Any
assignment_error: Any
dephasing_rate: Any
chi_eff: Any
validity: dict[str, Any]
notes: list[str]
summary()[source]

Print and return a formatted summary.

Concrete values only — call it outside jax.jit/grad regions.

Return type:

str

class quchip.analysis.EffectiveHamiltonianResult(h_eff, basis, device_labels)[source]

Bases: object

Store the des-Cloizeaux effective Hamiltonian on a labeled computational subspace.

h_eff is built as S^-1/2 (W E W^dagger) S^-1/2 with W the overlap block between the requested bare states and their assigned dressed states, E the labeled dressed energies, and S = W W^dagger the (generally non-orthonormal) overlap Gram matrix — the symmetric (Löwdin) orthonormalization of exact_reduction()’s pairwise construction, generalized to an arbitrary number of kept states. S^-1/2 W is unitary by construction, so h_eff is unitarily similar to diag(E): its eigenvalues are exactly the labeled dressed energies, to numerical precision, regardless of how strongly the kept states hybridize with the rest of the chip. Off-diagonal entries carry the effective couplings between kept states; the diagonal is not, in general, individually equal to any one dressed energy once couplings mix the kept states.

Parameters:
h_eff

Dense Hermitian matrix, GHz, ordered as basis.

Type:

Any

basis

Full chip-length bare-occupation tuples spanning the subspace, in h_eff row/column order.

Type:

tuple[tuple[int, …], …]

device_labels

Chip device labels in tensor-product order, for reading basis tuples.

Type:

tuple[str, …]

h_eff: Any
basis: tuple[tuple[int, ...], ...]
device_labels: tuple[str, ...]
describe()[source]

Print and return the matrix with labeled row/column kets.

Concrete values only — call outside jax.jit/grad regions; a traced matrix renders as <traced>.

Return type:

str

class quchip.analysis.StaticZZResult(zz, pathways, device_a, device_b, device_labels)[source]

Bases: object

Store exact static ZZ between two devices, plus its 2nd-order SW pathway attribution.

Parameters:
zz

E(1,1) - E(1,0) - E(0,1) + E(0,0), identical to dispersive_shift(device_a, device_b)() — exact, not perturbative.

Type:

Any

pathways

(bare_occupation, amount) pairs: the contribution of each virtual intermediate state to the 2nd-order SW correction of the (1_a, 1_b) diagonal matrix element, amount = 1/2 * V_ik*V_ki*(1/(E_i - E_k) + 1/(E_i - E_k)) for i the (1_a, 1_b) bare index — a decomposition of that one energy correction, not of zz itself (which combines four dressed energies exactly). bare_occupation is a full chip-length Fock tuple, in device order.

Type:

list[tuple[tuple[int, …], Any]]

device_a, device_b

Resolved device labels.

device_labels

Chip device labels in tensor-product order, for reading pathways’ occupation tuples.

Type:

tuple[str, …]

Amounts stay in the array namespace of the chip's parameters (JAX in, JAX
out) traceable and differentiable, precision-filtered only on the
concrete path (:func:`~quchip.chip.sw.pathway_attribution`).
zz: Any
pathways: list[tuple[tuple[int, ...], Any]]
device_a: str
device_b: str
device_labels: tuple[str, ...]
describe()[source]

Print and return the exact ZZ plus the leading virtual pathways.

Concrete values only — call outside jax.jit/grad regions; traced amounts render as <traced>.

Return type:

str

quchip.analysis.analyze_cross_resonance(durations, ctrl0, ctrl1, sigma_ctrl0=None, sigma_ctrl1=None, t_offset=0.0)[source]

Extract CR effective Hamiltonian coefficients from Bloch tomography data.

Fits the target-qubit Bloch trajectory under a CR pulse to the analytic model in bloch_model() — once with the control qubit in |0⟩ and once with it in |1⟩ — and combines the two fits to isolate the six coefficients {IX, IY, IZ, ZX, ZY, ZZ}.

The decomposition is:

p_ctrl0 = (I/2) part → ω_IX, ω_IY, ω_IZ
p_ctrl1 = (Z/2) part → ω_ZX, ω_ZY, ω_ZZ

Specifically:

ω_ZQ = (p_ctrl0_Q - p_ctrl1_Q) / 2 ω_IQ = (p_ctrl0_Q + p_ctrl1_Q) / 2

for Q ∈ {X, Y, Z}.

Parameters:
  • durations ((N,) ndarray) – CR pulse durations in ns (the package convention). Must be monotone; need not be equally spaced. Converted once to seconds at the function boundary for the fit.

  • ctrl0 (dict or 2D ndarray) – Target-qubit Bloch trajectory with control in |0⟩, as a dict with keys "x", "y", "z" or a 2D array shaped (3, N) or (N, 3) (see _as_xyz()).

  • ctrl1 (dict or 2D ndarray) – Same with control in |1⟩.

  • sigma_ctrl0 (dict with keys "x", "y", "z" (optional)) – Per-point standard deviations for the control-|0⟩ data (used as inverse weights in the least-squares fit).

  • sigma_ctrl1 (dict with keys "x", "y", "z" (optional)) – Same for the control-|1⟩ data.

  • t_offset (float) – Subtract this offset (in ns) from durations before fitting (useful to exclude a pulse-ramp transient).

Returns:

Six coefficients in GHz (package units contract; durations are taken in ns and the Hz-valued fit internals are converted exactly once at this boundary), each with a one-sigma uncertainty.

Return type:

CRHamiltonianResult

Raises:

RuntimeError – If all initial guesses fail to converge for either control state.

Examples

>>> import numpy as np
>>> from quchip import analyze_cross_resonance
>>> durations = np.linspace(0, 400, 20)  # ns
>>> ctrl0 = {"x": np.sin(0.02 * durations), "y": np.zeros_like(durations),
...          "z": np.cos(0.02 * durations)}
>>> ctrl1 = {"x": np.sin(0.03 * durations), "y": np.zeros_like(durations),
...          "z": np.cos(0.03 * durations)}
>>> result = analyze_cross_resonance(durations, ctrl0, ctrl1)
>>> zx, zx_err = result.coeffs()["ZX"]  # GHz
quchip.analysis.analyze_cr_susceptibility(chip, control, target, *, drive=None)[source]

Return the dressed weak-drive CR response of one directed edge.

The analysis projects the physical control-line operator onto the target’s dressed 0 -> 1 transition twice: once with the control in |0> and once in |1>. No pulse, rotating-frame solve, or time evolution is performed.

Parameters:
  • chip (Chip) – Coupled chip with attached control equipment.

  • control (str | 'BaseDevice') – Directed CR control and target, supplied as device objects or labels.

  • target (str | 'BaseDevice') – Directed CR control and target, supplied as device objects or labels.

  • drive (str | 'BaseDrive' | None) – Control line to project. When omitted, the unique wired device-target line attached to control is selected.

Returns:

Conditional matrix elements and the corresponding IX and ZX coefficients per unit programmed amplitude.

Return type:

CRSusceptibilityResult

Raises:

ValueError – If the edge is a self-edge, control equipment is absent, implicit drive resolution is ambiguous, or the selected line does not target the control.

References

Magesan and Gambetta, Phys. Rev. A 101, 052308 (2020). Malekakhlagh, Magesan, and McKay, Phys. Rev. A 102, 042605 (2020).

quchip.analysis.analyze_dispersive_readout(chi, kappa, tau, *, n_photons=None, eps=None, delta_r=0.0, n_crit=None, levels=2)[source]

Compute closed-form steady-state readout figures of merit from (chi, kappa).

Parameters:
  • chi (Any) – Dispersive pull χ_pull = f_r(qubit |1⟩) f_r(qubit |0⟩) in GHz — 2× the σ_z-convention χ. Take it from eliminate(...).effective_params[qubit]["chi"].

  • kappa (Any) – Resonator linewidth (rate) in 1/ns, e.g. effective_params[...]["kappa"].

  • tau (Any) – Integration time in ns.

  • n_photons (Any) – Target steady-state photon number with the qubit in |0⟩. Exactly one of n_photons and eps must be given; the drive rate is then ε = √(n̄₀·((κ/2)² + δ₀²)).

  • eps (Any) – Readout drive rate in rad/ns (power-user path; exactly one of n_photons and eps).

  • delta_r (Any) – Detuning of the qubit-in-ground resonator from the drive, delta_r = f_r|0 f_drive in GHz — the literature’s Δ_r = ω_r ω_d. 0.0 drives on the qubit-in-ground resonance; positive values place the drive below f_r|0.

  • n_crit (Any) – Critical photon number Δ²/(4g²). When given, the strong-drive collapse chi_eff = chi/(1 + n̄₀/n_crit) is applied and validity reports n_over_ncrit/below_ncrit.

  • levels (int) – Number of qubit levels to compute pointer states for (static Python int — it fixes array shapes; 3 includes |f⟩). The pull of level j is the linear-dispersive chi·j.

Return type:

DispersiveReadoutResult

Raises:

ValueError – If both or neither of n_photons and eps are given (a static argument-presence check — never a traced-value comparison).

Examples

>>> from quchip import analyze_dispersive_readout
>>> ro = analyze_dispersive_readout(chi=0.002, kappa=0.005, tau=500.0, n_photons=2.0)
>>> snr, p_err = ro.snr, ro.assignment_error

chi and kappa are typically taken from eliminate(chip, "readout_res").effective_params[qubit].

quchip.analysis.analyze_static_zz(chip, device_a, device_b)[source]

Compute exact static ZZ between two devices, plus its 2nd-order SW pathway attribution.

zz is dispersive_shift(), unchanged — the exact, all-orders residual coupling. pathways decomposes the 2nd-order SW correction to the (1_a, 1_b) diagonal energy into its virtual-intermediate-state contributions (pathway_attribution()), read off a partition that keeps only the four computational states of (a, b) (every other device grounded) — the natural loss primitive for a calibration sweep that holds zz near zero while some other exchange (e.g. a eliminate()-mediated J) stays on target.

Parameters:
  • chip (Chip)

  • device_a (str or BaseDevice) – The two devices whose static ZZ is analyzed.

  • device_b (str or BaseDevice) – The two devices whose static ZZ is analyzed.

Return type:

StaticZZResult

Examples

>>> from quchip import Capacitive, Chip, DuffingTransmon
>>> from quchip.analysis import analyze_static_zz
>>> q0 = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="q0")
>>> q1 = DuffingTransmon(freq=5.2, anharmonicity=-0.24, levels=3, label="q1")
>>> chip = Chip([q0, q1], couplings=[Capacitive(q0, q1, g=0.01)])
>>> result = analyze_static_zz(chip, "q0", "q1")
>>> zz = result.zz  # exact residual ZZ, GHz
quchip.analysis.effective_hamiltonian(chip, subspace)[source]

Compute the des-Cloizeaux effective Hamiltonian on a user-chosen computational subspace.

Reuses the chip’s dressed spectrum (_compute_array_labeled()) rather than re-diagonalizing: one full-chip diagonalization drives both this and dispersive_shift(). See EffectiveHamiltonianResult for the construction and its exactness guarantee.

Parameters:
  • chip (Chip)

  • subspace (mapping or sequence) – {device: levels} keeps range(levels) of each named device (spectators grounded); a bare sequence of devices keeps each one’s full qubit (Fock 0/1) subspace (spectators grounded). Both accept a device label string or the object itself.

Return type:

EffectiveHamiltonianResult

Examples

>>> from quchip import Capacitive, Chip, DuffingTransmon
>>> from quchip.analysis import effective_hamiltonian
>>> q0 = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="q0")
>>> q1 = DuffingTransmon(freq=5.2, anharmonicity=-0.24, levels=3, label="q1")
>>> chip = Chip([q0, q1], couplings=[Capacitive(q0, q1, g=0.01)])
>>> result = effective_hamiltonian(chip, ["q0", "q1"])
>>> result.h_eff.shape
(4, 4)
quchip.analysis.effective_hamiltonian_between_states(chip, state_a, state_b)[source]

Compute the 2x2 Löwdin-orthonormalized effective Hamiltonian between two explicit bare states.

The same des-Cloizeaux construction effective_hamiltonian() uses (see EffectiveHamiltonianResult), specialized to exactly the two-state subspace spanned by state_a and state_b — not the four-state product subspace a ["a", "b"] bare-sequence spec to effective_hamiltonian() would build (each device’s full qubit subspace independently), which is a different projection. This is the natural primitive for a static exchange rate between two single-excitation bare states \(|1_a, 0_b\rangle\) and \(|0_a, 1_b\rangle\): the returned matrix’s off-diagonal entry is that exchange rate, in GHz.

Parameters:
  • chip (Chip)

  • state_a (tuple[int, ...]) – Full chip-length bare-occupation tuples (one entry per device, in devices order).

  • state_b (tuple[int, ...]) – Full chip-length bare-occupation tuples (one entry per device, in devices order).

Returns:

(2, 2) Hermitian matrix, GHz, in the array namespace of the chip’s backend. Eigenvalues are exactly state_a and state_b’s labeled dressed energies, to numerical precision.

Return type:

Any

Examples

>>> from quchip import Capacitive, Chip, DuffingTransmon
>>> from quchip.analysis import effective_hamiltonian_between_states
>>> q0 = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="q0")
>>> q1 = DuffingTransmon(freq=5.2, anharmonicity=-0.24, levels=3, label="q1")
>>> chip = Chip([q0, q1], couplings=[Capacitive(q0, q1, g=0.01)])
>>> h_eff = effective_hamiltonian_between_states(chip, (1, 0), (0, 1))
>>> h_eff.shape
(2, 2)

Modules

cross_resonance

Cross-resonance Hamiltonian tomography analysis.

dispersive_readout

Closed-form dispersive-readout analysis — pointer states, SNR, assignment error.

effective_hamiltonian(chip, subspace)

Compute the des-Cloizeaux effective Hamiltonian on a user-chosen computational subspace.