mirror of
https://github.com/Farama-Foundation/Gymnasium.git
synced 2025-08-28 01:07:11 +00:00
Delete prng.py (#1196)
* Delete prng.py Since it seems like this seeding function is rarely used. * Update __init__.py * Update kellycoinflip.py * Update core.py * Update box.py * Update discrete.py * Update multi_binary.py * Update multi_discrete.py * Update test_determinism.py * Update test_determinism.py * Update test_determinism.py * Update core.py * Update box.py * Update test_determinism.py * Update core.py * Update box.py * Update discrete.py * Update multi_binary.py * Update multi_discrete.py * Update dict_space.py * Update tuple_space.py * Update core.py * Create space.py * Update __init__.py * Update __init__.py * Update box.py * Update dict_space.py * Update discrete.py * Update dict_space.py * Update multi_binary.py * Update multi_discrete.py * Update tuple_space.py * Update discrete.py * Update box.py * Update dict_space.py * Update multi_binary.py * Update multi_discrete.py * Update tuple_space.py * Update multi_discrete.py * Update multi_binary.py * Update dict_space.py * Update box.py * Update test_determinism.py * Update kellycoinflip.py * Update space.py
This commit is contained in:
39
gym/core.py
39
gym/core.py
@@ -190,45 +190,6 @@ class GoalEnv(Env):
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
# Space-related abstractions
|
|
||||||
|
|
||||||
class Space(object):
|
|
||||||
"""Defines the observation and action spaces, so you can write generic
|
|
||||||
code that applies to any Env. For example, you can choose a random
|
|
||||||
action.
|
|
||||||
"""
|
|
||||||
def __init__(self, shape=None, dtype=None):
|
|
||||||
import numpy as np # takes about 300-400ms to import, so we load lazily
|
|
||||||
self.shape = None if shape is None else tuple(shape)
|
|
||||||
self.dtype = None if dtype is None else np.dtype(dtype)
|
|
||||||
|
|
||||||
def sample(self):
|
|
||||||
"""
|
|
||||||
Uniformly randomly sample a random element of this space
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def contains(self, x):
|
|
||||||
"""
|
|
||||||
Return boolean specifying if x is a valid
|
|
||||||
member of this space
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
def __contains__(self, x):
|
|
||||||
return self.contains(x)
|
|
||||||
|
|
||||||
def to_jsonable(self, sample_n):
|
|
||||||
"""Convert a batch of samples from this space to a JSONable data type."""
|
|
||||||
# By default, assume identity is JSONable
|
|
||||||
return sample_n
|
|
||||||
|
|
||||||
def from_jsonable(self, sample_n):
|
|
||||||
"""Convert a JSONable data type to a batch of samples from this space."""
|
|
||||||
# By default, assume identity is JSONable
|
|
||||||
return sample_n
|
|
||||||
|
|
||||||
|
|
||||||
warn_once = True
|
warn_once = True
|
||||||
|
|
||||||
def deprecated_warn_once(text):
|
def deprecated_warn_once(text):
|
||||||
|
@@ -1,27 +1,25 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
from gym import spaces
|
|
||||||
from gym.envs.tests.spec_list import spec_list
|
from gym.envs.tests.spec_list import spec_list
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("spec", spec_list)
|
@pytest.mark.parametrize("spec", spec_list)
|
||||||
def test_env(spec):
|
def test_env(spec):
|
||||||
|
|
||||||
# Note that this precludes running this test in multiple
|
# Note that this precludes running this test in multiple
|
||||||
# threads. However, we probably already can't do multithreading
|
# threads. However, we probably already can't do multithreading
|
||||||
# due to some environments.
|
# due to some environments.
|
||||||
spaces.seed(0)
|
|
||||||
|
|
||||||
env1 = spec.make()
|
env1 = spec.make()
|
||||||
env1.seed(0)
|
env1.seed(0)
|
||||||
|
env1.action_space.seed(0)
|
||||||
action_samples1 = [env1.action_space.sample() for i in range(4)]
|
action_samples1 = [env1.action_space.sample() for i in range(4)]
|
||||||
initial_observation1 = env1.reset()
|
initial_observation1 = env1.reset()
|
||||||
step_responses1 = [env1.step(action) for action in action_samples1]
|
step_responses1 = [env1.step(action) for action in action_samples1]
|
||||||
env1.close()
|
env1.close()
|
||||||
|
|
||||||
spaces.seed(0)
|
|
||||||
|
|
||||||
env2 = spec.make()
|
env2 = spec.make()
|
||||||
env2.seed(0)
|
env2.seed(0)
|
||||||
|
env2.action_space.seed(0)
|
||||||
action_samples2 = [env2.action_space.sample() for i in range(4)]
|
action_samples2 = [env2.action_space.sample() for i in range(4)]
|
||||||
initial_observation2 = env2.reset()
|
initial_observation2 = env2.reset()
|
||||||
step_responses2 = [env2.step(action) for action in action_samples2]
|
step_responses2 = [env2.step(action) for action in action_samples2]
|
||||||
|
@@ -6,7 +6,6 @@ import numpy.random
|
|||||||
import gym
|
import gym
|
||||||
from gym import spaces
|
from gym import spaces
|
||||||
from gym.utils import seeding
|
from gym.utils import seeding
|
||||||
from gym.spaces import prng
|
|
||||||
|
|
||||||
|
|
||||||
def flip(edge, np_random):
|
def flip(edge, np_random):
|
||||||
@@ -81,10 +80,12 @@ class KellyCoinflipGeneralizedEnv(gym.Env):
|
|||||||
self.maxRoundsMean=maxRoundsMean
|
self.maxRoundsMean=maxRoundsMean
|
||||||
self.maxRoundsSD=maxRoundsSD
|
self.maxRoundsSD=maxRoundsSD
|
||||||
|
|
||||||
|
if reseed or not hasattr(self, 'np_random') : self.seed()
|
||||||
|
|
||||||
# draw this game's set of parameters:
|
# draw this game's set of parameters:
|
||||||
edge = prng.np_random.beta(edgePriorAlpha, edgePriorBeta)
|
edge = self.np_random.beta(edgePriorAlpha, edgePriorBeta)
|
||||||
maxWealth = round(genpareto.rvs(maxWealthAlpha, maxWealthM, random_state=prng.np_random))
|
maxWealth = round(genpareto.rvs(maxWealthAlpha, maxWealthM, random_state=self.np_random))
|
||||||
maxRounds = int(round(prng.np_random.normal(maxRoundsMean, maxRoundsSD)))
|
maxRounds = int(round(self.np_random.normal(maxRoundsMean, maxRoundsSD)))
|
||||||
|
|
||||||
# add an additional global variable which is the sufficient statistic for the Pareto distribution on wealth cap;
|
# add an additional global variable which is the sufficient statistic for the Pareto distribution on wealth cap;
|
||||||
# alpha doesn't update, but x_m does, and simply is the highest wealth count we've seen to date:
|
# alpha doesn't update, but x_m does, and simply is the highest wealth count we've seen to date:
|
||||||
@@ -109,7 +110,6 @@ class KellyCoinflipGeneralizedEnv(gym.Env):
|
|||||||
self.maxRounds = maxRounds
|
self.maxRounds = maxRounds
|
||||||
self.rounds = self.maxRounds
|
self.rounds = self.maxRounds
|
||||||
self.maxWealth = maxWealth
|
self.maxWealth = maxWealth
|
||||||
if reseed or not hasattr(self, 'np_random') : self.seed()
|
|
||||||
|
|
||||||
def seed(self, seed=None):
|
def seed(self, seed=None):
|
||||||
self.np_random, seed = seeding.np_random(seed)
|
self.np_random, seed = seeding.np_random(seed)
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
|
from gym.spaces.space import Space
|
||||||
from gym.spaces.box import Box
|
from gym.spaces.box import Box
|
||||||
from gym.spaces.discrete import Discrete
|
from gym.spaces.discrete import Discrete
|
||||||
from gym.spaces.multi_discrete import MultiDiscrete
|
from gym.spaces.multi_discrete import MultiDiscrete
|
||||||
from gym.spaces.multi_binary import MultiBinary
|
from gym.spaces.multi_binary import MultiBinary
|
||||||
from gym.spaces.prng import seed, np_random
|
|
||||||
from gym.spaces.tuple_space import Tuple
|
from gym.spaces.tuple_space import Tuple
|
||||||
from gym.spaces.dict_space import Dict
|
from gym.spaces.dict_space import Dict
|
||||||
|
|
||||||
__all__ = ["Box", "Discrete", "MultiDiscrete", "MultiBinary", "Tuple", "Dict"]
|
__all__ = ["Space", "Box", "Discrete", "MultiDiscrete", "MultiBinary", "Tuple", "Dict"]
|
||||||
|
@@ -2,8 +2,10 @@ import numpy as np
|
|||||||
|
|
||||||
import gym
|
import gym
|
||||||
from gym import logger
|
from gym import logger
|
||||||
|
from .space import Space
|
||||||
|
|
||||||
class Box(gym.Space):
|
|
||||||
|
class Box(Space):
|
||||||
"""
|
"""
|
||||||
A box in R^n.
|
A box in R^n.
|
||||||
I.e., each coordinate is bounded.
|
I.e., each coordinate is bounded.
|
||||||
@@ -32,10 +34,14 @@ class Box(gym.Space):
|
|||||||
logger.warn("gym.spaces.Box autodetected dtype as {}. Please provide explicit dtype.".format(dtype))
|
logger.warn("gym.spaces.Box autodetected dtype as {}. Please provide explicit dtype.".format(dtype))
|
||||||
self.low = low.astype(dtype)
|
self.low = low.astype(dtype)
|
||||||
self.high = high.astype(dtype)
|
self.high = high.astype(dtype)
|
||||||
gym.Space.__init__(self, shape, dtype)
|
super().__init__(shape, dtype)
|
||||||
|
self.np_random = np.random.RandomState()
|
||||||
|
|
||||||
|
def seed(self, seed):
|
||||||
|
self.np_random.seed(seed)
|
||||||
|
|
||||||
def sample(self):
|
def sample(self):
|
||||||
return gym.spaces.np_random.uniform(low=self.low, high=self.high + (0 if self.dtype.kind == 'f' else 1), size=self.low.shape).astype(self.dtype)
|
return self.np_random.uniform(low=self.low, high=self.high + (0 if self.dtype.kind == 'f' else 1), size=self.low.shape).astype(self.dtype)
|
||||||
|
|
||||||
def contains(self, x):
|
def contains(self, x):
|
||||||
return x.shape == self.shape and (x >= self.low).all() and (x <= self.high).all()
|
return x.shape == self.shape and (x >= self.low).all() and (x <= self.high).all()
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
import gym
|
import gym
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from .space import Space
|
||||||
|
|
||||||
class Dict(gym.Space):
|
|
||||||
|
class Dict(Space):
|
||||||
"""
|
"""
|
||||||
A dictionary of simpler spaces.
|
A dictionary of simpler spaces.
|
||||||
|
|
||||||
@@ -39,7 +41,10 @@ class Dict(gym.Space):
|
|||||||
if isinstance(spaces, list):
|
if isinstance(spaces, list):
|
||||||
spaces = OrderedDict(spaces)
|
spaces = OrderedDict(spaces)
|
||||||
self.spaces = spaces
|
self.spaces = spaces
|
||||||
gym.Space.__init__(self, None, None) # None for shape and dtype, since it'll require special handling
|
super().__init__(None, None) # None for shape and dtype, since it'll require special handling
|
||||||
|
|
||||||
|
def seed(self, seed):
|
||||||
|
[space.seed(seed) for space in self.spaces.values()]
|
||||||
|
|
||||||
def sample(self):
|
def sample(self):
|
||||||
return OrderedDict([(k, space.sample()) for k, space in self.spaces.items()])
|
return OrderedDict([(k, space.sample()) for k, space in self.spaces.items()])
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import gym
|
import gym
|
||||||
|
from .space import Space
|
||||||
|
|
||||||
class Discrete(gym.Space):
|
|
||||||
|
class Discrete(Space):
|
||||||
"""
|
"""
|
||||||
{0,1,...,n-1}
|
{0,1,...,n-1}
|
||||||
|
|
||||||
@@ -10,10 +12,14 @@ class Discrete(gym.Space):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, n):
|
def __init__(self, n):
|
||||||
self.n = n
|
self.n = n
|
||||||
gym.Space.__init__(self, (), np.int64)
|
super().__init__((), np.int64)
|
||||||
|
self.np_random = np.random.RandomState()
|
||||||
|
|
||||||
|
def seed(self, seed):
|
||||||
|
self.np_random.seed(seed)
|
||||||
|
|
||||||
def sample(self):
|
def sample(self):
|
||||||
return gym.spaces.np_random.randint(self.n)
|
return self.np_random.randint(self.n)
|
||||||
|
|
||||||
def contains(self, x):
|
def contains(self, x):
|
||||||
if isinstance(x, int):
|
if isinstance(x, int):
|
||||||
|
@@ -1,13 +1,19 @@
|
|||||||
import gym
|
import gym
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from .space import Space
|
||||||
|
|
||||||
class MultiBinary(gym.Space):
|
|
||||||
|
class MultiBinary(Space):
|
||||||
def __init__(self, n):
|
def __init__(self, n):
|
||||||
self.n = n
|
self.n = n
|
||||||
gym.Space.__init__(self, (self.n,), np.int8)
|
super().__init__((self.n,), np.int8)
|
||||||
|
self.np_random = np.random.RandomState()
|
||||||
|
|
||||||
|
def seed(self, seed):
|
||||||
|
self.np_random.seed(seed)
|
||||||
|
|
||||||
def sample(self):
|
def sample(self):
|
||||||
return gym.spaces.np_random.randint(low=0, high=2, size=self.n).astype(self.dtype)
|
return self.np_random.randint(low=0, high=2, size=self.n).astype(self.dtype)
|
||||||
|
|
||||||
def contains(self, x):
|
def contains(self, x):
|
||||||
return ((x==0) | (x==1)).all()
|
return ((x==0) | (x==1)).all()
|
||||||
|
@@ -1,17 +1,24 @@
|
|||||||
import gym
|
import gym
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from .space import Space
|
||||||
|
|
||||||
class MultiDiscrete(gym.Space):
|
|
||||||
|
class MultiDiscrete(Space):
|
||||||
def __init__(self, nvec):
|
def __init__(self, nvec):
|
||||||
"""
|
"""
|
||||||
nvec: vector of counts of each categorical variable
|
nvec: vector of counts of each categorical variable
|
||||||
"""
|
"""
|
||||||
assert (np.array(nvec) > 0).all(), 'nvec (counts) have to be positive'
|
assert (np.array(nvec) > 0).all(), 'nvec (counts) have to be positive'
|
||||||
self.nvec = np.asarray(nvec, dtype=np.uint32)
|
self.nvec = np.asarray(nvec, dtype=np.uint32)
|
||||||
gym.Space.__init__(self, self.nvec.shape, np.uint32)
|
|
||||||
|
super().__init__(self.nvec.shape, np.uint32)
|
||||||
|
self.np_random = np.random.RandomState()
|
||||||
|
|
||||||
|
def seed(self, seed):
|
||||||
|
self.np_random.seed(seed)
|
||||||
|
|
||||||
def sample(self):
|
def sample(self):
|
||||||
return (gym.spaces.np_random.random_sample(self.nvec.shape) * self.nvec).astype(self.dtype)
|
return (self.np_random.random_sample(self.nvec.shape) * self.nvec).astype(self.dtype)
|
||||||
|
|
||||||
def contains(self, x):
|
def contains(self, x):
|
||||||
# if nvec is uint32 and space dtype is uint32, then 0 <= x < self.nvec guarantees that x
|
# if nvec is uint32 and space dtype is uint32, then 0 <= x < self.nvec guarantees that x
|
||||||
|
@@ -1,20 +0,0 @@
|
|||||||
import numpy
|
|
||||||
|
|
||||||
np_random = numpy.random.RandomState()
|
|
||||||
|
|
||||||
def seed(seed=None):
|
|
||||||
"""Seed the common numpy.random.RandomState used in spaces
|
|
||||||
|
|
||||||
CF
|
|
||||||
https://github.com/openai/gym/commit/58e6aa95e5af2c738557431f812abb81c505a7cf#commitcomment-17669277
|
|
||||||
for some details about why we seed the spaces separately from the
|
|
||||||
envs, but tl;dr is that it's pretty uncommon for them to be used
|
|
||||||
within an actual algorithm, and the code becomes simpler to just
|
|
||||||
use this common numpy.random.RandomState.
|
|
||||||
"""
|
|
||||||
np_random.seed(seed)
|
|
||||||
|
|
||||||
# This numpy.random.RandomState gets used in all spaces for their
|
|
||||||
# 'sample' method. It's not really expected that people will be using
|
|
||||||
# these in their algorithms.
|
|
||||||
seed(0)
|
|
42
gym/spaces/space.py
Normal file
42
gym/spaces/space.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
class Space(object):
|
||||||
|
"""Defines the observation and action spaces, so you can write generic
|
||||||
|
code that applies to any Env. For example, you can choose a random
|
||||||
|
action.
|
||||||
|
"""
|
||||||
|
def __init__(self, shape=None, dtype=None):
|
||||||
|
import numpy as np # takes about 300-400ms to import, so we load lazily
|
||||||
|
self.shape = None if shape is None else tuple(shape)
|
||||||
|
self.dtype = None if dtype is None else np.dtype(dtype)
|
||||||
|
|
||||||
|
def sample(self):
|
||||||
|
"""
|
||||||
|
Uniformly randomly sample a random element of this space
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def seed(self, seed):
|
||||||
|
"""Set the seed for this space's pseudo-random number generator. """
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def contains(self, x):
|
||||||
|
"""
|
||||||
|
Return boolean specifying if x is a valid
|
||||||
|
member of this space
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def __contains__(self, x):
|
||||||
|
return self.contains(x)
|
||||||
|
|
||||||
|
def to_jsonable(self, sample_n):
|
||||||
|
"""Convert a batch of samples from this space to a JSONable data type."""
|
||||||
|
# By default, assume identity is JSONable
|
||||||
|
return sample_n
|
||||||
|
|
||||||
|
def from_jsonable(self, sample_n):
|
||||||
|
"""Convert a JSONable data type to a batch of samples from this space."""
|
||||||
|
# By default, assume identity is JSONable
|
||||||
|
return sample_n
|
@@ -1,6 +1,8 @@
|
|||||||
import gym
|
import gym
|
||||||
|
from .space import Space
|
||||||
|
|
||||||
class Tuple(gym.Space):
|
|
||||||
|
class Tuple(Space):
|
||||||
"""
|
"""
|
||||||
A tuple (i.e., product) of simpler spaces
|
A tuple (i.e., product) of simpler spaces
|
||||||
|
|
||||||
@@ -9,7 +11,10 @@ class Tuple(gym.Space):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, spaces):
|
def __init__(self, spaces):
|
||||||
self.spaces = spaces
|
self.spaces = spaces
|
||||||
gym.Space.__init__(self, None, None)
|
super().__init__(None, None)
|
||||||
|
|
||||||
|
def seed(self, seed):
|
||||||
|
[space.seed(seed) for space in self.spaces]
|
||||||
|
|
||||||
def sample(self):
|
def sample(self):
|
||||||
return tuple([space.sample() for space in self.spaces])
|
return tuple([space.sample() for space in self.spaces])
|
||||||
|
Reference in New Issue
Block a user