Spaces#

Spaces define the valid format of observation and action spaces for an environment.

General Functions#

Each space implements the following functions:

gym.spaces.Space.sample(self) gym.spaces.space.T_cov#

Randomly sample an element of this space. Can be uniform or non-uniform sampling based on boundedness of space.

gym.spaces.Space.contains(self, x) bool#

Return boolean specifying if x is a valid member of this space

property Space.shape: Optional[tuple[int, ...]]#

Return the shape of the space as an immutable property

property gym.spaces.Space.dtype#

Return the data type of this space.

gym.spaces.Space.seed(self, seed: Optional[int] = None) list#

Seed the PRNG of this space.

gym.spaces.Space.to_jsonable(self, sample_n: Sequence[gym.spaces.space.T_cov]) list#

Convert a batch of samples from this space to a JSONable data type.

gym.spaces.Space.from_jsonable(self, sample_n: list) list[+T_cov]#

Convert a JSONable data type to a batch of samples from this space.

Box#

class gym.spaces.Box(low: typing.Union[typing.SupportsFloat, numpy.ndarray], high: typing.Union[typing.SupportsFloat, numpy.ndarray], shape: typing.Optional[typing.Sequence[int]] = None, dtype: typing.Type = <class 'numpy.float32'>, seed: typing.Optional[int] = None)#

A (possibly unbounded) box in R^n. Specifically, a Box represents the Cartesian product of n closed intervals. Each interval has the form of one of [a, b], (-oo, b], [a, oo), or (-oo, oo).

There are two common use cases:

  • Identical bound for each dimension::
    >>> Box(low=-1.0, high=2.0, shape=(3, 4), dtype=np.float32)
    Box(3, 4)
    
  • Independent bound for each dimension::
    >>> Box(low=np.array([-1.0, -2.0]), high=np.array([2.0, 4.0]), dtype=np.float32)
    Box(2,)
    
is_bounded(manner: str = 'both') bool#
sample() numpy.ndarray#

Generates a single random sample inside of the Box.

In creating a sample of the box, each coordinate is sampled according to the form of the interval:

  • [a, b] : uniform distribution

  • [a, oo) : shifted exponential distribution

  • (-oo, b] : shifted negative exponential distribution

  • (-oo, oo) : normal distribution

Discrete#

class gym.spaces.Discrete(n: int, seed: Optional[int] = None, start: int = 0)#

A discrete space in \(\{ 0, 1, \\dots, n-1 \}\).

A start value can be optionally specified to shift the range to \(\{ a, a+1, \\dots, a+n-1 \}\).

Example:

>>> Discrete(2)            # {0, 1}
>>> Discrete(3, start=-1)  # {-1, 0, 1}

MultiBinary#

class gym.spaces.MultiBinary(n: Union[numpy.ndarray, Sequence[int], int], seed: Optional[int] = None)#

An n-shape binary space.

The argument to MultiBinary defines n, which could be a number or a list of numbers.

Example Usage:

>> self.observation_space = spaces.MultiBinary(5)

>> self.observation_space.sample()

array([0, 1, 0, 1, 0], dtype=int8)

>> self.observation_space = spaces.MultiBinary([3, 2])

>> self.observation_space.sample()

array([[0, 0],

[0, 1], [1, 1]], dtype=int8)

MultiDiscrete#

class gym.spaces.MultiDiscrete(nvec: list[int], dtype=<class 'numpy.int64'>, seed=None)#
  • The multi-discrete action space consists of a series of discrete action spaces with different number of actions in each

  • It is useful to represent game controllers or keyboards where each key can be represented as a discrete action space

  • It is parametrized by passing an array of positive integers specifying number of actions for each discrete action space

Note: Some environment wrappers assume a value of 0 always represents the NOOP action.

e.g. Nintendo Game Controller - Can be conceptualized as 3 discrete action spaces:

  1. Arrow Keys: Discrete 5 - NOOP[0], UP[1], RIGHT[2], DOWN[3], LEFT[4] - params: min: 0, max: 4

  2. Button A: Discrete 2 - NOOP[0], Pressed[1] - params: min: 0, max: 1

  3. Button B: Discrete 2 - NOOP[0], Pressed[1] - params: min: 0, max: 1

  • Can be initialized as

    MultiDiscrete([ 5, 2, 2 ])

Dict#

class gym.spaces.Dict(spaces: dict[str, Space] | None = None, seed: dict | int | None = None, **spaces_kwargs: Space)#

