Source code for quchip.chip.transformations.dispatch

"""Elimination target registry and the public ``eliminate`` dispatcher.

The unifying abstraction is the :class:`~quchip.chip.chip.Chip` type itself,
not a base class: a transformation consumes a chip and produces a new one, so
transformations compose through ``Chip`` (e.g.
``eliminate(fit_a_dress(chip).chip, "r").chip``). :class:`ChipTransform` is a
thin *structural* protocol capturing only the ``.chip`` output that every
transformation result exposes;
:class:`~quchip.inverse_design.types.FitADressResult` already satisfies it with
no changes.

``eliminate`` performs **model reduction**: it removes a far-detuned mode (or
an edge coupling) and replaces its effect on the survivors with ordinary
owned-Hamiltonian physics — a Lamb shift folded into ``freq``, Purcell decay
folded into ``T1``, mediated exchange folded into a coupling — so the engine
never special-cases the reduction. The approximation
is declared in :attr:`EliminationResult.notes` and
:attr:`EliminationResult.validity`.

Each target *kind* is an :class:`EliminationTarget` — a pair of ``(claims,
reduce)`` closures registered in :data:`_ELIMINATION_TARGETS`. The dispatcher
scans the registry, hands the target to the first kind that claims it, and
falls through to a clear error otherwise. The reductions themselves live in the
sibling handler modules (:mod:`quchip.chip.transformations.eliminate_device`,
:mod:`quchip.chip.transformations.eliminate_coupling`), which register at
import time; the generic P/Q partitioning physics lives in
:mod:`quchip.chip.sw`. This module owns only the registry and the dispatch, so
a new reducible target kind registers here without touching either.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Callable

from quchip.chip.transformations.methods import reduction_method_names
from quchip.chip.transformations.result import EliminationResult
from quchip.utils.labeling import resolve_label

if TYPE_CHECKING:
    from quchip.chip.chip import Chip


[docs] @dataclass(frozen=True) class EliminationTarget: """One registered elimination target kind — how it recognizes a target and reduces it. A new kind registers an instance with :func:`register_elimination_target` at its handler module's bottom; that module must be imported for the side effect (the package ``__init__`` does this for the shipped handlers) — the same registration ritual as :func:`~quchip.chip.retarget.register_retarget_rule`. Attributes ---------- kind A short label for the target kind (``"device"``, ``"coupling"``), for diagnostics. claims ``claims(chip, target) -> bool``: whether this kind owns ``target`` on ``chip`` (e.g. the label names a device, or a coupling). The device and coupling namespaces are disjoint by construction, so at most one kind claims any target. reduce ``reduce(chip, target, method) -> EliminationResult``: performs the reduction. ``method`` is the already-validated route string (a handler that has no notion of a route ignores it). """ kind: str claims: Callable[[Any, Any], bool] reduce: Callable[[Any, Any, str], EliminationResult]
_ELIMINATION_TARGETS: list[EliminationTarget] = []
[docs] def register_elimination_target(target: EliminationTarget) -> None: """Register an :class:`EliminationTarget` kind for :func:`eliminate` to dispatch on.""" _ELIMINATION_TARGETS.append(target)
[docs] def eliminate(chip: "Chip", target: Any, *, method: str = "sw") -> EliminationResult: """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 — :class:`~quchip.chip.chip.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 :mod:`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 :class:`~quchip.chip.couplings.Capacitive`; a mode that declares frequency control, has a retargeted flux line, or folds into an already-modulable edge emits a :class:`~quchip.chip.couplings.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 :class:`~quchip.chip.couplings.CrossKerr` carrying the dressed pull (see :func:`~quchip.chip.transformations.eliminate_coupling.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 Source chip (never mutated). target The device or coupling to eliminate — label string or object. method 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, :func:`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``. Returns ------- 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'] """ if method not in reduction_method_names(): expected = " or ".join(repr(n) for n in sorted(reduction_method_names())) raise ValueError(f"Unknown method {method!r} for eliminate(); expected {expected}.") for spec in _ELIMINATION_TARGETS: if spec.claims(chip, target): return spec.reduce(chip, target, method) raise KeyError(f"'{resolve_label(target)}' is neither a device nor a coupling on chip '{chip.label}'.")