Strategies and configuration reference#

OptimizerConfig (tauopt.OptimizerConfig) is the explicit, hashable unit of reproducibility: Client.suggest(experiment_id, config={...}) pins one, the hosted suggestion route accepts the same mapping under config, and every served suggestion records the config that produced it as provenance.config_hash. Omitting the config routes through the default policy. Every value on this page is read from the engine modules named in the frontmatter; the strategy names themselves are listed on the Python API page.

OptimizerConfig fields#

Field

Type

Default

Meaning

strategy

string

auto

random, sobol, gp_ei, ucb_cl, gp_nehvi, or auto. auto (the default, so config={"dedup": False} is a complete config on both drivers) routes through the default policy while carrying the other top-level fields; it takes no params. A v0 field: it serializes at its default ("strategy":"auto" stays in the canonical form), so the default moved no config_hash. A name the registry does not know is not refused: the ask falls through the whole ladder and records the name in provenance.fallback_from.

params

object

{}

Strategy-specific keys (the per-strategy tables). Every number must be finite. A key the named strategy does not read is refused at the ask (unknown params key '<key>' for strategy '<name>', with a close match when one exists and the accepted set, every unknown key named when there are several (unknown params keys '<a>', '<b>' for strategy '<name>'); <name> reads no params for sobol and random), a 400 validation_error through either driver, so a typo never reaches a served suggestion’s config_hash or derived seed (the config object itself still constructs and hashes; the ask refuses it before any rung runs). A custom strategy registered without an accepted_params declaration is not checked.

seed

integer or null

null

An explicit seed is used verbatim. null derives the seed from the strategy name, params, and the experiment state hash; sobol derives from the space hash instead, so its scramble is fixed for the experiment.

center_in_bootstrap

boolean

false

Puts the domain center on the sobol stream; the branch taken is recorded in provenance.center. Rides auto and the ladder.

dedup

boolean

true

The suggest-time duplicate boundary: exact re-suggestion is refused against observed, pending, and in-batch points, with strategy repair, an exhaustion proof, and a uniqueness status. false turns the boundary off and refuses intents.

duplicate_intents

object or null

null

Enables the authorized-duplicate kinds (block below). Requires dedup.

queue_selection

object or null

null

Temperature-annealed selection over each slot’s candidate queue (block below). Requires dedup.

categorical_mode

string or null

null

The gp_ei categorical embedding: one_hot, mixed, or mixed_capped. mixed and mixed_capped are experimental (the gp_ei table below quotes the module). This top-level form rides auto and the ladder; null means one_hot.

timebox_mode

string or null

null

The wall-clock posture: budget, off, or caps. This top-level form rides auto and the ladder; null behaves as budget. caps is accepted here only, never inside params.

base_noise

number

1e-3

The base observation-noise floor of the GP strategies, in relative variance units (a fraction of the observed variance). 0 opts out of the base floor: on the inferred-noise path the fit’s noise level keeps the 1e-4 numerical minimum, and on the fixed-noise path the reported variances are taken verbatim (the engine still never passes a zero variance into the kernel).

The model is frozen and rejects unknown fields. Validation at construction raises ValueError (400 validation_error through either driver):

  • duplicate_intents requires dedup=true

  • queue_selection requires dedup=true

  • base_noise must be a number, not a bool, and base_noise must be finite and >= 0, got <value>

  • params[<path>] is non-finite (<value>); param values must be finite: no NaN or infinity anywhere inside params

duplicate_intents#

Block

Field

Type

Default

Rule

variance_replication

max_replicas

integer

3

>= 1; the per-assignment replica cap

liar_verification

max_verifications

integer

1

>= 1; the per-source verification cap

At least one block must be present (omit duplicate_intents entirely to disable both), and each block rejects unknown fields. The liar kind’s age floor (3 later observations) and near-incumbent window (10 percent, relative) are engine constants rather than fields. Both kinds are inert on multimetric experiments.

queue_selection#

