Skip to content

Commit

Permalink
Fix empty constraints after dropping parameters (#448)
Browse files Browse the repository at this point in the history
When dropping parameters due to the use of cardinality constraints, it
can happen that an attempt is made to create a Constraint without any
parameters, causing the code to crash.

This PR introduces an explicit test for this scenario as well as a fix
by only including constraints that still have parameters after dropping
them.
  • Loading branch information
AVHopp authored Dec 11, 2024
2 parents 6d3a6fc + b28db43 commit eb29369
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `qNIPV` not working with single `MIN` targets
- Passing a `TargetTransformation` without passing `bounds` when createing a
`NumericalTarget` now raises an error
- Crash when using `ContinuousCardinalityConstraint` caused by an unintended interplay
between constraints and dropped parameters yielding empty parameter sets

### Deprecations
- Passing a dataframe via the `data` argument to `Objective.transform` is no longer
Expand Down
8 changes: 6 additions & 2 deletions baybe/searchspace/continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,14 @@ def _drop_parameters(self, parameter_names: Collection[str]) -> SubspaceContinuo
return SubspaceContinuous(
parameters=[p for p in self.parameters if p.name not in parameter_names],
constraints_lin_eq=[
c._drop_parameters(parameter_names) for c in self.constraints_lin_eq
c._drop_parameters(parameter_names)
for c in self.constraints_lin_eq
if set(c.parameters) - set(parameter_names)
],
constraints_lin_ineq=[
c._drop_parameters(parameter_names) for c in self.constraints_lin_ineq
c._drop_parameters(parameter_names)
for c in self.constraints_lin_ineq
if set(c.parameters) - set(parameter_names)
],
)

Expand Down
33 changes: 33 additions & 0 deletions tests/constraints/test_cardinality_constraint_continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,36 @@ def test_random_recommender_with_cardinality_constraint(
_validate_samples(
recommendations, max_cardinality=2, min_cardinality=1, batch_size=batch_size
)


def test_empty_constraints_after_cardinality_constraint():
"""Constraints that have no more parameters left due to activated
cardinality constraints do not cause crashes.""" # noqa

N_PARAMETERS = 2

parameters = [
NumericalContinuousParameter(name=f"x_{i+1}", bounds=(0, 1))
for i in range(N_PARAMETERS)
]
constraints = [
ContinuousLinearConstraint(
parameters=["x_1"],
operator="=",
coefficients=[1.0],
rhs=0.3,
),
ContinuousLinearConstraint(
parameters=["x_2"],
operator="<=",
coefficients=[1.0],
rhs=0.6,
),
ContinuousCardinalityConstraint(
parameters=["x_1", "x_2"],
max_cardinality=1,
min_cardinality=1,
),
]
subspace = SubspaceContinuous.from_product(parameters, constraints)
subspace.sample_uniform(1)

0 comments on commit eb29369

Please sign in to comment.