quchip.chip

Chip topology — the composite quantum system and its two-body couplings.

A Chip bundles devices, couplings, and (optionally) control equipment into a single composite system that the engine can assemble into a solver-ready problem. Dressed-state analysis lives in quchip.chip.analysis and is attached to every chip as chip._analysis (exposed via the chip’s public methods).

class quchip.chip.Chip(devices, couplings=None, control_equipment=None, label=None, frame='lab', rwa=True, backend=None, baths=None)[source]

Bases: object

Composite quantum system: devices + couplings + (optional) control.

The chip is the primary user-facing object. It exposes:

Methods that accept a device reference take either a device object or its label string; object references are preferred in examples.

Parameters:
  • devices (list[BaseDevice]) – Ordered device list. Tensor-product position equals list index; labels must be unique.

  • couplings (list[BaseCoupling], optional) – Two-body couplings. Each coupling’s referenced devices must be in devices.

  • control_equipment (ControlEquipment, optional) – Aggregates drive lines and signal-chain transforms (crosstalk, delays, gains). Can also be attached later via wire() or connect().

  • label (str, optional) – Human-readable chip label.

  • frame (FrameSpec) –

    Initial frame specification:

    • "lab" — all reference frequencies 0 GHz (default).

    • "rotating" — per-device rotating frame at dressed drive frequencies.

    • scalar-like — one shared reference frequency for all devices.

    • dict — per-device references keyed by label or device.

  • rwa (bool) – Default RWA policy for couplings and drives. Per-component rwa overrides inherit this (None means inherit).

  • backend (str or Backend, optional) – Chip-specific backend. None uses the process default.

  • baths (list[Bath] | None)

Examples

>>> from quchip import DuffingTransmon, Resonator, Capacitive, Chip
>>> q = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="q")
>>> r = Resonator(freq=7.0, levels=5, label="r")
>>> chip = Chip([q, r], couplings=[Capacitive(q, r, g=0.05)])
>>> chip.energy({q: 1})  # dressed |1,0⟩ eigenvalue, GHz
hamiltonian()[source]

Lab-frame static Hamiltonian.

Embeds every device Hamiltonian into the full tensor space and adds each coupling’s embedded interaction. Does not apply the rotating-frame transform or any drive envelopes.

Under resolved RWA (resolve_rwa()) each coupling contributes only the bands its rwa_keeps_band() retains — the apply_rwa_mask() of its full interaction. The same bands drop from stage 2’s decomposition, so the two views agree.

This is the lab-frame Hamiltonian. At solve time, the engine applies a rotating-frame transformation and subtracts Σ_i ω_ref,i n̂_i for each device, where ω_ref,i is the frame reference resolved by quchip.engine.stage1_frames.resolve_frame(). The 2π boundary crossing and the subtraction both live in quchip.engine.stage2_assembly._build_static_h0(). Use frame_info() to inspect which reference frequency each device will use.

Returns:

Backend-native operator on ⨂_d H_d.

Return type:

Operator

dynamic_contributions()[source]

Chip-owned time-dependent Hamiltonian contributions with their support.

Returns (local_op, time_dependence, support, origin, tag) tuples: one support index for a device-local operator, two for a coupling’s two-body operator. Operators are lab-frame, ordinary GHz — the engine applies the 2π boundary. Drive terms are not included; they are schedule-owned and enter through stage 2’s drive compilation.

Return type:

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

collapse_contributions()[source]

Every Lindblad collapse operator on the chip, with its support.

Returns (operator, support) pairs: one device index for a device- or drive-line-local operator, two for a coupling’s two-body operator, and an empty tuple for an operator already embedded in the full space (baths). Rates are in 1/ns, Lindblad-ready — each component owns its rate physics, including any intrinsic 2π (e.g. a resonator’s κ = 2π·f/Q).

Every returned operator is a component’s LOCAL (bare-basis) operator; the engine combines them with the dressed interacting Hamiltonian at solve time. This is the standard local-Lindblad approximation (Breuer & Petruccione, The Theory of Open Quantum Systems, Oxford, 2002, Ch. 3) rather than a dressed-basis (polaron-frame) master equation, and applies chip-wide regardless of which components carry noise — see the "chip" entry of physics_notes().

Return type:

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

property device_map: dict[str, BaseDevice]

Label → device mapping (the chip’s own dict; do not mutate).

property coupling_map: dict[str, BaseCoupling]

Couplings by label, insertion-ordered (do not mutate).

coupling(coupling)[source]

Return a coupling by label or object.

Parameters:

coupling (str | BaseCoupling)

Return type:

BaseCoupling

property backend: Backend

per-call override > chip-specific > process default.

The per-call override is the backend= argument of simulate() / simulate_batch (scoped through quchip.backend._backend_context()); it outranks even a chip-constructed backend so one chip can serve, e.g., QuTiP sweeps and dynamiqs gradient solves without global state flips.

Type:

Active backend

property frame: FrameSpec

Current frame specification (see set_frame()).

property rwa: bool

Default rotating-wave approximation policy for couplings and drives.

property control_equipment: ControlEquipment | None

Attached control equipment, if any.

property devices: tuple[BaseDevice, ...]

Ordered tuple of devices; index matches tensor-product position.

property couplings: tuple[BaseCoupling, ...]

Tuple of couplings in insertion order.

property dims: tuple[int, ...]

Per-device Hilbert-space dimensions (same order as devices).

property total_dim: int

Total Hilbert-space dimension (product of per-device dims).

property baths: tuple[Bath, ...]

Chip-level baths (shared/collective dissipation), insertion order.

add_bath(bath)[source]

Attach a bath to this chip and return it (for fluent use).

Baths may be added at any time after construction — the next simulate/solve collects the bath’s collapse operators automatically, no rebuild needed. The bath is validated immediately: a non-Bath argument, a target label not on this chip, or a label colliding with an already-attached bath fails here rather than cryptically at solve time (or, for a label collision, silently overwriting an entry on the physics_notes() audit surface).

