Files
Gymnasium/tests/vector/test_sync_vector_env.py

202 lines
6.6 KiB
Python
Raw Normal View History

import numpy as np
import pytest
Fixed batch spaces where the original space's seed was ignored. Issue 2680 (#2727) * Add a case for the Box shape where the low and high values are both scalars * Add seeding.RandomNumberGenerator parameter to Dict seed. Modify __repr__ for the dictionary space string looks similar to an actual dictionary * Add seeding.RandomNumberGenerator parameter to Multi Binary seed * Add seeding.RandomNumberGenerator parameter to Multi Binary seed. Modify nvec typing to include np.ndarray * Space seed typing can be a seeding.RandomNumberGenerator. If a seeding.RNG is provided then it is assigned to _np_random and .seed is not run * Fixed the tuple seeding type as List[int] is not a valid Space seed type * Added typing to batch_space. The batch_space seed is equal to the space's seeding * Fixed the seeding type * Add test for batch space seeds are identical to the original space's seeding * Add equivalence function for RandomNumberGenerator comparing the bit_generator.state * The batch_space functions uses a copy of the seed for the original space * Set the action space seed for sync_vector_env seed testing * Add test for the seeding of the sync vector environment * Update the test_batch_space_seed to check the resulting sampling are equivalent for testing * Revert representation back to the original version * Remove additional Box shape initialisation * Remove additional typing of MultiDiscrete * Fixed bug of Space batch space where the original space's np_random is not a complete copy of the original space * Add CustomSpace to the batched space seed test * Modify the CustomSpace sample to produce a random number not a static value * Fix CustomSpace to reflect the sample function * Copy the space.np_random for the batched_space seed to ensure that the original space doesn't sampling doesn't effect the batched_space * Parameterized the batch_space_seed, added testing for rng_different_at_each_index and test_deterministic * Black and isort pre-commit changes * Pre-commit fix * MacOS, test_read_from_shared_memory throws an error that the inner _process_write function was unpicklable. Making the function a top-level function solves this error * Fixed typing of seed where a space's seed function differs from Space.seed's typing * Added check that the sample lengths are equal and explicitly provided the number of batched spaces n=1 * Removed relative imports for absolute imports * Use deepcopy instead of copy * Replaces `from numpy.testing._private.utils import assert_array_equal` with `from numpy.testing import assert_array_equal` * Using the seeding `__eq__` function, replace `np_random.bit_generator.state` with `np_random` * Added docstrings and comments to the tests to explain their purpose * Remove __eq__ from RandomNumberGenerator and add to tests/vector/utils * Add sync vector determinism test for issue #2680 * Fixed bug for https://github.com/openai/gym/pull/2727/files/462101d3846bc35ff3fad9f65979c693472a93a8#r850740825 * Made the new seeds a list of integers
2022-04-24 17:14:33 +01:00
from gym.envs.registration import EnvSpec
from gym.spaces import Box, Discrete, MultiDiscrete, Tuple
from gym.vector.sync_vector_env import SyncVectorEnv
Fixed batch spaces where the original space's seed was ignored. Issue 2680 (#2727) * Add a case for the Box shape where the low and high values are both scalars * Add seeding.RandomNumberGenerator parameter to Dict seed. Modify __repr__ for the dictionary space string looks similar to an actual dictionary * Add seeding.RandomNumberGenerator parameter to Multi Binary seed * Add seeding.RandomNumberGenerator parameter to Multi Binary seed. Modify nvec typing to include np.ndarray * Space seed typing can be a seeding.RandomNumberGenerator. If a seeding.RNG is provided then it is assigned to _np_random and .seed is not run * Fixed the tuple seeding type as List[int] is not a valid Space seed type * Added typing to batch_space. The batch_space seed is equal to the space's seeding * Fixed the seeding type * Add test for batch space seeds are identical to the original space's seeding * Add equivalence function for RandomNumberGenerator comparing the bit_generator.state * The batch_space functions uses a copy of the seed for the original space * Set the action space seed for sync_vector_env seed testing * Add test for the seeding of the sync vector environment * Update the test_batch_space_seed to check the resulting sampling are equivalent for testing * Revert representation back to the original version * Remove additional Box shape initialisation * Remove additional typing of MultiDiscrete * Fixed bug of Space batch space where the original space's np_random is not a complete copy of the original space * Add CustomSpace to the batched space seed test * Modify the CustomSpace sample to produce a random number not a static value * Fix CustomSpace to reflect the sample function * Copy the space.np_random for the batched_space seed to ensure that the original space doesn't sampling doesn't effect the batched_space * Parameterized the batch_space_seed, added testing for rng_different_at_each_index and test_deterministic * Black and isort pre-commit changes * Pre-commit fix * MacOS, test_read_from_shared_memory throws an error that the inner _process_write function was unpicklable. Making the function a top-level function solves this error * Fixed typing of seed where a space's seed function differs from Space.seed's typing * Added check that the sample lengths are equal and explicitly provided the number of batched spaces n=1 * Removed relative imports for absolute imports * Use deepcopy instead of copy * Replaces `from numpy.testing._private.utils import assert_array_equal` with `from numpy.testing import assert_array_equal` * Using the seeding `__eq__` function, replace `np_random.bit_generator.state` with `np_random` * Added docstrings and comments to the tests to explain their purpose * Remove __eq__ from RandomNumberGenerator and add to tests/vector/utils * Add sync vector determinism test for issue #2680 * Fixed bug for https://github.com/openai/gym/pull/2727/files/462101d3846bc35ff3fad9f65979c693472a93a8#r850740825 * Made the new seeds a list of integers
2022-04-24 17:14:33 +01:00
from tests.envs.spec_list import spec_list
from tests.vector.utils import (
CustomSpace,
assert_rng_equal,
make_custom_space_env,
make_env,
)
2021-07-29 02:26:34 +02:00
def test_create_sync_vector_env():
2022-01-10 23:42:26 -05:00
env_fns = [make_env("FrozenLake-v1", i) for i in range(8)]
try:
env = SyncVectorEnv(env_fns)
finally:
env.close()
assert env.num_envs == 8
def test_reset_sync_vector_env():
2022-01-10 23:42:26 -05:00
env_fns = [make_env("CartPole-v1", i) for i in range(8)]
try:
env = SyncVectorEnv(env_fns)
observations = env.reset()
finally:
env.close()
assert isinstance(env.observation_space, Box)
assert isinstance(observations, np.ndarray)
assert observations.dtype == env.observation_space.dtype
assert observations.shape == (8,) + env.single_observation_space.shape
assert observations.shape == env.observation_space.shape
del observations
try:
env = SyncVectorEnv(env_fns)
observations = env.reset(return_info=False)
finally:
env.close()
assert isinstance(env.observation_space, Box)
assert isinstance(observations, np.ndarray)
assert observations.dtype == env.observation_space.dtype
assert observations.shape == (8,) + env.single_observation_space.shape
assert observations.shape == env.observation_space.shape
del observations
env_fns = [make_env("CartPole-v1", i) for i in range(8)]
try:
env = SyncVectorEnv(env_fns)
observations, infos = env.reset(return_info=True)
finally:
env.close()
assert isinstance(env.observation_space, Box)
assert isinstance(observations, np.ndarray)
assert observations.dtype == env.observation_space.dtype
assert observations.shape == (8,) + env.single_observation_space.shape
assert observations.shape == env.observation_space.shape
New `info` API for vectorized environments #2657 (#2773) * WIP refactor info API sync vector. * Add missing untracked file. * Add info strategy to reset_wait. * Add interface and docstring. * info with strategy pattern on async vector env. * Add default to async vecenv. * episode statistics for asyncvecnev. * Add tests info strategy format. * Add info strategy to reset_wait. * refactor and cleanup. * Code cleanup. Add tests. * Add tests for video recording with new info format. * fix test case. * fix camelcase. * rename enum. * update tests, docstrings, cleanup. * Changes brax strategy to numpy. add_strategy method in StrategyFactory. Add tests. * fix docstring and logging format. * Set Brax info format as default. Remove classic info format. Update tests. * breaking the wrong loop. * WIP: wrapper. * Add wrapper for brax to classic info. * WIP: wrapper with nested RecordEpisodeStatistic. * Add tests. Refactor docstrings. Cleanup. * cleanup. * patch conflicts. * rebase and conflicts. * new pre-commit conventions. * docstring. * renaming. * incorporate info_processor in vecEnv. * renaming. Create info dict only if needed. * remove all brax references. update docstring. Update duplicate test. * reviews. * pre-commit. * reviews. * docstring. * cleanup blank lines. * add support for numpy dtypes. * docstring fix. * formatting. * naming. * assert correct info from wrappers chaining. Test correct wrappers chaining. naming. * simplify episode_statistics. * change args orer. * update tests. * wip: refactor episode_statistics. * Add test for add_vecore_episode_statistics.
2022-05-24 16:36:35 +02:00
assert isinstance(infos, dict)
assert all([isinstance(info, dict) for info in infos])
2021-07-29 02:26:34 +02:00
@pytest.mark.parametrize("use_single_action_space", [True, False])
def test_step_sync_vector_env(use_single_action_space):
2022-01-10 23:42:26 -05:00
env_fns = [make_env("FrozenLake-v1", i) for i in range(8)]
try:
env = SyncVectorEnv(env_fns)
observations = env.reset()
assert isinstance(env.single_action_space, Discrete)
assert isinstance(env.action_space, MultiDiscrete)
if use_single_action_space:
actions = [env.single_action_space.sample() for _ in range(8)]
else:
actions = env.action_space.sample()
observations, rewards, dones, _ = env.step(actions)
finally:
env.close()
2022-01-10 23:42:26 -05:00
assert isinstance(env.observation_space, MultiDiscrete)
assert isinstance(observations, np.ndarray)
assert observations.dtype == env.observation_space.dtype
assert observations.shape == (8,) + env.single_observation_space.shape
assert observations.shape == env.observation_space.shape
assert isinstance(rewards, np.ndarray)
assert isinstance(rewards[0], (float, np.floating))
assert rewards.ndim == 1
assert rewards.size == 8
assert isinstance(dones, np.ndarray)
assert dones.dtype == np.bool_
assert dones.ndim == 1
assert dones.size == 8
def test_call_sync_vector_env():
Render API (#2671) * add pygame GUI for frozen_lake.py env * add new line at EOF * pre-commit reformat * improve graphics * new images and dynamic window size * darker tile borders and fix ICC profile * pre-commit hook * adjust elf and stool size * Update frozen_lake.py * reformat * fix #2600 * #2600 * add rgb_array support * reformat * test render api change on FrozenLake * add render support for reset on frozenlake * add clock on pygame render * new render api for blackjack * new render api for cliffwalking * new render api for Env class * update reset method, lunar and Env * fix wrapper * fix reset lunar * new render api for box2d envs * new render api for mujoco envs * fix bug * new render api for classic control envs * fix tests * add render_mode None for CartPole * new render api for test fake envs * pre-commit hook * fix FrozenLake * fix FrozenLake * more render_mode to super - frozenlake * remove kwargs from frozen_lake new * pre-commit hook * add deprecated render method * add backwards compatibility * fix test * add _render * move pygame.init() (avoid pygame dependency on init) * fix pygame dependencies * remove collect_render() maintain multi-behaviours .render() * add type hints * fix renderer * don't call .render() with None * improve docstring * add single_rgb_array to all envs * remove None from metadata["render_modes"] * add type hints to test_env_checkers * fix lint * add comments to renderer * add comments to single_depth_array and single_state_pixels * reformat * add deprecation warnings and env.render_mode declaration * fix lint * reformat * fix tests * add docs * fix car racing determinism * remove warning test envs, customizable modes on renderer * remove commments and add todo for env_checker * fix car racing * replace render mode check with assert * update new mujoco * reformat * reformat * change metaclass definition * fix tests * implement mark suggestions (test, docs, sets) * check_render Co-authored-by: J K Terry <jkterry0@gmail.com>
2022-06-08 00:20:56 +02:00
env_fns = [make_env("CartPole-v1", i, render_mode="rgb_array") for i in range(4)]
try:
env = SyncVectorEnv(env_fns)
_ = env.reset()
Render API (#2671) * add pygame GUI for frozen_lake.py env * add new line at EOF * pre-commit reformat * improve graphics * new images and dynamic window size * darker tile borders and fix ICC profile * pre-commit hook * adjust elf and stool size * Update frozen_lake.py * reformat * fix #2600 * #2600 * add rgb_array support * reformat * test render api change on FrozenLake * add render support for reset on frozenlake * add clock on pygame render * new render api for blackjack * new render api for cliffwalking * new render api for Env class * update reset method, lunar and Env * fix wrapper * fix reset lunar * new render api for box2d envs * new render api for mujoco envs * fix bug * new render api for classic control envs * fix tests * add render_mode None for CartPole * new render api for test fake envs * pre-commit hook * fix FrozenLake * fix FrozenLake * more render_mode to super - frozenlake * remove kwargs from frozen_lake new * pre-commit hook * add deprecated render method * add backwards compatibility * fix test * add _render * move pygame.init() (avoid pygame dependency on init) * fix pygame dependencies * remove collect_render() maintain multi-behaviours .render() * add type hints * fix renderer * don't call .render() with None * improve docstring * add single_rgb_array to all envs * remove None from metadata["render_modes"] * add type hints to test_env_checkers * fix lint * add comments to renderer * add comments to single_depth_array and single_state_pixels * reformat * add deprecation warnings and env.render_mode declaration * fix lint * reformat * fix tests * add docs * fix car racing determinism * remove warning test envs, customizable modes on renderer * remove commments and add todo for env_checker * fix car racing * replace render mode check with assert * update new mujoco * reformat * reformat * change metaclass definition * fix tests * implement mark suggestions (test, docs, sets) * check_render Co-authored-by: J K Terry <jkterry0@gmail.com>
2022-06-08 00:20:56 +02:00
images = env.call("render")
gravity = env.call("gravity")
finally:
env.close()
assert isinstance(images, tuple)
assert len(images) == 4
for i in range(4):
Render API (#2671) * add pygame GUI for frozen_lake.py env * add new line at EOF * pre-commit reformat * improve graphics * new images and dynamic window size * darker tile borders and fix ICC profile * pre-commit hook * adjust elf and stool size * Update frozen_lake.py * reformat * fix #2600 * #2600 * add rgb_array support * reformat * test render api change on FrozenLake * add render support for reset on frozenlake * add clock on pygame render * new render api for blackjack * new render api for cliffwalking * new render api for Env class * update reset method, lunar and Env * fix wrapper * fix reset lunar * new render api for box2d envs * new render api for mujoco envs * fix bug * new render api for classic control envs * fix tests * add render_mode None for CartPole * new render api for test fake envs * pre-commit hook * fix FrozenLake * fix FrozenLake * more render_mode to super - frozenlake * remove kwargs from frozen_lake new * pre-commit hook * add deprecated render method * add backwards compatibility * fix test * add _render * move pygame.init() (avoid pygame dependency on init) * fix pygame dependencies * remove collect_render() maintain multi-behaviours .render() * add type hints * fix renderer * don't call .render() with None * improve docstring * add single_rgb_array to all envs * remove None from metadata["render_modes"] * add type hints to test_env_checkers * fix lint * add comments to renderer * add comments to single_depth_array and single_state_pixels * reformat * add deprecation warnings and env.render_mode declaration * fix lint * reformat * fix tests * add docs * fix car racing determinism * remove warning test envs, customizable modes on renderer * remove commments and add todo for env_checker * fix car racing * replace render mode check with assert * update new mujoco * reformat * reformat * change metaclass definition * fix tests * implement mark suggestions (test, docs, sets) * check_render Co-authored-by: J K Terry <jkterry0@gmail.com>
2022-06-08 00:20:56 +02:00
assert len(images[i]) == 1
assert isinstance(images[i][0], np.ndarray)
assert isinstance(gravity, tuple)
assert len(gravity) == 4
for i in range(4):
assert isinstance(gravity[i], float)
assert gravity[i] == 9.8
def test_set_attr_sync_vector_env():
env_fns = [make_env("CartPole-v1", i) for i in range(4)]
try:
env = SyncVectorEnv(env_fns)
env.set_attr("gravity", [9.81, 3.72, 8.87, 1.62])
gravity = env.get_attr("gravity")
assert gravity == (9.81, 3.72, 8.87, 1.62)
finally:
env.close()
def test_check_spaces_sync_vector_env():
2022-01-10 23:42:26 -05:00
# CartPole-v1 - observation_space: Box(4,), action_space: Discrete(2)
env_fns = [make_env("CartPole-v1", i) for i in range(8)]
# FrozenLake-v1 - Discrete(16), action_space: Discrete(4)
env_fns[1] = make_env("FrozenLake-v1", 1)
with pytest.raises(RuntimeError):
env = SyncVectorEnv(env_fns)
env.close()
def test_custom_space_sync_vector_env():
env_fns = [make_custom_space_env(i) for i in range(4)]
try:
env = SyncVectorEnv(env_fns)
reset_observations = env.reset()
assert isinstance(env.single_action_space, CustomSpace)
assert isinstance(env.action_space, Tuple)
2021-07-29 02:26:34 +02:00
actions = ("action-2", "action-3", "action-5", "action-7")
step_observations, rewards, dones, _ = env.step(actions)
finally:
env.close()
assert isinstance(env.single_observation_space, CustomSpace)
assert isinstance(env.observation_space, Tuple)
assert isinstance(reset_observations, tuple)
2021-07-29 02:26:34 +02:00
assert reset_observations == ("reset", "reset", "reset", "reset")
assert isinstance(step_observations, tuple)
2021-07-29 02:26:34 +02:00
assert step_observations == (
"step(action-2)",
"step(action-3)",
"step(action-5)",
"step(action-7)",
)
Fixed batch spaces where the original space's seed was ignored. Issue 2680 (#2727) * Add a case for the Box shape where the low and high values are both scalars * Add seeding.RandomNumberGenerator parameter to Dict seed. Modify __repr__ for the dictionary space string looks similar to an actual dictionary * Add seeding.RandomNumberGenerator parameter to Multi Binary seed * Add seeding.RandomNumberGenerator parameter to Multi Binary seed. Modify nvec typing to include np.ndarray * Space seed typing can be a seeding.RandomNumberGenerator. If a seeding.RNG is provided then it is assigned to _np_random and .seed is not run * Fixed the tuple seeding type as List[int] is not a valid Space seed type * Added typing to batch_space. The batch_space seed is equal to the space's seeding * Fixed the seeding type * Add test for batch space seeds are identical to the original space's seeding * Add equivalence function for RandomNumberGenerator comparing the bit_generator.state * The batch_space functions uses a copy of the seed for the original space * Set the action space seed for sync_vector_env seed testing * Add test for the seeding of the sync vector environment * Update the test_batch_space_seed to check the resulting sampling are equivalent for testing * Revert representation back to the original version * Remove additional Box shape initialisation * Remove additional typing of MultiDiscrete * Fixed bug of Space batch space where the original space's np_random is not a complete copy of the original space * Add CustomSpace to the batched space seed test * Modify the CustomSpace sample to produce a random number not a static value * Fix CustomSpace to reflect the sample function * Copy the space.np_random for the batched_space seed to ensure that the original space doesn't sampling doesn't effect the batched_space * Parameterized the batch_space_seed, added testing for rng_different_at_each_index and test_deterministic * Black and isort pre-commit changes * Pre-commit fix * MacOS, test_read_from_shared_memory throws an error that the inner _process_write function was unpicklable. Making the function a top-level function solves this error * Fixed typing of seed where a space's seed function differs from Space.seed's typing * Added check that the sample lengths are equal and explicitly provided the number of batched spaces n=1 * Removed relative imports for absolute imports * Use deepcopy instead of copy * Replaces `from numpy.testing._private.utils import assert_array_equal` with `from numpy.testing import assert_array_equal` * Using the seeding `__eq__` function, replace `np_random.bit_generator.state` with `np_random` * Added docstrings and comments to the tests to explain their purpose * Remove __eq__ from RandomNumberGenerator and add to tests/vector/utils * Add sync vector determinism test for issue #2680 * Fixed bug for https://github.com/openai/gym/pull/2727/files/462101d3846bc35ff3fad9f65979c693472a93a8#r850740825 * Made the new seeds a list of integers
2022-04-24 17:14:33 +01:00
def test_sync_vector_env_seed():
env = make_env("BipedalWalker-v3", seed=123)()
sync_vector_env = SyncVectorEnv([make_env("BipedalWalker-v3", seed=123)])
assert_rng_equal(env.action_space.np_random, sync_vector_env.action_space.np_random)
for _ in range(100):
env_action = env.action_space.sample()
vector_action = sync_vector_env.action_space.sample()
assert np.all(env_action == vector_action)
@pytest.mark.parametrize("spec", spec_list, ids=[spec.id for spec in spec_list])
def test_sync_vector_determinism(spec: EnvSpec, seed: int = 123, n: int = 3):
"""Check that for all environments, the sync vector envs produce the same action samples using the same seeds"""
env_1 = SyncVectorEnv([make_env(spec.id, seed=seed) for _ in range(n)])
env_2 = SyncVectorEnv([make_env(spec.id, seed=seed) for _ in range(n)])
assert_rng_equal(env_1.action_space.np_random, env_2.action_space.np_random)
for _ in range(100):
env_1_samples = env_1.action_space.sample()
env_2_samples = env_2.action_space.sample()
assert np.all(env_1_samples == env_2_samples)