BoTorch Acquisition Wrapper

BoTorchAcquisition is a generic wrapper that exposes BoTorch’s analytic and Monte Carlo acquisition functions (qEI, qLogEI, qNEI, qUCB, and their analytic counterparts) through the ALF AcquisitionFunction interface, so strategies can be swapped via a single acquisition_type argument.

It operates in two modes: when the search function provides candidates, it scores the discrete pool; when the candidate list is empty (e.g. with BotorchContinuousSearch), it optimises the acquisition function directly in continuous space via BoTorch’s optimize_acqf, which requires the bounds parameter. Monte Carlo variants are configured with a BoTorchMCSampler; scipy optimiser behaviour is controlled via BoTorchAcquisitionOptConfig.

Batch acquisition (batch_size > 1) requires a surrogate with a joint posterior — a native BoTorch model or an ALF model exposing a trained botorch_model. Marginal-only predict()-based surrogates can only supply a diagonal posterior, so requesting batch_size > 1 with one raises a ValueError; score them one point at a time, or use ALF’s native CoreSet/ThompsonSampling acquisitions for batch selection.

Generic BoTorch acquisition function wrapper for ALF.

This module provides a unified interface to all BoTorch acquisition functions, making it easy to switch between different acquisition strategies.

class alf_tools.optimizer.acquisition_functions.botorch_acquisition.BoTorchAcquisition(acquisition_type, sampler=None, bounds=None, num_restarts=10, raw_samples=512, batch_size=1, sequential=False, beta=0.2, optimization_config=None, **kwargs)[source]

Bases: AcquisitionFunction

Generic wrapper for BoTorch acquisition functions.

This class provides a unified interface to switch between different BoTorch acquisition functions without changing code structure. It supports both: 1. Discrete mode: Score a provided pool of candidates 2. Continuous mode: Optimize acquisition function directly

Supported acquisition functions: - qEI (qExpectedImprovement): Standard batch expected improvement - qLogEI (qLogExpectedImprovement): Log batch expected improvement - qNEI (qNoisyExpectedImprovement): For noisy observations - qUCB (qUpperConfidenceBound): Upper confidence bound with exploration bonus

Example - Switching acquisition functions:
>>> from alf_tools.optimizer.acquisition_functions import (
...     BoTorchAcquisition, BoTorchMCSampler
... )
>>> from alf_tools.optimizer.search import BotorchContinuousSearch
>>>
>>> # Create sampler configuration
>>> sampler = BoTorchMCSampler(sampler_type="sobol", num_samples=512)
>>>
>>> # Try different acquisition functions
>>> acq_qei = BoTorchAcquisition(
...     acquisition_type="qEI",
...     sampler=sampler,
...     bounds=[[0, 1], [0, 1]]
... )
>>>
>>> acq_qucb = BoTorchAcquisition(
...     acquisition_type="qUCB",
...     sampler=sampler,
...     bounds=[[0, 1], [0, 1]],
...     beta=0.2  # Exploration parameter for UCB
... )
>>>
>>> # Use in optimizer
>>> from alf_core import Optimizer
>>> optimizer = Optimizer(
...     acquisition_fn=acq_qei,  # or acq_qucb
...     search_fn=BotorchContinuousSearch()
... )
Parameters:
  • acquisition_type (Literal['qEI', 'qLogEI', 'qNEI', 'qUCB', 'log_expected_improvement', 'upper_confidence_bound', 'probability_of_improvement', 'log_noisy_expected_improvement']) – Type of acquisition function. Options: - “qEI”: Expected Improvement (general purpose) - “qLogEI”: Log Expected Improvement (See [Ament2023logei] for details.) - “qNEI”: Noisy Expected Improvement (for noisy observations) - “qUCB”: Upper Confidence Bound (tunable exploration)

  • sampler (BoTorchMCSampler | None) – BoTorchMCSampler configuration or None for analytic acquisition. If None, uses default Sobol sampler with 512 samples.

  • bounds (list[list[float]] | None) – Bounds for continuous optimization. List of [lower, upper] for each dimension. Example: [[0, 1], [0, 1]] for 2D unit cube. Required for continuous optimization mode.

  • num_restarts (int) – Number of random restarts for optimization. Default: 10.

  • raw_samples (int) – Number of initial random samples for optimization. Default: 512.

  • batch_size (int) – Batch size for acquisition (q). Default: 1.

  • sequential (bool) – If True, optimize candidates sequentially (faster but less diverse). If False, jointly optimize (slower but better diversity). Default: False.

  • beta (float) – Exploration parameter for qUCB. Higher = more exploration. Default: 0.2. Only used when acquisition_type=”qUCB”.

  • optimization_config (BoTorchAcquisitionOptConfig | None) – Scipy optimizer options forwarded to optimize_acqf. If None, uses BoTorchAcquisitionOptConfig defaults.

  • kwargs – Additional keyword arguments passed to the specific acquisition function.

Raises:

ValueError – If acquisition_type is not supported.

class alf_tools.optimizer.acquisition_functions.botorch_acquisition.BoTorchAcquisitionOptConfig(batch_limit=64, maxiter=300, nonnegative=False, sample_around_best=True, sample_around_best_sigma=0.1)[source]

Bases: object

Configuration for acquisition function optimization.

These options are passed directly to BoTorch’s optimize_acqf via the options dict, which is forwarded to the underlying scipy optimizer (gen_candidates_scipy).

Parameters:
  • batch_limit (int) – Maximum number of candidate points processed in a single batch during optimization. Smaller values reduce memory usage at the cost of more iterations. Default: 64.

  • maxiter (int) – Maximum number of scipy L-BFGS-B iterations per restart. Default: 300.

  • nonnegative (bool) – If True, constrain candidate values to be non-negative during optimization. Default: False.

  • sample_around_best (bool) – If True, draw initial raw samples concentrated around the current best observed point in addition to global random samples. Improves warm-starting of local optimization. Default: True.

  • sample_around_best_sigma (float) – Standard deviation of the Gaussian noise added around the best point when sample_around_best is True. Default: 0.1.

batch_limit: int = 64
maxiter: int = 300
nonnegative: bool = False
sample_around_best: bool = True
sample_around_best_sigma: float = 0.1