tauopt.engine.space#

Search-space language: typed parameters with bounds, unit-cube transforms.

Stdlib + pydantic only – the space must be usable by the featherweight client (request validation) without any math extra installed.

Three composing axes – categorical values, grid value-lists, and conditions (parameters active only for given parent categories) – plus linear constraints over double parameters, and two geometric views:

  • SAMPLE view (to_unit/from_unit, dim = one u per parameter): what sobol/random draw from. Categorical/grid decode by equal-width bucket; conditional parameters consume their u and drop from the output when inactive (keeps sequence fast-forward semantics well-defined).

  • MODEL view (to_model/from_model, model_dim): what the GP strategies embed into. Numeric parameters keep their unit transform, categoricals one-hot (SigOpt parity; MixedSingleTaskGP is the upgrade path). Inactive parameters impute (numeric 0.5, categorical all-zero – all-zero matches no category, so “absent” is its own region to the GP).

Module Contents#

Classes#

Parameter

One tunable parameter.

LinearConstraint

sum of terms[name] * value op rhs – over double, non-log, non-grid, unconditional parameters only (the SigOpt restriction; it keeps the unit-space transform affine-exact, so GP candidates are feasible by construction in raw space).

Space

An ordered list of parameters. Order is semantic: it fixes unit-cube dimensions AND condition topology (a condition may only reference an earlier parameter).

Data#

API#

tauopt.engine.space.Assignments#

None

class tauopt.engine.space.Parameter(/, **data: Any)#

Bases: pydantic.BaseModel

One tunable parameter.

double is continuous, integer is an integer-valued box (optimized on its continuous relaxation, rounded on the way out), categorical takes one of categorical_values (strings). log_scale optimizes double parameters (and double grids) in log10 space (values must be > 0; integer parameters cannot be log-scaled). grid restricts a numeric parameter to an explicit value list (bounds derive from it). conditions makes the parameter active only when every named parent (an EARLIER categorical parameter) is assigned one of the listed values; inactive parameters are absent from assignments.

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

type: Literal[double, integer, categorical]#

None

bounds: tuple[float, float] | None#

None

log_scale: bool#

False

categorical_values: tuple[str, ...] | None#

None

grid: tuple[float, ...] | None#

None

conditions: dict[str, tuple[str, ...]] | None#

None

property effective_bounds: tuple[float, float]#

Numeric range: bounds, or the grid’s [min, max].

property model_width: int#

Dims this parameter contributes to the MODEL view (one-hot width).

to_unit(value: float | int | str) → float#

Map a raw value into [0, 1] (sample view; discrete types -> bucket center).

from_unit(u: float) → float | int | str#

Map u in [0, 1] back to a raw, in-bounds, correctly-typed value.

Non-finite u raises: silently clamping an inf/NaN optimizer output to a bound would stamp a garbage candidate with honest-looking provenance; raising lets the robustness ladder fall – and record – a real fallback.

to_model_block(value: float | int | str) → list[float]#

Encode a raw value as this parameter’s MODEL-view block: categoricals one-hot (1.0 at the value’s index), numerics a single unit-scale coordinate (affine or log10; a grid value embeds at its position in the grid’s range, not at a bucket center).

imputed_model_block() → list[float]#

The block an INACTIVE parameter contributes to GP training rows: numeric mid-range, categorical all-zero (matches no category – absent is its own region, not an arbitrary category’s neighbor).

from_model_block(block: list[float]) → float | int | str#

Decode a MODEL-view block back to a raw, in-bounds, correctly typed value.

Non-finite coordinates raise ValueError (as in from_unit: garbage optimizer output must fall to the robustness ladder, never clamp into a plausible value). Categoricals decode by argmax, numerics by clamped affine inverse (integers round, grids snap to the nearest value); ties break deterministically (P7).

class tauopt.engine.space.LinearConstraint(/, **data: Any)#

Bases: pydantic.BaseModel

