Skip to content

feat(bo): batch, asynchronous, constrained and integer Bayesian optimization, completing batch B - #415

Merged
tachsin merged 10 commits into
mainfrom
feat/bo-batch
Oct 2, 2026
Merged

tachsin merged 10 commits into
mainfrom
feat/bo-batch

Conversation

@tachsin

@tachsin tachsin commented Oct 2, 2026

Copy link
Copy Markdown
Owner

The second part of batch B in the optimization plan, after #382: Bayesian optimization in batches, asynchronously, with constraints, and on integer genes.

Batches: .batch(q) with .fantasy(bo::Fantasy::KrigingBeliever), the default, or ConstantLiar(Lie::Min | Mean | Max) (Ginsbourger, Le Riche and Carraro 2010, Algorithms 1 and 2, checked).

  • Each point of a batch is chosen after the earlier ones are added with a fantasized value, through GaussianProcess::with_points. Hyperparameters are not refit within a batch.
  • With Engine::parallel(true), a batch is evaluated in parallel, with the same bits on any number of threads.
  • batch(1) reproduces single-point runs bit for bit.
  • The believer is the default on evidence. With batches of 4 over 20 seeds, it ties the lowest lie and beats the mean and highest lies. Under AsyncEngine it reached Hartmann 3 in 5 of 5 runs, against 2 of 5 for the lowest lie.

Asynchronous: Bo implements Incremental, so AsyncEngine proposes a point while others are pending, with the pending points fantasized. A checkpoint holds them, and a resumed run matches an uninterrupted one. Incremental gains defaulted prepare, wants and receive_evaluation, and AsyncEngine evaluates the wanted extras.

Constraints (Gardner et al. 2014, checked):

  • Constraint values come from Constrained or a problem's own. Each constraint gets its own GP.
  • EI is multiplied by the probability of feasibility, and log-EI adds its logarithm. Before any feasible point exists, that probability alone is maximized.
  • UCB with constraints is an error.

Integer genes: Bo<R: bo::Space = Real>, with Space implemented for Real and Integer.

  • The model sees lattice points only (Garrido-Merchán and Hernández-Lobato 2020, eq. 7).
  • The acquisition is maximized on the lattice: exhaustively when the lattice is small, otherwise by raw samples and a ±1 hill climb.
  • A fully evaluated lattice ends the run as Converged.

In Python and the CLI:

  • Python: gx.Bo(..., batch=, fantasy=), run(f, constraints=m), and integer genomes.
  • CLI: batch, fantasy, asynchronous = true, integer genomes, and constraint values from fitness programs.

Examples (Rust and Python identical, except the asynchronous one):

  • bo_hartmann6: batches of 4 come within 1e-4 of the global minimum in 15 rounds (74 evaluations), against 36 rounds one point at a time. The global minimum depends on the seed: batches reach it in 13 of 20 seeds and single points in 12 of 20, the rest stopping at the local minimum −3.2032. The README says so.
  • bo_constrained: Gramacy et al.'s toy problem. It comes within 1e-5 of f* = 0.5997880520 (checked with mpmath and a grid scan) in 21 evaluations, and every one of 20 seeds within 39. Given only the total violation, the same search ends 0.34 above.
  • bo_asynchronous (Rust only): Hartmann 3 to 1e-4 with 4 workers and evaluations of 10-50 ms, in about 0.4 s, against 0.8 s for batches of 4. Its timings are masked in CI.

Tests:

  • Batch and fantasy behaviour; the same bits on 1, 2 and 8 threads.
  • Async with one worker reproducible.
  • Constrained BO on the Gramacy problem and CEC 2006 G24, and the probability of feasibility's gradients.
  • Integer BO.
  • Checkpoints, including pending points.
  • portable_runs entries and Python tests.

