tauopt.engine.state#

Experiment state: the engine’s complete view of an experiment.

Frozen models with append-only mutators (each returns a new state; history is never rewritten). Serialize->deserialize must round-trip exactly (pin P1); canonical JSON is the MINIMAL form (post-v0 fields drop at their defaults – the P8 contract in _canonical), so every v0-expressible state keeps its v0 bytes and hashes.

Metric shapes: metrics=() is v0 single-metric mode – objective is authoritative and observations carry value. A non-empty metrics tuple switches to metrics mode: observations carry values (every optimize/constraint metric required, stored metrics optional), objective becomes a derived legacy field (validator-pinned to the first optimized metric so the two can never disagree).

Caveat: pydantic frozen blocks attribute assignment, not mutation INSIDE dict fields (assignments) – treat states as values; mutating one in place voids the determinism contract. Deep-frozen mapping types are a backlog item.

Module Contents#

Classes#

Objective

The optimization target: a metric name plus a goal direction (“max” or “min”).

MetricSpec

One declared metric. optimize metrics drive the search (1-4 of them; >=2 => Pareto). store metrics are recorded, never modeled. constraint metrics are black-box feasibility requirements: goal=max => value >= threshold is feasible (min => <=). Thresholds on optimize metrics are only meaningful with >=2 optimized (SigOpt semantics: they shape the frontier region – and here, the qLogNEHVI reference point).

IntentTag

An authorized-duplicate grant’s identity: which policy kind authorized the row, which source it duplicates (the canonical assignment key), and the grant’s ordinal for that (kind, source). Preserved through the pending->observed transition so used-ordinal and verification counts stay state-derivable cross-process (P4/P7). Registered minimal-form (P8): absent on every non-grant row.

ObservationRecord

A reported result. failed=True records the attempt with no value; failed points are excluded from modeling. value is single-metric mode, values is metrics mode (never both); value_stddev/values_stddev report measurement noise (feeds the GP as fixed per-point variance). intent marks a row that was an authorized duplicate grant – copied from the open suggestion at observe.

OpenSuggestion

A suggestion handed out but not yet observed – the unit of parallelism.

ExperimentState

The engine’s complete record of one experiment: search space, objective (plus optional metrics declarations), observation history, and open suggestions.

Functions#

derive_objective

The legacy objective value a metrics-mode state must carry (first optimized metric) – construct states with this so the consistency validator holds.

API#

class tauopt.engine.state.Objective(/, **data: Any)#

Bases: pydantic.BaseModel

The optimization target: a metric name plus a goal direction (“max” or “min”).

Authoritative in v0 single-metric mode (metrics=()). In metrics mode it is a derived legacy mirror of the first optimized metric (construct with derive_objective; the ExperimentState validator rejects any disagreement).

Initialization

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

model_config#

‘ConfigDict(…)’

metric: str#

None

goal: Literal[max, min]#

‘max’

class tauopt.engine.state.MetricSpec(/, **data: Any)#

Bases: pydantic.BaseModel

One declared metric. optimize metrics drive the search (1-4 of them; >=2 => Pareto). store metrics are recorded, never modeled. constraint metrics are black-box feasibility requirements: goal=max => value >= threshold is feasible (min => <=). Thresholds on optimize metrics are only meaningful with >=2 optimized (SigOpt semantics: they shape the frontier region – and here, the qLogNEHVI reference point).

Initialization

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

model_config#

‘ConfigDict(…)’

name: str#

None

goal: Literal[max, min]#

‘max’

strategy: Literal[optimize, store, constraint]#

‘optimize’

threshold: float | None#

None

tauopt.engine.state.derive_objective(metrics: tuple[tauopt.engine.state.MetricSpec, ...]) → tauopt.engine.state.Objective#

The legacy objective value a metrics-mode state must carry (first optimized metric) – construct states with this so the consistency validator holds.

class tauopt.engine.state.IntentTag(/, **data: Any)#

Bases: pydantic.BaseModel

