Source code for saealib.acquisition.pof

"""Probability of Feasibility (PoF) acquisition function module."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

import numpy as np
from scipy.stats import norm

from saealib.acquisition.base import AcquisitionFunction
from saealib.surrogate.prediction import SurrogatePrediction

if TYPE_CHECKING:
    from saealib.population import Archive


[docs] class ProbabilityOfFeasibility(AcquisitionFunction): """ Probability of Feasibility (PoF) acquisition function. Estimates the probability that a candidate satisfies a constraint g(x) <= 0, using a surrogate model that predicts the constraint value. PoF(x) = Phi((0 - mu(x)) / sigma(x)) Typically used in combination with another acquisition function (e.g., EI * PoF) to handle black-box constraints. Requires a surrogate that provides uncertainty estimates (std). Parameters ---------- obj_idx : int Index of the predicted constraint to evaluate. Default: 0. """ requires_uncertainty: bool = True
[docs] def __init__(self, obj_idx: int = 0, reference: Any = None): self.obj_idx = obj_idx self.reference = reference
[docs] def compute_reference(self, archive: Archive) -> Any: """Return fixed reference if set, otherwise None.""" return self.reference
[docs] def score( self, prediction: SurrogatePrediction, reference: Any = None, ) -> np.ndarray: """ Compute Probability of Feasibility scores. Parameters ---------- prediction : SurrogatePrediction Surrogate predictions of constraint values. Must have std (has_uncertainty == True). reference : Any Not used. Accepted for interface compatibility. Returns ------- np.ndarray PoF scores in [0, 1]. shape: (n_samples,) Higher scores indicate a higher probability of feasibility. Raises ------ TypeError If prediction does not contain uncertainty estimates. """ if not prediction.has_uncertainty: raise TypeError( "ProbabilityOfFeasibility requires a surrogate with uncertainty " "estimates (prediction.std must not be None)." ) mu = prediction.value[:, self.obj_idx] # (n_samples,) sigma = prediction.std[:, self.obj_idx] # (n_samples,) sigma = np.maximum(sigma, 1e-9) return norm.cdf((0.0 - mu) / sigma) # P(g(x) <= 0)