Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
145 commits
Select commit Hold shift + click to select a range
030a78f
Drop SubspaceDiscrete.empty_encoding attribute
AdrianSosic Apr 7, 2026
2f41bec
Drop comp_rep parameter from SubspaceDiscrete.__init__
AdrianSosic Apr 7, 2026
985a519
Fix SubspaceDiscrete class and attribute docstrings
AdrianSosic Apr 7, 2026
8cd624f
Add missing validator to SubspaceDiscrete.parameters
AdrianSosic Apr 7, 2026
b99c0b1
Clean up SubspaceContinuous attributes
AdrianSosic Apr 7, 2026
6882273
Fix SubspaceContinuous class and attribute docstrings
AdrianSosic Apr 7, 2026
eb4545a
Add narwhal lazyframe converter
myrazma May 13, 2026
507a38b
Add polars(pyarrow) and narwhals as hard dependencies
myrazma May 13, 2026
f499cbb
Add InfiniteSpaceError
myrazma May 13, 2026
d920ae2
Add CandidateProtocol as well as TabelCandidates and ProductCandidates
myrazma May 13, 2026
2c724e2
Add tests for ProductCandidates and TableCandidates
myrazma May 13, 2026
22aa41b
Add parameter name check to Candidates
myrazma May 13, 2026
92af0ca
Update CHANGELOG.md
myrazma May 13, 2026
fc19bc4
Fix typo
myrazma May 13, 2026
4a43d8b
Remove attribute validation from CandidateProtocol
myrazma May 13, 2026
eacd434
Fix terminology: enumerable -> finite
AdrianSosic May 21, 2026
6cb0e34
Remove polars as hard dependency
AdrianSosic May 21, 2026
8be8647
Adjust narwhals version constraints
AdrianSosic May 21, 2026
2eacc75
Use narwhals stable.v2 namespace
AdrianSosic May 21, 2026
053c16a
Turn protocol (class) attribute into property
AdrianSosic May 21, 2026
05b3ad3
Refine attrs coding conventions in AGENTS.md
AdrianSosic May 21, 2026
831aafe
Add missing garbage collection step
AdrianSosic May 21, 2026
a4abf8f
Fix attribute definitions
AdrianSosic May 21, 2026
dda34ff
Drop unnecessary __attrs_post_init__
AdrianSosic May 21, 2026
adabdd4
Rework candidate module docstrings
AdrianSosic May 21, 2026
2a7f4b9
Turn delayed validation into eager validation
AdrianSosic May 21, 2026
c5ebbba
Add DiscreteParameter.is_finite
AdrianSosic May 21, 2026
4605151
Drop unused helper function
AdrianSosic May 21, 2026
0a4b9b8
Adjust lazyframe conversion utility
AdrianSosic May 21, 2026
10f8118
Rename CandidatesProtocol.to_lazy_candidates to to_lazy
AdrianSosic May 21, 2026
17fc099
Fix changelog
AdrianSosic May 21, 2026
41580f0
Refactor table candidates tests
AdrianSosic May 21, 2026
9d042f1
Enable check for extra dataframe columns
AdrianSosic May 21, 2026
8017b65
Refactor product candidates tests
AdrianSosic May 21, 2026
6b59e42
Expose candidates classes via namespace
AdrianSosic May 21, 2026
f6b516b
Fix CI: Add polars as an optional dependency for testing
fabianliebig May 23, 2026
d49042d
Make CandidatesProtocol slotted
AdrianSosic Jun 1, 2026
98a434a
Add deprecation mechanism for legacy constraint arguments
AdrianSosic Apr 7, 2026
7b9f3fc
User custom __init__ instead of deprecation attributes
AdrianSosic Apr 7, 2026
fe9c8f2
Add support for structuring from legacy arguments
AdrianSosic Apr 7, 2026
bc231c3
Add deprecation mechanism for legacy SubspaceDiscrete arguments
AdrianSosic Apr 7, 2026
e2793b0
Raise warning instead of error for empty_encoding
AdrianSosic Apr 7, 2026
104ccec
Update CHANGELOG.md
AdrianSosic Apr 7, 2026
a574146
Drop dead code
AdrianSosic Apr 7, 2026
b70cf3a
Add missing test step for toggled candidates recommendation
AdrianSosic Apr 7, 2026
4c4189f
Drop legacy arguments when filtering search space
AdrianSosic Jun 2, 2026
17eddd3
Add deserialization test for legacy SubspaceDiscrete format
AdrianSosic Apr 7, 2026
33697d7
Add missing attribute docstrings
AdrianSosic Apr 7, 2026
5fcb2c8
Move search space validation tests to tests/validation/
AdrianSosic Apr 7, 2026
1021186
Add missing SubspaceContinuous validation tests
AdrianSosic Apr 7, 2026
c91dc15
Validate constraint parameter names in SubspaceContinuous
AdrianSosic Apr 7, 2026
317c17a
Move simplex validation test to tests/validation/
AdrianSosic Apr 7, 2026
f969d4c
Add missing SubspaceDiscrete validation tests
AdrianSosic Apr 7, 2026
263b1bf
Parametrize tests and add hybrid case
AdrianSosic Apr 7, 2026
304011e
Refactor constraint parameter name validation
AdrianSosic Jun 2, 2026
d7fb8fc
Merge branch 'main' into refactor/searchspace
AdrianSosic Jun 3, 2026
308e006
Fix typing
AdrianSosic Jun 8, 2026
9e0e670
Fix test docstrings
AdrianSosic Jun 8, 2026
9777037
Drop duplicate test condition
AdrianSosic Jun 8, 2026
c2fa25f
Consolidate parameter and constraint validation
AdrianSosic Jun 8, 2026
385467d
Update CHANGELOG
AdrianSosic Jun 8, 2026
966518c
Suppress Sphinx warning for SubspaceDiscrete.comp_rep
AdrianSosic Jun 8, 2026
13f4dc6
Centralize empty and task parameter validation
AdrianSosic Jun 9, 2026
f63839c
Fix test setup
AdrianSosic Jun 9, 2026
224d6a9
Fix signature of custom __init__
AdrianSosic Jun 9, 2026
7ef7559
Fix typos
AdrianSosic Jun 1, 2026
4fe126e
Fix validate_parameter_input type annotations
AdrianSosic Jun 1, 2026
ce97cfd
Use minus syntax for set difference
AdrianSosic Jun 9, 2026
951bcdf
Fix attribute mechanics
AdrianSosic Jun 10, 2026
fa51388
Merge changelog "Changed" sections
AdrianSosic Jun 10, 2026
c2e202f
Adjust parameter definitions in searchspace test module
AdrianSosic Jun 10, 2026
59fa66a
Fix condition for dropping parameters
AdrianSosic Jun 10, 2026
3a9ff58
Mark deprecation code with comment block
AdrianSosic Jun 10, 2026
a87c093
Remove FitNr tracking from Campaign
AdrianSosic Jun 3, 2026
38f4627
Remove BatchNr tracking from Campaign
AdrianSosic Jun 3, 2026
a055f7f
Rename _measurements_exp to _measurements
AdrianSosic Jun 3, 2026
469a480
Store recommended experiments as DataFrame instead of metadata flags
AdrianSosic Jun 3, 2026
ccedd8e
Initialize empty DataFrames with correct schema
AdrianSosic Jun 3, 2026
511b668
Use public measurements property for read-only access
AdrianSosic Jun 3, 2026
3e52e2a
Compute measured-candidates mask on the fly
AdrianSosic Jun 3, 2026
556a583
Replace _searchspace_metadata with stored DataFrames
AdrianSosic Jun 3, 2026
e342199
Update CHANGELOG.md
AdrianSosic Jun 3, 2026
241e516
Fix toggle_discrete_candidates
AdrianSosic Jun 8, 2026
e459d0e
Refine candidate toggling logic
AdrianSosic Jun 8, 2026
cce25a4
Fix index-alignment bug in candidate filtering
AdrianSosic Jun 8, 2026
77987c0
Drop try-except blocks from legacy deserialization route
AdrianSosic Jun 11, 2026
bd6b780
Drop unnecessary logic from legacy deserialization route
AdrianSosic Jun 11, 2026
a84f86e
Avoid hardcoding constraint attribute name
AdrianSosic Jun 11, 2026
b00b8c3
Refactor Campaign (#821)
AdrianSosic Jun 11, 2026
46cd8e6
Merge branch 'dev/candidates' into feature/candidates_base
AdrianSosic Jun 18, 2026
bb92690
Add CandidatesProtocol (#800)
AdrianSosic Jun 18, 2026
af00b3e
Fix changelog
AdrianSosic Jun 18, 2026
e152e9f
Merge branch 'dev/candidates' into refactor/searchspace
AdrianSosic Jun 18, 2026
2e6859e
Drop duplicate validator
AdrianSosic Jun 18, 2026
3d25198
Fix type narrowing in SubspaceContinuous._drop_parameters
AdrianSosic Jun 18, 2026
a127c6b
Refactor searchspace attributes (#778)
AdrianSosic Jun 18, 2026
6596bf0
Fix select_constructor_hook to respect converter settings
AdrianSosic Jun 19, 2026
5f9e96b
Bump cattrs to 26.1.0 to support Annotated
AdrianSosic Jun 19, 2026
52cc0ae
Update CHANGELOG
AdrianSosic Jun 19, 2026
feef29b
Fix Serialization (#833)
AdrianSosic Jun 19, 2026
370ad14
Return dataframes instead of indices in discrete recommendation
AdrianSosic Jun 18, 2026
0834338
Update CHANGELOG.md
AdrianSosic Jun 18, 2026
a46a294
Update comment
AdrianSosic Jun 23, 2026
a7a3144
Recommendation Dataframes (#832)
AdrianSosic Jun 23, 2026
8fd6ab2
Add batch_constraints field and deprecate constraints on SubspaceDisc…
AdrianSosic Jun 19, 2026
5d00b39
Drop is_constrained properties
AdrianSosic Jun 19, 2026
11413b0
Update CHANGELOG.md
AdrianSosic Jun 19, 2026
1aa7da5
Drop unnecessary fallback
AdrianSosic Jun 23, 2026
d8083eb
Add missing validation step
AdrianSosic Jun 23, 2026
3c2ec13
Refine deprecation warning message
AdrianSosic Jun 23, 2026
e5329b6
Fix classmethod return types
AdrianSosic Jun 23, 2026
22c18be
Add missing constraint validation to from_simplex
AdrianSosic Jun 23, 2026
d8a51dc
Deprecate SubspaceDiscrete.constraints_batch property
AdrianSosic Jun 23, 2026
9c0f8b5
Add more details to changelog entry
AdrianSosic Jun 23, 2026
ff098b8
Raise warning when providing filtering constraints via init
AdrianSosic Jun 23, 2026
543c80f
Deprecate `SubspaceDiscrete.constraints` (#835)
AdrianSosic Jun 23, 2026
2bc056e
Merge branch 'main' into dev/candidates
AdrianSosic Jun 23, 2026
66a3e7c
Drop FilteredSubspaceDiscrete class
AdrianSosic Jun 19, 2026
e3ef5b0
Drop dead pending_experiments argument
AdrianSosic Jun 19, 2026
075f186
Drop redundant candidates_exp argument
AdrianSosic Jun 19, 2026
b2b8ee2
Update CHANGELOG.md
AdrianSosic Jun 23, 2026
2600746
Create shallow copy to avoid in-place dataframe mutation
AdrianSosic Jun 25, 2026
e9b1915
Drop redundant candidates_exp argument from subset methods
AdrianSosic Jun 25, 2026
1399e6b
Fix mypy error
AdrianSosic Jun 25, 2026
d7e50ec
Drop leftover comp_rep argument from SubspaceDiscrete call
AdrianSosic Jun 25, 2026
7ad1cec
Refactor recommendation mechanics (#838)
AdrianSosic Jun 25, 2026
fcd05b1
Turn exp_rep attribute private
AdrianSosic Jun 19, 2026
1d04b91
Adjust get_candidates signature
AdrianSosic Jun 19, 2026
b225071
Remove exp_rep/comp_rep from __str__ methods
AdrianSosic Jun 19, 2026
0d75b88
Replace exp_rep accesses in Campaign class
AdrianSosic Jun 19, 2026
632cbb3
Replace exp_rep accesses in recommenders
AdrianSosic Jun 19, 2026
7f4dcfd
Replace exp_rep accesses in simulation package
AdrianSosic Jun 19, 2026
ffb02e9
Replace exp_rep/comp_rep accesses in tests
AdrianSosic Jun 19, 2026
6a109ba
Replace exp_rep/comp_rep accesses in examples
AdrianSosic Jun 19, 2026
5a0d341
Replace remaining external comp_rep accesses
AdrianSosic Jun 19, 2026
5212fb3
Replace remaining internal comp_rep accesses
AdrianSosic Jun 19, 2026
e88491c
Deprecate exp_rep and comp_rep access
AdrianSosic Jun 19, 2026
559c40c
Update CHANGELOG.md
AdrianSosic Jun 25, 2026
e096cb8
Fix mypy
AdrianSosic Jun 25, 2026
071ae66
Update get_candidates call structure in examples
AdrianSosic Jun 25, 2026
51f03da
Replace leftover exp_rep accesses
AdrianSosic Jun 25, 2026
59d8869
Avoid duplicate get_candidates calls
AdrianSosic Jun 26, 2026
fdbe7ba
Fix bounds computation for empty parameter set
AdrianSosic Jun 26, 2026
cdf70ba
Refactor candidates interface (#840)
AdrianSosic Jun 26, 2026
c9f7a9b
Merge branch 'main' into dev/candidates
AdrianSosic Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 43 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,9 @@ More specific conventions for subdirectories:
### attrs Only
All domain classes use `attrs` `@define`. No dataclasses, no Pydantic.
- Immutable value objects (parameters, kernels, priors, transformations, objectives,
targets): `@define(frozen=True, slots=False)`.
targets): `@define(frozen=True)`.
- Mutable stateful objects (campaign, surrogates, recommenders): `@define`.
- `slots=False` required with `frozen=True` when `cached_property` is needed. See
`attrs` issue #164
- `slots=False` is required when `cached_property` is needed. See `attrs` issue #164
- Also use `slots=False` when monkeypatching is needed (e.g., `register_hooks`)

### Inheritance: ABC + SerialMixin + Protocol
Expand All @@ -71,14 +70,25 @@ All domain classes use `attrs` `@define`. No dataclasses, no Pydantic.
3. Concrete classes: Inherit from ABC.

### Fields and Methods
- Use `field()` with `validator=`, `converter=`, `default=`, `factory=`, `alias=`.
- Use `field()` with arguments in this order: 1) `alias=` (if needed), 2) `init=`
(if needed), 3) `default=` / `factory=`, 4) `converter=`, 5) `validator=`.
- Private fields: `_` prefix, typically `init=False`.
- Store each piece of information once — no data duplication.
- Use `attrs.evolve()` for modified copies of frozen objects.
- Use `on_setattr` hooks for cache invalidation on mutable objects.
- Use `kw_only=True` deliberately: only when positional construction would be
ambiguous or error-prone (e.g., multiple fields of the same type, or
optional/secondary fields that should not be passed positionally). Do not
apply `kw_only` to all fields by default.
- `ClassVar[bool]` for capability flags (`supports_transfer_learning`, etc.).
- Order class content like this: 1) Attributes, 2) validators and post_init, 3)
properties, 4) methods. Within each group use alphabetical order.
- Order class content like this: 1) Attributes, 2) default and validator methods,
3) `__attrs_post_init__`, 4) properties, 5) methods.
- Attributes are ordered by functionality/importance (primary identity fields
first, optional/secondary fields last), not alphabetically.
- Default and validator methods mirror the attribute order. For a given
attribute, the default method (`_default_<attr>`) comes before its validator
(`_validate_<attr>`).
- Regular methods are ordered alphabetically.