Parameters:

bath (Bath)

Return type:

Bath

set_noise(config=None, *, baths=None)[source]

Replace this chip’s entire noise description in one call.

The call is the chip’s complete noise state: for every device, each noise parameter (see noise_parameter_names()) is set from config when given and reset to None otherwise, and the chip’s baths become exactly baths (omitted → no baths). chip.set_noise() therefore clears all noise. Re-running the same call is a silent no-op, so notebook cells converge instead of stacking duplicate baths.

Only dissipation knobs are reachable — a key that is not a noise parameter of that device (e.g. freq) raises, so an optimized Hamiltonian cannot be perturbed by this call. The full target state is validated before anything is written (the same checks the constructors run); on error the chip is left exactly as it was. Applied changes are printed one per line; a no-op prints nothing.

Custom dissipation is supported by declaring it on the device class beforehand — a parameter(...) rate field plus a NoiseChannel entry (see the extension guide). The declared rate is then an ordinary noise parameter here: sweepable, differentiable, serializable. Runtime closure-style channels are deliberately not supported — their rates could be neither swept, nor differentiated, nor serialized.

Parameters:
  • config (mapping, optional) – {device_or_label: {noise_param: value}}. Devices may appear as objects or labels, once each.

  • baths (list[Bath], optional) – The chip’s complete new bath list (validated like add_bath()).

Return type:

None

property crosstalks: list[Crosstalk]

Convenience view — Crosstalk entries from the signal chain.

device_index(label)[source]

Tensor-product index of a device. Accepts a label string or object.

Parameters:

label (str | BaseDevice)

Return type:

int

plot_graph(path='chip_topology.html', *, full=True, exclude=None, **kwargs)[source]

Render chip topology — delegates to quchip.viz.chip.

Parameters:
Return type:

str

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

Render dressed spectrum — delegates to quchip.viz.chip.

Parameters:
Return type:

Any

set_frame(frame)[source]

Set the frame used when assembling simulation inputs.

Supported values:

  • "lab" — all reference frequencies are 0.0 GHz.

  • "rotating" — per-device references use dressed drive frequencies.

  • scalar-like — shared reference frequency for all devices.

  • dict — per-device references keyed by label or device.

Frame changes never alter dressed-state data — dressing is always computed from the lab-frame static Hamiltonian.

Parameters:

frame (FrameSpec)

Return type:

None

property analysis: ChipAnalysis

Dressed-state analysis namespace — the chip’s ChipAnalysis.

Canonical entry point for the full dressed-analysis surface (power users, less-common methods). The common quantities are also exposed as flat chip.* forwarders — energy(), freq(), dress(), dispersive_shift(), … — which delegate here; reach for chip.analysis for everything else.

dress(*, overlap_threshold=0.5, force=False, labeling='DE')[source]

Compute (or retrieve) the dressed-state decomposition. See ChipAnalysis.dress().

Parameters:
Return type:

DressedResult

property is_dressed: bool

Whether a valid dressed-state result is cached. See ChipAnalysis.is_dressed.

energy(device_states=None, /, **device_state_kwargs)[source]

Dressed eigenenergy (GHz) for a bare-state label. See ChipAnalysis.energy().

Parameters:
Return type:

float

dressed_spectrum()[source]

Raw dressed eigenvalue array without Python scalar coercion. See ChipAnalysis.dressed_spectrum().

Return type:

Any

dressed_index(device_states=None, /, **device_state_kwargs)[source]

Dressed-state index matching a bare-state label, or None. See ChipAnalysis.dressed_index().

Parameters:
Return type:

int | None

bare_label(dressed_index)[source]

Bare-state label assigned to a dressed-state index. See ChipAnalysis.bare_label().

Parameters:

dressed_index (int)

Return type:

tuple[int, …]

operator_in_dressed_basis(device, op, *, truncate=None)[source]

Embedded device operator transformed to the dressed eigenbasis.

See ChipAnalysis.operator_in_dressed_basis().

Parameters:
Return type:

Any

drive_matrix_elements(transition, *, drives=None)[source]

Return <final~|D_j|initial~> for wired drive lines.

The final dressed state is the row index and the initial dressed state is the column index. In the weak-drive projection these matrix elements set the effective driven-Hamiltonian coefficients. See E. Magesan and J. M. Gambetta, Phys. Rev. A 101, 052308 (2020), DOI 10.1103/PhysRevA.101.052308, and ChipAnalysis.drive_matrix_elements() for the transition shorthand, parameters, return type, and error conditions.

Parameters:
Return type:

LabelKeyedDict

state_components(state=None, /, *, n_components=5, **device_state_kwargs)[source]

Leading bare-basis probabilities for a dressed eigenstate. See ChipAnalysis.state_components().

Parameters:
Return type:

dict[tuple[int, …], float]

dispersive_shift(device_a, device_b)[source]

Dressed cross-Kerr shift (GHz): E(1,1) E(1,0) E(0,1) + E(0,0).

See ChipAnalysis.dispersive_shift().

Parameters:
Return type:

float

static_zz(device_a, device_b)

Dressed cross-Kerr shift (GHz): E(1,1) E(1,0) E(0,1) + E(0,0).

See ChipAnalysis.dispersive_shift().

Parameters:
Return type:

float

dressed_anharmonicity(device)[source]

Dressed anharmonicity of one device with others grounded (GHz).

See ChipAnalysis.dressed_anharmonicity().

Parameters:

device (str | BaseDevice)

Return type:

float

effective_subspace_hamiltonian(states)[source]

Dressed effective Hamiltonian in a labeled bare subspace.

See ChipAnalysis.effective_subspace_hamiltonian().

Parameters:

states (list[Mapping[str | BaseDevice, int] | tuple[int, ...]] | tuple[Mapping[str | BaseDevice, int] | tuple[int, ...], ...])

Return type:

Any

