diff --git a/docs/api/spaces/utils.md b/docs/api/spaces/utils.md index e26ecc636..be895a42d 100644 --- a/docs/api/spaces/utils.md +++ b/docs/api/spaces/utils.md @@ -5,8 +5,8 @@ title: Utils # Spaces Utils ```{eval-rst} -.. autofunction:: gymnasium.spaces.utils.flatdim .. autofunction:: gymnasium.spaces.utils.flatten_space .. autofunction:: gymnasium.spaces.utils.flatten +.. autofunction:: gymnasium.spaces.utils.flatdim .. autofunction:: gymnasium.spaces.utils.unflatten ``` \ No newline at end of file diff --git a/gymnasium/spaces/dict.py b/gymnasium/spaces/dict.py index 8c8ee592c..2166e5c50 100644 --- a/gymnasium/spaces/dict.py +++ b/gymnasium/spaces/dict.py @@ -46,8 +46,8 @@ class Dict(Space[typing.Dict[str, Any]], typing.Mapping[str, Space[Any]]): It can be convenient to use :class:`Dict` spaces if you want to make complex observations or actions more human-readable. Usually, it will not be possible to use elements of this space directly in learning code. However, you can easily - convert `Dict` observations to flat arrays by using a :class:`gym.wrappers.FlattenObservation` wrapper. Similar wrappers can be - implemented to deal with :class:`Dict` actions. + convert `Dict` observations to flat arrays by using a :class:`gymnasium.wrappers.FlattenObservation` wrapper. + Similar wrappers can be implemented to deal with :class:`Dict` actions. """ def __init__( @@ -121,9 +121,10 @@ class Dict(Space[typing.Dict[str, Any]], typing.Mapping[str, Space[Any]]): """Seed the PRNG of this space and all subspaces. Depending on the type of seed, the subspaces will be seeded differently - * None - All the subspaces will use a random initial seed - * Int - The integer is used to seed the `Dict` space that is used to generate seed values for each of the subspaces. Warning, this does not guarantee unique seeds for all of the subspaces. - * Dict - Using all the keys in the seed dictionary, the values are used to seed the subspaces. This allows the seeding of multiple composite subspaces (`Dict["space": Dict[...], ...]` with `{"space": {...}, ...}`). + + * ``None`` - All the subspaces will use a random initial seed + * ``Int`` - The integer is used to seed the :class:`Dict` space that is used to generate seed values for each of the subspaces. Warning, this does not guarantee unique seeds for all of the subspaces. + * ``Dict`` - Using all the keys in the seed dictionary, the values are used to seed the subspaces. This allows the seeding of multiple composite subspaces (``Dict["space": Dict[...], ...]`` with ``{"space": {...}, ...}``). Args: seed: An optional list of ints or int to seed the (sub-)spaces. diff --git a/gymnasium/spaces/sequence.py b/gymnasium/spaces/sequence.py index 8092be27f..dfb74f99f 100644 --- a/gymnasium/spaces/sequence.py +++ b/gymnasium/spaces/sequence.py @@ -72,9 +72,10 @@ class Sequence(Space[typing.Tuple[Any, ...]]): mask: An optional mask for (optionally) the length of the sequence and (optionally) the values in the sequence. If you specify `mask`, it is expected to be a tuple of the form `(length_mask, sample_mask)` where `length_mask` is - - `None` The length will be randomly drawn from a geometric distribution - - `np.ndarray` of integers, in which case the length of the sampled sequence is randomly drawn from this array. - - `int` for a fixed length sample + + * ``None`` The length will be randomly drawn from a geometric distribution + * ``np.ndarray`` of integers, in which case the length of the sampled sequence is randomly drawn from this array. + * ``int`` for a fixed length sample The second element of the mask tuple `sample` mask specifies a mask that is applied when sampling elements from the base space. The mask is applied for each feature space sample. diff --git a/gymnasium/spaces/tuple.py b/gymnasium/spaces/tuple.py index 1522c2fbd..1f7239fb8 100644 --- a/gymnasium/spaces/tuple.py +++ b/gymnasium/spaces/tuple.py @@ -52,9 +52,10 @@ class Tuple(Space[typing.Tuple[Any, ...]], typing.Sequence[Any]): """Seed the PRNG of this space and all subspaces. Depending on the type of seed, the subspaces will be seeded differently - * None - All the subspaces will use a random initial seed - * Int - The integer is used to seed the `Tuple` space that is used to generate seed values for each of the subspaces. Warning, this does not guarantee unique seeds for all of the subspaces. - * List - Values used to seed the subspaces. This allows the seeding of multiple composite subspaces (`List(42, 54, ...)`). + + * ``None`` - All the subspaces will use a random initial seed + * ``Int`` - The integer is used to seed the `Tuple` space that is used to generate seed values for each of the subspaces. Warning, this does not guarantee unique seeds for all of the subspaces. + * ``List`` - Values used to seed the subspaces. This allows the seeding of multiple composite subspaces (``List(42, 54, ...``). Args: seed: An optional list of ints or int to seed the (sub-)spaces. diff --git a/gymnasium/spaces/utils.py b/gymnasium/spaces/utils.py index aef2ea268..8d2636f42 100644 --- a/gymnasium/spaces/utils.py +++ b/gymnasium/spaces/utils.py @@ -47,8 +47,8 @@ def flatdim(space: Space[Any]) -> int: The number of dimensions for the flattened spaces Raises: - NotImplementedError: if the space is not defined in ``gym.spaces``. - ValueError: if the space cannot be flattened into a :class:`Box` + NotImplementedError: if the space is not defined in :mod:`gym.spaces`. + ValueError: if the space cannot be flattened into a :class:`gymnasium.spaces.Box` """ if space.is_np_flattenable is False: raise ValueError( @@ -135,20 +135,22 @@ def flatten(space: Space[T], x: T) -> FlatType: x: The value to flatten Returns: - - For ``Box`` and ``MultiBinary``, this is a flattened array - - For ``Discrete`` and ``MultiDiscrete``, this is a flattened one-hot array of the sample - - For ``Tuple`` and ``Dict``, this is a concatenated array the subspaces (does not support graph subspaces) - - For graph spaces, returns `GraphInstance` where: - - `nodes` are n x k arrays - - `edges` are either: - - m x k arrays - - None - - `edge_links` are either: - - m x 2 arrays - - None + The flattened datapoint + + - For :class:`gymnasium.spaces.Box` and :class:`gymnasium.spaces.MultiBinary`, this is a flattened array + - For :class:`gymnasium.spaces.Discrete` and :class:`gymnasium.spaces.MultiDiscrete`, this is a flattened one-hot array of the sample + - For :class:`gymnasium.spaces.Tuple` and :class:`gymnasium.spaces.Dict`, this is a concatenated array the subspaces (does not support graph subspaces) + - For graph spaces, returns :class:`GraphInstance` where: + - :attr:`GraphInstance.nodes` are n x k arrays + - :attr:`GraphInstance.edges` are either: + - m x k arrays + - None + - :attr:`GraphInstance.edge_links` are either: + - m x 2 arrays + - None Raises: - NotImplementedError: If the space is not defined in ``gymnasium.spaces``. + NotImplementedError: If the space is not defined in :mod:`gymnasium.spaces`. """ raise NotImplementedError(f"Unknown space: `{space}`") @@ -196,7 +198,7 @@ def _flatten_dict(space: Dict, x: dict[str, Any]) -> dict[str, Any] | NDArray[An @flatten.register(Graph) def _flatten_graph(space: Graph, x: GraphInstance) -> GraphInstance: - """We're not using `.unflatten() for :class:`Box` and :class:`Discrete` because a graph is not a homogeneous space, see `.flatten` docstring.""" + """We're not using ``.unflatten()`` for :class:`Box` and :class:`Discrete` because a graph is not a homogeneous space, see `.flatten` docstring.""" def _graph_unflatten( unflatten_space: Discrete | Box | None, @@ -254,7 +256,7 @@ def unflatten(space: Space[T], x: FlatType) -> T: A point with a structure that matches the space. Raises: - NotImplementedError: if the space is not defined in ``gymnasium.spaces``. + NotImplementedError: if the space is not defined in :mod:`gymnasium.spaces`. """ raise NotImplementedError(f"Unknown space: `{space}`") @@ -359,14 +361,16 @@ def _unflatten_sequence(space: Sequence, x: tuple[Any, ...]) -> tuple[Any, ...]: def flatten_space(space: Space[Any]) -> Box | Dict | Sequence | Tuple | Graph: """Flatten a space into a space that is as flat as possible. - This function will attempt to flatten `space` into a single :class:`Box` space. - However, this might not be possible when `space` is an instance of :class:`Graph`, - :class:`Sequence` or a compound space that contains a :class:`Graph` or :class:`Sequence`space. + This function will attempt to flatten ``space`` into a single :class:`gymnasium.spaces.Box` space. + However, this might not be possible when ``space`` is an instance of :class:`gymnasium.spaces.Graph`, + :class:`gymnasium.spaces.Sequence` or a compound space that contains a :class:`gymnasium.spaces.Graph` + or :class:`gymnasium.spaces.Sequence` space. This is equivalent to :func:`flatten`, but operates on the space itself. The - result for non-graph spaces is always a `Box` with flat boundaries. While - the result for graph spaces is always a `Graph` with `node_space` being a `Box` - with flat boundaries and `edge_space` being a `Box` with flat boundaries or - `None`. The box has exactly :func:`flatdim` dimensions. Flattening a sample + result for non-graph spaces is always a :class:`gymnasium.spaces.Box` with flat boundaries. While + the result for graph spaces is always a :class:`gymnasium.spaces.Graph` with + :attr:`Graph.node_space` being a ``Box`` + with flat boundaries and :attr:`Graph.edge_space` being a ``Box`` with flat boundaries or + ``None``. The box has exactly :func:`flatdim` dimensions. Flattening a sample of the original space has the same effect as taking a sample of the flattened space. However, sampling from the flattened space is not necessarily reversible. For example, sampling from a flattened Discrete space is the same as sampling from @@ -415,7 +419,7 @@ def flatten_space(space: Space[Any]) -> Box | Dict | Sequence | Tuple | Graph: A flattened Box Raises: - NotImplementedError: if the space is not defined in ``gym.spaces``. + NotImplementedError: if the space is not defined in :mod:`gymnasium.spaces`. """ raise NotImplementedError(f"Unknown space: `{space}`")