Files
Gymnasium/gym/spaces/discrete.py
Mark Towers 134de4a713 Updates the environment checker (#2864)
* Updated testing requirements based off extra["testing"]

* Updated setup to check the version is valid, added testing and all dependency groups and collects the requirements from requirements.txt to keep everything standardized.

* Updated requirements.txt based on the current minimum gym requirements.txt to work

* Updated requirements.txt based on the current minimum gym requirements.txt to work

* Updated test_requirements.txt based on the current gym full testing requirements

* Pre-commit updates

* Add integer check for the `n` parameter

* The type of self.spaces is an Iterable which is absorbed by the tuple.

* Simplifies the environment checker to two files, env_checker.py and passive_env_checker.py with a new wrapper env_checker.py

* Adds the passive environment checker on `gym.make`

* Ignore the `check_env` warn parameter

* Ignore the `check_env` warn parameter

* Use the `data_equivalence` function

* Revert rewrite setup.py changes

* Remove smart formatting for 3.6 support

* Fixed `check_action_space` and `check_observation_space`

* Added disable_env_checker to vector.make such that env_checker would only run on the first environment created.

* Removing check that different seeds would produce different initialising states

* Use the unwrapped environment np_random

* Fixed vector environment creator
2022-06-06 11:21:45 -04:00

99 lines
3.1 KiB
Python

"""Implementation of a space consisting of finitely many elements."""
from typing import Optional, Union
import numpy as np
from gym.spaces.space import Space
from gym.utils import seeding
class Discrete(Space[int]):
r"""A space consisting of finitely many elements.
This class represents a finite subset of integers, more specifically a set of the form :math:`\{ a, a+1, \dots, a+n-1 \}`.
Example::
>>> Discrete(2) # {0, 1}
>>> Discrete(3, start=-1) # {-1, 0, 1}
"""
def __init__(
self,
n: int,
seed: Optional[Union[int, seeding.RandomNumberGenerator]] = None,
start: int = 0,
):
r"""Constructor of :class:`Discrete` space.
This will construct the space :math:`\{\text{start}, ..., \text{start} + n - 1\}`.
Args:
n (int): The number of elements of this space.
seed: Optionally, you can use this argument to seed the RNG that is used to sample from the ``Dict`` space.
start (int): The smallest element of this space.
"""
assert isinstance(n, (int, np.integer))
assert n > 0, "n (counts) have to be positive"
assert isinstance(start, (int, np.integer))
self.n = int(n)
self.start = int(start)
super().__init__((), np.int64, seed)
def sample(self) -> int:
"""Generates a single random sample from this space.
A sample will be chosen uniformly at random.
Returns:
A sampled integer from the space
"""
return int(self.start + self.np_random.integers(self.n))
def contains(self, x) -> bool:
"""Return boolean specifying if x is a valid member of this space."""
if isinstance(x, int):
as_int = x
elif isinstance(x, (np.generic, np.ndarray)) and (
x.dtype.char in np.typecodes["AllInteger"] and x.shape == ()
):
as_int = int(x) # type: ignore
else:
return False
return self.start <= as_int < self.start + self.n
def __repr__(self) -> str:
"""Gives a string representation of this space."""
if self.start != 0:
return "Discrete(%d, start=%d)" % (self.n, self.start)
return "Discrete(%d)" % self.n
def __eq__(self, other) -> bool:
"""Check whether ``other`` is equivalent to this instance."""
return (
isinstance(other, Discrete)
and self.n == other.n
and self.start == other.start
)
def __setstate__(self, state):
"""Used when loading a pickled space.
This method has to be implemented explicitly to allow for loading of legacy states.
Args:
state: The new state
"""
super().__setstate__(state)
# Don't mutate the original state
state = dict(state)
# Allow for loading of legacy states.
# See https://github.com/openai/gym/pull/2470
if "start" not in state:
state["start"] = 0
# Update our state
self.__dict__.update(state)