freq(target: None = None, when: dict[str | BaseDevice, int] | None = None) dict[str, float][source]
freq(target: str | BaseDevice, when: dict[str | BaseDevice, int] | None = None) float

All dressed 0→1 frequencies (GHz), or one conditional transition. See ChipAnalysis.freq().

Overloaded: no target returns the full {label: freq} dict; a single target (label or device) returns one scalar 0→1 frequency. The runtime body is unchanged — under jax.jit the scalar is a traced 0-d array, so the overload is type-only and does not alter traceability.

Parameters:
Return type:

dict[str, float] | float

frame_info()[source]

Per-device frame reference frequency ω_ref,i (GHz). See ChipAnalysis.frame_info().

Return type:

dict[str, Any]

physics_notes()[source]

Aggregate physics_notes() across every component.

Returns a dict keyed "chip" for the chip-level entry, and "<kind>:<label>"kind one of "device", "coupling", "drive", "bath" — for every component, mapping to that component’s declared approximations: Hilbert truncation, model regime, RWA status, noise-channel selection, and any other non-obvious assumption the component explicitly declares. Keys are kind-qualified rather than bare labels because the label namespaces are not globally disjoint — a device, coupling, drive, and bath may share a label — and this is an audit surface, so one component’s entry silently overwriting another’s is unacceptable. Drives are enumerated from control_equipment’s wiring rather than per-device connected_drives, so an edge-target ParametricDrive (pumping a coupling, not a device) is included too. The chip-level entry keyed "chip" states the local-Lindblad approximation every collapse operator this chip assembles is built under (see collapse_contributions()) — present even with no baths, since it applies regardless. Intended for inspection/audit rather than for runtime dispatch.

Return type:

dict[str, list[str]]

to_dict()[source]

Serialize chip topology into a JSON-safe dictionary.

Return type:

dict[str, Any]

classmethod from_dict(d)[source]

Reconstruct a chip from to_dict() output.

Parameters:

d (dict[str, Any])

Return type:

Chip

clone()[source]

Isolated structural clone suitable for sweep evaluation.

Return type:

Chip

partition()[source]

Split into independent sub-chips along the independence graph.

Couplings, non-separable bath target sets, and drive-crosstalk pairs all count as connections. Exact — the joint solve factorizes as the tensor product of the component solves. simulate/seq.simulate consult this automatically; call it directly to orchestrate solves yourself.

Return type:

PartitionResult

updated(update_fn)[source]

Return a cloned chip after applying one structural update callback.

Convenience for sweeps:

modified = chip.updated(lambda c: setattr(c["q"], "freq", 5.1))
Parameters:

update_fn (Callable[[Chip], None])

Return type:

Chip

status()[source]

Print a lightweight diagnostic dashboard for the chip.

Return type:

None

from_array(data, device=None)[source]

Build a backend operator from a raw NumPy array.

With device, the array is interpreted as a local operator on that device’s subspace and embedded into the full tensor-product space. With device=None the array must already span the full chip Hilbert space.

Parameters:
Return type:

Any

observable(device, op)[source]

Embed a device operator onto the full chip Hilbert space.

Accepts either an operator name ("X", "Y", "Z", "n", "a", "a_dag", "I") or an already-built local-space operator, and returns it embedded on the chip’s tensor-product space.

This is for manual full-space operator construction and analysis; it is not a solver e_op. For solver expectation values use e_ops(), which keeps operators local so the demodulation pipeline can band-decompose and embed them correctly.

Parameters:
Return type:

Any

e_ops(*, correlators=None, **specs)[source]

Build a dict-form e_ops mapping for the solver pipeline.

Each keyword maps a device label to an operator specification: a name string, a list of names, a raw local-space operator, or a mixed list of strings and operators. Two-device correlators (e.g. ⟨Z₁⊗Z₂⟩) are specified via correlators as device-label pairs → operator pairs. Returns local-space operators (not embedded) — the demodulation pipeline embeds as needed.

Examples

>>> from quchip import DuffingTransmon, Capacitive, Chip
>>> q1 = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="q1")
>>> q2 = DuffingTransmon(freq=5.2, anharmonicity=-0.22, levels=3, label="q2")
>>> chip = Chip([q1, q2], couplings=[Capacitive(q1, q2, g=0.02)])
>>> e = chip.e_ops(
...     q1=["X", "Y", "Z"], q2=["X", "Y", "Z"],
...     correlators={("q1", "q2"): ("Z", "Z")},
... )
Parameters:
Return type:

dict[str | tuple[str, str], Any]

set_state_order(*devices, levels=None)[source]

Declare the device order used to parse string-state shorthands.

After this is called, bare_state(), state(), and superposition() accept single-string specifications where each character is one level per device in devices order. Level symbols default to g=0, e=1, f=2, h=3; digits 0..9 are always accepted as raw Fock indices.

Every chip device must be named exactly once.

Examples

>>> from quchip import DuffingTransmon, Resonator, Chip
>>> qb = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="qb")
>>> tc = DuffingTransmon(freq=5.5, anharmonicity=-0.20, levels=3, label="tc")
>>> cr = Resonator(freq=7.0, levels=4, label="cr")
>>> chip = Chip([qb, tc, cr])
>>> chip.set_state_order(qb, tc, cr)
>>> _ = chip.bare_state("eg1")  # {qb: 1, tc: 0, cr: 1}
Parameters:
Return type:

None

superposition(*components)[source]

Normalized bare-basis superposition of tensor-product states.

Each component is either a bare-state spec (dict keyed by device or label, or a string when set_state_order() has been called) or an (amplitude, spec) tuple for weighted mixing. Uniform weights by default; results are normalized to unit norm.

Unlike state(), this stays in the bare product basis — no dressed diagonalization — so the probe basis is explicit.

Examples