Presence of the block engages the selector; absence leaves each strategy’s native suggest path unchanged. The block rides auto and the fallback ladder like the other top-level fields, and the selection draw runs on its own forked random stream, so the strategy’s generation stream is unchanged by it. It applies on the rungs that expose a ranked candidate queue: gp_ei on the one_hot path and ucb_cl. For each slot such a rung hands the boundary its acquisition optimizer’s restart endpoints as a queue ranked by acquisition value (rank 1 is best; non-finite scores are dropped, canonical duplicates collapsed, and the queue capped at queue_cap); the boundary removes entries that collide with observed, pending, or earlier-slot points, then draws one eligible entry with probability proportional to exp(logit / T), where logit = -(rank - 1) + w * d, d is the entry’s smallest distance to any observed, pending, or earlier-slot point in the model embedding (L2, divided by the square root of the model dimension, so d lies in [0, 1]; 0 with no history), and w = distance_weight * (T / t_start). The temperature T anneals geometrically from t_start toward t_end with progress p = count / horizon, clamped to [0, 1], where count is the number of canonical-unique observed and pending points plus the slots already filled in this ask (authorized replicas count individually); at or past the horizon T is exactly 0 and the selector takes the top-ranked eligible entry without a draw. A slot with no eligible entry falls to the strategy’s repair path. gp_nehvi, sobol, random, and gp_ei under mixed or mixed_capped on a space with categoricals expose no queue: their fills pass through unchanged and are recorded as such. Every slot’s decision rides the suggestion as provenance.selection, one record per slot: slot, origin (selected, argmax_t0, repair, or pass_through), horizon and horizon_source (explicit or assumed_15d), progress, and temperature; selected and argmax_t0 records add queue_size, eligible_count, non_finite_count, non_finite_scores, selected_rank, distance, fork_label, and the drawn uniform u (None on argmax_t0); repair records add the queue size, eligible count, and non-finite fields but no rank, distance, or u; pass_through records carry the slot, origin, horizon, horizon_source, progress, and temperature fields only.

Field

Type

Default

Rule

t_start

number

1.0

finite, > 0

t_end

number

1e-3

finite, 0 < t_end <= t_start

distance_weight

number

1.0

finite, >= 0; 0 is the temperature-only form

queue_cap

integer

16

in [1, 16]

horizon

integer or null

null

>= 1 when set; the annealing budget. When unset, both drivers inject the experiment’s observation_budget (the injected value enters the config and its config_hash), and with neither the engine assumes 15 * dim (dim is the parameter count) and records horizon_source as assumed_15d.

Canonical form and config_hash#

config_hash is blake2b_ followed by 16 hex characters of the canonical JSON (sorted keys, compact separators). Seven later-added top-level fields drop out at their defaults – center_in_bootstrap at false, dedup at true, the two null blocks (duplicate_intents, queue_selection) and the two null modes (categorical_mode, timebox_mode), base_noise at 1e-3 – so a config written before a field existed keeps its hash; seed and params always serialize, and spelling a behavioral default (timebox_mode: "budget", categorical_mode: "one_hot") hashes differently from leaving it null. An explicit non-default (dedup: false, base_noise: 0) hashes distinctly.

Suggest-time knobs#

These ride the ask rather than the config: Client.suggest(experiment_id, config=None, max_wait_s=None, on_timeout=None, intents=None) and the hosted suggestion body.

Knob

Domain

Default

Meaning

max_wait_s

number in (0, 300], or null for no deadline

null

The deadline for the whole ask. The hosted body is validated as > 0 and <= 300; the engine refuses anything else, booleans included, with max_wait_s must be a number in (0, 300]. A deadline-bearing ask is also backstopped above the engine: a typed answer within max(1.25 * max_wait_s, max_wait_s + 3 s) whatever the cooperative clocks manage, past which the local driver’s worker process is killed and the ask refused as BackstopExceeded (Client(driver="local", supervisor=...); the hosted plane refuses the same on its queue lane, provenance.lane worker).

on_timeout

ladder or fail

ladder

ladder degrades down the fallback ladder and records the fallback in provenance; in budget and off mode fail raises TimeboxExceeded, which both drivers answer as 503 suggest_timeout; in caps mode the deadline is AskDeadlineExceeded in either on_timeout mode. The client raises ValueError for any other string before sending.

intents

array of {"kind", "source_id", "ordinal"}

none

Typed authorized-duplicate requests: kind is variance_replication or liar_verification, source_id a string, ordinal an integer >= 0. Requires dedup (intents require dedup=true on the config); refusals are recorded in provenance.dedup. Grants fill the slots left after unique search – liar verifications first, then variance replicas, request order kept within a kind.

The timebox_mode posture decides what max_wait_s does:

timebox_mode

max_wait_s unset

max_wait_s set

budget (or null)

each GP rung runs under its own timebox_s

each rung’s timebox_s is capped by the remaining ask budget; a budget exhausted between rungs raises in fail mode and lets the instant rungs answer in ladder mode

off

no wall budget: fits and acquisition run to convergence, no timeout machinery is installed

