designspace.Prop#
- class designspace.Prop(operand: ArithExpr, name: str)#
-
ds.param(“c”).prop(name): a custom type’s declared scalar property (int/float/bool/str only). operand is the custom-typed param reference; name is checked against the type’s properties() at resolution. Dual-typed like ParamExpr itself: a bool-declared prop is usable directly as a condition (.require(x.prop (“ok”)), &/|/~), not just inside a Compare, matching the same “bare BoolExpr coerces via bool(value)” convention every param reference already gets. Bare boolean-position usage carries no type_kind or declared-type gate anywhere in the library, while the declared and scalar checks do still apply uniformly here.
Exported because it is .prop()’s return type and no other public type captures it: being both an ArithExpr and a BoolExpr is what lets a bool-declared property serve as a bare condition, which neither base alone expresses.
- if_inactive(fallback: object) ArithExpr#
Substitute fallback when this expression has no value.
An expression over an inactive parameter, or an aggregate over a list that is switched off, evaluates to unknown, and a constraint that cannot be decided is treated as inapplicable rather than violated. That is usually right, but sometimes the intended reading is “absent means zero”. This says so.
It substitutes only for inactivity. An expression that is unknown because a value has not been chosen yet stays unknown, and an aggregate over an active but empty list keeps its own empty value, which the fallback would otherwise mask.
- Parameters:
fallback (object) – The value to use when the expression is inactive.
- Returns:
An expression that is never unknown for want of activity.
- Return type:
Examples
Without a fallback the budget cannot be decided, so it does not constrain anything:
>>> s = ds.space( ... ds.param("use_cache").bool(), ... ds.param("cache_mb").integer(64, 512).when(ds.param("use_cache")), ... ds.param("heap_mb").integer(64, 512), ... ) >>> total = ds.param("cache_mb") + ds.param("heap_mb") >>> loose = s.require(total <= 512) >>> loose.is_feasible({"use_cache": False, "heap_mb": 512}) True
With one, an absent cache counts as zero and the rule applies:
>>> guarded = s.require(ds.param("cache_mb").if_inactive(0) + ds.param("heap_mb") <= 400) >>> guarded.is_feasible({"use_cache": False, "heap_mb": 512}) False >>> guarded.is_feasible({"use_cache": False, "heap_mb": 256}) True
- implies(other: BoolExpr) BoolExpr#
Material implication: if this holds, other must too.
The natural shape for a conditional rule such as “if we are on GPU, the batch must be at least 32”, and much clearer than the equivalent ~a | b, which it is exactly (down to the fingerprint).
- Parameters:
other (BoolExpr) – The consequent.
- Returns:
A condition, false only when this holds and other does not.
- Return type:
- Raises:
TypeError – If other is not a boolean expression.
Examples
>>> s = ds.space( ... ds.param("gpu").bool(), ... ds.param("batch").integer(1, 64), ... ).require(ds.param("gpu").implies(ds.param("batch") >= 32)) >>> s.is_feasible({"gpu": True, "batch": 64}) True >>> s.is_feasible({"gpu": True, "batch": 8}) False
The rule says nothing when the antecedent is false:
>>> s.is_feasible({"gpu": False, "batch": 8}) True
- is_active() BoolExpr#
Whether the referenced parameter is active, as a condition.
Lets a constraint ask about presence rather than value: “if the cache is switched on at all, then …”. Distinct from reading the value, which would be unknown for an inactive parameter.
- Returns:
A condition, true when the parameter is present.
- Return type:
Examples
>>> s = ds.space( ... ds.param("use_cache").bool(), ... ds.param("cache_mb").integer(64, 512).when(ds.param("use_cache")), ... ds.param("workers").integer(1, 8), ... ) >>> s = s.require( ... ds.param("cache_mb").is_active().implies(ds.param("workers") <= 4) ... ) >>> s.is_feasible({"use_cache": True, "cache_mb": 128, "workers": 2}) True >>> s.is_feasible({"use_cache": True, "cache_mb": 128, "workers": 8}) False >>> s.is_feasible({"use_cache": False, "workers": 8}) True
- is_in(*values: Any) BoolExpr#
Whether the value is one of values.
The replacement for Python’s in, which cannot be used on an expression: in coerces its result to a bool and would collapse the tree.
- Parameters:
*values (Any) – The values to test membership against.
- Returns:
A condition.
- Return type:
Examples
>>> s = ds.space(ds.param("algo").categorical("a", "b", "c")) >>> s = s.require(ds.param("algo").is_in("a", "b")) >>> s.is_feasible({"algo": "a"}) True >>> s.is_feasible({"algo": "c"}) False