### Attribute Docstrings
String literals immediately below field declarations, blank lines between attributes.
Expand All @@ -98,6 +108,17 @@ Every module using `@define` must end with:
Name descriptively: `from_product`, `from_dataframe`, `from_parameter`, `from_config`,
`from_json`, `from_dict`, `from_preset`.

Use `Self` return type and `cls()` construction for proper subclass support:
```python
from typing_extensions import Self

@classmethod
def from_parameter(cls, parameter: DiscreteParameter) -> Self:
"""Create a subspace from a single parameter."""
return cls(parameters=[parameter], ...) # Use cls(), not ClassName()
```
This ensures subclasses return their own type, not the base class type.

### classproperty
Custom `@classproperty` from `baybe.utils.basic` for class-level computed properties.

Expand Down Expand Up @@ -227,11 +248,24 @@ Three tiers:

## 11. Validation Patterns
- Inline validators: `field(validator=(instance_of(str), min_len(1)))`, `in_()`,
`deep_iterable()`, custom `finite_float`, `gt()`.
`deep_iterable()`, custom `finite_float`, `gt()`. Order validators from simplest
to most complex: cheap structural checks (e.g., `min_len`, `instance_of`) before
expensive semantic checks (e.g., cross-field consistency, name uniqueness).
- Method validators: `@_field.validator` with `# noqa: DOC101, DOC103` for
validators needing `self` access.
- Cross-field: `__attrs_post_init__` when validation involves multiple fields.
- Cross-field: `__attrs_post_init__` is a last resort. Method validators
(`@field.validator`) already receive `self` and can read other already-set
attributes, so most cross-field checks belong there instead. When one field
must be compatible with another, attach the validator to the later field —
attrs sets fields in declaration order, so earlier fields are always available
via `self` at that point. When one attribute's value must be adjusted after
all fields are set — which is typically a workaround and should itself be
questioned — `__attrs_post_init__` is acceptable.
- Converters: `field(converter=to_searchspace)` for automatic type coercion.
- If a converter already guarantees a specific type (e.g., `converter=list`
always produces a `list`, a custom converter always returns a known type),
omit any `instance_of(...)` validator for that same type — the check is
redundant.
- Reusable validators in `baybe/utils/validation.py`: `finite_float`,
`non_nan_float`, `non_inf_float`, `validate_not_nan`, `validate_target_input`,
`validate_parameter_input`, `validate_object_names`.
Expand Down Expand Up @@ -296,6 +330,7 @@ For a full list of available tox environments and developer commands, see
- No hardcoded enum values in comments — link the enum.
- No private field names in user-facing messages — use public alias.
- No hardcoded class names in repr/errors — use `self.__class__.__name__`.
- No hardcoded class names in classmethods — use `cls()` and return `Self`.
- No silent errors. No mutation of caller-provided dicts.
- No silent defaults or "best effort" fallbacks — if input is invalid, raise.
- No proceeding past failed preconditions into expensive computation.
Expand Down
53 changes: 51 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,62 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Breaking Changes
- `Campaign.measurements` no longer contains `FitNr` or `BatchNr` metadata columns
- `validate_parameter_names`, `validate_cardinality_constraints_are_nonoverlapping`
and `validate_cardinality_constraint_parameter_bounds` are no longer available
as public utilities
- `is_constrained` property removed from `SubspaceDiscrete`, `SubspaceContinuous`,
and `SearchSpace`
- `candidates_exp` argument removed from `SubspaceDiscrete.subset_masks`,
`SubspaceDiscrete.sample_subset_masks`, `SearchSpace.subsets`, and
`SearchSpace.sample_subsets`
- `SubspaceDiscrete.get_candidates` now returns only the experimental representation
instead of a tuple of experimental and computational representations