the request deadline wins: the rung executes in budget mode with timebox_s equal to the remaining budget (at most 300); the config’s identity and seed are unchanged

caps

deterministic work ceilings (fit_maxiter, acq_maxiter), no clock on the suggest path

the deadline is checked only at rung boundaries and once after the answer is computed: an expired deadline raises AskDeadlineExceeded in both on_timeout modes, never substitutes a cheaper rung, and discards the computed drafts

Fallback ladder#

tauopt.engine.policy.default.FALLBACK_LADDER is gp_ei -> ucb_cl -> sobol -> random; MOO_FALLBACK_LADDER, used when two or more metrics are optimized, is gp_nehvi -> sobol -> random. An ask starts at the intended strategy and descends on a rung failure (a timeout in ladder mode, a math failure, or a state the rung cannot model; a bad params value refuses at the ask boundary before any rung); the last rung is stdlib-only and cannot fail to import. Its one refusal is the rejection cap under linear constraints (100,000 consecutive rejected draws), which surfaces as AskFailed with error_type all_rungs_failed (a 500 of the same type on both drivers) described in Troubleshooting.

Strategy

Successor on failure

Notes

gp_ei

ucb_cl

single-objective ladder

ucb_cl

sobol

gp_nehvi

sobol

multimetric ladder; ucb_cl is single-objective

sobol

random

random

none

the floor

any other name

gp_ei (single-objective) or gp_nehvi (multimetric)

the whole ladder runs beneath the unknown name

Rungs whose install extra is missing are skipped without an error. A fallback rung runs with its own default params; seed, center_in_bootstrap, dedup, duplicate_intents, queue_selection, categorical_mode, timebox_mode, and base_noise carry over. The answering rung is recorded in provenance.strategy, the intended one in provenance.fallback_from, and each failed attempt in provenance.fallback_attempts.

The default policy (default@v1, used when no config is given or strategy is auto): sobol until max(4, 2 * dim) non-failed observations exist, then gp_ei, or gp_nehvi when the experiment optimizes two or more metrics. Failed observations and open suggestions do not count toward the bootstrap.

Strategy params#

Each strategy declares the keys it reads (accepted_params on the class, mirrored in the registry; the tables below list them), and a key outside that set is refused before any rung runs (the params row above). Values are read strictly: an integer key refuses booleans and non-integral numbers (8.0 passes), a float key refuses booleans and non-numbers, and an enumerated key refuses unknown strings. Each value refusal is the caller’s 400 validation_error at the ask boundary, before any rung runs, on either driver, for the built-in strategies (a custom strategy without read_params keeps its values its own and the ladder sees the raise). The local driver answers invalid params value for strategy 'gp_ei': num_restarts must be an integer, got 'eight'; the hosted service answers the same text except for the timebox class (timebox_s, timebox_mode, the timebox_mode two-writer pair, timebox_mode="caps" with timebox_s, and the params-form caps pointer; a cap field outside caps, the categorical pair and the caps-mode bundle reach ask() and answer the engine text on both planes), which a non-exempt user’s config pre-check refuses first as config: <the same reader text> without the strategy name. The intended strategy’s read_params runs first, and the ladder descends on runtime failures only. The GP defaults are named module constants, read by attribute: DEFAULT_NUM_RESTARTS and DEFAULT_RAW_SAMPLES on each GP strategy module, and CAPS_MAXITER_CEILING = 10000 in the shared GP module.

Shared timebox rules (timebox_s, timebox_mode) for the three GP strategies:

  • timebox_s defaults to 10.0 seconds and must lie in (0, 300]

  • timebox_mode in params accepts budget (the default) or off; off together with an explicit timebox_s is refused (timebox_mode="off" conflicts with an explicit timebox_s -- set exactly one)

  • caps in params is refused with a pointer to the top-level field; the top-level caps together with an explicit timebox_s is refused too

  • setting timebox_mode both top-level and in params is refused regardless of agreement

  • fit_maxiter and acq_maxiter are accepted under caps only; set in any other posture they are refused (<key> requires timebox_mode="caps")

random#

Requires nothing (stdlib only). Reads no params. Linear constraints are honored by rejection sampling, capped at 100000 consecutive rejected draws; past the cap the rung raises instead of looping (the creation-time feasibility probe screens out most such regions).

sobol#

Requires tauopt[local]. Reads no params; center_in_bootstrap is the top-level flag. The scramble seed derives from the space hash, so successive asks continue one sequence; the engine fast-forwards past the points already drawn, and dismissed suggestions advance the cursor like observed ones. Linear constraints are honored by rejection with feasible-index accounting, under the same 100000-draw cap.

