Skip to content

Commit

Permalink
Merge pull request #395 from rte-france/dev_1.8.1
Browse files Browse the repository at this point in the history
Update to version 1.8.1
  • Loading branch information
BDonnot committed Jan 11, 2023
2 parents 5a4c89d + ffacd4e commit 46cc8f5
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 12 deletions.
12 changes: 10 additions & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,16 @@ Change Log
- [???] "asynch" multienv
- [???] properly model interconnecting powerlines

[1.8.0] - 2022-12-yy
--------------------
[1.8.1] - 2023-01-11
---------------------
- [FIXED] a deprecation with numpy>= 1.24 (**eg** np.bool and np.str)
- [ADDED] the baseAgent class now has two new template methods `save_state` and `load_state` to save and
load the agent's state during Grid2op simulations. Examples can be found in L2RPN baselines (PandapowerOPFAgent and curriculumagent).
- [IMPROVED] error message in pandapower backend when the grid do not converge due to disconnected
generators or loads.

[1.8.0] - 2022-12-12
---------------------
- [BREAKING] now requires numpy >= 1.20 to work (otherwise there are
issues with newer versions of pandas).
- [BREAKING] issue https://github.com/rte-france/Grid2Op/issues/379 requires
Expand Down
61 changes: 60 additions & 1 deletion grid2op/Agent/baseAgent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# This file is part of Grid2Op, Grid2Op a testbed platform to model sequential decision making in power systems.

import copy

import os
from abc import ABC, abstractmethod
from grid2op.Space import RandomObject

