quchip.devices.base

Base class for finite local quantum devices.

Devices own local Hamiltonians on an authored LocalSpace. Couplings and drives contribute separate terms. unresolved_hamiltonian() returns the authored operator, and hamiltonian() applies the local basis and frame policies. Each model must state its approximations and physical references.

Drive channels use the device’s physical lowering, raising, and number operators. sigma_x, sigma_y, and sigma_z act on the two lowest isolated energy states of the current local Hamiltonian.

Numerical physics parameters can be JAX tracers. Structural dimensions and settings stay fixed during tracing. Validation must not concretize traced values. Use quchip.utils.jax_utils.maybe_concrete_scalar() for concrete checks. StateVersioned tracks attribute writes, and Registrable dispatches deserialization.

Frequencies and energies E/h are in GHz, times in ns, and temperatures in mK. Engine assembly converts Hamiltonians to angular frequency.

Classes

BaseDevice(levels[, label, T1, T2, ...])

Abstract truncated-Hilbert-space quantum device.

class quchip.devices.base.BaseDevice(levels, label=None, *, T1=None, T2=None, thermal_occupation=None, thermal_population=unbound)[source]

Bases: StateVersioned, Registrable, ABC

Abstract truncated-Hilbert-space quantum device.

Concrete subclasses must:

  1. Set _type_prefix (used for auto-labeling).

  2. Expose a freq attribute holding the bare 0 -> 1 transition frequency in GHz, as any JAX-traceable scalar.

  3. Implement unresolved_hamiltonian() on the authored local space.

Noise parameters (all optional, None means the channel is absent):

  • T1: relaxation time (ns), giving an emission channel at rate 1/T1.

  • T2: total 0-1 coherence time (ns), with T2 <= 2*T1. It adds pure dephasing at gamma_phi = 1/T2 - 1/(2*T1).

  • thermal_occupation: unitless bath occupation n̄. It adds thermal absorption and increases emission.

The noise parameters are ordinary attributes, settable at construction or any time later. A newly built calculation uses the current values, and existing calculations keep their captured values. Writes get the same validation as construction. Setting a parameter to None removes its channel from later calculations.

Mutation tracking starts automatically when construction finishes (see StateVersioned). Subclasses do not call _finish_init.

Optional overrides:

  • dissipation(): append channels in addition to T1/T2.

  • to_dict() / from_dict(): for extra parameters.

  • computational: True if the device represents a computational qubit (default False).

See the module docstring for the full contract.

tunable_param_names: ClassVar[tuple[str, ...]] = ()

Parameters eligible for inverse design. DeviceModel derives these from declared fields unless the class or an ancestor supplies a tuple. Explicit tuples remain authoritative when inherited; an empty tuple excludes the device from inverse design. Plain BaseDevice subclasses default to an empty tuple without derivation.

dressed_fit_target_fields: ClassVar[tuple[tuple[str, str], ...]] = ()

(dressed_observable, declared_field) pairs used when this device appears in the desired-chip form of fit_a_dress. Empty means that the model makes no automatic dressed-target claim; circuit-level models can remain fixed until the user supplies explicit constraints.

dressed_fit_param_names: ClassVar[tuple[str, ...]] = ()

Bare parameters normally varied to reproduce dressed_fit_target_fields. This remains separate from tunable_param_names: a model may expose parameters for sweeps without claiming that inverse design can identify all of them from its default dressed observables.

basis: Literal['native', 'eigen'] | None = None
projection_levels: int | None = None
requires_projection_levels: ClassVar[bool] = False
T1: Any = Parameter(default=None, positive=True, nonnegative=False, serialize=True, unit='ns', symbol=None, noise=True, kw_only=True, required=False)
T2: Any = Parameter(default=None, positive=True, nonnegative=False, serialize=True, unit='ns', symbol=None, noise=True, kw_only=True, required=False)
thermal_occupation: Any = Parameter(default=None, positive=False, nonnegative=True, serialize=True, unit=None, symbol=None, noise=True, kw_only=True, required=False)
property thermal_population: Any

Deprecated alias for the bath’s mean thermal occupation.

tunable_params()[source]

Return {name: current_value} for every bare parameter the device exposes for fitting / sweeping.

By default, it walks tunable_param_names and reads each attribute. Subclasses with derived bare parameters, e.g. circuit-level devices that calculate freq from E_C/E_J/E_L, should override the class attribute, not this method. Override this method only when the list itself is not static, e.g. for flux-tunable devices that gain phi_ext only at some operating points.

default_dressed_targets()[source]

Return declared numbers interpreted as dressed-fit targets.

This hook reads component fields and never diagonalizes a chip. A device class opts in by declaring dressed_fit_target_fields.

default_fit_parameters()[source]

Return the conservative bare-parameter selection for default targets.

set_tunable_param(name, value)[source]

Update a bare parameter named in tunable_params().

Parameters:
  • name (str) – Tunable field name.

  • value (Any) – Replacement numerical value.

