Source code for quchip.approximations

"""Explicit strategies for reducing an authored Hamiltonian."""

from __future__ import annotations

from abc import ABC
from dataclasses import dataclass
from typing import Any, Iterable


def _freeze_bands(value: Iterable[tuple[int, ...]] | None) -> frozenset[tuple[int, ...]] | None:
    """Validate and freeze an optional replacement band selection."""
    if value is None:
        return None
    try:
        bands = frozenset(value)
    except TypeError as error:
        raise TypeError("keep_bands must be an iterable of integer tuples.") from error
    if not bands:
        raise ValueError("keep_bands must contain at least one integer tuple.")
    valid = all(
        isinstance(band, tuple)
        and band
        and all(not isinstance(number, bool) and isinstance(number, int) for number in band)
        for band in bands
    )
    if not valid:
        raise TypeError("keep_bands must be an iterable of non-empty integer tuples.")
    return bands


[docs] class Approximation(ABC): """Immutable engine strategy applied after authored physics is assembled.""" filters_terms: bool = False
[docs] def keeps_operator_band(self, weights: tuple[int, ...]) -> bool: """Return whether a structural operator band survives reduction.""" del weights return True
[docs] def to_dict(self) -> dict[str, Any]: """Return the stable serialized strategy tag.""" if type(self) is Exact: return {"type": "Exact"} if type(self) is RWA: data: dict[str, Any] = {"type": "RWA"} if self.keep_bands is not None: data["keep_bands"] = [list(band) for band in sorted(self.keep_bands)] return data raise TypeError(f"{type(self).__name__} must define its own stable approximation serialization.")
[docs] @staticmethod def from_dict(data: Any) -> "Approximation": """Restore one explicit strategy and reject retired schemas.""" if not isinstance(data, dict): raise TypeError( "approximation must be a serialized Exact or RWA strategy, " f"got {type(data).__name__}." ) strategy_type = data.get("type") if strategy_type == "Exact" and set(data) == {"type"}: return Exact() if strategy_type == "RWA" and set(data) <= {"type", "keep_bands"}: bands = data.get("keep_bands") return RWA(None if bands is None else {tuple(band) for band in bands}) if strategy_type in {"Exact", "RWA"}: fields = sorted(set(data) - {"type", "keep_bands"}) raise TypeError(f"Unsupported serialized approximation fields: {fields}") raise ValueError(f"Unknown approximation strategy {strategy_type!r}.")
[docs] @dataclass(frozen=True) class Exact(Approximation): """Retain every term in the authored finite-dimensional Hamiltonian."""
[docs] @dataclass(frozen=True, init=False) class RWA(Approximation): """First-order structural rotating-wave selection. ``keep_bands`` replaces, rather than extends, total-excitation conservation. """ keep_bands: frozenset[tuple[int, ...]] | None filters_terms = True def __init__(self, keep_bands: Iterable[tuple[int, ...]] | None = None) -> None: object.__setattr__(self, "keep_bands", _freeze_bands(keep_bands))
[docs] def keeps_operator_band(self, weights: tuple[int, ...]) -> bool: if self.keep_bands is not None: return weights in self.keep_bands return sum(weights) == 0
def require_approximation(value: Any) -> Approximation: """Validate a public approximation value without Boolean coercion.""" if not isinstance(value, Approximation): raise TypeError(f"approximation must be an Exact or RWA strategy, got {type(value).__name__}.") return value __all__ = ["Approximation", "Exact", "RWA"]