Expand Down Expand Up @@ -111,3 +111,62 @@ def act(self, observation, reward, done=False):
"""
pass

def save_state(self, savestate_path :os.PathLike):
"""
An optional method to save the internal state of your agent.
The saved state can later be re-loaded with `self.load_state`, e.g. to repeat
a Grid2Op time step with exactly the same internal parameterization. This
can be useful to repeat Grid2Op experiments and analyze why your agent performed
certain actions in past time steps. Concept developed by Fraunhofer IEE KES.
Notes
-----
First, the internal state your agent consists of attributes that are contained in
the :class:`grid2op.Agent.BaseAgent` and :class:`grid2op.Agent.BaseAgent.action_space`.
Examples are the parameterization and seeds of the random number generator that your
agent uses. Such attributes can easily be obtained with the :func:`getattr` and stored
in a common file format, such as `.npy`.
Second, your agent may contain custom attributes, such as e.g. a vector of line indices
from a Grid2Op observation. You could obtain and save them in the same way as explained
before.
Third, your agent may contain very specific modules such as `Tensorflow` that
do not support the simple :func:`getattr`. However, these modules normally have
their own methods to save an internal state. Examples of such methods are
:func:`save_weights` that you can integrate in your implementation of `self.save_state`.
Parameters
----------
savestate_path: ``string``
The path to which your agent state variables should be saved
"""
pass

def load_state(self, loadstate_path :os.PathLike):
"""
An optional method to re-load the internal agent state that was saved with `self.save_state`.
This can be useful to re-set your agent to an earlier simulation time step and reproduce
past experiments with Grid2Op. Concept developed by Fraunhofer IEE KES.
Notes
-----
First, the internal state your agent consists of attributes that are contained in
the :class:`grid2op.Agent.BaseAgent` and :class:`grid2op.Agent.BaseAgent.action_space`.
Such attributes can easily be re-set with :func:`setattr`.
Second, your agent may contain custom attributes, such as e.g. a vector of line indices
from a Grid2Op observation. You can re-set them with :func:`setattr` as well.
Third, your agent may contain very specific modules such as `Tensorflow` that
do not support the simple :func:`setattr`. However, these modules normally have
their own methods to re-load an internal state. Examples of such methods are
:func:`load_weights` that you can integrate in your implementation of `self.load_state`.
Parameters
----------
savestate_path: ``string``
The path from which your agent state variables should be loaded
"""
pass
16 changes: 12 additions & 4 deletions grid2op/Backend/PandaPowerBackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -1003,10 +1003,18 @@ def runpf(self, is_dc=False):

if np.any(~self._grid.load["in_service"]):
# TODO see if there is a better way here -> do not handle this here, but rather in Backend._next_grid_state
raise pp.powerflow.LoadflowNotConverged("Isolated load")
raise pp.powerflow.LoadflowNotConverged("Disconnected load: for now grid2op cannot handle properly"
" disconnected load. If you want to disconnect one, say it"
" consumes 0. instead. Please check loads: "
f"{np.where(~self._grid.load['in_service'])[0]}"
)
if np.any(~self._grid.gen["in_service"]):
# TODO see if there is a better way here -> do not handle this here, but rather in Backend._next_grid_state
raise pp.powerflow.LoadflowNotConverged("Isolated gen")
raise pp.powerflow.LoadflowNotConverged("Disconnected gen: for now grid2op cannot handle properly"
" disconnected generators. If you want to disconnect one, say it"
" produces 0. instead. Please check generators: "
f"{np.where(~self._grid.gen['in_service'])[0]}"
)

if is_dc:
pp.rundcpp(self._grid, check_connectivity=False)
Expand All @@ -1031,7 +1039,7 @@ def runpf(self, is_dc=False):
if self._grid.res_gen.isnull().values.any():
# TODO see if there is a better way here -> do not handle this here, but rather in Backend._next_grid_state
# sometimes pandapower does not detect divergence and put Nan.
raise pp.powerflow.LoadflowNotConverged("Isolated gen")
raise pp.powerflow.LoadflowNotConverged("Divergence due to Nan values in res_gen table.")

(
self.prod_p[:],
Expand Down Expand Up @@ -1337,7 +1345,7 @@ def get_topo_vect(self):
return self._topo_vect

def _get_topo_vect(self):
res = np.full(self.dim_topo, fill_value=np.NaN, dtype=dt_int)
res = np.full(self.dim_topo, fill_value=np.iinfo(dt_int).max, dtype=dt_int)

line_status = self.get_line_status()

Expand Down
4 changes: 2 additions & 2 deletions grid2op/Chronics/Settings_L2RPN2019.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,11 @@ def from_vect(self, vect):
next_ = self.n_line

self._switch_line_status = vect[prev_:next_]
self._switch_line_status = self._switch_line_status.astype(np.bool)
self._switch_line_status = self._switch_line_status.astype(np.bool_)
prev_ = next_
next_ += self.dim_topo
self._change_bus_vect = vect[prev_:next_]
self._change_bus_vect = self._change_bus_vect.astype(np.bool)
self._change_bus_vect = self._change_bus_vect.astype(np.bool_)

# self.disambiguate_reconnection()

Expand Down
2 changes: 1 addition & 1 deletion grid2op/Space/GridObjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -2264,7 +2264,7 @@ def _check_validity_shunt_data(cls):
if not isinstance(cls.name_shunt, np.ndarray):
try:
cls.name_shunt = np.array(cls.name_shunt)
cls.name_shunt = cls.name_shunt.astype(np.str)
cls.name_shunt = cls.name_shunt.astype(np.str_)
except Exception as exc:
raise EnvError(
'name_shunt should be convertible to a numpy array with dtype "str".'
Expand Down
3 changes: 2 additions & 1 deletion grid2op/dtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
dt_float = (
np.float32
) # dtype('float64') or dtype('float32') depending on platform => i force it to float32
dt_bool = np.bool

dt_bool = np.bool_ # mandatory for numpy >= 1.24
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ keywords = ML powergrid optmization RL power-systems
license = Mozilla Public License 2.0 (MPL 2.0)
classifiers =
Development Status :: 4 - Beta
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
Intended Audience :: Developers
Intended Audience :: Education
Expand Down

0 comments on commit 46cc8f5

Please sign in to comment.