designspace.space_from_ir#

designspace.space_from_ir(params: Mapping[str, ParamDef] | Iterable[ParamDef], conditions: Iterable[Condition], constraints: Iterable[Constraint], anchors: dict[str, dict[str, Any]] | None = None, meta: dict[str, Any] | None = None) Space#

Build a Space directly from IR, bypassing the builders.

The other half of the bidirectional IR: Space.to_json() and Space.params read it out, this puts it back. Whatever you supply is re-resolved and re-validated exactly like a hand-written declaration, so a programmatically assembled space is checked as thoroughly as any other. This is also what Space.map_params() uses internally.

It is the route to spaces the fluent API cannot express directly, and the supported way to write a structural Representation.

Parameters:
  • params (Mapping[str, ParamDef] | Iterable[ParamDef]) – The parameters, keyed by path or in declaration order.

  • conditions (Iterable[Condition]) – Activity conditions.

  • constraints (Iterable[Constraint]) – Constraints of any kind.

  • anchors (dict[str, dict[str, Any]] | None) – Named reference configurations, validated against the new space.

  • meta (dict[str, Any] | None) – Space-level metadata.

Returns:

The rebuilt space.

Return type:

Space

Raises:

ResolutionError – If the supplied IR does not form a valid space: a duplicate path, a dangling reference, an anchor that does not validate.

Examples

>>> s = ds.space(
...     ds.param("algo").categorical("greedy", "exact"),
...     ds.param("depth").integer(1, 4),
... )
>>> rebuilt = ds.space_from_ir(s.params, s.conditions, s.constraints)
>>> rebuilt.fingerprint() == s.fingerprint()
True