leanhebo 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. leanhebo-0.1.0/CHANGELOG.md +15 -0
  2. leanhebo-0.1.0/CITATION.cff +46 -0
  3. leanhebo-0.1.0/LICENSE +22 -0
  4. leanhebo-0.1.0/NOTICE.md +14 -0
  5. leanhebo-0.1.0/ORIGIN.md +23 -0
  6. leanhebo-0.1.0/PKG-INFO +192 -0
  7. leanhebo-0.1.0/README.md +162 -0
  8. leanhebo-0.1.0/examples/adapters.py +22 -0
  9. leanhebo-0.1.0/examples/basic.py +40 -0
  10. leanhebo-0.1.0/examples/contextual_checkpoint.py +20 -0
  11. leanhebo-0.1.0/pyproject.toml +120 -0
  12. leanhebo-0.1.0/pyproject.toml.orig +102 -0
  13. leanhebo-0.1.0/src/leanhebo/__init__.py +27 -0
  14. leanhebo-0.1.0/src/leanhebo/acquisition/__init__.py +8 -0
  15. leanhebo-0.1.0/src/leanhebo/acquisition/mace.py +91 -0
  16. leanhebo-0.1.0/src/leanhebo/acquisition/posterior.py +119 -0
  17. leanhebo-0.1.0/src/leanhebo/checkpoint.py +73 -0
  18. leanhebo-0.1.0/src/leanhebo/config.py +263 -0
  19. leanhebo-0.1.0/src/leanhebo/data/__init__.py +29 -0
  20. leanhebo-0.1.0/src/leanhebo/data/adapters/__init__.py +11 -0
  21. leanhebo-0.1.0/src/leanhebo/data/adapters/numpy.py +30 -0
  22. leanhebo-0.1.0/src/leanhebo/data/adapters/pandas.py +15 -0
  23. leanhebo-0.1.0/src/leanhebo/data/adapters/polars.py +15 -0
  24. leanhebo-0.1.0/src/leanhebo/data/adapters/registry.py +125 -0
  25. leanhebo-0.1.0/src/leanhebo/data/batch.py +255 -0
  26. leanhebo-0.1.0/src/leanhebo/data/store.py +355 -0
  27. leanhebo-0.1.0/src/leanhebo/diagnostics.py +134 -0
  28. leanhebo-0.1.0/src/leanhebo/errors.py +23 -0
  29. leanhebo-0.1.0/src/leanhebo/gp/__init__.py +8 -0
  30. leanhebo-0.1.0/src/leanhebo/gp/exact.py +742 -0
  31. leanhebo-0.1.0/src/leanhebo/gp/kernel.py +130 -0
  32. leanhebo-0.1.0/src/leanhebo/gp/optimizer.py +127 -0
  33. leanhebo-0.1.0/src/leanhebo/gp/reports.py +7 -0
  34. leanhebo-0.1.0/src/leanhebo/optimizer.py +628 -0
  35. leanhebo-0.1.0/src/leanhebo/py.typed +1 -0
  36. leanhebo-0.1.0/src/leanhebo/runtime/__init__.py +8 -0
  37. leanhebo-0.1.0/src/leanhebo/runtime/process.py +44 -0
  38. leanhebo-0.1.0/src/leanhebo/runtime/rng.py +82 -0
  39. leanhebo-0.1.0/src/leanhebo/search/__init__.py +82 -0
  40. leanhebo-0.1.0/src/leanhebo/search/duplicates.py +228 -0
  41. leanhebo-0.1.0/src/leanhebo/search/nsga2.py +599 -0
  42. leanhebo-0.1.0/src/leanhebo/search/operators.py +451 -0
  43. leanhebo-0.1.0/src/leanhebo/search/repair.py +307 -0
  44. leanhebo-0.1.0/src/leanhebo/search/sorting.py +187 -0
  45. leanhebo-0.1.0/src/leanhebo/search/survival.py +127 -0
  46. leanhebo-0.1.0/src/leanhebo/space/__init__.py +22 -0
  47. leanhebo-0.1.0/src/leanhebo/space/compiled.py +732 -0
  48. leanhebo-0.1.0/src/leanhebo/space/keys.py +92 -0
  49. leanhebo-0.1.0/src/leanhebo/space/parameters.py +488 -0
  50. leanhebo-0.1.0/src/leanhebo/space/space.py +101 -0
  51. leanhebo-0.1.0/src/leanhebo/transforms/__init__.py +53 -0
  52. leanhebo-0.1.0/src/leanhebo/transforms/power.py +957 -0
  53. leanhebo-0.1.0/src/leanhebo/transforms/scalers.py +362 -0
