quchip.chip.couplings

Coupling models for two-body interactions between devices.

Couplers own their local Hamiltonians. A coupling defines the interaction Hamiltonian H_int ∈ L(H_a ⊗ H_b) on the two-device subspace, and the engine embeds it into the full chip space at assembly time. Coupling strengths are in GHz.

References

Blais, A., Huang, R.-S., Wallraff, A., Girvin, S. M., & Schoelkopf, R. J.

Cavity quantum electrodynamics for superconducting electrical circuits: An architecture for quantum computation. PRA 69, 062320 (2004), Eq. 11.

Krantz, P., Kjaergaard, M., Yan, F., Orlando, T. P., Gustavsson, S., &

Oliver, W. D. A quantum engineer’s guide to superconducting qubits. Applied Physics Reviews 6, 021318 (2019), §V.

Blais, A., Grimsmo, A. L., Girvin, S. M., & Wallraff, A. Circuit quantum

electrodynamics. Rev. Mod. Phys. 93, 025005 (2021).

Classes

Capacitive(device_a, device_b[, g, label])

Capacitive (charge-charge) coupling between two devices.

Coupling(device_a, device_b, g, *[, op_a, ...])

Generic two-body coupling with a user-supplied interaction.

CrossKerr(device_a, device_b[, chi, label])

Cross-Kerr (dispersive) coupling H_int = χ · n̂_a n̂_b.

TunableCapacitive(device_a, device_b[, g_0, ...])

Capacitive coupling with a scheduled parametric pump.

class quchip.chip.couplings.Capacitive(device_a, device_b, g=unbound, *, label=None)[source]

Bases: CouplingModel

Capacitive (charge-charge) coupling between two devices.

The interaction is H_int = g · Q_a Q_b, where Q is each endpoint’s charge operator. A device declares Q with charge_coupling_operator(), the operator that ChargeDrive also uses. Between Fock devices, Q = i(a − a†):

  • Full form: H_int = g · i(a − a†) · i(b − b†) = g · (a†b + a b†) − g · (a b + a†b†)

  • Band-RWA form: H_int = g · (a†b + a b†) (derived, not authored)

The coupling authors only the full form. RWA keeps its Δa + Δb == 0 bands, which are exactly g · (a†b + a b†), and drops the counter-rotating terms a b and a† b†. This is valid when ω_a + ω_b ≫ g, which makes those terms fast-rotating and negligible. It differs from the dispersive condition |ω_a − ω_b| ≫ g, which determines whether the retained exchange term g · (a†b + a b†) can be treated perturbatively (see TunableCapacitive / eliminate() for the dispersive reduction). You select the approximation on the chip or for one solve, never on the coupling.

Parameters:
  • device_a (BaseDevice or str) – The two coupled devices, given as objects or label strings. Chip late-binds label-string references.

  • device_b (BaseDevice or str) – The two coupled devices, given as objects or label strings. Chip late-binds label-string references.

  • g (float) – Coupling strength in GHz. Can be a traced JAX scalar for sweeps / autodiff. The exchange matrix element is g times the endpoints’ 0 -> 1 charge elements. Their magnitude is 1 on a DuffingTransmon or Resonator, s(Φ) on a FluxTunableTransmon, and |<0|n|1>| on a charge-basis or phase-grid device.

  • label (str, optional) – Human-readable label; defaults to "cap_{n}".

References

Blais et al., PRA 69, 062320 (2004), Eq. 11. Krantz et al., Appl. Phys. Rev. 6, 021318 (2019), §V.B. Blais et al., Rev. Mod. Phys. 93, 025005 (2021), §II.B.

Examples

>>> from quchip import DuffingTransmon, Resonator, Capacitive
>>> q = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="q")
>>> r = Resonator(freq=7.0, levels=5, label="r")
>>> coupling = Capacitive(q, r, g=0.05)
reduces_to_crosskerr: ClassVar[bool] = True
default_fit_observable: ClassVar[str] = 'cross_kerr'

Observable represented by this coupling’s declared scalar when the enclosing chip is passed to fit_a_dress as a dressed specification. Concrete coupling models override this when their inverse-design quantity is a dressed interaction observable.

g: Any = Parameter(default=unbound, positive=False, nonnegative=False, serialize=True, unit='GHz', symbol='g', noise=False, kw_only=False, required=False)
default_dressed_target()[source]