gp_ei#

Requires tauopt[botorch]. Single-objective (multimetric experiment: gp_ei is single-objective (use gp_nehvi)); needs at least one successful observation (GP strategies require at least one successful observation).

Key

Type

Default

Domain

timebox_s

number

10.0

(0, 300]

timebox_mode

string

budget

budget or off

num_restarts

integer

8 (DEFAULT_NUM_RESTARTS)

[1, 64]

raw_samples

integer

128 (DEFAULT_RAW_SAMPLES)

[num_restarts, 4096]

fit_maxiter

integer

unset

[1, 10000], caps mode only; unset under caps means 10000, or 50 on the mixed categorical path

acq_maxiter

integer

unset

[1, 10000], caps mode only; unset under caps means 10000, or no cap on the mixed categorical path (the library’s own bound)

categorical_mode

string

one_hot

one_hot, mixed (experimental), or mixed_capped (experimental); refused when the top-level field is also set

noise_mode

string

median_impute

median_impute or mll_impute (experimental)

failure_mode

string

exclude

exclude, feasibility_gp (experimental), or feasibility_gp_fixed (experimental)

Experimental values: mixed, mixed_capped, mll_impute, feasibility_gp, and feasibility_gp_fixed. The gp_ei module lists them as “experimental mode params” and states that “each default preserves shipped behavior exactly; the non-default value is an upgrade candidate under measurement, promoted (or parked) on benchmark results”, with the efficacy of mixed_capped “still under benchmark measurement”. Each default is the shipped behavior; each non-default value is a candidate whose efficacy is still under measurement. The benchmark suite measures them as the tauopt/gp_ei-catmixed, -catmixed-capped, -mllimpute, -feasgp, and -feasgp-fixed arms (Run the benchmark suite).

Mixed-space constants: MIXED_CAPPED_RESTARTS = 4, MIXED_CAPPED_RAW_SAMPLES = 64, a fit maxiter of 50, and maxiter_alternating of 4. mixed_capped applies the bundle on spaces with categoricals, overriding num_restarts and raw_samples after validating them; under timebox_mode: caps, setting either together with mixed_capped is refused as ambiguous. Under caps on the mixed path the num_restarts and raw_samples defaults become 4 and 64. mixed and mixed_capped refuse conditional spaces, and feasibility_gp_fixed refuses both on spaces with categoricals. A categorical_mode other than one_hot is inert on spaces without categoricals.

ucb_cl#

Requires tauopt[botorch]. Single-objective (multimetric states are refused), and models the objective only: outcome-constraint metrics are not modeled on this rung; needs at least one successful observation (the shared GP refusal).

Key

Type

Default

Domain

beta

number

2.0

finite, [0, 1e6]; passed unchanged to BoTorch’s analytic UpperConfidenceBound, whose value is mean + sqrt(beta) * sigma (posterior mean and standard deviation), so the default bounds at about 1.41 standard deviations

timebox_s

number

10.0

(0, 300]

timebox_mode

string

budget

budget or off

num_restarts

integer

4 (DEFAULT_NUM_RESTARTS)

[1, 64]

raw_samples

integer

64 (DEFAULT_RAW_SAMPLES)

[num_restarts, 4096]

fit_maxiter

integer

unset (10000 under caps)

[1, 10000], caps mode only

acq_maxiter

integer

unset (10000 under caps)

[1, 10000], caps mode only

gp_nehvi#

Requires tauopt[botorch]. Needs two or more optimized metrics (gp_nehvi requires >= 2 optimized metrics (use gp_ei)) and at least one successful observation. Metric thresholds are the hypervolume reference point; a metric without a threshold contributes ten percent of the observed span beyond the worst observed value, away from the optimum (the engine computes it in its maximization frame as the minimum minus a tenth of the span; a zero span counts as one).

Key

Type

Default

Domain

timebox_s

number

10.0

(0, 300]

timebox_mode

string

budget

budget or off

num_restarts

integer

8 (DEFAULT_NUM_RESTARTS)

[1, 64]

raw_samples

integer

128 (DEFAULT_RAW_SAMPLES)

[num_restarts, 4096]

mc_samples

integer

128

[16, 1024]

fit_maxiter

integer

unset (10000 under caps)

[1, 10000], caps mode only

acq_maxiter

integer

unset (10000 under caps)

[1, 10000], caps mode only