diff --git a/botorch/exceptions/errors.py b/botorch/exceptions/errors.py index c92deb8820..a737cc8500 100644 --- a/botorch/exceptions/errors.py +++ b/botorch/exceptions/errors.py @@ -86,3 +86,9 @@ def __init__(self, /, *args: Any, current_x: npt.NDArray, **kwargs: Any) -> None """ super().__init__(*args, **kwargs) self.current_x = current_x + + +class InfeasibilityError(BotorchError, ValueError): + r"""Exception raised when infeasibility occurs.""" + + pass diff --git a/botorch/utils/sampling.py b/botorch/utils/sampling.py index f914dea24d..190ccfcd61 100644 --- a/botorch/utils/sampling.py +++ b/botorch/utils/sampling.py @@ -27,7 +27,7 @@ import numpy.typing as npt import scipy import torch -from botorch.exceptions.errors import BotorchError +from botorch.exceptions.errors import BotorchError, InfeasibilityError from botorch.exceptions.warnings import UserInputWarning from botorch.sampling.qmc import NormalQMCEngine from botorch.utils.transforms import unnormalize @@ -249,7 +249,7 @@ def sample_polytope( """ # Check that starting point satisfies the constraints. if not ((slack := A @ x0 - b) <= 0).all(): - raise ValueError( + raise InfeasibilityError( f"Starting point does not satisfy the constraints. Inputs: {A=}," f"{b=}, {x0=}, A@x0-b={slack}." ) @@ -442,7 +442,7 @@ def find_interior_point( ) if result.status == 2: - raise ValueError( + raise InfeasibilityError( "No feasible point found. Constraint polytope appears empty. " + "Check your constraints." ) @@ -524,7 +524,7 @@ def __init__( if self.feasible(interior_point): self.x0 = interior_point else: - raise ValueError("The given input point is not feasible.") + raise InfeasibilityError("The given input point is not feasible.") else: self.x0 = self.find_interior_point() diff --git a/test/exceptions/test_errors.py b/test/exceptions/test_errors.py index e0c42685eb..321a0e4a3f 100644 --- a/test/exceptions/test_errors.py +++ b/test/exceptions/test_errors.py @@ -11,6 +11,7 @@ BotorchTensorDimensionError, CandidateGenerationError, DeprecationError, + InfeasibilityError, InputDataError, OptimizationGradientError, OptimizationTimeoutError, @@ -28,6 +29,7 @@ def test_botorch_exception_hierarchy(self): InputDataError, UnsupportedError, BotorchTensorDimensionError, + InfeasibilityError, ]: self.assertIsInstance(ErrorClass(), BotorchError) @@ -38,6 +40,7 @@ def test_raise_botorch_exceptions(self): CandidateGenerationError, InputDataError, UnsupportedError, + InfeasibilityError, ): with self.assertRaises(ErrorClass): raise ErrorClass("message")