>>> import numpy as np
>>> from quchip import DuffingTransmon, Resonator, Chip
>>> qb = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="qb")
>>> cr = Resonator(freq=7.0, levels=4, label="cr")
>>> chip = Chip([qb, cr])
>>> _ = chip.superposition({qb: 0}, {qb: 1})  # equal |00> + |10>
>>> _ = chip.superposition(                   # weighted mix
...     (np.sqrt(0.3), {qb: 1, cr: 0}),
...     (np.sqrt(0.7), {qb: 1, cr: 1}),
... )
Parameters:

components (Mapping[str | BaseDevice, int] | str | tuple[Any, Any])

Return type:

Any

state(device_states=None, /, **device_state_kwargs)[source]

Dressed eigenstate for the given Fock-indexed bare-state labels.

Accepts a string shorthand (e.g. "eg1") when set_state_order() has been called.

Safe inside jax.jit/grad/vmap: under tracing the assigned eigenvector column is selected through the label_eigensystem() array kernel, so dressed initial states are differentiable end-to-end. The global phase is gauge-dependent (eigh column convention) — populations and |overlap| figures of merit are unaffected.

Parameters:
Return type:

Any

bare_state(device_states=None, /, **device_state_kwargs)[source]

Bare tensor-product state from per-device Fock indices or kets.

Each device may be specified as either a Fock index (int) or a ket vector in that device’s local space. Devices not mentioned default to the ground state (Fock index 0). Unlike state() this does not diagonalize the coupled system.

Accepts a string shorthand (e.g. "eg1") when set_state_order() has been called.

Parameters:
Return type:

Any

wire(*lines, signal_chain=None)[source]

Attach or replace classical control wiring.

Preferred user-facing API for attaching control to a chip. If lines is omitted, the existing connected lines are reused and only the signal chain is replaced.

Examples

>>> # chip.wire(drive_q, drive_r, signal_chain=[Crosstalk(drive_q, drive_r, c=0.05)])
Parameters:
Return type:

ControlEquipment

unwire(line)[source]

Remove one control line and every signal-chain transform referencing it.

The inverse of wire() for a single line. Accepts the drive object or its label. Returns the removed drive so it can be rewired later. Removing the last line detaches the equipment entirely (control_equipment becomes None).

Parameters:

line (BaseDrive | str)

Return type:

BaseDrive

connect(control_equipment)[source]

Attach control equipment to this chip (low-level API).

Validates every drive target and rejects duplicate drive labels, then reconnects each drive to this chip’s canonical device instances. User-facing code should prefer wire().

Parameters:

control_equipment (ControlEquipment)

Return type:

None

disconnect()[source]

Detach control equipment entirely (low-level API).

The inverse of connect()/wire(): removes all lines and the signal chain at once (control_equipment becomes None). Returns the detached equipment so it can be reconnected later.

Returns:

The equipment that was attached before detachment.

Return type:

ControlEquipment

solve(problem, *, check_truncation=True, truncation_threshold=0.001)[source]

Solve a typed SolveProblem through this chip’s backend.

Routes through the common solve_problem() chokepoint, so the Hilbert-truncation safety net applies by default; pass check_truncation=False to opt out or retune truncation_threshold.

Parameters:
Return type:

SimulationResult

solve_many(batch_or_problems, *, progress=True)[source]

Solve a SolveBatch, ProblemBatch, or list of problems.

Chip-level validation only enforces what needs self (every input was built for this chip); the input-shape dispatch and batching are delegated to quchip.engine.solve_many(), which owns the single ProblemBatch / SolveBatch / list ladder.

Parameters:
  • batch_or_problems (Any)

  • progress (bool)

Return type:

SimulationBatchResult

describe()[source]

Sectioned plain-text report of everything on the chip.

Devices with their declared parameters (units included), noise settings, couplings, control wiring, and baths — the “what did I just build?” view. Returns a string; print(chip.describe()). Traced parameters render as <traced> and are never concretized.

Return type:

str

resolve_rwa(term_owner)[source]

Resolve a coupling’s or drive’s RWA flag against the chip default.

Returns the chip’s default when the owner’s rwa is None; otherwise returns the owner’s explicit flag.

Parameters:

term_owner (Any)

Return type:

bool

class quchip.chip.DressedResult(eigenvalues, state_map, dressed_eigenvalues, assignment_overlaps, hybridized_labels, bare_labels, bare_labels_by_dressed_index, eigenvector_matrix=None, overlap_threshold=0.5, labeling='DE', _eigensystem=None)[source]

Bases: object

Store a frozen snapshot of a dressed-state diagonalization.

Parameters:
eigenvalues

Sorted dressed eigenvalues in GHz.

Type:

array-like

eigenstates

Backend eigenstate objects in the same order as eigenvalues. Materialized lazily on first access from the underlying EigensystemData — the dressing / sweep hot path never touches them, so the per-column backend kets are only built when a caller actually asks for states.

Type:

array-like

state_map

Assignment from bare product-basis label (one int per device) to the dressed eigenstate index it overlaps most with.

Type:

dict[tuple[int, …], int]

dressed_eigenvalues

Dressed eigenvalue for each assigned bare label — direct lookup path for Chip.energy().

Type:

dict[tuple[int, …], Any]

assignment_overlaps

|⟨bare|dressed⟩|² of each assignment; values below overlap_threshold flag hybridization.

Type:

dict[tuple[int, …], float]

hybridized_labels

Bare labels whose assignment quality is below overlap_threshold. A non-empty tuple triggers a user warning at dress time.

Type:

tuple[tuple[int, …], …]

bare_labels

Full canonical product-basis label set (all combinations of range(device.levels) for every device, in chip order).

Type:

tuple[tuple[int, …], …]

bare_labels_by_dressed_index

Inverse of state_map — dressed index → assigned bare label.

Type:

dict[int, tuple[int, …]]

eigenvector_matrix

Columns = dressed eigenvectors in the bare product basis. Used for ChipAnalysis.operator_in_dressed_basis() and ChipAnalysis.state_components().

Type:

array-like or None

overlap_threshold

Minimum overlap for a confident assignment.