An authorized-duplicate grant’s identity: which policy kind authorized the row, which source it duplicates (the canonical assignment key), and the grant’s ordinal for that (kind, source). Preserved through the pending->observed transition so used-ordinal and verification counts stay state-derivable cross-process (P4/P7). Registered minimal-form (P8): absent on every non-grant row.

Initialization

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

model_config#

‘ConfigDict(…)’

kind: Literal[variance_replication, liar_verification]#

None

source_id: str#

None

ordinal: int#

None

class tauopt.engine.state.ObservationRecord(/, **data: Any)#

Bases: pydantic.BaseModel

A reported result. failed=True records the attempt with no value; failed points are excluded from modeling. value is single-metric mode, values is metrics mode (never both); value_stddev/values_stddev report measurement noise (feeds the GP as fixed per-point variance). intent marks a row that was an authorized duplicate grant – copied from the open suggestion at observe.

Initialization

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

model_config#

‘ConfigDict(…)’

assignments: tauopt.engine.space.Assignments#

None

value: float | None#

None

failed: bool#

False

values: dict[str, float] | None#

None

value_stddev: float | None#

None

values_stddev: dict[str, float] | None#

None

intent: tauopt.engine.state.IntentTag | None#

None

class tauopt.engine.state.OpenSuggestion(/, **data: Any)#

Bases: pydantic.BaseModel

A suggestion handed out but not yet observed – the unit of parallelism.

Dedup marker fields (all P8-registered; since 0.3.0 the driver stamps them under CONSUMER-bearing configs, i.e. duplicate_intents / queue_selection present; before 0.3.0, while dedup was opt-in, the dedup flag itself gated the same set):

  • opened_at_obs: observation count when this row entered pending; age(p) = current count - it. None (unstamped rows) reads as 0 – maximally old, deterministic from state.

  • lie: the pessimistic constant-liar value in effect at open, RAW objective units (the worst scored raw value, exactly the flipped-to-max y.min() both GP strategies condition lies at). None when nothing was scored at open or the state is multimetric; rows without a lie never qualify as liar_verification sources.

  • intent: present iff this row is itself an authorized-duplicate grant (grant rows are NEVER liar_verification sources).

Initialization

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

model_config#

‘ConfigDict(…)’

id: str#

None

assignments: tauopt.engine.space.Assignments#

None

opened_at_obs: int | None#

None

lie: float | None#

None

intent: tauopt.engine.state.IntentTag | None#

None

class tauopt.engine.state.ExperimentState(/, **data: Any)#

Bases: pydantic.BaseModel

The engine’s complete record of one experiment: search space, objective (plus optional metrics declarations), observation history, and open suggestions.

Frozen and treated as a value: the mutators below return a successor state (append-only history), nothing mutates in place. Serializes to canonical minimal-form JSON (to_json/from_json, the P1 round-trip surface; P8 golden bytes), and state_hash over those bytes is the identity strategies derive their seeds from (P4).

Initialization

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

model_config#

‘ConfigDict(…)’

space: tauopt.engine.space.Space#

None

objective: tauopt.engine.state.Objective#

None

observations: tuple[tauopt.engine.state.ObservationRecord, ...]#

()

open_suggestions: tuple[tauopt.engine.state.OpenSuggestion, ...]#

()

n_dismissed: int#

0

metrics: tuple[tauopt.engine.state.MetricSpec, ...]#

()

property optimized_metrics: tuple[tauopt.engine.state.MetricSpec, ...]#

The metrics driving the search, in declaration order (never empty); in single-metric mode, one spec synthesized from objective.

property constraint_metrics: tuple[tauopt.engine.state.MetricSpec, ...]#

Declared constraint metrics (always empty in single-metric mode).

property is_multimetric: bool#

True when more than one metric is optimized (frontier semantics apply).

metric_value(obs: tauopt.engine.state.ObservationRecord, name: str) → float | None#

The value of metric name on obs under this state’s shape rules: obs.values[name] in metrics mode, obs.value for the objective metric in single-metric mode. None when unscored or the name is unknown (never raises).

