Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
34cb9c9
Delete prng.py
zuoxingdong Oct 12, 2018
6d9fbc7
Update __init__.py
zuoxingdong Oct 12, 2018
6cb417f
Update kellycoinflip.py
zuoxingdong Oct 12, 2018
3031da6
Update core.py
zuoxingdong Oct 25, 2018
17dfe18
Update box.py
zuoxingdong Oct 25, 2018
a034342
Update discrete.py
zuoxingdong Oct 25, 2018
efc75a7
Update multi_binary.py
zuoxingdong Oct 25, 2018
523938f
Update multi_discrete.py
zuoxingdong Oct 25, 2018
f9a53e7
Update test_determinism.py
zuoxingdong Oct 25, 2018
23eb4c7
Update test_determinism.py
zuoxingdong Oct 25, 2018
e78c4ef
Update test_determinism.py
zuoxingdong Oct 25, 2018
bbfb0e3
Merge pull request #1 from openai/master
zuoxingdong Oct 25, 2018
82ac203
Merge pull request #2 from zuoxingdong/patch-5
zuoxingdong Oct 25, 2018
9bd07e6
Merge pull request #3 from zuoxingdong/master
zuoxingdong Oct 25, 2018
b2b0917
Update core.py
zuoxingdong Oct 27, 2018
c148d6a
Update box.py
zuoxingdong Nov 21, 2018
8e868f4
Update test_determinism.py
zuoxingdong Nov 21, 2018
c6741ad
Update core.py
zuoxingdong Nov 21, 2018
39ea1d3
Update box.py
zuoxingdong Nov 21, 2018
e97fcff
Update discrete.py
zuoxingdong Nov 21, 2018
fa7c088
Update multi_binary.py
zuoxingdong Nov 21, 2018
675d866
Update multi_discrete.py
zuoxingdong Nov 21, 2018
847c2c9
Update dict_space.py
zuoxingdong Nov 21, 2018
c57e8d9
Update tuple_space.py
zuoxingdong Nov 21, 2018
2c6f850
Update core.py
zuoxingdong Nov 21, 2018
6018ec7
Create space.py
zuoxingdong Nov 21, 2018
0fbd18c
Update __init__.py
zuoxingdong Nov 21, 2018
9432464
Update __init__.py
zuoxingdong Nov 21, 2018
f172fa7
Merge branch 'master' into patch-5
zuoxingdong Nov 21, 2018
e0242f7
Update box.py
zuoxingdong Nov 21, 2018
981687d
Update dict_space.py
zuoxingdong Nov 21, 2018
4f33c58
Update discrete.py
zuoxingdong Nov 21, 2018
4e117c9
Update dict_space.py
zuoxingdong Nov 21, 2018
cbe4849
Update multi_binary.py
zuoxingdong Nov 21, 2018
3d54341
Update multi_discrete.py
zuoxingdong Nov 21, 2018
2c3c5b1
Update tuple_space.py
zuoxingdong Nov 21, 2018
d5d1990
Update discrete.py
zuoxingdong Nov 21, 2018
7401d27
Update box.py
zuoxingdong Nov 21, 2018
590e019
Update dict_space.py
zuoxingdong Nov 21, 2018
ee34af8
Update multi_binary.py
zuoxingdong Nov 21, 2018
d529e3b
Update multi_discrete.py
zuoxingdong Nov 21, 2018
556711c
Update tuple_space.py
zuoxingdong Nov 21, 2018
f54ccbd
Update multi_discrete.py
zuoxingdong Nov 21, 2018
62ae3af
Update multi_binary.py
zuoxingdong Nov 21, 2018
52525e8
Update dict_space.py
zuoxingdong Nov 21, 2018
43ebedd
Update box.py
zuoxingdong Nov 21, 2018
c42c281
Update test_determinism.py
zuoxingdong Nov 22, 2018
969d6fb
Update kellycoinflip.py
zuoxingdong Nov 22, 2018
59ccca2
Merge branch 'master' into patch-5
zuoxingdong Jan 29, 2019
cb298ba
Update space.py
zuoxingdong Jan 30, 2019
f77b82f
Merge branch 'master' into patch-5
zuoxingdong Jan 30, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 0 additions & 39 deletions gym/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,45 +190,6 @@ def compute_reward(self, achieved_goal, desired_goal, info):
"""
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

def deprecated_warn_once(text):
Expand Down
10 changes: 4 additions & 6 deletions gym/envs/tests/test_determinism.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
import numpy as np
import pytest
from gym import spaces

from gym.envs.tests.spec_list import spec_list


@pytest.mark.parametrize("spec", spec_list)
def test_env(spec):

# Note that this precludes running this test in multiple
# threads. However, we probably already can't do multithreading
# due to some environments.
spaces.seed(0)

env1 = spec.make()
env1.seed(0)
env1.action_space.seed(0)
action_samples1 = [env1.action_space.sample() for i in range(4)]
initial_observation1 = env1.reset()
step_responses1 = [env1.step(action) for action in action_samples1]
env1.close()

spaces.seed(0)

env2 = spec.make()
env2.seed(0)
env2.action_space.seed(0)
action_samples2 = [env2.action_space.sample() for i in range(4)]
initial_observation2 = env2.reset()
step_responses2 = [env2.step(action) for action in action_samples2]
Expand Down
10 changes: 5 additions & 5 deletions gym/envs/toy_text/kellycoinflip.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import gym
from gym import spaces
from gym.utils import seeding
from gym.spaces import prng


def flip(edge, np_random):
Expand Down Expand Up @@ -81,10 +80,12 @@ def __init__(self, initialWealth=25.0, edgePriorAlpha=7, edgePriorBeta=3, maxWea
self.maxRoundsMean=maxRoundsMean
self.maxRoundsSD=maxRoundsSD

if reseed or not hasattr(self, 'np_random') : self.seed()

# draw this game's set of parameters:
edge = prng.np_random.beta(edgePriorAlpha, edgePriorBeta)
maxWealth = round(genpareto.rvs(maxWealthAlpha, maxWealthM, random_state=prng.np_random))
maxRounds = int(round(prng.np_random.normal(maxRoundsMean, maxRoundsSD)))
edge = self.np_random.beta(edgePriorAlpha, edgePriorBeta)
maxWealth = round(genpareto.rvs(maxWealthAlpha, maxWealthM, random_state=self.np_random))
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;
# alpha doesn't update, but x_m does, and simply is the highest wealth count we've seen to date:
Expand All @@ -109,7 +110,6 @@ def __init__(self, initialWealth=25.0, edgePriorAlpha=7, edgePriorBeta=3, maxWea
self.maxRounds = maxRounds
self.rounds = self.maxRounds
self.maxWealth = maxWealth
if reseed or not hasattr(self, 'np_random') : self.seed()

def seed(self, seed=None):
self.np_random, seed = seeding.np_random(seed)
Expand Down
4 changes: 2 additions & 2 deletions gym/spaces/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from gym.spaces.space import Space
from gym.spaces.box import Box
from gym.spaces.discrete import Discrete
from gym.spaces.multi_discrete import MultiDiscrete
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.dict_space import Dict

__all__ = ["Box", "Discrete", "MultiDiscrete", "MultiBinary", "Tuple", "Dict"]
__all__ = ["Space", "Box", "Discrete", "MultiDiscrete", "MultiBinary", "Tuple", "Dict"]
12 changes: 9 additions & 3 deletions gym/spaces/box.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import gym
from gym import logger
from .space import Space

class Box(gym.Space):

class Box(Space):
"""
A box in R^n.
I.e., each coordinate is bounded.
Expand Down Expand Up @@ -32,10 +34,14 @@ def __init__(self, low=None, high=None, shape=None, dtype=None):
logger.warn("gym.spaces.Box autodetected dtype as {}. Please provide explicit dtype.".format(dtype))
self.low = low.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):
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):
return x.shape == self.shape and (x >= self.low).all() and (x <= self.high).all()
Expand Down
9 changes: 7 additions & 2 deletions gym/spaces/dict_space.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import gym
from collections import OrderedDict
from .space import Space

