Skip to content

Commit

Permalink
some tests do not pass, but beside that it looks ok
Browse files Browse the repository at this point in the history
  • Loading branch information
BDonnot committed Jul 27, 2021
1 parent db48d12 commit 80d3b1f
Show file tree
Hide file tree
Showing 15 changed files with 90 additions and 22 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,8 @@ grid2op/data_test/l2rpn_neurips_2020_track1_with_alert/_statistics_do_nothing/
save/
shorten_env.py
test_hash_env.py
test_pickle.py
test_rllib_vincevaki.py

# profiling files
**.prof
Original file line number Diff line number Diff line change
Expand Up @@ -1167,7 +1167,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
"version": "3.8.10"
}
},
"nbformat": 4,
Expand Down
6 changes: 5 additions & 1 deletion grid2op/Action/ActionSpace.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ class ActionSpace(SerializableActionSpace):
"""

def __init__(self, gridobj, legal_action, actionClass=BaseAction):
def __init__(self, gridobj,
legal_action,
actionClass=BaseAction # need to be a base grid2op type (and not a type generated on the fly)
):
"""
INTERNAL USE ONLY
Expand All @@ -61,6 +64,7 @@ def __init__(self, gridobj, legal_action, actionClass=BaseAction):
Class specifying the rules of the game used to check the legality of the actions.
"""
actionClass._update_value_set()
SerializableActionSpace.__init__(self, gridobj, actionClass=actionClass)
self.legal_action = legal_action

Expand Down
2 changes: 0 additions & 2 deletions grid2op/Action/DontAct.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ def __init__(self):
"""
PlayableAction.__init__(self)
if DontAct.attr_list_set:
self._update_value_set()