Notes

The default implementation uses setattr(), so any direct attribute (freq, anharmonicity, E_C, …) works. Subclasses with derived properties that must back-propagate to private state should override this method.

tunable_param_bounds(name, value)[source]

Return (lower, upper) bounds for a tunable parameter at a seed value.

Parameters:
  • name (str) – Tunable parameter name.

  • value (float) – Concrete seed used to construct bounds.

Notes

The inverse-design optimizer uses these bounds to keep searches physical. The default uses well-named conventions that cover the common circuit-QED parameters:

  • freq, E_C, E_J, E_L: positive, [0.5·s, 1.5·s] around a positive seed (s).

  • anharmonicity: sign-preserving. Negative seeds bound in (2·s, -ε), and positive seeds bound in (ε, 2·s).

  • phi_ext: in [-0.5, 0.5] (one full flux period symmetric around the integer-flux point).

Subclasses override this method for parameters with other physical constraints. Raises ValueError for unknown names rather than silently optimizing over an unbounded axis, and for a value that is not a concrete real scalar. Bounds for a JAX tracer are undefined because the optimizer needs a concrete numeric seed.

property connected_drives: list['BaseDrive']

Drives wired to this device, as a fresh list (mutation-safe copy).

copy()[source]

Structural copy detached from drive wiring (used by sweep cloning).

parameter_values()[source]

Return declared bindable values, including inactive optional fields.

set_parameter_value(name, value)[source]

Apply one validated local parameter value on an isolated device copy.

Parameters:
  • name (str) – Declared or tunable parameter name.

  • value (Any) – Replacement value.

set_parameter_values(values)[source]

Validate a complete candidate before applying a local parameter group.

Parameters:

values (mapping[str, Any]) – Parameter names and replacement values, applied atomically.

validate()[source]

Validate cross-field constraints at construction and grouped rebinding.

Subclasses implement their joint constraints here. Gate numerical checks on concrete scalars so traced parameters remain supported.

property reference_freq: Any

Return the authored readout/frame reference in GHz, or None.

None lets each chip calculation resolve its dressed reference. An explicit value fixes the readout reference independently of pulse carriers and is captured in each calculation’s resolved frame.

to_dict()[source]

Return a JSON-safe serialization. Subclasses extend it with their own parameters.

abstractmethod unresolved_hamiltonian()[source]

Return the authored local Hamiltonian before engine policies.

hamiltonian()[source]

Return the local Hamiltonian after basis and frame policies.

resolve(*, frame=None)[source]

Resolve isolated device physics with its own basis and explicit frame.

Parameters:
  • frame (FrameSpec or None, keyword-only) – Explicit rotating-frame specification; None uses the lab frame.

  • affect (The default frame is the lab frame. Chip membership does not)

  • queries. (this local calculation; use the chip for coupled-system)

truncation_boundary()[source]

Return the authored-space cutoff used by sampled truncation checks.

Intrinsically finite models override this method to return None. Custom spaces with a numerical cutoff return a TruncationBoundary describing its indices.

physics_notes()[source]

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

Each entry names a non-obvious assumption, approximation, or truncation of this device. Examples include “Hilbert truncation: 3 levels”, a model regime (Duffing), or a noise-channel selection (charge- vs flux-coupled T1).

The baseline entry is a truncation note, because every BaseDevice has some form of Hilbert-space truncation. A pure-dephasing note is added when T2 is set, because the number-operator dephasing model has non-obvious assumptions. Subclasses call super().physics_notes() and append their own model-specific notes.

local_space()[source]

Return this device’s authored local operator space.

resolved_basis(chip_basis='native')[source]

Return the device override or inherited chip basis policy.

Parameters:

chip_basis ({"native", "eigen"}, default "native") – Fallback policy when the device has no explicit basis setting.

resolved_dimension(chip_basis='native')[source]

Return the local dimension delivered to the solver.

Parameters:

chip_basis ({"native", "eigen"}, default "native") – Fallback basis policy.

lowering_operator()[source]

Bosonic lowering operator a on the truncated Fock basis.

raising_operator()[source]

Bosonic raising operator a† on the truncated Fock basis.

number_operator()[source]

Number operator n̂ = a†a on the truncated Fock basis.

energy_level_operator()[source]

Return the energy-level index expressed in the authored local basis.

identity()[source]

Identity operator on the truncated Fock basis.

local_operator(name)[source]

Map an operator-name string to this device’s own local operator.

Parameters:

name (str) – Operator vocabulary name such as "X", "n", "a", "charge" or "I".

Notes

Recognized names: "X" / "Y" / "Z" (Pauli projections on the computational |0>, |1> subspace), "n" (number), "a" (lowering), "a_dag" (raising), "I" (identity). The device owns this vocabulary. "charge", "phase" and "flux" use the corresponding physical coupling operator when the device declares it. Other names are found in local_space(). A subclass can override this method to supply more derived operators.

basis_state(n)[source]

Return Fock basis state |n>.