sum of terms[name] * value op rhs – over double, non-log, non-grid, unconditional parameters only (the SigOpt restriction; it keeps the unit-space transform affine-exact, so GP candidates are feasible by construction in raw space).

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(…)’

terms: dict[str, float]#

None

op: Literal[>=, <=]#

None

rhs: float#

None

satisfied(assignments: tauopt.engine.space.Assignments) → bool#

Whether assignments satisfies the constraint, within the relative eps below; raises KeyError if a term’s parameter is absent.

class tauopt.engine.space.Space(/, **data: Any)#

Bases: pydantic.BaseModel

An ordered list of parameters. Order is semantic: it fixes unit-cube dimensions AND condition topology (a condition may only reference an earlier parameter).

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(…)’

parameters: tuple[tauopt.engine.space.Parameter, ...]#

None

linear_constraints: tuple[tauopt.engine.space.LinearConstraint, ...]#

()

property dim: int#

SAMPLE-view dimension: one u per parameter.

property model_dim: int#

MODEL-view dimension: one-hot width for categoricals, 1 per numeric.

active_parameters(assignments: tauopt.engine.space.Assignments) → list[tauopt.engine.space.Parameter]#

Parameters active under assignments, resolved in list order (parents are earlier, so one forward pass settles chains; an inactive parent’s absence deactivates its children).

validate_assignments(assignments: tauopt.engine.space.Assignments) → None#

Raise ValueError unless assignments is exactly the ACTIVE set, each value typed, in-bounds/in-list, and every linear constraint satisfied.

to_unit(assignments: tauopt.engine.space.Assignments) → list[float]#

Sample-view embedding; INACTIVE parameters impute at 0.5 (used for diversity distances, never for round-tripping suggestions).

from_unit(unit: list[float]) → tauopt.engine.space.Assignments#

Decode a full sample-view vector; parents resolve in order and inactive parameters consume their coordinate but drop from the output.

property has_categoricals: bool#

True if any parameter is categorical.

property has_conditions: bool#

True if any parameter is conditional (carries conditions).

mixed_cat_dims() → dict[int, int]#

Column index -> category count, for the mixed-model view (columns are parameter positions: every parameter is exactly one column).

to_model_mixed(assignments: tauopt.engine.space.Assignments) → list[float]#

Encode assignments as one mixed-model row (one column per parameter): numerics their unit coordinate, categoricals their category index as a float. ValueError on conditional spaces; KeyError if any parameter is unassigned.

from_model_mixed(vector: list[float]) → tauopt.engine.space.Assignments#

Decode a mixed-model row back to assignments: category coordinates clamp to range and round to an index, numerics decode via from_model_block. ValueError on conditional spaces, a length mismatch, or non-finite coordinates.

unit_linear_constraints_mixed() → list[tuple[list[int], list[float], float]]#

unit_linear_constraints, at mixed-view offsets (one column per parameter).

to_model(assignments: tauopt.engine.space.Assignments) → list[float]#

MODEL-view embedding (the GP strategies’ row, model_dim wide): assigned parameters contribute to_model_block, absent (inactive) parameters their imputed_model_block.

from_model(vector: list[float]) → tauopt.engine.space.Assignments#

Decode a full MODEL-view vector (model_dim wide, else ValueError); parents resolve in order and inactive parameters consume their block but drop from the output.

unit_linear_constraints() → list[tuple[list[int], list[float], float]]#

Linear constraints transformed to MODEL-view coordinates, normalized to the sum of coef * x[idx] >= rhs convention (botorch optimize_acqf shape). Exact: constrained parameters are plain doubles, so raw = lo + u * (hi-lo) is affine.

constraints_feasible_fraction(n: int = 4096) → float#

Fixed-seed Sobol probe of the linear-constraint feasible fraction (needs the local extra). Used at experiment create: 0 hits => reject (“constraint region too small”). Deterministic by construction.

canonical_json() → str#

Canonical serialization: minimal form (later-added fields drop at their defaults – the P8 contract in _canonical), stable key order, no whitespace variance. Parameter order is preserved (it is semantic); keys within objects sort.