tauopt.engine.strategies.gp_ei#
GP + LogEI workhorse strategy (BoTorch behind the owned seam).
SingleTaskGP with current BoTorch defaults (dimension-scaled Hvarfner priors), LogEI acquisition, double precision, MODEL-view geometry (one-hot categoricals – SigOpt parity). Hyperparameters fit on real observations only; open suggestions enter as constant-liar fantasies by conditioning (pessimistic lie), so parallel asks spread without distorting the fit (see _gp_common).
Outcome-constraint metrics (strategy=”constraint”) each get their own GP component; acquisition becomes feasibility-weighted LogEI (analytic for n=1, MC for n>1). The incumbent is the best FEASIBLE observation – with none yet feasible, the worst observed value (pessimistic: EI then rewards any probably-feasible improvement). Constraint fantasies lie AT the threshold (neutral: pending points collapse local variance without inventing feasibility evidence); the objective lie stays pessimistic (y.min). Linear parameter constraints pass to the acquisition optimizer exactly (affine in the model view), so candidates are feasible by construction.
params: timebox_s float, default 10.0, ceiling 300 – cooperative wall-clock budget; overruns raise TimeboxExceeded and the robustness ladder takes over. Checked at phase boundaries and passed to BoTorch’s fit/optimize timeouts; a single long linear-algebra call inside a phase cannot be interrupted (the sync-suggest latency envelope accounts for this). NOTE: which ladder rung answers can therefore depend on machine load – the provenance receipt records the EXECUTED strategy + seed, so any served suggestion re-derives exactly even when the live fallback decision was load-dependent. timebox_mode “budget” (default) | “off” | “caps” – “off” (the benchmarking posture) removes the wall budget entirely: fits and acquisition run to convergence, no timeout machinery is installed, TimeboxExceeded is unreachable, and no clock read can influence the suggestion (wall-independence is pinned by test). Refuses when combined with an explicit timebox_s (ambiguous intent). An ask-level max_wait_s still governs BETWEEN ladder rungs and, when set, wins over “off” for the executed rung (ask.py injects a budget-mode pair as execution context – identity unaffected). “caps”: off’s clock structure with deterministic WORK ceilings – quality-under-budget. TOP-LEVEL ONLY (this params form refuses with a pointer: fallback rungs reset params, so a params-form caps would silently re-enter budget mode down the ladder). Under caps, an ask-level max_wait_s is enforced by the ask boundary alone (cooperative rung-boundary refusal + one post-completion delivery decision, AskDeadlineExceeded) – never by injection or timeouts. num_restarts int, default 8, in [1, 64] – acqf multi-start count raw_samples int, default 128, in [restarts, 4096] – acqf raw candidate pool fit_maxiter int, in [1, 10000] – caps-mode ONLY (set outside caps refuses): per-component GP-fit L-BFGS iteration cap via fit_options (each iteration’s line search is scipy-bounded, maxls=20). Unset => the version-pinned per-stratum default (the field ceiling on uncalibrated strata; the pinned constant 50 on mixed strata). Work exhaustion returns best-so-far – never ladders. acq_maxiter int, in [1, 10000] – caps-mode ONLY: the acqf inner optimizer’s iteration cap (optimize_acqf options.maxiter; on mixed spaces it binds the alternating optimizer’s continuous steps, whose round count is pinned at the capped-mode alternating constant). Unset => the ceiling default on continuous strata; on mixed strata the library’s own deps-pinned iteration bounds govern.
Experimental mode params – each default preserves shipped behavior exactly; the non-default value is an upgrade candidate under measurement, promoted (or parked) on benchmark results:
categorical_mode "one_hot" (default) | "mixed" | "mixed_capped"
"mixed": MixedSingleTaskGP over the mixed-model view (one column
per parameter, CategoricalKernel on category-index columns) +
optimize_acqf_mixed_alternating. No-op on spaces without
categoricals; conditional spaces are refused (ladders with
provenance). The alternating optimizer takes no timeout: the
timebox is checked at phase boundaries only.
"mixed_capped" (cost-engineered candidate): "mixed" with the
LOCKED cap bundle (module constants) -- an L-BFGS maxiter cap on
every MLL fit this mode performs plus alternating-acqf caps
(maxiter_alternating / num_restarts / raw_samples). The plain
"mixed" mode's ~90% fit-cost blowup engineered down; efficacy
still under benchmark measurement. User
num_restarts/raw_samples params are
VALIDATED-THEN-OVERRIDDEN on the mixed path (out-of-range
values still reject as bad config; in-range values are
ignored -- the mode IS the bundle; use "mixed" for tunable
knobs); timebox_s applies unchanged. Same
no-op on categorical-free spaces (byte-identical to the default
path, caps inert), same conditional-space and
feasibility_gp_fixed refusals as "mixed".
The same enum also exists as the TOP-LEVEL config field
``categorical_mode`` (the composable surface that rides auto +
the ladder); resolution = ``effective_categorical_mode``
(both-set refused, params form unchanged for explicit
strategy configs).
noise_mode "median_impute" (default) | "mll_impute"
"mll_impute": stddev-less observations impute at the stage-1
inferred-noise level (marginal-likelihood-optimal on the same
data) instead of the median reported stddev. Identical to the
default at full or zero stddev coverage.
failure_mode "exclude" (default) | "feasibility_gp" | "feasibility_gp_fixed"
"feasibility_gp": a label GP (1=scored, 0=failed, ALL reported
observations) joins the constrained-acquisition path at
threshold 0.5 -- EI is weighted by the probability the point
succeeds. Identical to the default while no failure is recorded.
"feasibility_gp_fixed" (cost-engineered candidate): the same
label component with FIXED hyperparameters and no MLL fit
(see _gp_common.make_fixed_label_gp) -- feasibility_gp's 8-20x
label-fit blowup removed; the component costs one Cholesky.
Same inertness contract (identical to the default while no
failure is recorded); one-hot model view only -- composing
with categorical_mode="mixed" is refused on spaces WITH
categoricals (ladders with provenance) and stays mixed's
documented no-op on categorical-free spaces.
Module Contents#
Classes#
gp_ei’s resolved |
|
Single-objective GP + LogEI strategy (the module docstring carries the full model and params contract). The default policy’s post-bootstrap rung for single-metric experiments, atop the never-fail ladder gp_ei -> ucb_cl -> sobol -> random (pin P6). Requires tauopt[botorch] (torch/botorch/gpytorch). |
Functions#
Composed-flag resolution: the top-level field (the composable
surface that rides auto + the ladder) and the |
Data#
API#
- tauopt.engine.strategies.gp_ei.MIXED_CAPPED_RESTARTS#
4
- tauopt.engine.strategies.gp_ei.MIXED_CAPPED_RAW_SAMPLES#
64
- tauopt.engine.strategies.gp_ei.DEFAULT_NUM_RESTARTS#
8
- tauopt.engine.strategies.gp_ei.DEFAULT_RAW_SAMPLES#
128
- tauopt.engine.strategies.gp_ei.effective_categorical_mode(cfg: tauopt.engine.config.OptimizerConfig) str#
Composed-flag resolution: the top-level field (the composable surface that rides auto + the ladder) and the
paramsform are ONE fact with two possible writers – BOTH set is refused as ambiguous, even when equal (agreement would still be two homes for one fact). The top-level value is Literal-validated at config parse; the params form keeps its str_param enum check. Absent everywhere => “one_hot”, the default.
- class tauopt.engine.strategies.gp_ei.GpEiParams#
Bases:
typing.NamedTuplegp_ei’s resolved
paramsfor one (state, cfg): whatread_paramsreturns andsuggestexecutes.
- class tauopt.engine.strategies.gp_ei.GpEiStrategy#
Single-objective GP + LogEI strategy (the module docstring carries the full model and params contract). The default policy’s post-bootstrap rung for single-metric experiments, atop the never-fail ladder gp_ei -> ucb_cl -> sobol -> random (pin P6). Requires tauopt[botorch] (torch/botorch/gpytorch).
- name#
‘gp_ei’
- read_params(state: tauopt.engine.state.ExperimentState, cfg: tauopt.engine.config.OptimizerConfig) tauopt.engine.strategies.gp_ei.GpEiParams#
The ONE reading of
cfg.paramsfor this strategy – the strict typed readers, their ranges, the two-writer refusals (categorical_modeandtimebox_modeset both top-level and inparams), the caps posture rules, and the compositions of valid values this space cannot run (the mixed mode on a conditional space; the fixed feasibility GP with the mixed mode on a space with categoricals) – resolved against the space (the mixed strata’s defaults).suggestexecutes exactly what this returns; the ask boundary runs it for the intended strategy BEFORE any rung and answers aValueErrorraised here as the caller’s 400 (AskValidationErrornaming the strategy and the key: the value and the expected domain for a typed, range or enumerated refusal, the keys and the rule for a conflict), so a mistyped value never reaches a served suggestion. Pure in (state, cfg); no math imports.
- suggest(state: tauopt.engine.state.ExperimentState, cfg: tauopt.engine.config.OptimizerConfig, n: int = 1) list[tauopt.engine.strategies.base.SuggestionDraft]#
Fit the objective GP (plus constraint/label components when configured) on aggregated scored observations, condition constant-liar fantasies for open suggestions, optimize LogEI (analytic at n=1, MC qLogEI at n>1, feasibility-weighted when constraint components exist), and return the n decoded drafts. Pure in (state, cfg) (pin P4): explicit derived seeds under torch fork_rng, single-thread compute. Raises ValueError on a multimetric state or zero scored observations, and TimeboxExceeded on wall overrun; the ask boundary catches both and descends the ladder (pin P6). Bad config never reaches here on any path:
read_paramsrefused it at the boundary first, for an explicit gp_ei and for the gp_ei the policy routes underauto(the routed config carries the caller’s top-level flags).
- suggest_unique(state: tauopt.engine.state.ExperimentState, cfg: tauopt.engine.config.OptimizerConfig, n: int = 1, exclude: frozenset[str] = frozenset()) list[tauopt.engine.strategies.base.SuggestionDraft]#
Uniqueness repair path: next eligible queue entry from the SAME acqf optimization’s restart pool (zero extra optimizer work), then <= PER_SLOT_REOPT_ALLOWANCE bounded re-optimize attempts per slot – same acqf, fresh derived IC seed; models are never re-conditioned (the acquisition function is reused unchanged).
- suggest_selected(state: tauopt.engine.state.ExperimentState, cfg: tauopt.engine.config.OptimizerConfig, n: int = 1, exclude: frozenset[str] = frozenset(), select=None) list[tauopt.engine.strategies.base.SuggestionDraft]#
Per-slot selection handshake: the SAME acqf optimization’s restart-endpoint pool becomes each slot’s capped ranked queue (zero extra optimizer work; a joint-q restart’s slot-s row is scored by the restart’s joint acquisition value); the boundary’s selector picks. No eligible entry => the owner-repair path fills the slot (recorded, no draw). Mixed-alternating mode exposes no restart pool (best-only API) – refused BEFORE any compute so the boundary falls back to the rung’s repair path, recorded pass-through.