Pydocstyle spaces docstring (#2798)

* Added docstrings for spaces, WIP

* Formatting changes

* Use raw docstring for Box.sample

* Formatting fix

* Formatting fix

* Use :class:, :meth:, formatting fixes, resolve TODO, use Optional
This commit is contained in:
Markus Krimmel
2022-05-10 17:18:06 +02:00
committed by GitHub
parent 1c62d3c6ad
commit 745e7059e7
9 changed files with 274 additions and 85 deletions

View File

@@ -1,3 +1,4 @@
"""Implementation of a space that represents the cartesian product of other spaces."""
from __future__ import annotations
from typing import Iterable, Optional, Sequence
@@ -9,12 +10,15 @@ from gym.utils import seeding
class Tuple(Space[tuple], Sequence):
"""
A tuple (i.e., product) of simpler spaces
"""A tuple (more precisely: the cartesian product) of :class:`Space` instances.
Elements of this space are tuples of elements of the constituent spaces.
Example usage::
self.observation_space = spaces.Tuple((spaces.Discrete(2), spaces.Discrete(3)))
>> observation_space = spaces.Tuple((spaces.Discrete(2), spaces.Box(-1, 1, shape=(2,))))
>> observation_space.sample()
(0, array([0.03633198, 0.42370757], dtype=float32))
"""
def __init__(
@@ -22,6 +26,14 @@ class Tuple(Space[tuple], Sequence):
spaces: Iterable[Space],
seed: Optional[int | list[int] | seeding.RandomNumberGenerator] = None,
):
r"""Constructor of :class:`Tuple`` space.
The generated instance will represent the cartesian product :math:`\text{spaces}[0] \times ... \times \text{spaces}[-1]`.
Args:
spaces (Iterable[Space]): The spaces that are involved in the cartesian product.
seed: Optionally, you can use this argument to seed the RNGs of the ``spaces`` to ensure reproducible sampling.
"""
spaces = tuple(spaces)
self.spaces = spaces
for space in spaces:
@@ -31,6 +43,7 @@ class Tuple(Space[tuple], Sequence):
super().__init__(None, None, seed) # type: ignore
def seed(self, seed: Optional[int | list[int]] = None) -> list:
"""Seed the PRNG of this space and all subspaces."""
seeds = []
if isinstance(seed, list):
@@ -62,9 +75,14 @@ class Tuple(Space[tuple], Sequence):
return seeds
def sample(self) -> tuple:
"""Generates a single random sample inside this space.
This method draws independent samples from the subspaces.
"""
return tuple(space.sample() for space in self.spaces)
def contains(self, x) -> bool:
"""Return boolean specifying if x is a valid member of this space."""
if isinstance(x, (list, np.ndarray)):
x = tuple(x) # Promote list and ndarray to tuple for contains check
return (
@@ -74,9 +92,11 @@ class Tuple(Space[tuple], Sequence):
)
def __repr__(self) -> str:
"""Gives a string representation of this space."""
return "Tuple(" + ", ".join([str(s) for s in self.spaces]) + ")"
def to_jsonable(self, sample_n: Sequence) -> list:
"""Convert a batch of samples from this space to a JSONable data type."""
# serialize as list-repr of tuple of vectors
return [
space.to_jsonable([sample[i] for sample in sample_n])
@@ -84,6 +104,7 @@ class Tuple(Space[tuple], Sequence):
]
def from_jsonable(self, sample_n) -> list:
"""Convert a JSONable data type to a batch of samples from this space."""
return [
sample
for sample in zip(
@@ -95,10 +116,13 @@ class Tuple(Space[tuple], Sequence):
]
def __getitem__(self, index: int) -> Space:
"""Get the subspace at specific `index`."""
return self.spaces[index]
def __len__(self) -> int:
"""Get the number of subspaces that are involved in the cartesian product."""
return len(self.spaces)
def __eq__(self, other) -> bool:
"""Check whether ``other`` is equivalent to this instance."""
return isinstance(other, Tuple) and self.spaces == other.spaces