Spaces:
Running
Running
"""Numpy utility functions: concatenate space samples and create empty array.""" | |
from collections import OrderedDict | |
from functools import singledispatch | |
from typing import Iterable, Union | |
import numpy as np | |
from gym.spaces import Box, Dict, Discrete, MultiBinary, MultiDiscrete, Space, Tuple | |
__all__ = ["concatenate", "create_empty_array"] | |
def concatenate( | |
space: Space, items: Iterable, out: Union[tuple, dict, np.ndarray] | |
) -> Union[tuple, dict, np.ndarray]: | |
"""Concatenate multiple samples from space into a single object. | |
Example:: | |
>>> from gym.spaces import Box | |
>>> space = Box(low=0, high=1, shape=(3,), dtype=np.float32) | |
>>> out = np.zeros((2, 3), dtype=np.float32) | |
>>> items = [space.sample() for _ in range(2)] | |
>>> concatenate(space, items, out) | |
array([[0.6348213 , 0.28607962, 0.60760117], | |
[0.87383074, 0.192658 , 0.2148103 ]], dtype=float32) | |
Args: | |
space: Observation space of a single environment in the vectorized environment. | |
items: Samples to be concatenated. | |
out: The output object. This object is a (possibly nested) numpy array. | |
Returns: | |
The output object. This object is a (possibly nested) numpy array. | |
Raises: | |
ValueError: Space is not a valid :class:`gym.Space` instance | |
""" | |
raise ValueError( | |
f"Space of type `{type(space)}` is not a valid `gym.Space` instance." | |
) | |
def _concatenate_base(space, items, out): | |
return np.stack(items, axis=0, out=out) | |
def _concatenate_tuple(space, items, out): | |
return tuple( | |
concatenate(subspace, [item[i] for item in items], out[i]) | |
for (i, subspace) in enumerate(space.spaces) | |
) | |
def _concatenate_dict(space, items, out): | |
return OrderedDict( | |
[ | |
(key, concatenate(subspace, [item[key] for item in items], out[key])) | |
for (key, subspace) in space.spaces.items() | |
] | |
) | |
def _concatenate_custom(space, items, out): | |
return tuple(items) | |
def create_empty_array( | |
space: Space, n: int = 1, fn: callable = np.zeros | |
) -> Union[tuple, dict, np.ndarray]: | |
"""Create an empty (possibly nested) numpy array. | |
Example:: | |
>>> from gym.spaces import Box, Dict | |
>>> space = Dict({ | |
... 'position': Box(low=0, high=1, shape=(3,), dtype=np.float32), | |
... 'velocity': Box(low=0, high=1, shape=(2,), dtype=np.float32)}) | |
>>> create_empty_array(space, n=2, fn=np.zeros) | |
OrderedDict([('position', array([[0., 0., 0.], | |
[0., 0., 0.]], dtype=float32)), | |
('velocity', array([[0., 0.], | |
[0., 0.]], dtype=float32))]) | |
Args: | |
space: Observation space of a single environment in the vectorized environment. | |
n: Number of environments in the vectorized environment. If `None`, creates an empty sample from `space`. | |
fn: Function to apply when creating the empty numpy array. Examples of such functions are `np.empty` or `np.zeros`. | |
Returns: | |
The output object. This object is a (possibly nested) numpy array. | |
Raises: | |
ValueError: Space is not a valid :class:`gym.Space` instance | |
""" | |
raise ValueError( | |
f"Space of type `{type(space)}` is not a valid `gym.Space` instance." | |
) | |
def _create_empty_array_base(space, n=1, fn=np.zeros): | |
shape = space.shape if (n is None) else (n,) + space.shape | |
return fn(shape, dtype=space.dtype) | |
def _create_empty_array_tuple(space, n=1, fn=np.zeros): | |
return tuple(create_empty_array(subspace, n=n, fn=fn) for subspace in space.spaces) | |
def _create_empty_array_dict(space, n=1, fn=np.zeros): | |
return OrderedDict( | |
[ | |
(key, create_empty_array(subspace, n=n, fn=fn)) | |
for (key, subspace) in space.spaces.items() | |
] | |
) | |
def _create_empty_array_custom(space, n=1, fn=np.zeros): | |
return None | |