### Added
- `narwhals` as a hard dependency
- `CandidatesProtocol` as an interface for candidates generation
- `TableCandidates` and `ProductCandidates` classes implementing `CandidatesProtocol`
- `DiscreteParameter.is_finite` property
- `SubspaceDiscrete.batch_constraints` field for storing batch-level constraints
- `SubspaceDiscrete.from_dataframe` now accepts `batch_constraints`

### Changed
- Internal `Campaign` state model simplified: recommended and excluded experiments
are now stored as dataframes instead of being tracked as metadata flags
- `SubspaceContinuous` now offers a simpler interface for passing constraints,
no longer requiring users to manually group constraints according to their type
- Parameter and constraint validation has been streamlined, using `validate_parameters`
and `validate_constraints` as the only remaining public entry points
- `_recommend_discrete` and kin now return a `pd.DataFrame` subselection of the
candidates instead of a `pd.Index`
- `SubspaceDiscrete.from_product` and `SubspaceDiscrete.from_simplex` now split
their `constraints` argument into filtering constraints (applied during construction)
and batch constraints (stored in `batch_constraints`)
- Internal search space and recommender logic simplified by reducing indirection and
argument passing between methods
- `BOTORCH` GP preset now includes `BetaPrior(2.5, 1.5)` for the task covariance
kernel in multi-task scenarios, matching BoTorch's `MultiTaskGP` defaults introduced
in version `0.18.0`
- The `BOTORCH` GP preset now requires BoTorch `>= 0.18.0` and raises an
`IncompatibilityError` if an older version is installed


