Skip to content

Commit b1636fa

Browse files
authored
Merge: Constraint Refactor 3: Merge *NoLabelDuplicates* and *LinkedParameters* into *Repetition* (#881)
Closes #874 Based on #880
2 parents 16fd963 + 28a1be2 commit b1636fa

16 files changed

Lines changed: 520 additions & 181 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4040
`TransferLearningMode` enum) for selecting the kernel that models the task
4141
correlations in transfer learning, taking precedence over the task kernel of the
4242
configured kernel factory
43+
- `DiscreteRepetitionLimitConstraint` for controlling value repetition across parameters
44+
via `n_max_repetitions` (replaces `DiscreteNoLabelDuplicatesConstraint` and
45+
`DiscreteLinkedParametersConstraint`)
4346

4447
### Changed
4548
- `BOTORCH` GP preset now includes `BetaPrior(2.5, 1.5)` for the task covariance
@@ -63,6 +66,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6366
### Deprecations
6467
- `DiscreteExcludeConstraint` in favor of
6568
`DiscreteSelectionConstraint(..., exclude=True)`
69+
- `DiscreteNoLabelDuplicatesConstraint` in favor of
70+
`DiscreteRepetitionLimitConstraint(..., n_max_repetitions=1)`
71+
- `DiscreteLinkedParametersConstraint` in favor of
72+
`DiscreteRepetitionLimitConstraint(..., n_max_repetitions=len(parameters)-1,
73+
exclude=True)`
6674

6775
## [0.15.0] - 2026-06-11
6876
### Breaking Changes

baybe/campaign.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from attrs.validators import instance_of
1818
from typing_extensions import override
1919

20-
from baybe.constraints.base import DiscreteConstraint, DiscreteFilteringConstraint
20+
from baybe.constraints.base import DiscreteFilteringConstraint
2121
from baybe.exceptions import (
2222
IncompatibilityError,
2323
NoMeasurementsError,
@@ -426,7 +426,7 @@ def update_measurements(
426426

427427
def toggle_discrete_candidates( # noqa: DOC501
428428
self,
429-
constraints: Collection[DiscreteConstraint] | pd.DataFrame,
429+
constraints: Collection[DiscreteFilteringConstraint] | pd.DataFrame,
430430
exclude: bool,
431431
complement: bool = False,
432432
dry_run: bool = False,
@@ -436,8 +436,8 @@ def toggle_discrete_candidates( # noqa: DOC501
436436
Args:
437437
constraints: A filtering mechanism determining the candidates subset to be
438438
in-/excluded. Can be either a collection of
439-
:class:`~baybe.constraints.base.DiscreteConstraint` or a dataframe.
440-
For the latter, see :func:`~baybe.utils.dataframe.filter_df`
439+
:class:`~baybe.constraints.base.DiscreteFilteringConstraint` or a
440+
dataframe. For the latter, see :func:`~baybe.utils.dataframe.filter_df`
441441
for details.
442442
exclude: If ``True``, the specified candidates are excluded.
443443
If ``False``, the candidates are considered for recommendation.
@@ -483,8 +483,8 @@ def toggle_discrete_candidates( # noqa: DOC501
483483

484484
else:
485485
raise TypeError(
486-
"Candidate toggling is not implemented for the given type of "
487-
"constraint specifications."
486+
f"Candidate toggling requires a dataframe or a collection of "
487+
f"'{DiscreteFilteringConstraint.__name__}' instances."
488488
)
489489

490490
if not dry_run:

baybe/constraints/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
DiscreteNoLabelDuplicatesConstraint,
1717
DiscretePermutationInvarianceConstraint,
1818
DiscreteProductConstraint,
19+
DiscreteRepetitionLimitConstraint,
1920
DiscreteSelectionConstraint,
2021
DiscreteSumConstraint,
2122
)
@@ -34,11 +35,12 @@
3435
"DiscreteCustomConstraint",
3536
"DiscreteDependenciesConstraint",
3637
"DiscreteExcludeConstraint",
37-
"DiscreteSelectionConstraint",
3838
"DiscreteLinkedParametersConstraint",
3939
"DiscreteNoLabelDuplicatesConstraint",
4040
"DiscretePermutationInvarianceConstraint",
4141
"DiscreteProductConstraint",
42+
"DiscreteRepetitionLimitConstraint",
43+
"DiscreteSelectionConstraint",
4244
"DiscreteSumConstraint",
4345
# --- Other --- #
4446
"validate_constraints",

baybe/constraints/base.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,25 +197,31 @@ def has_polars_implementation(cls) -> bool:
197197
is not DiscreteFilteringConstraint._get_matching_rows_polars
198198
)
199199

200-
def get_invalid_polars(self) -> pl.Expr:
200+
def get_invalid_polars(self, schema: pl.Schema) -> pl.Expr:
201201
"""Translate the constraint to a Polars expression identifying rows to remove.
202202
203+
Args:
204+
schema: The Polars schema of the dataframe being filtered.
205+
203206
Returns:
204207
The Polars expression.
205208
"""
206-
matching_expr = self._get_matching_rows_polars()
209+
matching_expr = self._get_matching_rows_polars(schema)
207210
if self.exclude:
208211
return matching_expr
209212
return ~matching_expr
210213

211-
def _get_matching_rows_polars(self) -> pl.Expr:
214+
def _get_matching_rows_polars(self, schema: pl.Schema) -> pl.Expr:
212215
"""Translate the constraint to a Polars expression identifying matching rows.
213216
214217
Subclasses with a Polars implementation override this method. The expression
215218
should evaluate to ``True`` for rows that the specification matches/keeps
216219
(as if ``exclude=False``). The ``exclude`` inversion is applied by the base
217220
class in :meth:`get_invalid_polars`, not here.
218221
222+
Args:
223+
schema: The Polars schema of the dataframe being filtered.
224+
219225
Returns:
220226
A Polars expression that evaluates to ``True`` for matching rows.
221227

0 commit comments

Comments
 (0)