Use exchange rate for an edge between non-computational modes.

interaction(a, b, p)[source]

Return the full capacitive interaction g * Q_a Q_b.

Parameters:
physics_notes()[source]

Return the declared capacitive interaction.

classmethod from_dict(d, device_a, device_b)[source]

Reconstruct a capacitive coupling from serialized state.

Parameters:
  • d (dict[str, Any]) – Serialized coupling fields.

  • device_a (BaseDevice) – Resolved endpoint devices.

  • device_b (BaseDevice) – Resolved endpoint devices.

class quchip.chip.couplings.Coupling(device_a, device_b, g, *, op_a=None, op_b=None, interaction=None, label=None)[source]

Bases: BaseCoupling

Generic two-body coupling with a user-supplied interaction.

Use this escape hatch when no concrete coupling class models the required physics (inductive, longitudinal, cross-Kerr test forms, synthetic spin-spin couplings, photonics-style beam-splitters, …). The user supplies the operator structure, and this class supplies only the g scaling, RWA pass-through, and bookkeeping.

Two mutually exclusive modes:

Product form — H_int = g · op_a(device_a) ⊗ op_b(device_b):

Coupling(q, r, g=0.02,
    op_a=lambda d: d.number_operator(),
    op_b=lambda d: d.number_operator())

Callable form — H_int = g · interaction(device_a, device_b, backend):

Coupling(q, r, g=0.02,
    interaction=lambda a, b, bk: (
        bk.tensor(bk.dag(a.lowering_operator()), b.lowering_operator())
        + bk.tensor(a.lowering_operator(), bk.dag(b.lowering_operator()))
    ))

The selected chip approximation is applied to the complete user-supplied operator after authored physics is assembled.

Parameters:
  • device_a (BaseDevice or str) – Coupled devices or late-bound labels.

  • device_b (BaseDevice or str) – Coupled devices or late-bound labels.

  • g (float) – Scalar interaction strength in GHz.

  • op_a (callable or None, default=None) – Local operator factories for product form.

  • op_b (callable or None, default=None) – Local operator factories for product form.

  • interaction (callable or None, default=None) – Callable receiving both devices and the active backend.

  • label (str or None, default=None) – Coupling label; generated when omitted.

structural_setting_names: ClassVar[tuple[str, ...]] = ('_op_a', '_op_b', '_interaction')
property coupling_strength: float

Scalar prefactor g supplied by the user.

interaction_hamiltonian()[source]

User-defined interaction on H_a ⊗ H_b, scaled by g.

physics_notes()[source]

Return notes describing the user-supplied interaction mode.

to_dict()[source]

Reject serialization because callables cannot be persisted.

classmethod from_dict(d, device_a, device_b)[source]

Reject deserialization because callables cannot be reconstructed.

Parameters:
  • d (dict[str, Any]) – Serialized fields; unsupported for callable interactions.

  • device_a (BaseDevice) – Endpoint devices; unused because deserialization is unsupported.

  • device_b (BaseDevice) – Endpoint devices; unused because deserialization is unsupported.

class quchip.chip.couplings.CrossKerr(device_a, device_b, chi=unbound, *, label=None)[source]

Bases: CouplingModel

Cross-Kerr (dispersive) coupling H_int = χ · n̂_a n̂_b.

This effective diagonal interaction remains when an exchange coupling is reduced in the dispersive regime. It suits effective readout chips (qubit + resonator + CrossKerr probed by an ordinary charge line) and static-ZZ modelling. The term is diagonal in both endpoints, so its RWA and full forms coincide and it is frame-trivial.

Declared approximation: this is a uniform-pull model with one χ per edge and the same shift per endpoint excitation. It does not represent per-level χ differences, dispersive breakdown at the critical photon number, or Purcell decay. If Purcell decay matters, fold it into the endpoint T1 with eliminate().

Parameters:
  • device_a (BaseDevice or str) – The two coupled devices, as objects or label strings.

  • device_b (BaseDevice or str) – The two coupled devices, as objects or label strings.

  • chi (float) – Cross-Kerr shift in GHz per excitation pair, sign included (convention: full pull E₁₁ − E₁₀ − E₀₁ + E₀₀). Can be a JAX tracer.

  • label (str, optional) – Defaults to "crosskerr_{n}".