Type:

float

labeling

Algorithm id (currently only "DE"), resolved to the confidence-ordered row-greedy overlap-matching policy actually run by ChipAnalysis.dress() (assign_rowwise_greedy()).

Type:

str

eigenvalues: Any
state_map: dict[tuple[int, ...], int]
dressed_eigenvalues: dict[tuple[int, ...], Any]
assignment_overlaps: dict[tuple[int, ...], float]
hybridized_labels: tuple[tuple[int, ...], ...]
bare_labels: tuple[tuple[int, ...], ...]
bare_labels_by_dressed_index: dict[int, tuple[int, ...]]
eigenvector_matrix: Any = None
overlap_threshold: float = 0.5
labeling: str = 'DE'
property eigenstates: Any

Backend eigenstate kets, materialized lazily from the eigensystem.

class quchip.chip.Bath(recipe, targets=None, *, temperature=None, rate=None, correlated=False, label=None)[source]

Bases: object

A shared environment coupling a set of devices to a common bath.

Attach at construction (Chip(..., baths=[...])) or at any time after via add_bath() — the next simulate/solve collects the bath’s collapse operators automatically.

Parameters:
  • recipe (str) – One of "thermal", "collective_decay", "correlated_dephasing".

  • targets (list[BaseDevice | str] | None) – Devices the bath couples to (objects or labels). None (default) means every device in the chip — natural for a global thermal bath.

  • temperature (float | None) – Bath temperature in mK (required for "thermal"). May be a JAX tracer for sweeps / gradients.

  • rate (float | None) – Bath–device coupling rate γ in 1/ns. For "thermal" it is the environmental coupling rate (explicit — never silently borrowed from a device T1, so it cannot double-count device-level noise). For the collective recipes it is the overall jump rate. None defaults to 1.0 (user controls the absolute scale elsewhere).

  • correlated (bool) – "thermal" only: False (default) emits independent per-device channels sharing one temperature. True is reserved for a genuinely collective thermal jump operator and currently raises NotImplementedError — it is a documented future refinement, not a silent no-op. The collective recipes always emit a single correlated operator regardless of this flag.

  • label (str | None) – Auto-generated "bath_{n}" when omitted.

Examples

>>> from quchip import DuffingTransmon, Chip, Bath
>>> q = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="q")
>>> chip = Chip([q])
>>> _ = chip.add_bath(Bath("thermal", temperature=20.0))  # global 20 mK bath
>>> _ = chip.add_bath(Bath("collective_decay", targets=[q], rate=0.01))
resolve_targets(chip)[source]

Return the ordered target device labels (defaults to all devices).

Parameters:

chip (Chip)

Return type:

list[str]

property separable: bool

Whether this bath factorizes into independent per-target channels.

True for recipes that emit one collapse operator per target ("thermal" with independent channels); False for recipes that emit a single jump operator summed over targets ("collective_decay", "correlated_dephasing"). Partitioning treats a non-separable bath’s target set as one inseparable block.

to_dict()[source]

Serialize the bath; targets are stored as label strings.

Return type:

dict[str, Any]

classmethod from_dict(d)[source]

Reconstruct a bath from serialized state (targets as label strings).

Parameters:

d (dict[str, Any])

Return type:

Bath

physics_notes()[source]

Return human-readable declarations of this bath’s recipe and scope.

Mirrors physics_notes(): one entry naming the recipe and its targets, plus a recipe-specific assumption a user of this bath should be aware of.

Return type:

list[str]

copy()[source]

Independent copy of this bath (targets normalize to label strings).

Used by Chip.clone and eliminate so a transformed chip never shares live Bath objects with its source — mutating one chip’s bath must not silently change another chip’s physics. Parameter values (temperature, rate) are carried by reference, so traced values stay traced.

Return type:

Bath

collapse_operators(chip)[source]

Fully-embedded collapse operators for this bath.

"thermal" emits independent per-target relaxation/absorption pairs sharing one bath temperature (_bose()). The two collective recipes instead each emit a single jump operator summed over the resolved targets:

  • "collective_decay": L = sqrt(gamma) * sum_i a_i — an equal-phase, equal-weight rank-one collective channel, not general collective (super/subradiant) decay, which requires per-pair phase and weight factors set by the target geometry (Lehmberg, Phys. Rev. A 2, 883 (1970), for the general collective-radiative-decay construction).

  • "correlated_dephasing": L = sqrt(gamma) * sum_i n_i — maximally correlated common-mode dephasing (every target shares the identical dephasing fluctuation), not general correlated dephasing with a target-dependent correlation structure (Breuer & Petruccione, The Theory of Open Quantum Systems, Oxford, 2002, Ch. 3, for the general Lindblad construction).

Always called from inside with _backend_context(chip.backend): (see quchip.engine.stage4_problem._collect_c_ops()), so this method must not open its own backend context.

Parameters:

chip (Chip)

Return type:

list[Operator]

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

Bases: CouplingModel

Capacitive (charge-charge) coupling between two devices.

The capacitive interaction between two electromagnetic modes takes the canonical dipole-dipole form in the raising/lowering basis:

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

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

The coupling authors only the full form; the RWA form is the engine retaining the Δa + Δb == 0 bands of it, which is exactly g · (a†b + a b†). The RWA drops the counter-rotating terms a b and a† b†, valid when ω_a + ω_b g — the sum-frequency condition that makes those terms fast-rotating and hence negligible. This is distinct from the dispersive condition |ω_a ω_b| g, which instead governs whether the retained exchange term g · (a†b + a b†) can be treated perturbatively (see TunableCapacitive / eliminate() for the dispersive reduction). Whether to take the RWA is a per-coupling policy; resolution against the chip default happens in Chip.resolve_rwa().

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

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

  • g (float) – Coupling strength in GHz. May be a traced JAX scalar for sweeps / autodiff.

  • rwa (bool or None) – Per-coupling RWA override. None inherits the chip default.

  • 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)           # RWA inherited from chip
