Result and state dataclasses

All result types are frozen=True, slots=True dataclasses. The outer search history is an immutable tuple[IterationRecord, ...] — there is no mutable monitor.

class sparho.SolverResult[source]

Bases: object

Outcome of one inner solve at a fixed hyperparameter.

Parameters:
  • coef (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.floating]]) – Estimated coefficient vector β̂.

  • active_set (numpy.ndarray[tuple[Any, ...], numpy.dtype[numpy.int32]]) – 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 (float) – Final duality gap (or a non-negative proxy for it). Used to assert inner-loop convergence at the tolerance the adapter targeted.

  • n_iter (int) – Number of inner iterations the adapter consumed.

  • extras (dict[str, Any]) – Adapter-specific escape hatch. SVM/SVR adapters in a future phase will stash the converged dual variable here.

coef: ndarray[tuple[Any, ...], dtype[floating]]
active_set: ndarray[tuple[Any, ...], dtype[int32]]
dual_gap: float
n_iter: int
extras: dict[str, Any]
__init__(coef, active_set, dual_gap, n_iter, extras=<factory>)
Parameters:
Return type:

None

class sparho.IterationRecord[source]

Bases: object

One outer-loop snapshot. Tuples of these form a SearchResult.history.

extras is a mapping of optional diagnostics keyed by short strings (e.g. "cg_nonconvergence", "cg_nonfinite") — populated by the search loop when implicit-diff fails. The schema is stability-experimental (see docs/stability.md). Defaults to an empty dict; treat it as read-only — the record is frozen, but Python can’t enforce mapping immutability without breaking pickle on 3.11.

iteration: int
hyperparam: float | ndarray[tuple[Any, ...], dtype[floating]]
value: float
grad_norm: float
n_inner_iter: int
extras: Mapping[str, object]
__init__(iteration, hyperparam, value, grad_norm, n_inner_iter, extras=<factory>)
Parameters:
Return type:

None

class sparho.SearchState[source]

Bases: object

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: float | ndarray[tuple[Any, ...], dtype[floating]]
value: float
grad: ndarray[tuple[Any, ...], dtype[floating]]
solver_result: SolverResult
optimizer_state: Any
history: tuple[IterationRecord, ...]
__init__(iteration, hyperparam, value, grad, solver_result, optimizer_state, history)
Parameters:
Return type:

None

class sparho.SearchResult[source]

Bases: object

Final outcome of grad_search.

best_hyperparam: float | ndarray[tuple[Any, ...], dtype[floating]]
best_coef: ndarray[tuple[Any, ...], dtype[floating]]
history: tuple[IterationRecord, ...]
converged: bool
n_iter: int
__init__(best_hyperparam, best_coef, history, converged, n_iter)
Parameters:
Return type:

None