Source code for sparho.state

"""Result and state dataclasses for the inner solver and outer search.

All dataclasses are ``frozen=True, slots=True``. Outer-search state is built
incrementally as an immutable ``tuple`` of ``IterationRecord``; there is no
mutable monitor.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any

from .core.types import Array, Hyperparam, IndexArray

# ---------------------------------------------------------------- Inner solver


[docs] @dataclass(frozen=True, slots=True) class SolverResult: """Outcome of one inner solve at a fixed hyperparameter. Parameters ---------- coef Estimated coefficient vector ``β̂``. active_set Integer indices ``j`` where ``β̂ⱼ ≠ 0``. Sorted ascending. ``int32`` to match scipy.sparse CSC index types — the hypergradient linear solve restricts to this set. dual_gap Final duality gap (or a non-negative proxy for it). Used to assert inner-loop convergence at the tolerance the adapter targeted. n_iter Number of inner iterations the adapter consumed. extras Adapter-specific escape hatch. SVM/SVR adapters in a future phase will stash the converged dual variable here. """ coef: Array active_set: IndexArray dual_gap: float n_iter: int extras: dict[str, Any] = field(default_factory=dict)
# ---------------------------------------------------------------- Outer search
[docs] @dataclass(frozen=True, slots=True) class IterationRecord: """One outer-loop snapshot. Tuples of these form a ``SearchResult.history``.""" iteration: int hyperparam: Hyperparam value: float grad_norm: float n_inner_iter: int
[docs] @dataclass(frozen=True, slots=True) class SearchState: """In-flight outer-loop state, threaded through ``grad_search``'s for-loop. Each algorithmic step is a pure function ``(state, ...) -> state``; ``grad_search`` is the only place the loop is written imperatively. """ iteration: int hyperparam: Hyperparam value: float grad: Array solver_result: SolverResult optimizer_state: Any # opaque, per-optimizer; pickleable but not introspected history: tuple[IterationRecord, ...]
[docs] @dataclass(frozen=True, slots=True) class SearchResult: """Final outcome of ``grad_search``.""" best_hyperparam: Hyperparam best_coef: Array history: tuple[IterationRecord, ...] converged: bool n_iter: int