A dictionary of simpler spaces.

Example usage: self.observation_space = spaces.Dict({“position”: spaces.Discrete(2), “velocity”: spaces.Discrete(3)})

Example usage [nested]: self.nested_observation_space = spaces.Dict({

‘sensors’: spaces.Dict({

‘position’: spaces.Box(low=-100, high=100, shape=(3,)), ‘velocity’: spaces.Box(low=-1, high=1, shape=(3,)), ‘front_cam’: spaces.Tuple((

spaces.Box(low=0, high=1, shape=(10, 10, 3)), spaces.Box(low=0, high=1, shape=(10, 10, 3))

)), ‘rear_cam’: spaces.Box(low=0, high=1, shape=(10, 10, 3)),

}), ‘ext_controller’: spaces.MultiDiscrete((5, 2, 2)), ‘inner_state’:spaces.Dict({

‘charge’: spaces.Discrete(100), ‘system_checks’: spaces.MultiBinary(10), ‘job_status’: spaces.Dict({

‘task’: spaces.Discrete(5), ‘progress’: spaces.Box(low=0, high=100, shape=()),

})

})

})

Tuple#

class gym.spaces.Tuple(spaces: Iterable[gym.spaces.space.Space], seed: Optional[Union[int, List[int]]] = None)#

A tuple (i.e., product) of simpler spaces

Example usage: self.observation_space = spaces.Tuple((spaces.Discrete(2), spaces.Discrete(3)))

Utility Functions#

gym.spaces.utils.flatdim(space: gym.spaces.space.Space) int#

Return the number of dimensions a flattened equivalent of this space would have.

Accepts a space and returns an integer. Raises NotImplementedError if the space is not defined in gym.spaces.

gym.spaces.utils.flatten_space(space: gym.spaces.space.Space) gym.spaces.box.Box#

Flatten a space into a single Box.

This is equivalent to flatten(), but operates on the space itself. The result always is a Box with flat boundaries. The box has exactly flatdim(space) dimensions. Flattening a sample of the original space has the same effect as taking a sample of the flattenend space.

Raises NotImplementedError if the space is not defined in gym.spaces.

Example:

>>> box = Box(0.0, 1.0, shape=(3, 4, 5))
>>> box
Box(3, 4, 5)
>>> flatten_space(box)
Box(60,)
>>> flatten(box, box.sample()) in flatten_space(box)
True

Example that flattens a discrete space:

>>> discrete = Discrete(5)
>>> flatten_space(discrete)
Box(5,)
>>> flatten(box, box.sample()) in flatten_space(box)
True

Example that recursively flattens a dict:

>>> space = Dict({"position": Discrete(2),
...               "velocity": Box(0, 1, shape=(2, 2))})
>>> flatten_space(space)
Box(6,)
>>> flatten(space, space.sample()) in flatten_space(space)
True
gym.spaces.utils.flatten(space: gym.spaces.space.Space[gym.spaces.utils.T], x: gym.spaces.utils.T) numpy.ndarray#
gym.spaces.utils.flatten(space: gym.spaces.multi_binary.MultiBinary, x) numpy.ndarray
gym.spaces.utils.flatten(space: gym.spaces.box.Box, x) numpy.ndarray
gym.spaces.utils.flatten(space: gym.spaces.discrete.Discrete, x) numpy.ndarray
gym.spaces.utils.flatten(space: gym.spaces.multi_discrete.MultiDiscrete, x) numpy.ndarray
gym.spaces.utils.flatten(space: gym.spaces.tuple.Tuple, x) numpy.ndarray
gym.spaces.utils.flatten(space: gym.spaces.dict.Dict, x) numpy.ndarray

Flatten a data point from a space.

This is useful when e.g. points from spaces must be passed to a neural network, which only understands flat arrays of floats.

Accepts a space and a point from that space. Always returns a 1D array. Raises NotImplementedError if the space is not defined in gym.spaces.

gym.spaces.utils.unflatten(space: gym.spaces.space.Space[gym.spaces.utils.T], x: numpy.ndarray) gym.spaces.utils.T#

Unflatten a data point from a space.

This reverses the transformation applied by flatten(). You must ensure that the space argument is the same as for the flatten() call.

Accepts a space and a flattened point. Returns a point with a structure that matches the space. Raises NotImplementedError if the space is not defined in gym.spaces.