Repository navigation
0.38.0
This release focuses on two things:
- Faster optimization loops: surrogates are now updated incrementally between iterations instead of
being retrained from scratch, and the infill / hyperparameter optimizers move to pure Rust (basin). - A cleaner Python API: standard Python exceptions, consistent names and shapes, per-constraint
tolerances, and results you can feed back to the optimizer. Old names keep working with a
DeprecationWarningand will be removed in the next release.
Highlights
Adaptive surrogate update (#454, #461, #462)
- Surrogate models are persisted across iterations. When the clustering is fixed and the new data stays
consistent with the current model (z-score check), the GP is updated with the new points without
re-optimizing its hyperparameters; otherwise a full training is triggered. - TREGO local steps reuse and incrementally update the persisted models instead of retraining all
surrogates from scratch at each local iteration. - Redundant retraining at the start of each EGO step is skipped.
- The
persistentfeature is now always on inegobox-egoandegobox-moe. - Fixes along the way: derived constraint models updated in the wrong space, stale virtual observations
with q-batch, duplicated training data with mixed-integer variables.
Pure Rust optimizers by default (#458, #459, #460)
basinoptimizers (COBYLA, SLSQP) replaceargminand are used by
default for infill optimization and GP hyperparameters training.- The C-ported NLopt crates are still available behind the opt-in features
c-cobylaandc-slsqp.
The formerbasinfeature is gone (it is now the default). - The optional
nloptdependency is removed.
Python API
New and improved
- Standard exceptions (#466): invalid input or failure raises
ValueError,TypeError,OSErroror
RuntimeErrorinstead ofPanicException. Errors raised by your constraint functions are propagated as
is.Gpx.save()/SparseGpx.save()raise on failure instead of returningFalse. - Results:
EgorOptimforwardsx_opt,y_opt,x_doe,y_doefrom itsresultand unpacks as
x_opt, y_opt = egor.minimize(...). - Initial DOE as two arrays:
Egor(x_doe=..., y_doe=...), likeEgor.suggest(). - Per-constraint tolerance:
CstrSpec.leq(bound, tol=1e-3)or{"leq": bound, "tol": 1e-3}.
Whencstr_specsis given,n_cstris inferred and a mismatchingn_cstrraisesValueError. - Raw constraint layout in results (#475): with
cstr_specs,OptimResult.y_opt/OptimResult.y_doe
(Rust and Pythonminimize()) hold the constraint values as returned by your function (1 + n_cstr
columns) instead of the internal<= 0form (sign-flipped forgeq, two columns foreq/between).
They can be given back tobest_result()orEgor(x_doe=..., y_doe=...). DOE files saved inoutdir
keep the internal form. best_index()/best_result()(#474) interpret raw constraint values withcstr_specsand their
tolerances, as the optimizer does. Ay_doenot of shape(ns, 1 + n_cstr)raisesValueError.- Function constraints (#473):
minimize(fcstrs=...)also accepts a(g, grad_g)tuple or a
{"fun": g, "jac": grad_g}dict, with one-argument callables. Theg(x, return_grad)form stays.
Constraints remaing(x) <= 0: a scipy-like"type"key raisesValueError, usefcstr_specsinstead. Egor(seed=..., verbose=...)gives defaults forminimize()andsuggest(); values passed to those
methods take precedence.- GP models:
Gpx.predict(x, return_std=True)/SparseGpx.predict(x, return_std=True)return
(mean, std); newnx/nyproperties onGpxandSparseGpx. Input shapes are handled
consistently acrossGpxandSparseGpx(#470). sampling(xspecs, n_samples, method=Sampling.LHS, seed=None):methodis optional, LHS by default.- Long enum aliases:
ConstraintStrategy.MEAN_CONSTRAINT/UPPER_TRUST_BOUND,
QEiStrategy.KRIGING_BELIEVER/KRIGING_BELIEVER_LOWER_BOUND/KRIGING_BELIEVER_UPPER_BOUND/
CONSTANT_LIAR_MINIMUM,FeasibleInfillStrategy.EFI_PROBABILITY/EFI_FEASIBILITY_ENHANCED. - Type stubs brought in sync with the runtime (#467), and several silent bugs found during the Python API
review fixed (#468).
Deprecations
Deprecated names still work but emit a DeprecationWarning. Passing both a deprecated keyword and its
replacement raises TypeError.
| Deprecated | Use instead |
|---|---|
Egor(n_start=...) |
Egor(infill_n_start=...) |
GpConfig(n_start=...), GpConfig.n_start, gp_config={"n_start": ...} |
theta_n_start |
GpConfig(max_eval=...), GpConfig.max_eval, gp_config={"max_eval": ...} |
theta_max_eval |
GpMix / Gpx.builder(n_start=..., max_eval=...) |
theta_n_start=..., theta_max_eval=... |
SparseGpMix / SparseGpx.builder(n_start=...) |
theta_n_start=... |
SparseGpMix / SparseGpx.builder(nz=..., z=...) |
n_inducing=..., inducing=... |
Egor.get_result(x_doe, y_doe) |
Egor.best_result(x_doe, y_doe) |
Egor.get_result_index(y_doe) |
Egor.best_index(y_doe) |
Egor(doe=...) |
Egor(x_doe=..., y_doe=...) |
Egor(cstr_tol=[...]) |
per-spec tolerance: Egor(cstr_specs=[CstrSpec.leq(0.0, tol=...)]), minimize(fcstr_specs=[...]) |
CstrSpec.btw(lower, upper), {"btw": (lower, upper)} |
CstrSpec.between(lower, upper), {"between": (lower, upper)} |
QEiConfig(optmod=...), QEiConfig.optmod, qei_config={"optmod": ...} |
optim_every |
TregoConfig(n_gl_steps=...), TregoConfig.n_gl_steps, trego={"n_gl_steps": ...} |
n_global_local_steps |
TregoConfig(d=...), TregoConfig.d, trego={"d": ...} |
radius_bounds |
sampling(method, xspecs, n_samples, seed) (positional) |
sampling(xspecs, n_samples, method=..., seed=...) |
Upcoming breaking changes (next release)
Gpx.thetas(),Gpx.variances()andGpx.likelihoods()become read-only properties
(gpx.thetasinstead ofgpx.thetas()).- The deprecated names above are removed, and
samplingaccepts only the
sampling(xspecs, n_samples, method=..., seed=...)argument order.
Breaking changes
- Previously deprecated APIs are removed (#456):
- Rust
EgorConfig::q_batch(),qei_strategy(),q_optmod()(use the q-EI configuration),
use_max_proba_of_feasibility(),disable_middlepicker_multistarter(), and the deprecated
re-exports ofSurrogateBuilder/XType(useegobox_moe::SurrogateBuilder/egobox_moe::XType). - Runtime flags
EGOR_DO_NOT_USE_MIDDLEPICKER_MULTISTARTERandEGOR_USE_MAX_PROBA_OF_FEASIBILITY. - Python
Egor(outdir=..., warm_start=..., hot_start=...): pass them tominimize().
- Rust
- The run recorder is removed; state recording is kept for debugging and demos (#455).
- Cargo features:
basinremoved (now default),nloptremoved,persistentalways on;
new opt-inc-cobyla/c-slsqp. - Mixed-integer GP mixture refactored (#457):
MixintGpMixturehandles continuous-only problems without
overhead and is the only mixture used from Python;load_gp_modelsis removed. - With
cstr_specs,OptimResult.y_opt/y_doenow use the raw constraint layout (see above).
Bug fixes
- Egor no longer stops at iteration 1 when no initial point is feasible: it falls back to the probability
of feasibility, then to a random point as a last resort (#465). - Best point no longer
nanwhen the failsafe strategy is imputation (#464). - A function constraint may return a one-element array instead of a scalar.
Documentation
- Cookbook recipe and example for constrained engineering problems (lessons from an aero-structural MDO
study), and extended Egor tuning skill with constraint/failure handling and run diagnosis (#463). - Docs and typo fixes (#469).
Full Changelog: 0.37.9...0.38.0