unienv_interface.space.spaces.box¶
BoxSpace
¶
BoxSpace(backend: ComputeBackend[BArrayType, BDeviceType, BDtypeType, BRNGType], low: SupportsFloat | BArrayType, high: SupportsFloat | BArrayType, dtype: BDtypeType, device: Optional[BDeviceType] = None, shape: Optional[Sequence[int]] = None, metadata: Optional[Mapping[str, Any]] = None)
Bases: Space[BArrayType, BDeviceType, BDtypeType, BRNGType]
Continuous or integer hyper-rectangle defined by elementwise bounds.
A box is immutable after construction (_low/_high are never
reassigned), so values derived from the bounds are computed lazily and
cached on the instance; caches are dropped when pickling.
Create a box with broadcastable low and high bounds.
metadata is an optional JSON-serializable description of the data (see Space).
metadata
property
¶
metadata: SpaceMetadata
Read-only description of the data (see "Metadata" in the class docstring); empty if none was given.
shape
property
¶
shape: tuple[int, ...] | None
Return the shape of the space as an immutable property.
to
¶
to(backend: Optional[ComputeBackend] = None, device: Optional[Union[BDeviceType, Any]] = None) -> Union[BoxSpace[BArrayType, BDeviceType, BDtypeType, BRNGType], BoxSpace]
Return an equivalent box on another backend and/or device.
sample
¶
sample(rng: BRNGType) -> Tuple[BRNGType, BArrayType]
Generates a single random sample inside the Box.
In creating a sample of the box, each coordinate is sampled (independently) from a distribution that is chosen according to the form of the interval:
- :math:
[a, b]: uniform distribution - :math:
[a, \infty): shifted exponential distribution - :math:
(-\infty, b]: shifted negative exponential distribution - :math:
(-\infty, \infty): normal distribution
Returns:
| Type | Description |
|---|---|
Tuple[BRNGType, BArrayType]
|
A sampled value from the Box |
create_empty
¶
create_empty() -> BArrayType
Allocate an uninitialized array with the box shape and dtype.
clip
¶
clip(x: BArrayType) -> BArrayType
Clamp x elementwise to the bounds of this box (see Space.clip).
x is cast to the box dtype first (members of a superset box are
losslessly castable), so the result always has the box dtype; ±inf
bounds leave the corresponding coordinates untouched. Never raises
for data of the box shape. Returns a new array.
get_repr
¶
get_repr(abbreviate: bool = False, include_backend: bool = True, include_device: bool = True, include_dtype: bool = True) -> str
is_subspaceeq
¶
is_subspaceeq(other: Any) -> bool
Return whether this box is a non-strict subspace of other (⊆).
True iff other is a BoxSpace on the same backend, with equal
shape and dtype, and other's bounds contain self's bounds
elementwise (other.low <= self.low and other.high >= self.high).
Infinite bounds are handled correctly via direct comparison since
±inf compares as expected against finite values and itself.
device is ignored.
data_to
¶
data_to(data: BArrayType, backend: Optional[ComputeBackend] = None, device: Optional[Union[BDeviceType, Any]] = None) -> Union[BArrayType, Any]
Convert data to another backend.
with_metadata
¶
with_metadata(metadata: Optional[Mapping[str, Any]] = None, /, *, replace: bool = False, **updates: Any) -> Space[SpaceDataT, _SpaceBDeviceT, _SpaceBDTypeT, _SpaceBDRNGT]
Return a copy of this space with updated metadata (this space is left unchanged).
metadata and updates are merged into the current metadata, or
replace it entirely with replace=True (space.with_metadata(replace=True)
clears it). Nested spaces are shared with this space, not copied.
is_subspace
¶
is_subspace(other: Space) -> bool
Return whether this space is a STRICT subspace of other (self ⊂ other).
Defined uniformly for all spaces as::
self.is_subspace(other) ⟺ self.is_subspaceeq(other) and not other.is_subspaceeq(self)
I.e. self ⊆ other holds but other ⊆ self does not, so self
is a PROPER (strict) subspace of other. This is the ⊂ relation
versus the non-strict ⊆ provided by :meth:is_subspaceeq.
This definition is used instead of relying on __eq__ because some
space classes only have identity __eq__; defining strict
containment via the symmetric non-strict check works uniformly for all
classes regardless of their __eq__ implementation.
For structurally-distinct-but-mutually-containing spaces (which should
not occur under the strict dtype/shape policies enforced by the
per-class is_subspaceeq implementations) this degrades gracefully
to False: if both self.is_subspaceeq(other) and
other.is_subspaceeq(self) hold, the two spaces are considered
equivalent and neither is a STRICT subspace of the other.
If either side's is_subspaceeq is not implemented (the base
:meth:is_subspaceeq raises NotImplementedError), the exception
propagates to the caller — it is NOT swallowed into False so that
callers can tell that the comparison is unsupported.
Note: controller-required-space checks should typically use
:meth:is_subspaceeq (a controller's required space may exactly equal
the env space, in which case the strict is_subspace would return
False).
abbr_device
staticmethod
¶
abbr_device(spaces: Iterable[Space[Any, _SpaceBDeviceT, _SpaceBDTypeT, _SpaceBDRNGT]]) -> Optional[_SpaceBDeviceT]
Return the shared device across spaces, or None if mixed/empty.