def update(self, dict_):
"""
Expand Down
3 changes: 2 additions & 1 deletion grid2op/Backend/Backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -1532,10 +1532,11 @@ def assert_grid_correct(self):
# class is already initialized
# and set up the proper class and everything
self._init_class_attr()

# type(self)._INIT_GRID_CLS = orig_type
# hack due to changing class of imported module in the module itself
self.__class__ = type(self).init_grid(type(self), force_module=type(self).__module__)
setattr(sys.modules[type(self).__module__], self.__class__.__name__, self.__class__)

# reset the attribute of the grid2op.Backend.Backend class
# that can be messed up with depending on the initialization of the backend
Backend._clear_class_attribute()
Expand Down
3 changes: 3 additions & 0 deletions grid2op/Environment/BaseEnv.py
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,9 @@ def _init_myclass(self):
if self._backend_action_class is not None:
# the class has already been initialized
return
# remember the original grid2op class
type(self)._INIT_GRID_CLS = type(self)

bk_type = type(self.backend) # be careful here: you need to initialize from the class, and not from the object
# create the proper environment class for this specific environment
self.__class__ = type(self).init_grid(bk_type)
Expand Down
5 changes: 4 additions & 1 deletion grid2op/Environment/Environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ def _init_backend(self, chronics_handler, backend,
# action affecting the grid that will be made by the agent
bk_type = type(self.backend) # be careful here: you need to initialize from the class, and not from the object
self._rewardClass = rewardClass
actionClass._update_value_set()
self._actionClass = actionClass.init_grid(gridobj=bk_type)
self._observationClass = observationClass.init_grid(gridobj=bk_type)

Expand All @@ -244,6 +245,7 @@ def _init_backend(self, chronics_handler, backend,
actionClass=actionClass,
legal_action=self._game_rules.legal_action)
# action that affect the grid made by the environment.
CompleteAction._update_value_set()
self._helper_action_env = self._helper_action_class(gridobj=bk_type,
actionClass=CompleteAction,
legal_action=self._game_rules.legal_action)
Expand Down Expand Up @@ -285,7 +287,8 @@ def _init_backend(self, chronics_handler, backend,
raise Grid2OpException("Parameter \"voltagecontrolClass\" should derive from \"ControlVoltageFromFile\".")

self._voltage_controler = self._voltagecontrolerClass(gridobj=bk_type,
controler_backend=self.backend)
controler_backend=self.backend,
actionSpace_cls=self._helper_action_class)

# create the opponent
# At least the 3 following attributes should be set before calling _create_opponent
Expand Down
4 changes: 2 additions & 2 deletions grid2op/Observation/ObservationSpace.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ def __init__(self,
actionClass = CompleteAction

SerializableObservationSpace.__init__(self, gridobj, observationClass=observationClass)

self.with_forecast = with_forecast
self._simulate_parameters = copy.deepcopy(env.parameters)

Expand All @@ -90,9 +89,10 @@ def __init__(self,

other_rewards = {k: v.rewardClass for k, v in env.other_rewards.items()}

# TODO here: have another backend maybe
# TODO here: have another backend class maybe
self._backend_obs = env.backend.copy()
_ObsEnv_class = _ObsEnv.init_grid(type(env.backend), force_module=_ObsEnv.__module__)
_ObsEnv_class._INIT_GRID_CLS = _ObsEnv # otherwise it's lost
setattr(sys.modules[_ObsEnv.__module__], _ObsEnv_class.__name__, _ObsEnv_class)
self.obs_env = _ObsEnv_class(init_grid_path=None, # don't leak the path of the real grid to the observation space
backend_instanciated=self._backend_obs,
Expand Down
12 changes: 7 additions & 5 deletions grid2op/Observation/_ObsEnv.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ def __init__(self,
kwargs_attention_budget=kwargs_attention_budget)
self._helper_action_class = helper_action_class
self._reward_helper = reward_helper
self._obsClass = None
self._obsClass = obsClass.init_grid(type(backend_instanciated))

# initialize the observation space
self._obsClass = None

self.gen_activeprod_t_init = np.zeros(self.n_gen, dtype=dt_float)
self.gen_activeprod_t_redisp_init = np.zeros(self.n_gen, dtype=dt_float)
self.times_before_line_status_actionable_init = np.zeros(self.n_line, dtype=dt_int)
Expand All @@ -91,7 +92,7 @@ def __init__(self,
backend=backend_instanciated,
names_chronics_to_backend=None,
actionClass=action_helper.actionClass,
observationClass=self._obsClass,
observationClass=obsClass,
rewardClass=None,
legalActClass=legalActClass)
self.no_overflow_disconnection = parameters.NO_OVERFLOW_DISCONNECTION
Expand Down Expand Up @@ -155,7 +156,7 @@ def _init_backend(self,
backend,
names_chronics_to_backend,
actionClass,
observationClass,
observationClass, # base grid2op type
rewardClass,
legalActClass):
self._env_dc = self.parameters.ENV_DC
Expand All @@ -178,7 +179,8 @@ def _init_backend(self,

# create the attention budget
self._create_attention_budget()

self._obsClass = observationClass.init_grid(type(self.backend))
self._obsClass._INIT_GRID_CLS = observationClass
self.current_obs_init = self._obsClass(seed=None,
obs_env=None,
action_helper=None)
Expand Down
4 changes: 3 additions & 1 deletion grid2op/Opponent/OpponentSpace.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ def __init__(self,
opponent,
attack_duration, # maximum duration of an attack
attack_cooldown, # minimum duration between two consecutive attack
budget_per_timestep=0., action_space=None):
budget_per_timestep=0.,
action_space=None):

if action_space is not None:
if not isinstance(action_space, compute_budget.action_space):
raise OpponentError("BaseAction space provided to build the agent is not a subclass from the"
Expand Down
49 changes: 49 additions & 0 deletions grid2op/Space/GridObjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -2141,6 +2141,13 @@ def init_grid(cls, gridobj, force=False, extra_name=None, force_module=None):
cls_attr_as_dict = {}
GridObjects._make_cls_dict_extended(gridobj, cls_attr_as_dict, as_list=False)
res_cls = type(name_res, (cls, ), cls_attr_as_dict)
if hasattr(cls, "_INIT_GRID_CLS"):
# original class is not modified
res_cls._INIT_GRID_CLS = cls._INIT_GRID_CLS
else:
# i am the original class from grid2op
res_cls._INIT_GRID_CLS = cls

res_cls._compute_pos_big_topo_cls()
if res_cls.glop_version != grid2op.__version__:
res_cls.process_grid2op_compat()
Expand Down Expand Up @@ -2900,3 +2907,45 @@ def same_grid_class(cls, other_cls) -> bool:
if not np.array_equal(getattr(cls, attr_nm), getattr(other_cls, attr_nm)):
return False
return True

@staticmethod
def init_grid_from_dict_for_pickle(name_res, orig_cls, cls_attr):
"""
This function is used internally for pickle to build the classes of the
objects instead of loading them from the module (which is impossible as
most classes are defined on the fly in grid2op)
"""

# define properly the class
res_cls = type(name_res, (orig_cls, ), cls_attr)
res_cls._compute_pos_big_topo_cls()
res_cls._INIT_GRID_CLS = orig_cls # don't forget to remember the base class
if res_cls.glop_version != grid2op.__version__:
res_cls.process_grid2op_compat()
# now create an "empty" object (using new)
res = res_cls.__new__(res_cls)
return res

# test for pickle
def __reduce__(self):
cls_attr_as_dict = {}
GridObjects._make_cls_dict_extended(type(self), cls_attr_as_dict, as_list=False)
if hasattr(self, "__getstate__"):
my_state = self.__getstate__()
else:
my_state = {}
for k, v in self.__dict__.items():
my_state[k] = copy.copy(v)

my_cls = type(self)
if hasattr(my_cls, "_INIT_GRID_CLS"):
# I am a type created when an environment is loaded
base_cls = my_cls._INIT_GRID_CLS
else:
# i am a "raw" type directly coming from grid2op
base_cls = my_cls
return GridObjects.init_grid_from_dict_for_pickle, \
(type(self).__name__,
base_cls,
cls_attr_as_dict), \
my_state
1 change: 0 additions & 1 deletion grid2op/Space/SerializableSpace.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ def __init__(self,

GridObjects.__init__(self)
RandomObject.__init__(self)

self._init_subtype = subtype # do not use, use to save restore only !!!
if _init_grid:
self.subtype = subtype.init_grid(gridobj)
Expand Down
8 changes: 4 additions & 4 deletions grid2op/VoltageControler/BaseVoltageController.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class BaseVoltageController(RandomObject, ABC):
If the voltages are not on the chronics (missing files), it will not change the voltage setpoints at all.
"""
def __init__(self, gridobj, controler_backend):
def __init__(self, gridobj, controler_backend, actionSpace_cls):
"""
Parameters
Expand All @@ -36,9 +36,9 @@ def __init__(self, gridobj, controler_backend):
"""
RandomObject.__init__(self)
legal_act = AlwaysLegal()
self.action_space = ActionSpace(gridobj=gridobj,
actionClass=VoltageOnlyAction,
legal_action=legal_act)
self.action_space = actionSpace_cls(gridobj=gridobj,
actionClass=VoltageOnlyAction,
legal_action=legal_act)
self.backend = controler_backend.copy()