tachsin added 10 commits October 2, 2026 13:27
A model conditioned on points with given values, its kernel's hyperparameters and standardization
kept and its constant mean estimated again: what batch and asynchronous Bayesian optimization add
for the points not yet evaluated. The unit-cube map takes any bounds, for integer genes too.
Incremental gains prepare, wants and receive_evaluation, defaulted as on Algorithm: the engine
asks the fitness function for the wanted extras with buffers per worker, applies the NaN policy
to them, and hands them over with the fitness.
…osals

Bo chooses q points per generation by the Kriging believer or the constant liar (Ginsbourger,
Le Riche and Carraro, 2010), weighs its acquisition by the probability of feasibility under a
Gaussian process per constraint (Gardner et al., 2014), searches Integer genomes on their lattice
with the genes rounded inside the kernel (Garrido-Merchán and Hernández-Lobato, 2020), and
proposes points to an AsyncEngine with the pending ones fantasized.
The fantasies' mechanism and batches on Branin, the same bits on 1, 2 and 8 threads, one worker's
asynchronous run reproducible, a checkpoint's pending points proposed again after resuming, the
toy problem of Gramacy et al. (2016) and CEC 2006's G24 by their constraints' values, an integer
quadratic's lattice minimum, and portable runs of each. The toy problem's minimum comes from a
reference script with mpmath.
Under an AsyncEngine every proposal has the points being evaluated fantasized, and the lowest lie
keeps their region at the best value: Hartmann 3 reached f* + 1e-4 in 2 runs of 5 with 4 workers,
against 5 of 5 with the believer, which batches find as good as the lowest lie.
batch and fantasy settings, readable and settable in control; run(..., constraints=m) with a
fitness function that returns (value, g), and the constraints of the test problems evaluated in
Rust; Integer genomes; RunningBo.probability_of_feasibility_at.
…zation

bo_hartmann6: 4 points a round in parallel to within 1e-4 of Hartmann 6's minimum in 15 rounds,
against 36 one point a round. bo_asynchronous: an AsyncEngine of 4 workers on evaluations of 10
to 50 ms, against batches waiting for their slowest. bo_constrained: Gramacy et al.'s toy problem
to within 1e-5 by the probability of feasibility, against the same search told only the
violation. The surrogate plot takes its panels' titles from the trace.
…s for bo

`batch`, `fantasy` and `asynchronous` settings; `fitness.constraints` without
`fitness.gradient`, a program writing the value and then the constraints' values; integer
genomes. docs/cli.md describes them.
…yesian optimization

AGENTS.md's section with a program for each, the README, docs/features.md, the crate docs'
table, llms.txt, the Python README and the ROADMAP's 0.13 item ticked; the plan's status with the
sources read for batch B's second part and where the implementation differs from its notes.
…them

A run whose fitness function gives constraints, after evaluations told by hand without their
values, is an error instead of an index out of bounds. Also the clippy findings, the CLI test of
the built-in program's constraints and the Python docstring example's import.
@tachsin
tachsin merged commit 5e8977b into main Oct 2, 2026
22 checks passed
@tachsin
tachsin deleted the feat/bo-batch branch October 2, 2026 11:36
@github-actions github-actions Bot mentioned this pull request Oct 2, 2026
tachsin added a commit that referenced this pull request Oct 2, 2026
## 🤖 New release

* `genoxide`: 0.12.0 -> 0.13.0 (✓ API compatible changes)
* `genoxide-python`: 0.12.0 -> 0.13.0

<details><summary><i><b>Changelog</b></i></summary><p>

## `genoxide`

<blockquote>

##
[0.13.0](v0.12.0...v0.13.0)
- 2026-10-02

### <!-- 0 -->Added

- *(bo)* Bayesian optimization with a Gaussian process model, log-EI and
a Latin hypercube design
([#382](#382))
- *(bo)* batch, asynchronous, constrained and integer Bayesian
optimization, completing batch B
([#415](#415))

### <!-- 4 -->Documentation

- correct citations found in an audit of every reference
([#412](#412))
</blockquote>



</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: tachsin <tachsinachmet@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant