diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5ac5d96bc..c59a18639 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -24,7 +24,8 @@ Change Log - [FIXED] `Issue #133 `_: Missing positional argument `space_prng` in `Action.SerializableActionSpace` - [FIXED] `Issue #131 `_: Forecast values are accessible without needing to call `obs.simulate` beforehand. - [FIXED] `Issue #134 `_: Backend iadd actions with lines extremities disconnections (set -1) -- [FIXED] issue `Issue 122 `_ +- [FIXED] issue `Issue #125 `_ +- [FIXED] issue `Issue #126 `_ Loading runner logs no longer checks environment actions ambiguity [1.1.1] - 2020-07-07 --------------------- diff --git a/grid2op/Action/_BackendAction.py b/grid2op/Action/_BackendAction.py index 13cb48f84..b505ea708 100644 --- a/grid2op/Action/_BackendAction.py +++ b/grid2op/Action/_BackendAction.py @@ -220,6 +220,9 @@ def all_changed(self): # self.shunt_q.all_changed() # self.shunt_bus.all_changed() + def set_redispatch(self, new_redispatching): + self.prod_p.change_val(new_redispatching) + def __iadd__(self, other): """ other: a grid2op action standard diff --git a/grid2op/Environment/BaseEnv.py b/grid2op/Environment/BaseEnv.py index 3c66b1ff1..118a782e3 100644 --- a/grid2op/Environment/BaseEnv.py +++ b/grid2op/Environment/BaseEnv.py @@ -902,12 +902,8 @@ def step(self, action): self._backend_action += action action._redispatch[:] = init_disp - self.env_modification._redispatch[:] = self.actual_dispatch self._backend_action += self.env_modification - - # action, for redispatching is composed of multiple actions, so basically i won't check - # ramp_min and ramp_max - self.env_modification._single_act = False + self._backend_action.set_redispatch(self.actual_dispatch) # now get the new generator voltage setpoint voltage_control_act = self._voltage_control(action, prod_v_chronics) diff --git a/grid2op/Episode/EpisodeData.py b/grid2op/Episode/EpisodeData.py index 34f2984fd..272e6244f 100644 --- a/grid2op/Episode/EpisodeData.py +++ b/grid2op/Episode/EpisodeData.py @@ -110,7 +110,8 @@ def __init__(self, "observations") self.env_actions = CollectionWrapper(env_actions, helper_action_env, - "env_actions") + "env_actions", + check_legit=False) # gives a unique game over for everyone # TODO this needs testing! action_go = self.actions._game_over @@ -218,7 +219,7 @@ def __len__(self): def from_disk(cls, agent_path, name=str(1)): if agent_path is None: - raise Grid2OpException("A path to an episode should be provided, please call \"from_disck\" with " + raise Grid2OpException("A path to an episode should be provided, please call \"from_disk\" with " "\"agent_path other\" than None") episode_path = os.path.abspath(os.path.join(agent_path, name)) @@ -269,7 +270,7 @@ def from_disk(cls, agent_path, name=str(1)): observation_space=observation_space, action_space=action_space, helper_action_env=helper_action_env, - path_save=agent_path, + path_save=None, # No save when reading attack=attack, attack_space=attack_space, name=name, @@ -457,7 +458,7 @@ class CollectionWrapper: """ - def __init__(self, collection, helper, collection_name): + def __init__(self, collection, helper, collection_name, check_legit=True): self.collection = collection if not hasattr(helper, "from_vect"): raise Grid2OpException(f"Object {helper} must implement a " @@ -470,8 +471,9 @@ def __init__(self, collection, helper, collection_name): self.objects = [] for i, elem in enumerate(self.collection): try: - self.objects.append( - self.helper.from_vect(self.collection[i, :])) + collection_obj = self.helper.from_vect(self.collection[i, :], + check_legit=check_legit) + self.objects.append(collection_obj) except AmbiguousAction: self._game_over = i break diff --git a/grid2op/Observation/CompleteObservation.py b/grid2op/Observation/CompleteObservation.py index 2b2d5501f..f5ed1b150 100644 --- a/grid2op/Observation/CompleteObservation.py +++ b/grid2op/Observation/CompleteObservation.py @@ -179,7 +179,7 @@ def update(self, env, with_forecast=True): self.target_dispatch[:] = env.target_dispatch self.actual_dispatch[:] = env.actual_dispatch - def from_vect(self, vect): + def from_vect(self, vect, check_legit=True): """ Convert back an observation represented as a vector into a proper observation. @@ -196,7 +196,7 @@ def from_vect(self, vect): # reset the matrices self._reset_matrices() # and ensure everything is reloaded properly - super().from_vect(vect) + super().from_vect(vect, check_legit=check_legit) def to_dict(self): """ diff --git a/grid2op/Space/GridObjects.py b/grid2op/Space/GridObjects.py index 1105d955f..06106f4f1 100644 --- a/grid2op/Space/GridObjects.py +++ b/grid2op/Space/GridObjects.py @@ -564,7 +564,7 @@ def _assign_attr_from_name(self, attr_nm, vect): def check_space_legit(self): pass - def from_vect(self, vect): + def from_vect(self, vect, check_legit=True): """ Convert a GridObjects, represented as a vector, into an GridObjects object. @@ -602,7 +602,9 @@ def from_vect(self, vect): tmp = vect[prev_:(prev_ + sh)].astype(dt) self._assign_attr_from_name(attr_nm, tmp) prev_ += sh - self.check_space_legit() + + if check_legit: + self.check_space_legit() def size(self): """ diff --git a/grid2op/Space/SerializableSpace.py b/grid2op/Space/SerializableSpace.py index 30816d8f1..5745be40a 100644 --- a/grid2op/Space/SerializableSpace.py +++ b/grid2op/Space/SerializableSpace.py @@ -192,7 +192,7 @@ def size(self): """ return self.n - def from_vect(self, obj_as_vect): + def from_vect(self, obj_as_vect, check_legit=True): """ Convert an action, represented as a vector to a valid :class:`BaseAction` instance @@ -210,7 +210,7 @@ def from_vect(self, obj_as_vect): """ res = copy.deepcopy(self._template_obj) - res.from_vect(obj_as_vect) + res.from_vect(obj_as_vect, check_legit=check_legit) return res def extract_from_vect(self, obj_as_vect, attr_name): diff --git a/grid2op/tests/issue_126.py b/grid2op/tests/issue_126.py new file mode 100644 index 000000000..ce4487e77 --- /dev/null +++ b/grid2op/tests/issue_126.py @@ -0,0 +1,45 @@ +import unittest +import warnings +import grid2op +from grid2op.Agent import DeltaRedispatchRandomAgent +from grid2op.Runner import Runner +from grid2op import make +from grid2op.Episode import EpisodeData +import os +import numpy as np +import tempfile + +class Issue126Tester(unittest.TestCase): + + def test_issue_126(self): + with tempfile.TemporaryDirectory() as tmpdirname: + #run redispatch agent on one scenario for 100 timesteps + dataset = "rte_case14_realistic" + nb_episode=1 + nb_timesteps=100 + + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + env = make(dataset) + agent = DeltaRedispatchRandomAgent(env.action_space) + runner = Runner(**env.get_params_for_runner(), + agentClass=None, + agentInstance=agent) + nb_episode=1 + res = runner.run(nb_episode=nb_episode, + path_save=tmpdirname, + nb_process=1, + max_iter=nb_timesteps, + env_seeds=[0], + agent_seeds=[0], + pbar=False) + + episode_data = EpisodeData.from_disk(tmpdirname, '000') + + assert len(episode_data.actions.objects) == nb_timesteps + assert len(episode_data.observations.objects) == (nb_timesteps + 1) + assert len(episode_data.actions) == nb_timesteps + assert len(episode_data.observations) == (nb_timesteps + 1) + +if __name__ == "__main__": + unittest.main()