Skip to content

Commit

Permalink
Raise error when specifying transformation without bounds (#451)
Browse files Browse the repository at this point in the history
This PR fixes #449 by now checking whether a `NumericalTarget` has
bounds if a transformation is provided.

Introduces a new step in the validation, raising a value error if the
user provides a transformation but no bounds. Also adds an according
test.
  • Loading branch information
AVHopp authored Dec 11, 2024
2 parents f4669a2 + eed6545 commit 6d3a6fc
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Search spaces are now stateless, preventing unintended side effects that could lead to
incorrect candidate sets when reused in different optimization contexts
- `qNIPV` not working with single `MIN` targets
- Passing a `TargetTransformation` without passing `bounds` when createing a
`NumericalTarget` now raises an error

### Deprecations
- Passing a dataframe via the `data` argument to `Objective.transform` is no longer
Expand Down
9 changes: 8 additions & 1 deletion baybe/targets/numerical.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,18 @@ def _validate_bounds(self, _: Any, bounds: Interval) -> None: # noqa: DOC101, D
def _validate_transformation( # noqa: DOC101, DOC103
self, _: Any, value: TargetTransformation | None
) -> None:
"""Validate that the given transformation is compatible with the specified mode.
"""Validate compatability between transformation, bounds and the mode.
Raises:
ValueError: If a target transformation was provided for an unbounded
target.
ValueError: If the target transformation and mode are not compatible.
"""
if (value is not None) and (not self.bounds.is_bounded):
raise ValueError(
f"You specified a transformation for target '{self.name}', but "
f"did not specify any bounds."
)
if (value is not None) and (value not in _VALID_TRANSFORMATIONS[self.mode]):
raise ValueError(
f"You specified bounds for target '{self.name}', but your "
Expand Down
6 changes: 4 additions & 2 deletions tests/hypothesis_strategies/targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ def numerical_targets(
"""
name = draw(target_name)
mode = draw(st.sampled_from(TargetMode))
transformation = draw(st.sampled_from(_VALID_TRANSFORMATIONS[mode]))
if bounds_strategy is None:
bounds_strategy = st_intervals(
exclude_half_bounded=True, exclude_fully_unbounded=mode is TargetMode.MATCH
exclude_half_bounded=True,
exclude_fully_unbounded=mode is TargetMode.MATCH
or transformation is not None,
)
bounds = draw(bounds_strategy)
transformation = draw(st.sampled_from(_VALID_TRANSFORMATIONS[mode]))

return NumericalTarget(
name=name, mode=mode, bounds=bounds, transformation=transformation
Expand Down
12 changes: 12 additions & 0 deletions tests/validation/test_target_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,15 @@ def test_binary_target_invalid_values(choices, error, match):
success_value=choices[0],
failure_value=choices[1],
)


@pytest.mark.parametrize(
"mode",
["MIN", "MAX"],
)
def test_providing_transformation_without_bounds(mode):
"""Providing a transformation without bounds raises an error."""
with pytest.raises(ValueError, match="but did not specify any bounds."):
NumericalTarget(
name="transformation_without_bounds", mode=mode, transformation="LINEAR"
)

0 comments on commit 6d3a6fc

Please sign in to comment.