Skip to content

Deprecate SubspaceDiscrete.constraints#835

Open
AdrianSosic wants to merge 9 commits into
dev/candidatesfrom
refactor/deprecate_constraints
Open

Deprecate SubspaceDiscrete.constraints#835
AdrianSosic wants to merge 9 commits into
dev/candidatesfrom
refactor/deprecate_constraints

Conversation

@AdrianSosic

@AdrianSosic AdrianSosic commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Related to #794

The constraints attribute on SubspaceDiscrete conflated two fundamentally different roles:

  • filtering constraints (applied once during construction to prune the candidate grid) and
  • batch constraints (applied at recommendation time to enforce structure across the recommended batch)

Storing both under a single field was misleading – filtering constraints are only relevant during construction, and even then only for certain construction routes: when building via from_dataframe, the candidate grid is already fully specified by the caller, so filtering constraints were meaningless from the very beginning and had no effect whatsoever. Retaining them on the object after construction served no purpose and gave a false impression that they remained active throughout the object's lifetime. As a further consequence, from_dataframe never accepted any constraint objects at all – since filtering constraints are not needed there, and batch constraints were introduced later, users had no way to attach batch constraints when constructing a subspace from a dataframe.

This PR makes the distinction explicit and removes the dead storage:

  • Adds SubspaceDiscrete.batch_constraints: a dedicated field for DiscreteBatchConstraint instances that are evaluated during recommendation. from_dataframe now accepts a batch_constraints argument – fixing the previously missing ability to attach batch constraints when constructing from a dataframe. Filtering constraints passed to from_product/from_simplex are applied during construction as before and then discarded – there is nothing left for them to do.
  • Deprecates SubspaceDiscrete.constraints: passing it emits a DeprecationWarning; any DiscreteBatchConstraint instances are automatically migrated to batch_constraints to ease the transition.
  • Removes is_constrained properties from SubspaceDiscrete, SubspaceContinuous, and SearchSpace: these were thin Boolean wrappers that obscured which kind of constraint was being checked and, in the discrete case, were backed by the now-meaningless stored filtering constraints.

…rete

The constraints field on SubspaceDiscrete conflated two fundamentally
different kinds of constraints: filtering constraints (eval_during_creation)
that are applied during construction to reduce the candidate set, and batch
constraints (eval_during_modeling) that operate at recommendation time to
partition candidates into subsets. Storing filtering constraints after
construction is redundant since exp_rep already reflects their effect, and
batch constraints had no dedicated home, making them unreachable via
from_dataframe entirely.

This change separates the two concerns by introducing a dedicated
batch_constraints field and deprecating the catch-all constraints field,
with automatic migration of batch constraints for backward compatibility.
@AdrianSosic AdrianSosic added this to the 0.16.0 milestone Jun 23, 2026
@AdrianSosic AdrianSosic self-assigned this Jun 23, 2026
@AdrianSosic AdrianSosic requested a review from Scienfitz as a code owner June 23, 2026 06:09
Copilot AI review requested due to automatic review settings June 23, 2026 06:09
@AdrianSosic AdrianSosic requested a review from AVHopp as a code owner June 23, 2026 06:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors discrete-subspace constraint handling by separating creation-time filtering constraints from recommendation-time batch constraints, deprecating the legacy SubspaceDiscrete.constraints storage/usage, and removing ambiguous is_constrained convenience properties.

Changes:

  • Introduces SubspaceDiscrete.batch_constraints and migrates legacy constraints (argument/serialization) to batch constraints with deprecation warnings.
  • Updates discrete subspace constructors/serialization to split filtering vs batch constraints and discard filtering constraints after construction.
  • Removes is_constrained from SubspaceDiscrete, SubspaceContinuous, and SearchSpace, updating call sites and tests.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