>>> _strong = Capacitive(q, r, g=0.05, rwa=False) # force full quantum-Rabi form
folds_exchange: bool = True
reduces_to_crosskerr: bool = True
g: Any = Parameter(default=<object object>, positive=False, nonnegative=False, serialize=True, unit='GHz')
interaction(a, b)[source]

Return the full capacitive interaction g * (a + a†)(b + b†).

Parameters:
Return type:

PhysicsExpr

physics_notes()[source]

Return declared capacitive-coupling and RWA assumptions.

Return type:

list[str]

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

Reconstruct a capacitive coupling from serialized state.

Parameters:
Return type:

Capacitive

class quchip.chip.Coupling(device_a, device_b, g, *, op_a=None, op_b=None, interaction=None, rwa=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 desired physics (inductive, longitudinal, cross-Kerr test forms, synthetic spin-spin couplings, photonics-style beam-splitters, …). The user supplies the operator structure; this class only provides the g scaling, RWA pass-through, and bookkeeping.

Two mutually exclusive modes:

Product formH_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 formH_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 resolved RWA applies the structural band filter to the user-supplied operator too, keeping only the bands rwa_keeps_band() accepts. Supply rwa=False (or override rwa_keeps_band) to keep a hand-built form untouched.

Parameters:
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.

Return type:

Any

physics_notes()[source]

Return notes describing the user-supplied interaction mode.

Return type:

list[str]

to_dict()[source]

Reject serialization because callables cannot be made persistent.

Return type:

dict[str, Any]

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

Reject deserialization because callables cannot be reconstructed.

Parameters:
Return type:

Coupling

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

Bases: CouplingModel

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

The effective diagonal interaction left when an exchange coupling is reduced in the dispersive regime — the natural coupling for effective readout chips (qubit + resonator + CrossKerr probed by an ordinary charge line) and static-ZZ modeling. Diagonal in both endpoints, so the RWA and full forms coincide and the term is frame-trivial.

Declared approximation: this is a uniform-pull model — one χ per edge, the same shift per endpoint excitation; per-level χ differences, dispersive breakdown at the critical photon number, and Purcell decay are not represented (fold Purcell into endpoint T1 via eliminate() when it matters).

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₀₀). May be a JAX tracer.

  • rwa (bool or None) – Per-coupling RWA override; irrelevant to the produced operator (both forms coincide) but stored for policy uniformity.

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

is_effective: bool = True
chi: Any = Parameter(default=<object object>, positive=False, nonnegative=False, serialize=True, unit='GHz')
interaction(a, b)[source]

Full form χ · n̂_a n̂_b (diagonal; identical under RWA).

Parameters:
Return type:

PhysicsExpr

parametric_interaction(a, b)[source]

Modulable structure n̂_a n̂_b — δχ(t) pumps ride this.

Parameters:
Return type:

PhysicsExpr

physics_notes()[source]

Return the declared dispersive-approximation provenance.

Return type:

list[str]

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

Bases: CouplingModel

Capacitive coupling with a scheduled parametric pump.

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