@@ -0,0 +1,15 @@
1
+ # Changelog
2
+
3
+ All notable changes to LeanHEBO will be documented here.
4
+
5
+ ## 0.1.0 - 2026-08-09
6
+
7
+ - Establish the independent `uv` project and provenance boundary.
8
+ - Implement the initial exact-GP LeanHEBO optimization path.
9
+ - Fit and checkpoint the HEBO-compatible observed-range input scaler used by the exact GP.
10
+ - Preserve append-only observation state, reserved duplicate keys, diagnostics, search history,
11
+ and exact version counters across safe checkpoints.
12
+ - Raise a typed exhaustion error instead of silently returning duplicate suggestions.
13
+ - Retry numerical fit or posterior failures once with a clean full GP refit.
14
+ - Add a pinned, dependency-locked upstream benchmark environment and a fail-closed paired
15
+ comparison harness with actual-work checks and bootstrap confidence intervals.
@@ -0,0 +1,46 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use LeanHEBO, cite both LeanHEBO and the original HEBO work."
3
+ title: "LeanHEBO"
4
+ type: software
5
+ version: 0.1.0
6
+ date-released: 2026-08-09
7
+ license: MIT
8
+ authors:
9
+ - name: "LeanHEBO contributors"
10
+ repository-code: "https://github.com/dimitrismoustakas/LeanHEBO"
11
+ references:
12
+ - type: article
13
+ title: "HEBO: Pushing the Limits of Sample-Efficient Hyperparameter Optimisation"
14
+ authors:
15
+ - family-names: Cowen-Rivers
16
+ given-names: Alexander I.
17
+ - family-names: Lyu
18
+ given-names: Wenlong
19
+ - family-names: Tutunov
20
+ given-names: Rasul
21
+ - family-names: Wang
22
+ given-names: Zhi
23
+ - family-names: Grosnit
24
+ given-names: Antoine
25
+ - family-names: Griffiths
26
+ given-names: Ryan-Rhys
27
+ - family-names: Maravel
28
+ given-names: Alexandre M.
29
+ - family-names: Hao
30
+ given-names: Jianye
31
+ - family-names: Wang
32
+ given-names: Jun
33
+ - family-names: Peters
34
+ given-names: Jan
35
+ - family-names: Bou-Ammar
36
+ given-names: Haitham
37
+ journal: "Journal of Artificial Intelligence Research"
38
+ volume: 74
39
+ year: 2022
40
+ doi: "10.1613/jair.1.13643"
41
+ - type: software
42
+ title: "HEBO"
43
+ authors:
44
+ - name: "Huawei Technologies Co., Ltd."
45
+ repository-code: "https://github.com/huawei-noah/HEBO"
46
+ version: "ee6112d39d1a9e9703fecaf9057193e1ec9dae72"
leanhebo-0.1.0/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
4
+ Copyright (c) 2026 LeanHEBO contributors
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,14 @@
1
+ # Notice
2
+
3
+ LeanHEBO is an independent implementation derived in part from the HEBO project by
4
+ Huawei Technologies Co., Ltd. It is not affiliated with, sponsored by, or endorsed by
5
+ Huawei.
6
+
7
+ - Upstream project: <https://github.com/huawei-noah/HEBO>
8
+ - Audited package: `HEBO/`
9
+ - Audited commit: `ee6112d39d1a9e9703fecaf9057193e1ec9dae72`
10
+ - Upstream license: MIT
11
+
12
+ The HEBO method is described by Cowen-Rivers et al., “HEBO: Pushing the Limits of
13
+ Sample-Efficient Hyperparameter Optimisation,” *Journal of Artificial Intelligence
14
+ Research*, volume 74, 2022.
@@ -0,0 +1,23 @@
1
+ # Code origin
2
+
3
+ LeanHEBO reimplements the main single-objective exact-GP path of Huawei's HEBO package,
4
+ audited at commit `ee6112d39d1a9e9703fecaf9057193e1ec9dae72`.
5
+
6
+ ## Reimplemented components
7
+
8
+ - mixed-variable design-space encoding and Sobol sampling;
9
+ - output standardization and Box-Cox/Yeo-Johnson transformation behavior;
10
+ - exact Gaussian-process regression and HEBO-compatible kernel construction;
11
+ - the three-objective MACE acquisition calculation;
12
+ - HEBO-style batch candidate selection.
13
+
14
+ ## Independently implemented components
15
+
16
+ - immutable compiled-space metadata and `CandidateBatch` boundary;
17
+ - append-only tensor observation storage and incremental duplicate membership;
18
+ - persistent GP/model/optimizer lifecycle;
19
+ - tensor-native mixed-variable NSGA-II;
20
+ - configuration, diagnostics, checkpointing, and optional table adapters.
21
+
22
+ Files that substantially copy upstream implementation text must retain Huawei copyright
23
+ headers. New implementations use SPDX identifiers and refer to `NOTICE.md`.
@@ -0,0 +1,192 @@
1
+ Metadata-Version: 2.4
2
+ Name: leanhebo
3
+ Version: 0.1.0
4
+ Summary: A tensor-native, low-latency implementation of the HEBO method
5
+ Keywords: bayesian-optimization,gaussian-process,hebo,pytorch
6
+ Author: LeanHEBO contributors
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ License-File: NOTICE.md
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Requires-Dist: gpytorch>=1.14
18
+ Requires-Dist: numpy>=2.0
19
+ Requires-Dist: torch>=2.5
20
+ Requires-Dist: pandas>=2.2 ; extra == 'pandas'
21
+ Requires-Dist: polars>=1.0 ; extra == 'polars'
22
+ Requires-Python: >=3.11
23
+ Project-URL: Homepage, https://github.com/dimitrismoustakas/LeanHEBO
24
+ Project-URL: Repository, https://github.com/dimitrismoustakas/LeanHEBO
25
+ Project-URL: Issues, https://github.com/dimitrismoustakas/LeanHEBO/issues
26
+ Project-URL: Changelog, https://github.com/dimitrismoustakas/LeanHEBO/blob/main/CHANGELOG.md
27
+ Provides-Extra: pandas
28
+ Provides-Extra: polars
29
+ Description-Content-Type: text/markdown
30
+
31
+ # LeanHEBO
32
+
33
+ LeanHEBO is a tensor-native, low-latency implementation of the established HEBO Bayesian
34
+ optimization strategy. It focuses on the single-objective exact-GP path, persistent model
35
+ state, mixed-variable search, and explicit CPU or CUDA execution.
36
+
37
+ LeanHEBO is an independent project. It is not affiliated with or endorsed by Huawei and
38
+ does not claim a new optimization algorithm. See
39
+ [NOTICE.md](https://github.com/dimitrismoustakas/LeanHEBO/blob/main/NOTICE.md) and
40
+ [ORIGIN.md](https://github.com/dimitrismoustakas/LeanHEBO/blob/main/ORIGIN.md) for provenance.
41
+
42
+ The package is under active initial development. Its first release targets continuous,
43
+ log-continuous, integer, stepped-integer, power/exponent-integer, Boolean, and categorical
44
+ variables; batch and contextual suggestions; HEBO output warping; MACE acquisition; and a
45
+ tensor-native NSGA-II search.
46
+
47
+ ## Installation
48
+
49
+ LeanHEBO requires Python 3.11 or newer; the initial release is tested on Python 3.11 through
50
+ 3.13. Install the released package with either pip or uv:
51
+
52
+ ```console
53
+ python -m pip install leanhebo
54
+ ```
55
+
56
+ ```console
57
+ uv add leanhebo
58
+ ```
59
+
60
+ Pandas and Polars adapters are optional extras:
61
+
62
+ ```console
63
+ python -m pip install "leanhebo[pandas,polars]"
64
+ # or: uv add "leanhebo[pandas,polars]"
65
+ ```
66
+
67
+ CPU is the primary supported path for the initial alpha release. CUDA execution is available,
68
+ but accelerator support depends on the Torch build and the local CUDA stack. Install the
69
+ appropriate Torch build using the [PyTorch installation guide](https://pytorch.org/get-started/locally/)
70
+ before installing LeanHEBO; the package does not silently switch between CPU and CUDA.
71
+
72
+ ## Quick start
73
+
74
+ LeanHEBO minimizes the objective values supplied to `observe`. This complete example optimizes
75
+ a small mixed-variable loss:
76
+
77
+ ```python
78
+ import numpy as np
79
+
80
+ from leanhebo import LeanHEBO
81
+ from leanhebo.config import GPConfig, LeanHEBOConfig, RuntimeConfig, SearchConfig
82
+ from leanhebo.space import Bool, Categorical, Float, Integer, Space
83
+
84
+
85
+ def objective(row: dict[str, object]) -> float:
86
+ """Return a loss: LeanHEBO minimizes the values passed to observe."""
87
+ x = float(row["x"])
88
+ depth = int(row["depth"])
89
+ activation_penalty = 0.0 if row["activation"] == "gelu" else 0.25
90
+ bias_penalty = 0.0 if bool(row["use_bias"]) else 0.1
91
+ return (x - 0.3) ** 2 + (depth - 6) ** 2 / 25 + activation_penalty + bias_penalty
92
+
93
+
94
+ space = Space(
95
+ Float("x", -2.0, 2.0),
96
+ Integer("depth", 1, 12),
97
+ Categorical("activation", ("relu", "gelu", "silu")),
98
+ Bool("use_bias"),
99
+ )
100
+ config = LeanHEBOConfig(
101
+ runtime=RuntimeConfig(seed=7),
102
+ # Small settings keep this example quick; use the defaults for real optimization.
103
+ gp=GPConfig(initial_steps=15, update_steps=3),
104
+ search=SearchConfig(population_size=32, generations=15),
105
+ )
106
+ optimizer = LeanHEBO(space, config=config)
107
+
108
+ for _ in range(3):
109
+ candidates = optimizer.suggest(3)
110
+ losses = np.asarray([objective(row) for row in candidates.to_records()])
111
+ optimizer.observe(candidates, losses)
112
+
113
+ print(optimizer.best_x.to_records()[0], optimizer.best_y)
114
+ ```
115
+
116
+ Passing the original `CandidateBatch` to `observe` avoids re-encoding; the observation store takes
117
+ one owned tensor snapshot so later caller mutation cannot rewrite history. Records, NumPy arrays,
118
+ Pandas DataFrames, and Polars DataFrames are also accepted at the boundary and encoded once.
119
+
120
+ Contextual values are fixed without a DataFrame round trip:
121
+
122
+ ```python
123
+ candidates = optimizer.suggest(8, fix_input={"use_bias": True})
124
+ ```
125
+
126
+ ```python
127
+ candidates = optimizer.suggest(3)
128
+ frame = candidates.to_polars() # or candidates.to_pandas()
129
+ losses = np.asarray([objective(row) for row in candidates.to_records()])
130
+ optimizer.observe(frame, losses)
131
+ ```
132
+
133
+ ## Runtime behavior
134
+
135
+ Runtime code keeps encoded observations, transforms, GP state, acquisition evaluation, random
136
+ streams, and evolutionary populations in Torch. NumPy and optional table libraries are boundary
137
+ formats only. The GP and likelihood survive ordinary updates; new training data are installed
138
+ with GPyTorch's persistent exact-GP API and receive the configured short update schedule.
139
+
140
+ CPU is the default. CUDA is selected explicitly with `RuntimeConfig(device="cuda")`; LeanHEBO
141
+ does not silently move work between devices. Both `float32` and `float64` are supported. The
142
+ project is currently alpha software: CPU behavior receives the broadest release validation,
143
+ while CUDA compatibility can vary across Torch, driver, and device combinations.
144
+
145
+ Importing LeanHEBO does not change Torch or BLAS thread counts. Applications that want an
146
+ explicit process-wide policy should call the startup helper before other Torch work:
147
+
148
+ ```python
149
+ from leanhebo.runtime import configure_process
150
+
151
+ configure_process(torch_num_threads=1, torch_num_interop_threads=1)
152
+ ```
153
+
154
+ Every configuration group has one documented set of defaults and serializes with
155
+ `optimizer.config.to_dict()`. There are no hidden execution modes or preset profiles.
156
+
157
+ ## Checkpointing
158
+
159
+ ```python
160
+ optimizer.save("run.leanhebo")
161
+ restored = LeanHEBO.load("run.leanhebo", map_location="cpu")
162
+ ```
163
+
164
+ The versioned checkpoint contains only LeanHEBO-defined state, tensors, and primitive schema
165
+ values. It restores observations, transforms, model and likelihood parameters, optimizer state,
166
+ Sobol progress, and independent Torch generator states. User functions are never pickled.
167
+
168
+ ## Scope
169
+
170
+ The initial implementation is intentionally narrow: one user objective, an exact Gaussian
171
+ process, MACE, and mixed-variable NSGA-II. Random forests, CatBoost, neural ensembles, sparse
172
+ GPs, constrained user objectives, and general multi-objective user objectives are not part of
173
+ the first release.
174
+
175
+ No performance or quality claim should be made without the pinned, matched-work benchmark and
176
+ multi-seed quality suite described in
177
+ [benchmarks/README.md](https://github.com/dimitrismoustakas/LeanHEBO/blob/main/benchmarks/README.md).
178
+
179
+ ## Development
180
+
181
+ ```console
182
+ uv sync --all-groups --all-extras
183
+ uv run pytest
184
+ uv run ruff check .
185
+ uv run ruff format --check .
186
+ uv run mypy src/leanhebo
187
+ uv build
188
+ ```
189
+
190
+ The repository uses Python 3.11+, a `src/` layout, the pure-Python `uv_build` backend, and a
191
+ committed CPU development lock. Optional accelerator environments should override only the
192
+ explicit Torch package index.
@@ -0,0 +1,162 @@
1
+ # LeanHEBO
2
+
3
+ LeanHEBO is a tensor-native, low-latency implementation of the established HEBO Bayesian
4
+ optimization strategy. It focuses on the single-objective exact-GP path, persistent model
5
+ state, mixed-variable search, and explicit CPU or CUDA execution.
6
+
7
+ LeanHEBO is an independent project. It is not affiliated with or endorsed by Huawei and
8
+ does not claim a new optimization algorithm. See
9
+ [NOTICE.md](https://github.com/dimitrismoustakas/LeanHEBO/blob/main/NOTICE.md) and
10
+ [ORIGIN.md](https://github.com/dimitrismoustakas/LeanHEBO/blob/main/ORIGIN.md) for provenance.
11
+
12
+ The package is under active initial development. Its first release targets continuous,
13
+ log-continuous, integer, stepped-integer, power/exponent-integer, Boolean, and categorical
14
+ variables; batch and contextual suggestions; HEBO output warping; MACE acquisition; and a
15
+ tensor-native NSGA-II search.
16
+
17
+ ## Installation
18
+
19
+ LeanHEBO requires Python 3.11 or newer; the initial release is tested on Python 3.11 through
20
+ 3.13. Install the released package with either pip or uv:
21
+
22
+ ```console
23
+ python -m pip install leanhebo
24
+ ```
25
+
26
+ ```console
27
+ uv add leanhebo
28
+ ```
29
+
30
+ Pandas and Polars adapters are optional extras:
31
+
32
+ ```console
33
+ python -m pip install "leanhebo[pandas,polars]"
34
+ # or: uv add "leanhebo[pandas,polars]"
35
+ ```
36
+
37
+ CPU is the primary supported path for the initial alpha release. CUDA execution is available,
38
+ but accelerator support depends on the Torch build and the local CUDA stack. Install the
39
+ appropriate Torch build using the [PyTorch installation guide](https://pytorch.org/get-started/locally/)
40
+ before installing LeanHEBO; the package does not silently switch between CPU and CUDA.
41
+
42
+ ## Quick start
43
+
44
+ LeanHEBO minimizes the objective values supplied to `observe`. This complete example optimizes
45
+ a small mixed-variable loss:
46
+
47
+ ```python
48
+ import numpy as np
49
+
50
+ from leanhebo import LeanHEBO
51
+ from leanhebo.config import GPConfig, LeanHEBOConfig, RuntimeConfig, SearchConfig
52
+ from leanhebo.space import Bool, Categorical, Float, Integer, Space
53
+
54
+
55
+ def objective(row: dict[str, object]) -> float:
56
+ """Return a loss: LeanHEBO minimizes the values passed to observe."""
57
+ x = float(row["x"])
58
+ depth = int(row["depth"])
59
+ activation_penalty = 0.0 if row["activation"] == "gelu" else 0.25
60
+ bias_penalty = 0.0 if bool(row["use_bias"]) else 0.1
61
+ return (x - 0.3) ** 2 + (depth - 6) ** 2 / 25 + activation_penalty + bias_penalty
62
+
63
+
64
+ space = Space(
65
+ Float("x", -2.0, 2.0),
66
+ Integer("depth", 1, 12),
67
+ Categorical("activation", ("relu", "gelu", "silu")),
68
+ Bool("use_bias"),
69
+ )
70
+ config = LeanHEBOConfig(
71
+ runtime=RuntimeConfig(seed=7),
72
+ # Small settings keep this example quick; use the defaults for real optimization.
73
+ gp=GPConfig(initial_steps=15, update_steps=3),
74
+ search=SearchConfig(population_size=32, generations=15),
75
+ )
76
+ optimizer = LeanHEBO(space, config=config)
77
+
78
+ for _ in range(3):
79
+ candidates = optimizer.suggest(3)
80
+ losses = np.asarray([objective(row) for row in candidates.to_records()])
81
+ optimizer.observe(candidates, losses)
82
+
83
+ print(optimizer.best_x.to_records()[0], optimizer.best_y)
84
+ ```
85
+
86
+ Passing the original `CandidateBatch` to `observe` avoids re-encoding; the observation store takes
87
+ one owned tensor snapshot so later caller mutation cannot rewrite history. Records, NumPy arrays,
88
+ Pandas DataFrames, and Polars DataFrames are also accepted at the boundary and encoded once.
89
+
90
+ Contextual values are fixed without a DataFrame round trip:
91
+
92
+ ```python
93
+ candidates = optimizer.suggest(8, fix_input={"use_bias": True})
94
+ ```
95
+
96
+ ```python
97
+ candidates = optimizer.suggest(3)
98
+ frame = candidates.to_polars() # or candidates.to_pandas()
99
+ losses = np.asarray([objective(row) for row in candidates.to_records()])
100
+ optimizer.observe(frame, losses)
101
+ ```
102
+
103
+ ## Runtime behavior
104
+
105
+ Runtime code keeps encoded observations, transforms, GP state, acquisition evaluation, random
106
+ streams, and evolutionary populations in Torch. NumPy and optional table libraries are boundary
107
+ formats only. The GP and likelihood survive ordinary updates; new training data are installed
108
+ with GPyTorch's persistent exact-GP API and receive the configured short update schedule.
109
+
110
+ CPU is the default. CUDA is selected explicitly with `RuntimeConfig(device="cuda")`; LeanHEBO
111
+ does not silently move work between devices. Both `float32` and `float64` are supported. The
112
+ project is currently alpha software: CPU behavior receives the broadest release validation,
113
+ while CUDA compatibility can vary across Torch, driver, and device combinations.
114
+
115
+ Importing LeanHEBO does not change Torch or BLAS thread counts. Applications that want an
116
+ explicit process-wide policy should call the startup helper before other Torch work:
117
+
118
+ ```python
119
+ from leanhebo.runtime import configure_process
120
+
121
+ configure_process(torch_num_threads=1, torch_num_interop_threads=1)
122
+ ```
123
+
124
+ Every configuration group has one documented set of defaults and serializes with
125
+ `optimizer.config.to_dict()`. There are no hidden execution modes or preset profiles.
126
+
127
+ ## Checkpointing
128
+
129
+ ```python
130
+ optimizer.save("run.leanhebo")
131
+ restored = LeanHEBO.load("run.leanhebo", map_location="cpu")
132
+ ```
133
+
134
+ The versioned checkpoint contains only LeanHEBO-defined state, tensors, and primitive schema
135
+ values. It restores observations, transforms, model and likelihood parameters, optimizer state,
136
+ Sobol progress, and independent Torch generator states. User functions are never pickled.
137
+
138
+ ## Scope
139
+
140
+ The initial implementation is intentionally narrow: one user objective, an exact Gaussian
141
+ process, MACE, and mixed-variable NSGA-II. Random forests, CatBoost, neural ensembles, sparse
142
+ GPs, constrained user objectives, and general multi-objective user objectives are not part of
143
+ the first release.
144
+
145
+ No performance or quality claim should be made without the pinned, matched-work benchmark and
146
+ multi-seed quality suite described in
147
+ [benchmarks/README.md](https://github.com/dimitrismoustakas/LeanHEBO/blob/main/benchmarks/README.md).
148
+
149
+ ## Development
150
+
151
+ ```console
152
+ uv sync --all-groups --all-extras
153
+ uv run pytest
154
+ uv run ruff check .
155
+ uv run ruff format --check .
156
+ uv run mypy src/leanhebo
157
+ uv build
158
+ ```
159
+
160
+ The repository uses Python 3.11+, a `src/` layout, the pure-Python `uv_build` backend, and a
161
+ committed CPU development lock. Optional accelerator environments should override only the
162
+ explicit Torch package index.
@@ -0,0 +1,22 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Optional table adapters remain outside the optimization hot path."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import numpy as np
8
+
9
+ from leanhebo import LeanHEBO
10
+ from leanhebo.config import LeanHEBOConfig, RuntimeConfig
11
+ from leanhebo.space import Categorical, Float, Space
12
+
13
+ space = Space(Float("x", -1.0, 1.0), Categorical("kind", ("left", "right")))
14
+ optimizer = LeanHEBO(space, config=LeanHEBOConfig(runtime=RuntimeConfig(seed=3)))
15
+
16
+ candidates = optimizer.suggest(4)
17
+ pandas_frame = candidates.to_pandas()
18
+ polars_frame = candidates.to_polars()
19
+ assert pandas_frame.shape == polars_frame.shape
20
+
21
+ values = np.square(pandas_frame["x"].to_numpy())
22
+ optimizer.observe(candidates, values) # reuses CandidateBatch tensors
@@ -0,0 +1,40 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """A small mixed-variable LeanHEBO loop."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import numpy as np
8
+
9
+ from leanhebo import LeanHEBO
10
+ from leanhebo.config import GPConfig, LeanHEBOConfig, RuntimeConfig, SearchConfig
11
+ from leanhebo.space import Bool, Categorical, Float, Integer, Space
12
+
13
+
14
+ def objective(row: dict[str, object]) -> float:
15
+ x = float(row["x"])
16
+ depth = int(row["depth"])
17
+ category_penalty = 0.0 if row["activation"] == "gelu" else 0.25
18
+ bias_penalty = 0.0 if bool(row["use_bias"]) else 0.1
19
+ return (x - 0.3) ** 2 + (depth - 6) ** 2 / 25 + category_penalty + bias_penalty
20
+
21
+
22
+ space = Space(
23
+ Float("x", -2.0, 2.0),
24
+ Integer("depth", 1, 12),
25
+ Categorical("activation", ("relu", "gelu", "silu")),
26
+ Bool("use_bias"),
27
+ )
28
+ config = LeanHEBOConfig(
29
+ runtime=RuntimeConfig(seed=7),
30
+ gp=GPConfig(initial_steps=30, update_steps=5),
31
+ search=SearchConfig(population_size=64, generations=30),
32
+ )
33
+ optimizer = LeanHEBO(space, config=config)
34
+
35
+ for _ in range(12):
36
+ batch = optimizer.suggest(3)
37
+ y = np.asarray([objective(record) for record in batch.to_records()])
38
+ optimizer.observe(batch, y)
39
+
40
+ print(optimizer.best_x.to_records()[0], optimizer.best_y)
@@ -0,0 +1,20 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Contextual suggestions and deterministic checkpoint continuation."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from leanhebo import LeanHEBO
8
+ from leanhebo.config import LeanHEBOConfig, RuntimeConfig
9
+ from leanhebo.space import Categorical, Float, Space
10
+
11
+ space = Space(Float("dose", 0.0, 1.0), Categorical("site", ("north", "south")))
12
+ optimizer = LeanHEBO(space, config=LeanHEBOConfig(runtime=RuntimeConfig(seed=19)))
13
+
14
+ south_batch = optimizer.suggest(4, fix_input={"site": "south"})
15
+ assert all(record["site"] == "south" for record in south_batch.to_records())
16
+
17
+ optimizer.save("contextual.leanhebo")
18
+ restored = LeanHEBO.load("contextual.leanhebo", map_location="cpu")
19
+ next_batch = restored.suggest(2, fix_input={"site": "south"})
20
+ print(next_batch.to_records())
@@ -0,0 +1,120 @@
1
+ [project]
2
+ name = "leanhebo"
3
+ version = "0.1.0"
4
+ description = "A tensor-native, low-latency implementation of the HEBO method"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license = "MIT"
8
+ license-files = [
9
+ "LICENSE",
10
+ "NOTICE.md",
11
+ ]
12
+ keywords = [
13
+ "bayesian-optimization",
14
+ "gaussian-process",
15
+ "hebo",
16
+ "pytorch",
17
+ ]
18
+ classifiers = [
19
+ "Development Status :: 3 - Alpha",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
26
+ ]
27
+ dependencies = [
28
+ "gpytorch>=1.14",
29
+ "numpy>=2.0",
30
+ "torch>=2.5",
31
+ ]
32
+
33
+ [[project.authors]]
34
+ name = "LeanHEBO contributors"
35
+
36
+ [project.urls]
37
+ Homepage = "https://github.com/dimitrismoustakas/LeanHEBO"
38
+ Repository = "https://github.com/dimitrismoustakas/LeanHEBO"
39
+ Issues = "https://github.com/dimitrismoustakas/LeanHEBO/issues"
40
+ Changelog = "https://github.com/dimitrismoustakas/LeanHEBO/blob/main/CHANGELOG.md"
41
+
42
+ [project.optional-dependencies]
43
+ pandas = ["pandas>=2.2"]
44
+ polars = ["polars>=1.0"]
45
+
46
+ [dependency-groups]
47
+ dev = [
48
+ "hypothesis>=6.100",
49
+ "mypy>=1.11",
50
+ "pandas>=2.2",
51
+ "polars>=1.0",
52
+ "pre-commit>=3.7",
53
+ "pymoo>=0.6",
54
+ "pytest>=8",
55
+ "pytest-cov>=5",
56
+ "ruff>=0.6",
57
+ "scikit-learn>=1.5",
58
+ "scipy>=1.14",
59
+ ]
60
+ bench = [
61
+ "asv>=0.6",
62
+ "psutil>=6",
63
+ "py-spy>=0.4",
64
+ "pytest-benchmark>=4",
65
+ ]
66
+
67
+ [build-system]
68
+ requires = ["uv_build>=0.12.0,<0.13"]
69
+ build-backend = "uv_build"
70
+
71
+ [tool.uv.build-backend]
72
+ module-name = "leanhebo"
73
+ module-root = "src"
74
+ source-include = [
75
+ "CHANGELOG.md",
76
+ "CITATION.cff",
77
+ "ORIGIN.md",
78
+ "examples/**",
79
+ ]
80
+
81
+ [tool.pytest.ini_options]
82
+ addopts = "-ra --strict-config --strict-markers"
83
+ testpaths = ["tests"]
84
+ markers = [
85
+ "gpu: requires a CUDA-capable Torch installation",
86
+ "performance: structural or timing performance tests",
87
+ ]
88
+
89
+ [tool.coverage.run]
90
+ branch = true
91
+ source = ["leanhebo"]
92
+
93
+ [tool.coverage.report]
94
+ show_missing = true
95
+ skip_covered = true
96
+
97
+ [tool.ruff]
98
+ line-length = 100
99
+ target-version = "py311"
100
+
101
+ [tool.ruff.lint]
102
+ select = [
103
+ "E",
104
+ "F",
105
+ "I",
106
+ "UP",
107
+ "B",
108
+ "SIM",
109
+ "RUF",
110
+ ]
111
+
112
+ [tool.ruff.lint.per-file-ignores]
113
+ "tests/**/*.py" = ["S101"]
114
+
115
+ [tool.mypy]
116
+ python_version = "3.11"
117
+ strict = true
118
+ warn_unreachable = true
119
+ packages = ["leanhebo"]
120
+ mypy_path = "src"