Source code for quchip.inverse_design.observables

"""Target compilation for :func:`quchip.fit_a_dress`.

Targets come from component declarations and explicit constraints, without
diagonalizing the desired model.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any

from quchip.utils.labeling import resolve_label


_DRESSED_KIND_ALIASES = {
    "g": "coupling_strength",
    "coupling_strength": "coupling_strength",
    "chi": "cross_kerr",
    "cross_kerr": "cross_kerr",
    "static_zz": "cross_kerr",
    "zz": "cross_kerr",
    "exchange": "exchange_rate",
    "exchange_rate": "exchange_rate",
    "freq": "freq",
    "anharmonicity": "anharmonicity",
}


[docs] @dataclass(frozen=True) class TargetSpec: """A single optimization target. Attributes ---------- kind Observable kind. One of ``"freq"``, ``"anharmonicity"``, ``"cross_kerr"``, ``"exchange_rate"``, ``"coupling_strength"``. label Device label, ``(label_a, label_b)`` tuple, or coupling label that locates this target on the chip. target Desired value in GHz. source Origin: ``"component default"`` or ``"explicit"``. """ kind: str label: Any target: float source: str = "explicit"
def _normalize_dressed_kind(kind: object) -> str: """Return the canonical desired-chip observable name for *kind*.""" name = str(kind) try: return _DRESSED_KIND_ALIASES[name] except KeyError as exc: available = sorted(set(_DRESSED_KIND_ALIASES.values())) raise ValueError(f"Unknown dressed constraint {name!r}. Available canonical names: {available}.") from exc def _resolve_target_locator(locator: Any) -> Any: """Normalize a component or pair locator without evaluating a chip.""" if isinstance(locator, tuple): if len(locator) != 2: raise ValueError(f"Pair constraints require exactly two device objects or labels, got {locator!r}.") return tuple(resolve_label(part) for part in locator) return resolve_label(locator)
[docs] def build_dressed_target_specs( chip, constraints: dict | None = None, ) -> tuple[TargetSpec, ...]: """Compile a desired chip's declared numbers into dressed constraints. Compilation never calls a dressed-analysis method on ``chip``. Devices and couplings supply their component-owned defaults. Explicit constraints extend those defaults, replace the same ``(kind, locator)`` entry, or remove it with ``None``. Parameters ---------- chip Numerical desired-chip specification. constraints Optional ``{component_or_pair: {observable: value_or_none}}`` mapping. Pair locators do not have to agree with a direct coupling edge. """ keyed: dict[tuple[str, Any], TargetSpec] = {} for device in chip.devices: for kind, value in device.default_dressed_targets().items(): canonical = _normalize_dressed_kind(kind) spec = TargetSpec(canonical, device.label, float(value), "component default") keyed[(spec.kind, spec.label)] = spec for coupling in chip.couplings: kind, value = coupling.default_dressed_target() canonical = _normalize_dressed_kind(kind) spec = TargetSpec(canonical, coupling.label, float(value), "component default") keyed[(spec.kind, spec.label)] = spec if constraints is None: return tuple(keyed.values()) if not isinstance(constraints, dict): raise TypeError(f"constraints must be None or a dict, got {type(constraints).__name__}") for raw_locator, metrics in constraints.items(): locator = _resolve_target_locator(raw_locator) if not isinstance(metrics, dict): raise TypeError( "constraints values must be dicts mapping observable names to " f"numeric values or None, got {type(metrics).__name__} for {locator!r}." ) for raw_kind, value in metrics.items(): kind = _normalize_dressed_kind(raw_kind) key = (kind, locator) if value is None: keyed.pop(key, None) else: keyed[key] = TargetSpec(kind, locator, float(value), "explicit") return tuple(keyed.values())