From 7715ff4605f85581e613ecd24bc23253dc9fba69 Mon Sep 17 00:00:00 2001 From: Di Jin Date: Mon, 16 Dec 2024 09:59:59 -0800 Subject: [PATCH] Add InfeasibilityError exception (#2652) Summary: ## Motivation Add customised error for infeasible problem. Details see https://github.com/pytorch/botorch/issues/2631 ### Have you read the [Contributing Guidelines on pull requests](https://github.com/pytorch/botorch/blob/main/CONTRIBUTING.md#pull-requests)? Yes. Pull Request resolved: https://github.com/pytorch/botorch/pull/2652 Test Plan: The customised error is tested in a similar way as the other customised errors. ## Related PRs (If this PR adds or changes functionality, please take some time to update the docs at https://github.com/pytorch/botorch, and link to your PR here.) Reviewed By: saitcakmak Differential Revision: D67280696 Pulled By: Balandat fbshipit-source-id: 581dbe23d304966632c83feb1286071d7fbddade --- botorch/exceptions/errors.py | 6 ++++++ botorch/utils/sampling.py | 8 ++++---- test/exceptions/test_errors.py | 3 +++ 3 files changed, 13 insertions(+), 4 deletions(-) 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")