Source code for baybe.acquisition.utils

"""Utilities for acquisition functions."""

from __future__ import annotations

from typing import TYPE_CHECKING

from baybe.acquisition.base import AcquisitionFunction

if TYPE_CHECKING:
    from botorch.utils.multi_objective.box_decompositions.box_decomposition import (
        BoxDecomposition,
    )
    from torch import Tensor


[docs] def str_to_acqf(name: str, /) -> AcquisitionFunction: """Create an ACQF object from a given ACQF name.""" return AcquisitionFunction.from_dict({"type": name})
[docs] def convert_acqf(acqf: AcquisitionFunction | str, /) -> AcquisitionFunction: """Convert an ACQF name into an ACQF object (with ACQF object passthrough).""" return acqf if isinstance(acqf, AcquisitionFunction) else str_to_acqf(acqf)
[docs] def make_partitioning( predictions: Tensor, ref_point: Tensor, alpha: float | None ) -> BoxDecomposition: """Create a :class:`~botorch.utils.multi_objective.box_decompositions.box_decomposition.BoxDecomposition` object for the given predictions and reference point. For details on the arguments, see :class:`~botorch.utils.multi_objective.box_decompositions.non_dominated.NondominatedPartitioning`. Args: predictions: The predictions tensor of shape (n_samples, n_outputs). ref_point: The reference point tensor of shape (n_outputs,). alpha: Optional threshold parameter controlling the partitioning generation. Hypercells with a volume fraction (relative to the total Pareto set hypervolume) less than the specified value will be dropped, leading to more approximation but faster computation. Raises: ValueError: If the predictions or reference point do not have the expected shapes. Returns: A partitioning object for hypervolume acquisition functions. """ # noqa: E501 from botorch.acquisition.input_constructors import ( get_default_partitioning_alpha, ) from botorch.utils.multi_objective.box_decompositions.non_dominated import ( FastNondominatedPartitioning, NondominatedPartitioning, ) if predictions.ndim != 2: raise ValueError( f"Predictions must be a 2-D tensor, got shape {predictions.shape}." ) if ref_point.ndim != 1: raise ValueError( f"Reference point must be a 1-D tensor, got shape {ref_point.shape}." ) if (n_p := predictions.shape[1]) != (n_r := len(ref_point)): raise ValueError( f"Predictions dimensionality {n_p} does not match reference point " f"dimensionality {n_r}." ) alpha = ( get_default_partitioning_alpha(num_objectives=len(ref_point)) if alpha is None else alpha ) # alpha=0 means requesting an exact partitioning, for which there is a specialized # faster algorithm available if alpha == 0: return FastNondominatedPartitioning(ref_point=ref_point, Y=predictions) return NondominatedPartitioning(ref_point=ref_point, Y=predictions, alpha=alpha)