"""Component labels and lookup by object or label.
A component without an explicit label gets ``"{prefix}_{n}"``. Each prefix has
a process-wide counter starting at zero. Labels identify components in a chip.
:func:`resolve_label` accepts the component or its label. Use
:func:`reset_label_counters` to get deterministic labels in tests.
"""
from __future__ import annotations
from typing import Any, Mapping, Sequence
import numpy as np
_label_counters: dict[str, int] = {}
[docs]
def auto_label(prefix: str) -> str:
r"""Return the next ``"{prefix}_{n}"`` label, where each prefix starts at zero.
Parameters
----------
prefix : str
Prefix of the component type. Each prefix has its own process-wide counter.
"""
idx = _label_counters.get(prefix, 0)
_label_counters[prefix] = idx + 1
return f"{prefix}_{idx}"
[docs]
def reset_label_counters() -> None:
"""Reset the process-wide label counters, usually in test fixtures."""
_label_counters.clear()
[docs]
def resolve_label(obj: str | Any) -> str:
r"""Return a string label from a string or a labeled component.
Raise ``TypeError`` if the object has no usable label.
Parameters
----------
obj : str or object
A label string, returned unchanged, or an object with a non-None label attribute.
"""
if isinstance(obj, str):
return obj
label = getattr(obj, "label", None)
if label is None:
raise TypeError(
f"Expected a label string or an object with .label, got {type(obj).__name__}: {obj!r}"
)
return str(label)
[docs]
def merge_labeled_values(
mapping: Mapping[Any, Any] | None,
kwargs: Mapping[str, Any],
) -> dict[str, Any]:
"""Merge object-or-label keys and keyword arguments into a dict with label keys.
Duplicate labels raise ``ValueError``, including a label supplied through
both inputs. Values pass through unchanged, and callers validate their types
and bounds.
"""
merged: dict[str, Any] = {}
if mapping is not None:
for key, value in mapping.items():
label = resolve_label(key)
if label in merged:
raise ValueError(f"Duplicate device specification for '{label}'")
merged[label] = value
for label, value in kwargs.items():
if label in merged:
raise ValueError(f"Duplicate device specification for '{label}'")
merged[label] = value
return merged
[docs]
def bare_label_from_mapping(
device_labels: Sequence[str],
mapping: Mapping[Any, Any] | None,
kwargs: Mapping[str, Any],
) -> tuple[int, ...]:
"""Build a bare-state tuple in ``device_labels`` order from a partial mapping.
Keys can be devices or labels. Unspecified devices get the default Fock index
zero. Unknown or duplicate labels raise ``ValueError``. Callers validate
values.
"""
merged = merge_labeled_values(mapping, kwargs)
unknown = sorted(set(merged) - set(device_labels))
if unknown:
raise ValueError(f"Unknown device labels {unknown}. Available labels: {list(device_labels)}")
return tuple(merged.get(label, 0) for label in device_labels)
[docs]
class LabelKeyedDict(dict):
"""Result mapping with label keys that also accepts component objects.
Tuple keys with two elements match in each order. Iteration and serialization show
the stored keys.
"""
@staticmethod
def _canonical(key: Any) -> Any:
"""Resolve *key* (or each element of a tuple key) to its label form."""
try:
if isinstance(key, tuple):
return tuple(resolve_label(part) for part in key)
return resolve_label(key)
except TypeError:
return key # keys that are neither labels nor labeled objects pass through
def __getitem__(self, key: Any) -> Any:
"""Find *key*, and use the reversed 2-tuple key if the forward order does not match."""
resolved = self._canonical(key)
if not super().__contains__(resolved) and isinstance(resolved, tuple) and len(resolved) == 2:
reordered = resolved[::-1]
if super().__contains__(reordered):
resolved = reordered
return super().__getitem__(resolved)
def __contains__(self, key: Any) -> bool:
"""Report membership, and match the reversed 2-tuple key if the forward order does not match."""
resolved = self._canonical(key)
if super().__contains__(resolved):
return True
return isinstance(resolved, tuple) and len(resolved) == 2 and super().__contains__(resolved[::-1])
[docs]
def get(self, key: Any, default: Any = None) -> Any:
"""Return the value for *key*, or *default* if *key* is absent (through :meth:`__getitem__`)."""
try:
return self[key]
except KeyError:
return default
[docs]
def top_components(
eigenvector_matrix: Any,
bare_labels: Sequence[tuple[int, ...]],
dressed_idx: int,
n: int,
) -> dict[tuple[int, ...], float]:
"""Return the top ``n`` bare-basis probabilities of a dressed eigenvector.
It pairs the squared amplitudes from column ``dressed_idx`` with bare
labels in descending order. It requires a concrete eigenvector matrix.
"""
probs = np.asarray(np.abs(eigenvector_matrix[:, dressed_idx]) ** 2, dtype=float)
order = np.argsort(probs)[::-1][:n]
return {bare_labels[idx]: float(probs[idx]) for idx in order}