def copy(self):
Expand Down
7 changes: 5 additions & 2 deletions grid2op/VoltageControler/ControlVoltageFromFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ControlVoltageFromFile(BaseVoltageController):
If the voltages are not on the chronics (missing files), it will not change the voltage setpoint at all.
"""
def __init__(self, gridobj, controler_backend):
def __init__(self, gridobj, controler_backend, actionSpace_cls):
"""
Parameters
Expand All @@ -30,7 +30,10 @@ def __init__(self, gridobj, controler_backend):
An instanciated backend to perform some computation on a powergrid, before taking some actions.
"""
BaseVoltageController.__init__(self, gridobj=gridobj, controler_backend=controler_backend)
BaseVoltageController.__init__(self,
gridobj=gridobj,
controler_backend=controler_backend,
actionSpace_cls=actionSpace_cls)

def fix_voltage(self, observation, agent_action, env_action, prod_v_chronics):
"""
Expand Down
4 changes: 3 additions & 1 deletion grid2op/tests/test_Action.py
Original file line number Diff line number Diff line change
Expand Up @@ -1413,9 +1413,11 @@ def test_add_modify(self):
act1_init = self.aux_get_act(self.action_space_1)
act1 = copy.deepcopy(act1_init)
act2 = self.aux_get_act(self.action_space_2)
list_2 = copy.deepcopy(act2.attr_list_set)
list_1 = copy.deepcopy(act1.attr_list_set)
with warnings.catch_warnings():
warnings.filterwarnings("error")
if act2.attr_list_set - act1.attr_list_set:
if len(list_2 - list_1):
# it should raise a warning if i attempt to set an attribute it's not supposed to
with self.assertWarns(UserWarning):
res = act1 + act2
Expand Down

0 comments on commit 80d3b1f

Please sign in to comment.