Parameters:

n (int) – Non-negative basis index below levels.

coherent_state(alpha)[source]

Return coherent state |alpha> on the truncated Fock basis.

Parameters:

alpha (complex) – Dimensionless coherent-state amplitude.

plot_energy_levels(*, ax=None, **kwargs)[source]

Plot the device’s bare energy-level ladder.

Parameters:
  • ax (matplotlib Axes or None, keyword-only) – Existing axes, or None to create one.

  • **kwargs (Any) – Plot styling forwarded to the visualization helper.

plot_wavefunction(n, *, ax=None, **kwargs)[source]

Plot an eigenstate wavefunction.

Parameters:
  • n (int) – Eigenstate index.

  • ax (matplotlib Axes or None, keyword-only) – Existing axes, or None to create one.

  • **kwargs (Any) – Plot styling forwarded to the visualization helper.

property sigma_x: Any

Return |0><1| + |1><0| on isolated energy levels, zero elsewhere.

property sigma_y: Any

Return -i|0><1| + i|1><0| on isolated energy levels, zero elsewhere.

property sigma_z: Any

Return |0><0| - |1><1| on isolated energy levels, zero elsewhere.

property sigma_plus: Any

Return |1><0| between the lowest isolated energy levels.

property sigma_minus: Any

Return |0><1| between the lowest isolated energy levels.

projector(i, j)[source]

|i><j| on the authored local basis.

Parameters:
  • i (int) – Ket and bra indices in the authored local basis.

  • j (int) – Ket and bra indices in the authored local basis.

  • ``projector(i (|i><i| and) –

  • projector (i)`` for the population)

  • ``projector(i –

  • subspace (j)`` for |i><j|. No)

  • approximation (the operator acts on the full authored local space.)

transition(lower, upper)[source]

Hermitian transition between isolated energy states.

Parameters:
  • lower (int) – Isolated energy-level indices with lower < upper.

  • upper (int) – Isolated energy-level indices with lower < upper.

  • the (The operator |lower><upper| + |upper><lower| is returned in)

  • basis. (authored local)

transition_frequency(lower, upper)[source]

Return the isolated E_upper - E_lower transition in GHz.

Parameters:
  • lower (int) – Isolated energy-level indices with lower < upper.

  • upper (int) – Isolated energy-level indices with lower < upper.

property computational: bool

Return True if this device is a computational qubit. Override in subclasses.

dissipation(op, p)[source]

Return T1/T2 channels using the device’s lowering, raising and number hooks.

collapse_operators()[source]

Materialize the device’s authored Lindblad collapse operators.

The built-in channels cover T1, T2, and thermal_occupation. Subclasses append channels in dissipation().

References

Breuer & Petruccione, Theory of Open Quantum Systems (Oxford, 2002), Ch. 3. For circuit-QED conventions see Krantz et al., Applied Physics Reviews 6, 021318 (2019), §V.

collapse_channels(basis=None)[source]

Return normalized local collapse channels.

Parameters:

basis (BasisRecord or None, optional) – Resolved basis for matrix-element channels. None resolves the device’s current basis policy.

classmethod noise_parameter_names()[source]

Declared fields that Chip.set_noise() can configure.

intrinsic_decay_rate()[source]

Return the total lowering-channel (downward) Lindblad rate in 1/ns, or None if there is no decay channel.

Reports the sum of squared amplitudes of the lowering-operator collapse channel(s) that collapse_operators() builds from the common thermal-emission construction. It reproduces that construction exactly:

  • T1 set (thermal_occupation set or not): (n̄+1)/T1, the rate of the sqrt(gamma*(n̄+1))·a channel with gamma = 1/T1. n̄ defaults to 0 when thermal_occupation is unset, so the rate reduces to plain 1/T1.

  • T1 unset, thermal_occupation set: n̄+1, the same channel with gamma = 1 (the unitless-bath-occupation branch).

  • Neither set: None, because there is no lowering channel.

Subclasses whose collapse_operators() combines several lowering-operator channels override this method to report the summed rate. An example is the Q-derived photon loss of Resonator together with T1.

The method reports only the downward rate, not the sqrt(gamma*n̄)·a† upward (thermal-absorption) channel. A caller that needs to know whether that channel is present reads thermal_occupation directly.

connect(drive)[source]

Register a drive as connected, idempotently on identity and replacing it on relabel.

Parameters:
  • drive (BaseDrive) – Drive object to attach.

  • line (A drive's label is its stable identity as a control)

  • one ((chip.wire already rejects duplicate labels within)

  • chip.clone() (equipment). Clone-and-rewire flows —)

:param : :param eliminate()’s equipment reattachment: :param chip.partition() —: :param build a fresh drive object bound to the same label when: :param re-wiring a device that already carries a connected drive: :param so a: :param same-label: :param different-object entry marks a stale copy of the same: :param line rather than a second physical line. That stale entry is: :param replaced in place (position preserved); a drive with a distinct: :param label is always appended as an independent line.: