quchip.chip.coupling_base

Coupling base class and registry.

Split out of quchip.chip.couplings so the declarative API in quchip.declarative.models can subclass BaseCoupling without re-entering the import chain through Capacitive (Capacitive now itself depends on CouplingModel). The concrete coupling classes — Capacitive, TunableCapacitive, Coupling — still live in quchip.chip.couplings.

Classes

BaseCoupling(device_a, device_b, *[, label])

Abstract base for a two-body coupling between :class:`BaseDevice`s.

class quchip.chip.coupling_base.BaseCoupling(device_a, device_b, *, label=None)[source]

Bases: StateVersioned, Registrable, ABC

Abstract base for a two-body coupling between :class:`BaseDevice`s.

Subclasses own their local interaction Hamiltonian H_int acting on H_a H_b. The engine embeds this local form into the full chip tensor space; couplings never touch the engine directly.

Subclasses auto-register via the shared Registrable mixin — no manual registration step is needed. Ensure the module defining the subclass is imported so the registration runs.

Parameters:
  • device_a (BaseDevice or str) – The two coupled devices, given as device objects or their label strings. Label-string references are late-bound: the coupling remembers the string, and Chip resolves it to the matching device instance at construction time. Before that resolution the coupling cannot produce an interaction Hamiltonian.

  • device_b (BaseDevice or str) – The two coupled devices, given as device objects or their label strings. Label-string references are late-bound: the coupling remembers the string, and Chip resolves it to the matching device instance at construction time. Before that resolution the coupling cannot produce an interaction Hamiltonian.

  • label (str, optional) – Human-readable label. Auto-generated from _type_prefix when omitted (e.g. "cap_0" for Capacitive).

Notes

All coupling parameters (g, any tunable envelope, etc.) must be JAX-traceable so sweeps and gradient-based optimization work without forcing concretization.

folds_exchange: bool = False
reduces_to_crosskerr: bool = False
copy(device_map)[source]

Shallow copy rebound to the device instances in device_map.

Parameters:

device_map (dict[str, BaseDevice])

Return type:

BaseCoupling

property device_a_label: str

Label of the first coupled device (works pre- and post-binding).

property device_b_label: str

Label of the second coupled device (works pre- and post-binding).

property is_resolved: bool

Whether both device references are bound to BaseDevice instances.

abstract property coupling_strength: float

Scalar coupling strength in GHz.

property coupling_strength_name: str

Display name of the scalar coupling_strength parameter.

Default "g" (the conventional coupling-strength symbol, and the actual attribute name on Coupling). CouplingModel overrides this to the name of its first declared parameter field; a subclass with a different primary-scalar convention overrides it directly.

set_coupling_strength(value)[source]

Write value into the scalar named by coupling_strength_name.

The mutation counterpart of coupling_strength: callers that need to move a coupling’s primary scalar (optimizers, sweeps) go through this seam instead of assuming an attribute name (g holds only for Capacitive / Coupling; TunableCapacitive uses g_0, CrossKerr uses chi). Default implementation covers the common case where the writable attribute name matches coupling_strength_name exactly; a subclass whose writable attribute differs from its display name overrides this.

Parameters:

value (Any)

Return type:

None

property rwa: bool | None

Per-coupling RWA override; None inherits the chip’s default.

rwa_keeps_band(delta_a, delta_b)[source]

Whether the RWA retains the (Δa, Δb) excitation-change band.

The structural RWA policy for this coupling: when the chip resolves RWA (Chip.resolve_rwa()), only bands accepted here survive — in Chip.hamiltonian()’s mask and in stage 2’s band filter alike. Offsets follow the engine convention Δ = col row (+1 = lowering). Overrides must stay symmetric under joint sign flip so the retained operator is Hermitian, and must depend only on the integer offsets — never on frequency values, which may be traced.

Default: total-excitation-conserving (Δa + Δb == 0), the beam-splitter selection of the textbook coupling RWA.

Parameters:
Return type:

bool

abstractmethod interaction_hamiltonian()[source]

Return the full H_int on the local H_a H_b subspace.

Always the complete (non-RWA) interaction: the RWA is a chip policy the engine applies structurally, keeping only the bands rwa_keeps_band() accepts when Chip.resolve_rwa() resolves True for this coupling. Couplings author one form.

Return type:

Any

physics_notes()[source]

Return human-readable declarations of this coupling’s approximations.

Return type:

list[str]

parametric_operator(chip)[source]

Backend operator a scheduled edge pump multiplies, or None when this coupling is not modulable.

The base coupling is static-only; declarative couplings opt in by implementing CouplingModel.parametric_interaction().

Parameters:

chip (Any)

Return type:

Any | None

dropped_terms()[source]

Return advisory records for terms this coupling’s model itself elides.

RWA band drops are reported generically by stage 2; this hook is for other approximations a coupling applies inside interaction_hamiltonian(). Default: nothing is dropped.

Return type:

list[‘DroppedTerm’]

dynamic_interaction_terms(chip)[source]

Time-dependent interaction terms (default: none).

Parameters:

chip (Chip)

Return type:

list[tuple[Operator, ‘ScalarModulation’]]

collapse_operators(chip)[source]

Lindblad collapse operators on the local subspace (default: none).

Parameters:

chip (Chip)

Return type:

list[Operator]

to_dict()[source]

Serialize structural fields into a JSON-safe dictionary.

Return type:

dict[str, Any]