is_effective: ClassVar[bool] = True
default_fit_observable: ClassVar[str] = 'cross_kerr'

Observable represented by this coupling’s declared scalar when the enclosing chip is passed to fit_a_dress as a dressed specification. Concrete coupling models override this when their inverse-design quantity is a dressed interaction observable.

chi: Any = Parameter(default=unbound, positive=False, nonnegative=False, serialize=True, unit='GHz', symbol='\\chi', noise=False, kw_only=False, required=False)
interaction(a, b, p)[source]

Return χ · n̂_a n̂_b, identical under RWA.

Parameters:
parametric_interaction(a, b, p)[source]

Return the number-number structure multiplied by a pump.

Parameters:
physics_notes()[source]

Return the declared dispersive-approximation provenance.

class quchip.chip.couplings.TunableCapacitive(device_a, device_b, g_0=unbound, *, label=None)[source]

Bases: CouplingModel

Capacitive coupling with a scheduled parametric pump.

Effective two-body interaction with a static mean coupling strength:

\[H_{\text{int}} \;=\; g_0\,\hat Q_a\hat Q_b\]

where \(\hat Q\) is each endpoint’s charge operator, as in Capacitive (\(i(\hat a - \hat a^\dagger)\) for a Fock model). The engine applies any requested RWA after local-basis materialization. \(g_0\) is the static coupling strength in GHz and can be a JAX tracer that flows through jax.grad() without concretization.

Time dependence is not a construction-time parameter. A ParametricDrive wired onto this coupling schedules a pump δ(t) via pump(). The pump multiplies the same operator structure as the static term (parametric_interaction()).

Parameters:
  • device_a (BaseDevice) – The two coupled devices.

  • device_b (BaseDevice) – The two coupled devices.

  • g_0 (float) – Static (mean) coupling strength in GHz. Can be a JAX tracer.

  • label (str, optional) – Human-readable label; defaults to "tunable_cap_{n}".

Notes

The pump multiplies parametric_interaction(), and frame and RWA logic stay in the engine. A pump tone at the qubits’ difference frequency |ω_a − ω_b| activates the parametric beam-splitter / iSWAP exchange. A tone at the sum frequency ω_a + ω_b activates two-mode-squeezing (a†b†) terms. Express either tone with the drive’s freq argument, not with a coupling-side carrier.

References

McKay, Filipp, Mezzacapo, Magesan, Chow & Gambetta, Universal Gate for Fixed-Frequency Qubits via a Tunable Bus, Phys. Rev. Applied 6, 064007 (2016) — parametric two-qubit gates via coupler flux modulation.

Krantz et al., A quantum engineer’s guide to superconducting qubits, Appl. Phys. Rev. 6, 021318 (2019), §V.D — tunable couplers.

Examples

>>> from quchip import Chip, ControlEquipment, DuffingTransmon, ParametricDrive, TunableCapacitive
>>> q0 = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="q0")
>>> q1 = DuffingTransmon(freq=5.2, anharmonicity=-0.22, levels=3, label="q1")
>>> tc = TunableCapacitive(q0, q1, g_0=0.0, label="tc")
>>> pump = ParametricDrive(tc, label="pump")
>>> chip = Chip([q0, q1], couplings=[tc], control_equipment=ControlEquipment([pump]))
>>> # seq.pump(tc, envelope=..., freq=...) schedules δg(t); see QuantumSequence.pump.
is_effective: ClassVar[bool] = True
reduces_to_crosskerr: ClassVar[bool] = True
default_fit_observable: ClassVar[str] = 'cross_kerr'

Observable represented by this coupling’s declared scalar when the enclosing chip is passed to fit_a_dress as a dressed specification. Concrete coupling models override this when their inverse-design quantity is a dressed interaction observable.

g_0: Any = Parameter(default=unbound, positive=False, nonnegative=False, serialize=True, unit='GHz', symbol='g_0', noise=False, kw_only=False, required=False)
interaction(a, b, p)[source]

Return the static g_0 · Q_a Q_b contribution.

Parameters:
parametric_interaction(a, b, p)[source]

Return the charge-charge structure multiplied by a pump.

Parameters:
physics_notes()[source]

Return the tunable-coupling and effective-model assumptions.