Source code for confopt.selection.sampling.bound_samplers

"""
Bound-based acquisition strategies for conformal prediction optimization.

This module implements acquisition strategies that use prediction interval bounds
for optimization decisions. The approaches focus on conservative uncertainty
quantification through lower bound sampling and exploration-exploitation
trade-offs through adaptive confidence bound strategies.

Bound-based methodology:
These samplers utilize specific bounds (typically lower bounds for minimization)
from prediction intervals to make acquisition decisions. This approach provides
direct interpretable acquisition values while maintaining proper uncertainty
quantification through conformal prediction intervals.

Key strategies:
- Pessimistic Lower Bound: Conservative approach using only lower bounds
- Lower Confidence Bound (LCB): UCB-style exploration with decay schedules
- Adaptive interval width adjustment based on coverage feedback

The module provides both simple bound-based acquisition and sophisticated
exploration strategies with theoretical guarantees for convergence in
optimization under uncertainty scenarios.
"""

from typing import Optional, List, Literal
import numpy as np
from confopt.selection.sampling.utils import (
    initialize_single_adapter,
    update_single_interval_width,
)


[docs] class PessimisticLowerBoundSampler: """ Conservative acquisition strategy using pessimistic lower bounds. This sampler implements a conservative approach to uncertainty quantification by focusing exclusively on the lower bounds of prediction intervals. The strategy prioritizes risk-averse decision making by assuming pessimistic scenarios, making it suitable for applications where conservative estimates are preferred over aggressive exploration. The approach provides simple, interpretable acquisition values while maintaining proper uncertainty quantification through conformal prediction intervals. The single-interval design offers computational efficiency and straightforward interpretation. Methodological characteristics: - Single confidence level with configurable interval width - Direct lower bound extraction for acquisition decisions - Optional adaptive interval width adjustment - Conservative bias suitable for risk-averse optimization """ def __init__( self, interval_width: float = 0.8, adapter: Optional[Literal["DtACI", "ACI"]] = None, ): """ Initialize pessimistic lower bound sampler with specified confidence level. Args: interval_width: Confidence level for prediction intervals (e.g., 0.8 for 80% intervals). Higher values provide wider intervals with more conservative bounds. Typical values: 0.7-0.95. adapter: Interval width adaptation strategy. "DtACI" provides aggressive multi-scale adaptation, "ACI" offers conservative adaptation, None disables adaptation. """ self.interval_width = interval_width self.alpha = 1 - interval_width self.adapter = initialize_single_adapter(self.alpha, adapter)
[docs] def fetch_alphas(self) -> List[float]: """ Retrieve current alpha value for interval construction. Returns: Single-element list containing the current alpha value (miscoverage rate). """ return [self.alpha]
[docs] def update_interval_width(self, beta: float) -> None: """ Update interval width based on observed coverage rate. This method applies adaptive interval width adjustment using empirical coverage feedback. The alpha parameter is updated to maintain target coverage while optimizing interval efficiency for conservative bound estimation. Args: beta: Observed coverage rate for the prediction interval, representing the fraction of true values falling within the interval. """ self.alpha = update_single_interval_width(self.adapter, self.alpha, beta)
[docs] class LowerBoundSampler(PessimisticLowerBoundSampler): """ Lower Confidence Bound acquisition strategy with adaptive exploration. This sampler implements a Lower Confidence Bound (LCB) strategy adapted for minimization problems. The approach balances exploitation of promising regions with exploration of uncertain areas through an adaptive exploration parameter that decays over time, providing theoretical guarantees for convergence. The strategy extends the pessimistic lower bound approach with sophisticated exploration control, making it suitable for efficient optimization under uncertainty with provable regret bounds. Mathematical formulation: LCB(x) = μ(x) - β(t) * σ(x) where μ(x) is the point estimate, σ(x) is the interval width, and β(t) is the time-dependent exploration parameter. Exploration decay strategies: - Inverse square root: β(t) = sqrt(c/t) for aggressive decay - Logarithmic: β(t) = sqrt(c*log(t)/t) for balanced exploration Performance characteristics: - Theoretical regret guarantees under appropriate decay schedules - Adaptive exploration balancing exploitation and uncertainty quantification - Efficient single-interval computation with optional adaptation """ def __init__( self, interval_width: float = 0.8, adapter: Optional[Literal["DtACI", "ACI"]] = None, beta_decay: Optional[ Literal[ "inverse_square_root_decay", "logarithmic_decay", ] ] = "logarithmic_decay", c: float = 1, beta_max: float = 10, ): """ Initialize LCB sampler with exploration decay schedule. Args: interval_width: Confidence level for prediction intervals (e.g., 0.8 for 80% intervals). Higher values provide wider intervals with larger exploration bonuses. adapter: Interval width adaptation strategy for coverage maintenance. beta_decay: Exploration parameter decay strategy. "logarithmic_decay" provides balanced exploration with theoretical guarantees, "inverse_square_root_decay" offers more aggressive decay. c: Exploration constant controlling the magnitude of exploration bonus. Higher values increase exploration, lower values favor exploitation. Typical values: 0.1-10. beta_max: Maximum exploration parameter value to prevent excessive exploration in early iterations. Provides stability for the acquisition function. """ super().__init__(interval_width, adapter) self.beta_decay = beta_decay self.c = c self.t = 1 # Time step counter for decay computation self.beta = 1 # Current exploration parameter self.beta_max = beta_max self.mu_max = float("-inf") # Tracking for potential future use
[docs] def update_exploration_step(self): """ Update exploration parameter based on decay schedule and time step. This method advances the time step and computes the new exploration parameter according to the specified decay strategy. The decay ensures that exploration decreases over time as confidence in the model increases, following theoretical requirements for convergence guarantees. """ self.t += 1 if self.beta_decay == "inverse_square_root_decay": self.beta = np.sqrt(self.c / self.t) elif self.beta_decay == "logarithmic_decay": self.beta = np.sqrt((self.c * np.log(self.t)) / self.t) elif self.beta_decay is None: self.beta = 1 else: raise ValueError( "beta_decay must be 'inverse_square_root_decay', 'logarithmic_decay', or None." )
[docs] def calculate_ucb_predictions( self, point_estimates: np.ndarray = None, half_width: np.ndarray = None, ) -> np.ndarray: """ Calculate Lower Confidence Bound predictions for acquisition. This method computes LCB values by combining point estimates with exploration bonuses based on interval widths and the current exploration parameter. The result provides acquisition values that balance exploitation of promising regions with exploration of uncertain areas. Args: point_estimates: Point predictions (e.g., posterior means) for each candidate. These represent the exploitation component. half_width: Uncertainty estimates (e.g., half interval widths) for each candidate. These drive the exploration component. Returns: Array of LCB acquisition values. Lower values indicate more attractive candidates for minimization problems. """ return point_estimates - self.beta * half_width