\[\begin{split}H_{\text{int}} \;=\; g_0 \cdot \left\{\begin{array}{ll} (a + a^\dagger)(b + b^\dagger) & \text{if } \texttt{rwa} = \texttt{False} \\ (a^\dagger b + a b^\dagger) & \text{if } \texttt{rwa} = \texttt{True} \end{array}\right.\end{split}\]

where \(g_0\) is the static coupling strength in GHz; it may be a JAX tracer and 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(), multiplying the same operator structure the static term uses (parametric_interaction() / rwa_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. May be a JAX tracer.

  • rwa (bool or None) – Per-coupling RWA override; None inherits the chip default.

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

Notes

The pump multiplies parametric_interaction() / rwa_parametric_interaction() in the chip’s frame natively — no separate frame or carrier logic lives on the coupling; a pump tone at the qubits’ difference frequency |ω_a ω_b| activates the parametric beam-splitter / iSWAP exchange, while a tone at the sum frequency ω_a + ω_b instead activates two-mode-squeezing (a†b†) terms. Either is expressed via the drive’s freq argument, not 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: bool = True
folds_exchange: bool = True
reduces_to_crosskerr: bool = True
g_0: Any = Parameter(default=<object object>, positive=False, nonnegative=False, serialize=True, unit='GHz')
interaction(a, b)[source]

Static contribution g_0 · (a + a†)(b + b†).

Parameters:
Return type:

PhysicsExpr

parametric_interaction(a, b)[source]

Modulable structure (a + a†)(b + b†) a scheduled pump multiplies.

Parameters:
Return type:

PhysicsExpr

rwa_parametric_interaction(a, b)[source]

Beam-splitter structure a†b + a b† retained under RWA.

Parameters:
Return type:

PhysicsExpr

physics_notes()[source]

Return the tunable-coupling, RWA, and effective-model assumptions.

Return type:

list[str]

class quchip.chip.ChipTransform(*args, **kwargs)[source]

Bases: Protocol

Structural protocol for any transformation result that yields a chip.

property chip: Chip
class quchip.chip.EliminationResult(chip, effective_params, validity, notes=<factory>)[source]

Bases: object

Store the result of eliminate().

Parameters:
chip

The reduced chip (eliminated mode removed; effect folded into ordinary surviving devices). The input chip is never mutated.

Type:

Chip

effective_params

Derived quantities per survivor: {label: {"lamb_shift", "purcell_rate", "freq_after", "chi", "kappa"}} (GHz for frequencies, 1/ns for rates). chi is the dispersive pull χ_pull f_mode(survivor in |1⟩) f_mode(survivor in |0⟩) — the full resonator pull per survivor excitation, i.e. the σ_z-convention χ of H_disp = (ω_r + χσ_z)a†a. For a mode touching more than one survivor, the mode is a bus / coupler, not a readout mode, so chi is reported as 0.0 for every survivor. Otherwise chi is a deferred entry: computed from the input chip’s dressed spectrum (one full-chip diagonalization) on the first ["chi"] access and cached, so reductions that never read it stay pure algebra (LazyEffectiveParams); gradients through it follow Chip.dispersive_shift’s backend rule, while every other entry remains backend-independent algebra. kappa is the eliminated mode’s own decay rate, from its intrinsic_decay_rate() (e.g. a resonator’s combined 2π·f_mode/Q photon loss plus 1/T1), or 0.0 when the mode declares no decay channel.

A mode touching two or more survivors additionally emits an "exchange" entry describing the mediated survivor-survivor coupling(s) derived from the Sylvester/exact pair extraction (quchip.chip.sw). For exactly two survivors (the bridge case) this is a single dict: {"j_eff", "dJ_domega_c", "between", "folded_into", "zz", "pathways"}. For three or more survivors, every survivor pair induces its own mediated exchange, so "exchange" is instead a dict keyed by the pair (label_a, label_b), each value the same per-pair schema. In both cases: j_eff is the mediated exchange J = g_a g_b / 2 · (1/Δ_a + 1/Δ_b) (F. Yan et al., Phys. Rev. Applied 10, 054062 (2018)), read off the method="sw"/"exact" pair extraction; dJ_domega_c is its analytic derivative w.r.t. the eliminated mode’s frequency (used by the flux-drive retarget rule); folded_into is the label of the effective edge the exchange landed on (an existing direct coupling between the pair, or a freshly emitted Capacitive or TunableCapacitive); zz is the exact residual ZZ between the pair (method="exact" only — None under "sw", where it is a higher-order correction not represented); pathways is the top virtual-state attribution of the exchange (method="sw" only, from quchip.chip.sw.pathway_attribution()None under "exact", which has no perturbative generator to attribute).

Type:

dict[str, Any]

validity

Per eliminated coupling: {coupling_label: {"g_over_delta", "is_valid", "min_block_gap"}}. min_block_gap is the smallest bare-energy gap the Sylvester generator crossed for this mode (quchip.chip.sw.sylvester_generator()), shared across every coupling touching the mode. When eliminate runs under jax.jit/grad, is_valid (g_over_delta < 0.1) is a traced boolean, not a Python bool — read it outside the traced region, or branch on it with jnp.where rather than if.

Type:

dict[str, Any]

notes

Explicitly dropped physics (counter-rotating, transients, higher order).

Type:

list[str]

Every mapping above is a :class:`~quchip.utils.labeling.LabelKeyedDict`
the device or coupling *object* is as good a key as its label, and pair
keys match in either order
``res.effective_params[q1]``, ``res.validity[leg]``, and
``exchange[(q1, q0)]`` all resolve.
chip: Chip
effective_params: dict[str, Any]
validity: dict[str, Any]
notes: list[str]
describe()[source]

Plain-text fold report: every fold stated explicitly, before -> after.

Per survivor: freq (and T1 when either side carries one), each Lamb-shifted/Purcell-folded value read back from effective_params rather than a stored “before” chip — freq_before = freq_after - lamb_shift and T1_before from purcell_rate are exact identities of how eliminate() derives freq_after/T1, not an approximation. Multi-survivor targets add the emitted exchange edge (Yan-formula tag) and a ZZ line (placeholder under method="sw", the exact residual under method="exact"); any control-line retarget and the per-coupling validity verdict follow. Traced parameters render as <traced> and are never concretized; for use outside jit/grad regions, like every other describe() in the package.

Return type:

str

quchip.chip.eliminate(chip, target, *, method='sw')[source]

Reduce a far-detuned device or an edge coupling, returning a reduced chip.

target is resolved against the chip’s device and coupling namespaces (disjoint by construction — Chip rejects a coupling label that collides with a device label) and dispatches to one of two model reductions:

  • Device target — adiabatic elimination of a far-detuned mode, via quchip.chip.sw. A mode touching one survivor folds into a Lamb shift (and a Purcell channel when the mode dissipates). A mode touching two or more survivors — bus / tunable-coupler (bridge) or several at once — additionally induces a mediated exchange J = g_a g_b / 2 · (1/Δ_a + 1/Δ_b) between every survivor pair (with ∂J/∂ω_c recorded alongside it), folded into the direct coupling between that pair when one exists or added as a new edge otherwise. A fixed eliminated mode emits a Capacitive; a mode that declares frequency control, has a retargeted flux line, or folds into an already-modulable edge emits a TunableCapacitive. At a tunable coupler’s idle point, its g_0 is the net coupling the pair feels, including any direct-edge cancellation. Eliminating several couplers is sequential composition: eliminate(eliminate(chip, "TC1").chip, "TC2").

  • Coupling target — dispersive reduction of an exchange edge to its dressed cross-Kerr shift: both endpoint devices survive (Lamb-shifted), and the coupling itself is replaced by a CrossKerr carrying the dressed pull (see reduce_coupling()). This is the effective-readout-chip flow — reduce a qubit-resonator exchange edge to the diagonal interaction an ordinary charge line probes. method has no effect here: no mode is removed, so the reduction always reads the chip’s exact dressed spectrum.

Parameters:
  • chip (Chip) – Source chip (never mutated).

  • target (Any) – The device or coupling to eliminate — label string or object.

  • method (str) – Device targets only. "sw" (default) is the 2nd-order Schrieffer-Wolff reduction (Bravyi, DiVincenzo & Loss, Ann. Phys. 326, 2793 (2011)) — cheap, differentiable, and what every effective parameter above is derived from perturbatively. "exact" instead reads the reduced parameters off the chip’s exact dressed spectrum (exact-from-dressing, quchip.chip.sw.exact_reduction()) — exact kept-block energies (what residual ZZ needs) at the cost of a full diagonalization, and it raises when near-degenerate dressed states make the bare labeling ambiguous. Any other value raises ValueError.

Return type:

EliminationResult

Examples

>>> from quchip import DuffingTransmon, Resonator, Capacitive, Chip
>>> from quchip.chip.transformations import eliminate
>>> q = DuffingTransmon(freq=5.0, anharmonicity=-0.25, levels=3, label="q")
>>> r = Resonator(freq=7.0, levels=5, label="r")
>>> chip = Chip([q, r], couplings=[Capacitive(q, r, g=0.05)])
>>> result = eliminate(chip, r)          # r removed; Lamb shift folded into q.freq
>>> reduced = result.chip
>>> [d.label for d in reduced.devices]
['q']
class quchip.chip.ActivePatchResult(chip, sequence, active_labels, eliminated_labels, steps, notes)[source]

Bases: object

A reduced patch chip, the re-bound sequence, and the reduction’s honesty record.

Parameters:
chip

The patch chip: schedule-active devices plus whatever spectators active_patch() could not eliminate (unreachable, or where elimination itself declined — see notes).

Type:

Any

sequence

A QuantumSequence bound to chip, replaying the source sequence’s entries verbatim.

Type:

Any

active_labels

Sorted schedule-active device labels (never eliminated).

Type:

tuple[str, …]

eliminated_labels

Device labels actually folded away, in elimination order (farthest-from-active first).

Type:

tuple[str, …]

steps

The EliminationResult from each successful eliminate() call, verbatim and in eliminated_labels order — reshape nothing here; read .validity/.effective_params off the step objects through the convenience properties below.

Type:

tuple

notes

Every explicitly dropped or deferred piece of physics: unreachable spectators left in place, control lines stripped as unused, and (if elimination itself couldn’t proceed past some spectator) why the reduction stopped early — plus every step’s own notes.

Type:

tuple[str, …]

chip: Any
sequence: Any
active_labels: tuple[str, ...]
eliminated_labels: tuple[str, ...]
steps: tuple
notes: tuple[str, ...]
property validity: dict[str, Any]

{eliminated label: that step's .validity} — verbatim, per-coupling shape untouched.

property effective_params: dict[str, Any]

{eliminated label: that step's .effective_params} — verbatim, per-survivor shape untouched.

simulate(**kwargs)[source]

Solve the patch sequence (automatic partitioning still applies inside).

Parameters:

kwargs (Any)

Return type:

Any

quchip.chip.active_patch(sequence, *, hops=1, method='sw')[source]

Reduce a chip to its schedule-active patch by eliminating spectators.

Spectators are eliminated one at a time via eliminate(), farthest-from-active first; every step’s validity metrics ride on the result untouched. Explicit opt-in — this approximates (Schrieffer-Wolff, or the exact dressed-spectrum route under method="exact"), unlike the exact automatic partitioning simulate() performs internally at solve time.

The elimination order and reachability are recomputed from the current reduced chip before every step, not just once up front: a fold can only ever add a bridging edge between the eliminated mode’s neighbors, never remove one, so a label’s distance from the active set can shorten but never make a previously reachable label unreachable — still, reading the graph fresh each time means a label that has already been folded away is never re-considered, and the order always reflects what eliminate will actually see. Bridging edges created by earlier folds may be Capacitive edges carrying g or TunableCapacitive edges carrying g_0. Both fold onward, so cycles among spectators reduce all the way down. If eliminate still declines a step (its typed NotImplementedError signal for an unsupported elimination — e.g. a Purcell decay fold onto a survivor that carries thermal occupation, which no collapse-channel API can represent without inventing physics that was never present), the reduction stops there: everything eliminated so far stays folded, and the remaining spectators — including the one that failed — are left on the patch chip untouched, with the reason recorded in notes.

Parameters:
  • sequence (QuantumSequence) – The schedule to reduce around.

  • hops (int) – Coupling-graph hops the active set expands beyond the scheduled targets (see active_labels()).

  • method (str) – Forwarded to eliminate() for every device elimination.

Return type:

ActivePatchResult

quchip.chip.register_retarget_rule(drive_type, target_type, result_kind, rule)[source]

Register a converter for (drive type, eliminated-target type, result kind).

Lookup (lookup_retarget_rule()) walks both types’ MROs, so a rule registered for a base type also covers its subclasses; result_kind matches exactly. This is the extension point for teaching eliminate() to carry a new kind of stranded control line without modifying it.

Parameters:
  • drive_type (type) – Control-line class the rule handles.

  • target_type (type) – Eliminated-target class the rule handles: a device type (the eliminated mode itself) for "edge"/"leaf-fold".

  • result_kind (str) – "edge", "leaf-fold", or "crosskerr".

  • rule (callable) – rule(line, ctx: RetargetContext) -> RetargetResult.

Return type:

None

quchip.chip.register_elimination_target(target)[source]

Register an EliminationTarget kind for eliminate() to dispatch on.

Parameters:

target (EliminationTarget)

Return type:

None

quchip.chip.register_reduction_method(method)[source]

Register a reduction strategy under its ReductionMethod.name.

Parameters:

method (ReductionMethod)

Return type:

None

Modules

analysis

Dressed-state analysis owned by quchip.chip.chip.Chip.

baths

Chip-level baths — shared / collective Lindblad dissipation.

chip

Composite quantum system — Chip bundles devices, couplings, and control.

coupling_base

Coupling base class and registry.

couplings

Coupling models for two-body interactions between devices.

describe

Human-readable text summaries — the describe() surface.

dressing

JAX-traceable dressed-state labeling primitives.

observables

Observable construction for Chip.

partition

Exact subsystem partitioning — connected components of a chip's independence graph.

retarget

Retarget registry: convert control lines stranded by eliminate() (spec §6.4).

rwa

Structural rotating-wave kernels for coupling RWA policy.

serialization

Chip serialization, deserialization, and structural cloning.

states

State factories for Chip.

sw

Schrieffer-Wolff reduction kernels (2nd order) on bare chip blocks.

transformations

Model reduction: eliminate() and its device/coupling target registry.