mixle.evolve.space module¶
A small typed search space: the categorical/integer/box gap-filler over the numeric BO backend.
mixle.doe optimizes over a continuous numeric box (a sequence of (low, high) bounds). Real
configuration search needs categorical and integer knobs too, and the evolutionary/bandit backends want
to sample and walk neighbors natively. Space is the encoding layer that gives both:
Space.to_bounds()– a continuous(low, high)box for the BO backend, with categoricals encoded as integer indices ([-0.5, k - 0.5]so a round lands on each level with equal width).Space.encode()/Space.decode()– the lossy round-trip between a config dict and the numeric vector the BO backend proposes (decode rounds integers / categorical indices, clips to range).Space.sample()/Space.neighbors()– native draws and local moves for the evolutionary/bandit backends that handle categoricals without going through the numeric box.
The space lives in evolve (not doe) on purpose: doe stays a pure numeric-box optimizer, and
the encoding policy that bridges categoricals into it is an evolve concern.
- class Space(dims)[source]
Bases:
objectA typed, named search space over
Real/Integer/Categoricaldims.Construct from a dict mapping each parameter name to its dimension:
space = Space({"mu": Real(-5, 5), "k": Integer(1, 4), "family": Categorical(["a", "b"])})
Dimension order is the insertion order of the dict;
encode()/decode()andto_bounds()all use that same fixed order so the numeric vector and the box align.- property dims: MappingProxyType
The named dimensions, read-only.
This was a plain public dict.
__init__validates that a space is non-empty and that every dimension has a supported type, and then the caller couldspace.dims.clear()and get an object reportingndim == 0andsample() == {}– a space that the constructor would have refused to build, reached by mutating one it had just approved. Checks that run once only hold if the thing they checked cannot change afterwards. Build a newSpaceto change the dimensions.
- property names: tuple[str, ...]
The fixed dimension order, always read straight from
dims.This was a tuple snapshotted in
__init__whiledimsstayed a public mutable dict, so adding or removing a dimension afterwards left the two disagreeing:ndimand every encode/decode kept using the old order and silently ignored the new dimension, whiledimsreported it as present. Deriving the order removes the possibility rather than documenting it.
- property ndim: int
Number of dimensions in the fixed search-space order.
- to_bounds()[source]
The continuous
(low, high)box for the BO backend (categoricals as integer indices).
- sample(rng)[source]
Draw a random config dict, each dimension sampled natively.
- Parameters:
rng (RandomState)
- Return type:
- encode(config)[source]
Encode a config dict into the numeric vector (in the fixed dimension order).
- decode(vector)[source]
Decode a numeric vector (BO proposal) back into a config dict (rounding / clipping).
- class Real(lo, hi)[source]
Bases:
objectA continuous dimension over
[lo, hi].Both bounds must be finite. An infinite (or NaN) bound would construct fine but then silently poison downstream
sample/neighborsdraws withinf/nan(or crash deep inside NumPy’s RNG with an opaqueOverflowError), far from this actual root cause – so it is rejected here instead.- bounds()[source]
Return the numeric bounds used by continuous optimizers.
- sample(rng)[source]
Draw a uniformly distributed value from the interval.
- Parameters:
rng (RandomState)
- Return type:
- encode(value)[source]
Clip and encode
valueas a floating-point coordinate.
- decode(x)[source]
Clip a numeric optimizer coordinate back into the interval.
- class Integer(lo, hi)[source]
Bases:
objectAn integer dimension over the inclusive range
[lo, hi].- bounds()[source]
Return widened numeric bounds so rounding covers each integer level.
- sample(rng)[source]
Draw an integer uniformly from the inclusive range.
- Parameters:
rng (RandomState)
- Return type:
- encode(value)[source]
Round, clip, and encode
valueas a numeric coordinate.
- decode(x)[source]
Round and clip a numeric optimizer coordinate to an integer value.
- class Categorical(choices)[source]
Bases:
objectAn unordered categorical dimension over a finite list of
choices.choicesmust be unique under==(the same equality_index_of()uses to look a value up) – a duplicate raisesValueErrorat construction. Without this check,encodewould silently collapse a duplicate to its first occurrence’s index whilesample/bounds/ the dimension’s own length would still count it as a distinct, independently-selectable level, so the dimension’s notion of “how many choices” would disagree with itself depending which path asked.- bounds()[source]
Return widened index bounds so rounding covers each categorical choice.
- sample(rng)[source]
Draw one choice uniformly at random.
- Parameters:
rng (RandomState)
- Return type:
- encode(value)[source]
Encode a choice as its floating-point index.
- decode(x)[source]
Round and clip an optimizer coordinate back to a choice.