tauopt.engine.strategies.gp_nehvi#

Multi-objective GP strategy: qLogNoisyExpectedHypervolumeImprovement.

One SingleTaskGP per optimized metric (shared X, ModelListGP), qLogNEHVI acquisition, MODEL-view geometry, double precision. Metric thresholds ARE the hypervolume reference point (the mathematically-native reading of SigOpt’s frontier-shaping thresholds); metrics without a threshold contribute a worst-observed-based component (min observed - 10% of the observed span, per metric).

Open suggestions enter as X_pending (qNEHVI integrates over their posterior – the MOO-native analog of constant-liar, no lie value needed). Outcome-constraint metrics get their own GP components and enter through qLogNEHVI’s native feasibility weighting. Linear parameter constraints pass to the acquisition optimizer exactly.

Requires >= 2 optimized metrics (single-objective states route to gp_ei; the ladder enforces this by construction).

params: timebox_s float, default 10.0, ceiling 300 (MOO is the heaviest rung – raise via config or the ask-level max_wait_s when the envelope needs it) timebox_mode “budget” (default) | “off” | “caps” – see gp_ei.py: “off” removes the wall budget entirely (no timeout machinery, TimeboxExceeded unreachable, clock reads cannot influence the suggestion); refuses combined with an explicit timebox_s. “caps” (TOP-LEVEL ONLY – the params form refuses with a pointer): off’s clock structure plus deterministic work ceilings; an ask-level max_wait_s is enforced by the ask boundary alone (AskDeadlineExceeded), never by injection. num_restarts int, default 8, in [1, 64] raw_samples int, default 128, in [restarts, 4096] mc_samples int, default 128, in [16, 1024] – qLogNEHVI sampler width (a load-bearing work bound in caps mode: each acqf evaluation costs q x mc_samples sampler width) fit_maxiter int, in [1, 10000] – caps-mode ONLY (set outside caps refuses): per-component GP-fit L-BFGS iteration cap; unset => the version-pinned stratum default (the field ceiling until calibrated) acq_maxiter int, in [1, 10000] – caps-mode ONLY: the qNEHVI optimizer’s iteration cap (optimize_acqf options.maxiter); same defaults law

Module Contents#

Classes#

GpNehviParams

gp_nehvi’s resolved params for one cfg: what read_params returns and suggest executes.

GpNehviStrategy

Multi-objective GP + qLogNEHVI strategy (the module docstring carries the full model and params contract). The default policy’s post-bootstrap rung when >= 2 metrics are optimized, atop the multimetric never-fail ladder gp_nehvi -> sobol -> random (pin P6). Requires tauopt[botorch] (torch/botorch/gpytorch).

Data#

API#

tauopt.engine.strategies.gp_nehvi.DEFAULT_NUM_RESTARTS#

8

tauopt.engine.strategies.gp_nehvi.DEFAULT_RAW_SAMPLES#

128

class tauopt.engine.strategies.gp_nehvi.GpNehviParams#

Bases: typing.NamedTuple

gp_nehvi’s resolved params for one cfg: what read_params returns and suggest executes.

box_mode: str#

None

timebox_s: float#

None

num_restarts: int#

None

raw_samples: int#

None

mc_samples: int#

None

fit_cap: int | None#

None

acq_cap: int | None#

None

class tauopt.engine.strategies.gp_nehvi.GpNehviStrategy#

Multi-objective GP + qLogNEHVI strategy (the module docstring carries the full model and params contract). The default policy’s post-bootstrap rung when >= 2 metrics are optimized, atop the multimetric never-fail ladder gp_nehvi -> sobol -> random (pin P6). Requires tauopt[botorch] (torch/botorch/gpytorch).

name#

‘gp_nehvi’

requires: tuple[str, ...]#

(‘botorch’,)

accepted_params: frozenset[str]#

‘frozenset(…)’

read_params(state: tauopt.engine.state.ExperimentState, cfg: tauopt.engine.config.OptimizerConfig) → tauopt.engine.strategies.gp_nehvi.GpNehviParams#

The ONE reading of cfg.params for this strategy (see gp_ei): the typed readers, their ranges, the timebox two-writer refusals, and the caps posture. The ask boundary runs it for the intended strategy before any rung and answers a ValueError raised here as the caller’s 400; suggest executes what it returns. Pure; no math imports. state is unused here (no space-dependent defaults) and kept for the one shared signature.

suggest(state: tauopt.engine.state.ExperimentState, cfg: tauopt.engine.config.OptimizerConfig, n: int = 1) → list[tauopt.engine.strategies.base.SuggestionDraft]#

Fit one GP per optimized and constraint metric (shared X in a ModelListGP) on aggregated scored observations, optimize qLogNEHVI with metric thresholds (nadir-based components where absent) as the reference point and open suggestions integrated as X_pending, and return the n-point batch decoded. Pure in (state, cfg) (pin P4): explicit derived seeds under torch fork_rng, single-thread compute. Raises ValueError on fewer than 2 optimized metrics 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 for the intended strategy: read_params refused it at the boundary first.

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]#

Dedup repair path: NO internal re-optimization (acquisition internals are out of repair scope) – select the best non-duplicate among the already-evaluated restart pool; exhausted => the multimetric P6 ladder descends with the exclusion set propagated.