### Fixed
- Deserialization with constructor selection now correctly respects converter settings

### Deprecations
- `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` attribute (use `batch_constraints` to provide and
access batch-level constraints; filtering constraints are only needed during subspace
construction and are thus no longer stored).
- `SubspaceDiscrete.constraints_batch` property (use `batch_constraints` instead)
- `SubspaceDiscrete.exp_rep` attribute (use `get_candidates()` instead)
- `SubspaceDiscrete.comp_rep` attribute (use `transform(get_candidates())` instead)

## [0.15.0] - 2026-06-11
### Breaking Changes
- `GaussianProcessSurrogate` no longer automatically adds a task kernel in multi-task
Expand Down Expand Up @@ -77,12 +126,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Broken cache validation for certain `Campaign.recommend` cases
- `ContinuousCardinalityConstraint` now works in hybrid search spaces
- Typo in `_FixedNumericalContinuousParameter` where `is_numeric` was used
instead of `is_numerical`
- `SHAPInsight` breaking with `numpy>=2.4` due to no longer accepted implicit array to
scalar conversion
- Using `np.isclose` for assessing equality of `Interval` bounds instead of hard
equality check
- Typo in `_FixedNumericalContinuousParameter` where `is_numeric` was used
instead of `is_numerical`

### Removed
- `parallel_runs` argument from `simulate_scenarios`, since parallelization
Expand Down
4 changes: 3 additions & 1 deletion baybe/acquisition/acqfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ def get_integration_points(self, searchspace: SearchSpace) -> pd.DataFrame:

# Discrete part
if not searchspace.discrete.is_empty:
candidates_discrete = searchspace.discrete.comp_rep
candidates_discrete = searchspace.discrete.transform(
searchspace.discrete.get_candidates()
)
n_candidates = self.sampling_n_points or math.ceil(
self.sampling_fraction * len(candidates_discrete) # type: ignore[operator]
)
Expand Down
Loading
Loading