Source code for mixle.doe._contracts

"""Structural (duck-typed) contracts for the DOE layer, as runtime-checkable Protocols (WS-E).

The DOE layer follows a "register, don't branch" pattern: acquisition functions go through
:func:`mixle.doe.bayesopt.register_acquisition`, optimality criteria through
:func:`mixle.doe.optimal.register_criterion`, and the GP surrogate is passed in as a duck-typed
``gp=`` argument. This module formalizes those three contracts as ``@runtime_checkable`` Protocols
so the registry value types and the ``gp=`` parameters can be annotated precisely (instead of bare
``Callable[..., ...]`` / ``Any``), and so a surrogate can be validated with ``isinstance``.

These are typing-level only: they add no behavior and the registries / call sites are unchanged.
"""

from __future__ import annotations

from typing import Any, Protocol, runtime_checkable

import numpy as np


[docs] @runtime_checkable class Acquisition(Protocol): """The acquisition-function contract registered via ``register_acquisition`` (EI/PI/UCB). An acquisition scores candidate points from their surrogate posterior moments and returns a *merit* array that the proposal loop maximizes over the candidate set. It is called as ``fn(mean, std, best, *, maximize, **params)`` where ``mean`` / ``std`` are the predictive mean and standard deviation at the candidates, ``best`` is the incumbent objective value, ``maximize`` selects the optimization sense, and ``**params`` carries per-acquisition knobs (e.g. ``xi`` for EI/PI, ``kappa`` for UCB). Built-ins :func:`mixle.doe.bayesopt.expected_improvement`, :func:`probability_of_improvement`, and :func:`upper_confidence_bound` satisfy this contract. """ def __call__(self, mean: Any, std: Any, best: float, *, maximize: bool = ..., **params: Any) -> np.ndarray: ...
[docs] @runtime_checkable class Surrogate(Protocol): """The GP-surrogate contract passed as ``gp=`` to the Bayesian-optimization loops. A surrogate is fit to the observed ``(x, y)`` and queried for the posterior predictive moments at new candidate points. The call convention is the one used by :class:`mixle.models.gaussian_process.GaussianProcessRegressor`: ``fit`` trains in place (it may return diagnostics, which the loops ignore), and ``predict`` takes the training data alongside the query points, returning the posterior mean (``return_cov=False``) or ``(mean, cov)`` pair (``return_cov=True``). """
[docs] def fit(self, x: Any, y: Any, **kwargs: Any) -> Any: ...
[docs] def predict(self, x_train: Any, y_train: Any, x_new: Any, return_cov: bool = ...) -> Any: ...
[docs] @runtime_checkable class Criterion(Protocol): """The optimality-criterion contract registered via ``register_criterion`` (D/A/I-optimality). A criterion maps the information matrix ``M = F.T @ F`` to a scalar *merit* that :func:`mixle.doe.optimal.optimal_design` maximizes over candidate designs. It is called as ``fn(info, *, ref)`` where ``ref`` is an optional reference model matrix (used by I-optimality). Built-ins :func:`mixle.doe.optimal.d_criterion`, :func:`a_criterion`, and :func:`i_criterion` satisfy this contract. """ def __call__(self, info: np.ndarray, *, ref: np.ndarray | None = ...) -> float: ...
__all__ = ["Acquisition", "Surrogate", "Criterion"]