class Dict(gym.Space):

class Dict(Space):
"""
A dictionary of simpler spaces.

Expand Down Expand Up @@ -39,7 +41,10 @@ def __init__(self, spaces=None, **spaces_kwargs):
if isinstance(spaces, list):
spaces = OrderedDict(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):
return OrderedDict([(k, space.sample()) for k, space in self.spaces.items()])
Expand Down
12 changes: 9 additions & 3 deletions gym/spaces/discrete.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import numpy as np
import gym
from .space import Space

class Discrete(gym.Space):

class Discrete(Space):
"""
{0,1,...,n-1}

Expand All @@ -10,10 +12,14 @@ class Discrete(gym.Space):
"""
def __init__(self, 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):
return gym.spaces.np_random.randint(self.n)
return self.np_random.randint(self.n)

def contains(self, x):
if isinstance(x, int):
Expand Down
12 changes: 9 additions & 3 deletions gym/spaces/multi_binary.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import gym
import numpy as np
from .space import Space

class MultiBinary(gym.Space):

class MultiBinary(Space):
def __init__(self, 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):
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):
return ((x==0) | (x==1)).all()
Expand Down
13 changes: 10 additions & 3 deletions gym/spaces/multi_discrete.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import gym
import numpy as np
from .space import Space

class MultiDiscrete(gym.Space):

class MultiDiscrete(Space):
def __init__(self, nvec):
"""
nvec: vector of counts of each categorical variable
"""
assert (np.array(nvec) > 0).all(), 'nvec (counts) have to be positive'
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):
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):
# if nvec is uint32 and space dtype is uint32, then 0 <= x < self.nvec guarantees that x
Expand Down
20 changes: 0 additions & 20 deletions gym/spaces/prng.py

This file was deleted.

42 changes: 42 additions & 0 deletions gym/spaces/space.py
Original file line number Diff line number Diff line change
@@ -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
9 changes: 7 additions & 2 deletions gym/spaces/tuple_space.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import gym
from .space import Space

class Tuple(gym.Space):

class Tuple(Space):
"""
A tuple (i.e., product) of simpler spaces

Expand All @@ -9,7 +11,10 @@ class Tuple(gym.Space):
"""
def __init__(self, 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):
return tuple([space.sample() for space in self.spaces])
Expand Down