metric_stddev(obs: tauopt.engine.state.ObservationRecord, name: str) → float | None#

The reported measurement stddev of metric name on obs (lookup rules as in metric_value); None when not reported or the name is unknown.

is_feasible(obs: tauopt.engine.state.ObservationRecord) → bool#

Outcome-constraint feasibility (black-box constraint metrics only; linear parameter constraints are enforced at assignment validation).

with_observation(obs: tauopt.engine.state.ObservationRecord) → tauopt.engine.state.ExperimentState#

Append obs, returning the successor state. Raises ValueError unless the assignments validate against the space and the value shape matches this state’s metrics. Does not close a matching open suggestion; callers compose with without_open_suggestion.

with_open_suggestion(sug: tauopt.engine.state.OpenSuggestion) → tauopt.engine.state.ExperimentState#

Append an open suggestion, returning the successor state. Raises ValueError unless the assignments validate against the space (the write door’s rule, as with_observation) or if a suggestion with that id is already open.

without_open_suggestion(suggestion_id: str) → tauopt.engine.state.ExperimentState#

Close because it was OBSERVED – the observation itself advances history.

dismiss_open_suggestion(suggestion_id: str) → tauopt.engine.state.ExperimentState#

Close WITHOUT an observation (user dismissal) – counted into n_dismissed, which advances the sequential streams. The dismissed point leaves the dedup universe and may be re-suggested later.

scored_observations() → tuple[tauopt.engine.state.ObservationRecord, ...]#

Non-failed observations carrying the value shape this state models.

best_observation() → tauopt.engine.state.ObservationRecord | None#

Single-objective best among FEASIBLE scored observations. Multimetric callers must route to pareto_frontier – a scalar best does not exist there.

pareto_frontier() → tuple[tauopt.engine.state.ObservationRecord, ...]#

Non-dominated FEASIBLE scored observations over the optimized metrics, filtered to threshold-satisfying points when thresholds are set (SigOpt frontier semantics). Insertion order preserved; the records are the state’s own (identity, not copies). On numpy the hosted plan cap of 4,000 observations builds in a fraction of a second whatever the data; without numpy, or for rows that are not plain floats, the pairwise loop runs.

The dominance test runs on numpy when it is installed (the [local] extra, the prerequisite of every strategy beyond the stdlib random rung): the flipped rows are sorted so that every dominator precedes what it dominates, then each row is compared against the frontier found so far and its own block – output-sensitive, about n x (frontier + block) x k element comparisons after an n log n sort, n^2 k at worst when every point survives (the shape a converged multi-objective run produces), with working memory bounded by a fixed budget until the frontier itself outgrows it (two million non-dominated rows). The pure-Python pairwise loop runs without numpy, and for rows carrying anything but Python floats (an int past 2**53 planted through model_copy, which skips validation): it short-circuits on data where most points are dominated early and pays every pair where they are not – fine at hundreds of observations, seconds at the cap (4,000 observations at the engine’s ceiling of four optimized metrics) on a frontier-heavy history.

diverse_best(k: int) → tuple[tauopt.engine.state.ObservationRecord, ...]#

k diverse good solutions (multisolution, single-objective only): greedy max-min distance in the sample-view unit cube, seeded at the best point, candidates = top max(2k, 20%) by value. Deterministic (ties -> better value, then earlier observation).

to_json() → str#

Serialize to canonical minimal-form JSON (the P1 round-trip surface; P8 golden bytes: post-v0 fields drop at their defaults).

classmethod from_json(payload: str) → tauopt.engine.state.ExperimentState#

Parse a to_json payload back into a fully validated state (the P1 round-trip inverse); every construction-time validator runs on load.

state_hash() → str#

Content address of this state: blake2b_<16hex> over the to_json bytes, stable across processes; the seed scope point strategies derive from (see resolve_seed).

space_hash() → str#

Content address of the space alone: blake2b_<16hex> over its canonical JSON, stable as observations accrue; the sequence-scope seed source for Sobol (see resolve_seed).