Skip to content

Commit 8e01464

Browse files
committed
trying to fix the issue after gymnasium upgrade [skip ci]
1 parent 945ebc7 commit 8e01464

File tree

3 files changed

+119
-8
lines changed

3 files changed

+119
-8
lines changed

grid2op/Chronics/multiFolder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ def sample_next_chronics(self, probabilities=None):
357357
id_sel = (self._order == selected).nonzero()[0]
358358
self._prev_cache_id = selected - 1
359359
return id_sel
360-
360+
361361
def reset(self):
362362
"""
363363
Rebuilt the :attr:`Multifolder._order`. This should be called after a call to :func:`Multifolder.set_filter`

grid2op/gym_compat/gymenv.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,17 @@ def _aux_reset(self,
181181
def _aux_reset_new(self,
182182
seed: Optional[int]=None,
183183
options: RESET_OPTIONS_TYPING=None) -> Tuple[ObsType,RESET_INFO_GYM_TYPING]:
184-
# used for gym > 0.26
185-
if (self._shuffle_chronics and
186-
isinstance(self.init_env.chronics_handler.real_data, Multifolder) and
187-
(options is not None and _TIME_SERIE_ID not in options)):
188-
self.init_env.chronics_handler.sample_next_chronics()
189184

190185
super().reset(seed=seed) # seed gymnasium env
191186
if seed is not None:
192187
self._aux_seed_spaces()
193188
seed, next_seed, underlying_env_seeds = self._aux_seed_g2op(seed)
189+
190+
# used for gym > 0.26
191+
if (self._shuffle_chronics and
192+
isinstance(self.init_env.chronics_handler.real_data, Multifolder) and
193+
(not (options is not None and _TIME_SERIE_ID in options))):
194+
self.init_env.chronics_handler.sample_next_chronics()
194195

195196
# we don't seed grid2op with reset as it is done
196197
# earlier

grid2op/tests/test_issue_379.py

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
# SPDX-License-Identifier: MPL-2.0
77
# This file is part of Grid2Op, Grid2Op a testbed platform to model sequential decision making in power systems.
88

9-
import grid2op
109
import unittest
1110
import warnings
1211

@@ -17,7 +16,118 @@
1716
CAN_TEST_ALL = True
1817
if GYMNASIUM_AVAILABLE:
1918
from gymnasium.utils.env_checker import check_env
20-
from gymnasium.utils.env_checker import check_reset_return_type, check_reset_options, check_reset_seed
19+
from gymnasium.utils.env_checker import check_reset_return_type, check_reset_options
20+
try:
21+
from gymnasium.utils.env_checker import check_reset_seed
22+
except ImportError:
23+
# not present in most recent version of gymnasium, I copy pasted
24+
# it from an oldest version
25+
import gymnasium
26+
from logging import getLogger
27+
import inspect
28+
from copy import deepcopy
29+
import numpy as np
30+
logger = getLogger()
31+
32+
33+
def data_equivalence(data_1, data_2) -> bool:
34+
"""Assert equality between data 1 and 2, i.e observations, actions, info.
35+
36+
Args:
37+
data_1: data structure 1
38+
data_2: data structure 2
39+
40+
Returns:
41+
If observation 1 and 2 are equivalent
42+
"""
43+
if type(data_1) == type(data_2):
44+
if isinstance(data_1, dict):
45+
return data_1.keys() == data_2.keys() and all(
46+
data_equivalence(data_1[k], data_2[k]) for k in data_1.keys()
47+
)
48+
elif isinstance(data_1, (tuple, list)):
49+
return len(data_1) == len(data_2) and all(
50+
data_equivalence(o_1, o_2) for o_1, o_2 in zip(data_1, data_2)
51+
)
52+
elif isinstance(data_1, np.ndarray):
53+
return data_1.shape == data_2.shape and np.allclose(
54+
data_1, data_2, atol=0.00001
55+
)
56+
else:
57+
return data_1 == data_2
58+
else:
59+
return False
60+
61+
62+
def check_reset_seed(env: gymnasium.Env):
63+
"""Check that the environment can be reset with a seed.
64+
65+
Args:
66+
env: The environment to check
67+
68+
Raises:
69+
AssertionError: The environment cannot be reset with a random seed,
70+
even though `seed` or `kwargs` appear in the signature.
71+
"""
72+
signature = inspect.signature(env.reset)
73+
if "seed" in signature.parameters or (
74+
"kwargs" in signature.parameters
75+
and signature.parameters["kwargs"].kind is inspect.Parameter.VAR_KEYWORD
76+
):
77+
try:
78+
obs_1, info = env.reset(seed=123)
79+
assert (
80+
obs_1 in env.observation_space
81+
), "The observation returned by `env.reset(seed=123)` is not within the observation space."
82+
assert (
83+
env.unwrapped._np_random # pyright: ignore [reportPrivateUsage]
84+
is not None
85+
), "Expects the random number generator to have been generated given a seed was passed to reset. Mostly likely the environment reset function does not call `super().reset(seed=seed)`."
86+
seed_123_rng = deepcopy(
87+
env.unwrapped._np_random # pyright: ignore [reportPrivateUsage]
88+
)
89+
90+
obs_2, info = env.reset(seed=123)
91+
assert (
92+
obs_2 in env.observation_space
93+
), "The observation returned by `env.reset(seed=123)` is not within the observation space."
94+
if env.spec is not None and env.spec.nondeterministic is False:
95+
assert data_equivalence(
96+
obs_1, obs_2
97+
), "Using `env.reset(seed=123)` is non-deterministic as the observations are not equivalent."
98+
assert (
99+
env.unwrapped._np_random.bit_generator.state # pyright: ignore [reportPrivateUsage]
100+
== seed_123_rng.bit_generator.state
101+
), "Mostly likely the environment reset function does not call `super().reset(seed=seed)` as the random generates are not same when the same seeds are passed to `env.reset`."
102+
103+
obs_3, info = env.reset(seed=456)
104+
assert (
105+
obs_3 in env.observation_space
106+
), "The observation returned by `env.reset(seed=456)` is not within the observation space."
107+
assert (
108+
env.unwrapped._np_random.bit_generator.state # pyright: ignore [reportPrivateUsage]
109+
!= seed_123_rng.bit_generator.state
110+
), "Mostly likely the environment reset function does not call `super().reset(seed=seed)` as the random number generators are not different when different seeds are passed to `env.reset`."
111+
112+
except TypeError as e:
113+
raise AssertionError(
114+
"The environment cannot be reset with a random seed, even though `seed` or `kwargs` appear in the signature. "
115+
f"This should never happen, please report this issue. The error was: {e}"
116+
) from e
117+
118+
seed_param = signature.parameters.get("seed")
119+
# Check the default value is None
120+
if seed_param is not None and seed_param.default is not None:
121+
logger.warning(
122+
"The default seed argument in reset should be `None`, otherwise the environment will by default always be deterministic. "
123+
f"Actual default: {seed_param.default}"
124+
)
125+
else:
126+
raise gymnasium.error.Error(
127+
"The `reset` method does not provide a `seed` or `**kwargs` keyword argument."
128+
)
129+
130+
21131
elif GYM_AVAILABLE:
22132
from gym.utils.env_checker import check_env
23133
from gym.utils.env_checker import check_reset_return_type, check_reset_options, check_reset_seed

0 commit comments

Comments
 (0)