designspace.ParamType#
- class designspace.ParamType(*args, **kwargs)#
Bases:
ProtocolThe full .custom(param_type) protocol. Required: type_key, validate, to_json, from_json, describe.
Optional capabilities (checked via hasattr, not declared in this Protocol’s static shape; see the module docstring):
sample(self, rng) -> Any, generative iff present; absent, the param is non-generative: sampling raises SamplingError naming the param iff a value must be materialized, and .default()/freeze/slice/inactivity each satisfy that instead.
cardinality(self) -> int | None, contributing a finite factor to Space.cardinality() iff present; absent, the whole space’s cardinality is None whenever this param is included.
properties(self) -> dict[str, type] and extract(self, value, prop) -> Any, which present together enable .prop() in expressions. Reading an undeclared property, declaring a non-scalar property type, or comparing a property against a value of another type is a resolution error.
Examples
A complete implementation. The five required members are enough to declare, validate, and serialize; sample makes it generative, and properties/extract let constraints read into the value.
>>> class IntervalType: ... type_key = "interval" ... ... def validate(self, value): ... return value["lo"] < value["hi"] ... ... def to_json(self, value): ... return value ... ... def from_json(self, data): ... return data ... ... def describe(self): ... return {"fields": ["lo", "hi"]} ... ... def sample(self, rng): ... lo = float(rng.random()) ... return {"lo": lo, "hi": lo + float(rng.random())} ... ... def properties(self): ... return {"width": float} ... ... def extract(self, value, prop): ... return value["hi"] - value["lo"] >>> s = ds.space(ds.param("band").custom(IntervalType())) >>> s.validate({"band": {"lo": 0.1, "hi": 0.4}}).valid True >>> s.validate({"band": {"lo": 0.9, "hi": 0.4}}).valid False
Because it declares properties/extract, constraints can read into the value:
>>> narrow = s.require(ds.param("band").prop("width") <= 0.5) >>> narrow.is_feasible({"band": {"lo": 0.1, "hi": 0.4}}) True >>> narrow.is_feasible({"band": {"lo": 0.1, "hi": 0.9}}) False
- property type_key: str#
A stable name for this type.
It identifies the type in a serialized document and is the key a consumer’s registry uses when rebuilding a space with Space.from_json(…, custom_types=…). Solver adapters key off it too. Choose something durable, since it is part of the wire format.
- validate(value: Any) bool#
Whether value is a legal value of this type.
Receives the type’s native form. Called by Space.validate() and by the sampler after a draw.
- Parameters:
value (Any) – A candidate value, in native form.
- Returns:
Whether it is acceptable.
- Return type:
- to_json(value: Any) Any#
Convert a native value to its JSON-safe form.
This is the bridge between the type’s internal representation and the form that appears in configuration dicts, .sample_one() results, hashes, and serialized documents, so it runs on every value leaving the type, not only when writing JSON.
- Parameters:
value (Any) – A value in native form.
- Returns:
A JSON-safe equivalent.
- Return type:
Any
- from_json(data: Any) Any#
Convert a JSON-safe value back to native form.
The inverse of to_json, called before validate or extract runs on a value that came from a configuration.
- Parameters:
data (Any) – A value in JSON-safe form.
- Returns:
The native equivalent.
- Return type:
Any