baybe/searchspace/discrete.py Adds batch_constraints, migration/deprecation logic, constructor updates, and a temporary structure hook for legacy constraints key.
baybe/searchspace/core.py Updates SearchSpace.constraints to use discrete batch_constraints; removes is_constrained.
baybe/searchspace/continuous.py Removes is_constrained and updates sampling logic to check constraints directly.
baybe/searchspace/_filtered.py Drops deprecated _constraints when cloning filtered subspaces.
tests/test_deprecations.py Adds regression tests for legacy constraints argument/key migration into batch_constraints.
CHANGELOG.md Documents additions/changes/deprecations around constraint API updates and is_constrained removal.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread baybe/searchspace/discrete.py
Comment thread baybe/searchspace/discrete.py
Comment thread baybe/searchspace/discrete.py
Comment thread baybe/searchspace/discrete.py
Comment thread baybe/searchspace/discrete.py
Comment thread CHANGELOG.md
- `Campaign.n_fits_done` and `Campaign.n_batches_done` attributes
- `SubspaceDiscrete` ignores any `empty_encoding` when provided
- `SubspaceDiscrete` no longer accepts a `comp_rep` argument
- `SubspaceDiscrete.constraints` field
Comment thread baybe/searchspace/discrete.py
Comment thread baybe/searchspace/discrete.py
Comment thread baybe/searchspace/discrete.py Outdated
Comment thread baybe/searchspace/discrete.py Outdated
def __attrs_post_init__(self) -> None:
"""Migrate deprecated ``constraints`` argument to ``batch_constraints``."""
# >>>>>>>>>> Deprecation
if self._constraints is not None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This silently drops all non-batch constraints a user provided. Should we at least give a warning or similar if they still provided them, just to make sure that users are aware of this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is: there is really no change in terms of the underlying behavior! This is exactly what also happened before because – as explained in the PR description –  the constraints were stored but nowhere actually used. So the runtime behavior is 100% identical. In the past, I guess this weird interface didn't bother anyone because probably 0% of users ever explicitly called the regular constructor. People would usually go via from_product, from_dataframe and from_simplex. So in that sense, I don't think we have to warn here because we're giving the users the same experience as before. Or what is your opinion?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, doing it wrong and bad in the past is not an argument why not to do it better. If we now see that we should have actually warned people previously and agree on that (do we?) then we can still include this now.

Comment on lines +304 to +305
batch_constraints: Optional batch constraints to be applied at
recommendation time.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, those are not optional as we do not allow None but provide an empty list as default. So we should either also accept None as input or change the docstring to (Potentially empty) list of batch constraints to be applied at recommendation time. or similar

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are maybe confusing the term "optional" with Python's legacy typing.Optional. While the latter was indeed a shorthand for | None, optional in natural language simply means you can but do not need to provide it, right?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on the layer of optionality in my opinion: For the function, it is not optional - you have to provide a value. As a user, you do not need to do so since we provide a default - so probably we need to align on what Optional means on the semantic level. And I'd say that since it is not optional from the POV of the function, it should not be called optional, even if it might be from the user's perspective. Or what is your take here (or maybe there is even some well-defined semantics for this in the python world)?

Comment thread baybe/searchspace/discrete.py Outdated
Comment thread baybe/searchspace/discrete.py
Comment thread baybe/searchspace/continuous.py
@AdrianSosic AdrianSosic mentioned this pull request Jun 23, 2026
4 tasks

@myrazma myrazma left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, just some minor comments.
I like the separation of filtered and batch constraints. Previously when they were combined, it created the false impression that the filtered constraints were applied to exp_rep after creating the Searchspace, which they are not. So this update removes that ambiguity and hopefully prevent user confusion.

Comment thread baybe/searchspace/discrete.py Outdated
Comment thread baybe/searchspace/discrete.py Outdated
@AdrianSosic

Copy link
Copy Markdown
Collaborator Author

So this update removes that ambiguity and hopefully prevent user confusion.

@myrazma: yes, but the user will never actually see this state of the code. Once merged to main, we'll have the full architecture in place, including your Candidates as the new attributed populating SubspaceDiscrete. There, constraints will be cleanly re-introduced as part of ProductCandidates – the only context where constraints actually make sense and are then also used during lifetime 🙃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants