Skip to content

Commit

Permalink
Merge pull request #664 from BDonnot/bd_dev
Browse files Browse the repository at this point in the history
[BREAKING] add name of backend class in the env (allows to load env with different backends with different orders)
  • Loading branch information
BDonnot authored Nov 22, 2024
2 parents 8407f6d + 37029ad commit 26e8e33
Show file tree
Hide file tree
Showing 19 changed files with 674 additions and 236 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ Native multi agents support:
when creating the data.
- [BREAKING] deprecation of `backend.check_kirchoff` in favor of `backend.check_kirchhoff`
(fix the typo in the name)
- [BREAKING] change the name of the generated classes: now by default the backend class
name is added. This behaviour can be turned off by passing `_add_cls_nm_bk=False`
when calling `grid2op.make(...)`. If you develop a new Backend, you can also
customize the added name by overloading the `get_class_added_name` class method.
- [FIXED] issue https://github.com/Grid2op/grid2op/issues/657
- [FIXED] missing an import on the `MaskedEnvironment` class
- [FIXED] a bug when trying to set the load_p, load_q, gen_p, gen_v by names.
Expand All @@ -114,7 +118,7 @@ Native multi agents support:
with `gridobj.get_line_info(...)`, `gridobj.get_load_info(...)`, `gridobj.get_gen_info(...)`
or , `gridobj.get_storage_info(...)`
- [ADDED] codacy badge on the readme
- [ADDED] a method to check the KCL (`obs.check_kirchoff`) directly from the observation
- [ADDED] a method to check the KCL (`obs.check_kirchhoff`) directly from the observation
(previously it was only possible to do it from the backend). This should
be used for testing purpose only
- [IMPROVED] possibility to set the injections values with names
Expand All @@ -132,6 +136,8 @@ Native multi agents support:
- [IMPROVED] some type hints for some agent class
- [IMPROVED] the `backend.update_from_obs` function to work even when observation
does not have shunt information but there are not shunts on the grid.
- [IMPROVED] consistency of `MultiMixEnv` in case of automatic_classes (only one
class is generated for all mixes)

[1.10.4] - 2024-10-15
-------------------------
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
author = 'Benjamin Donnot'

# The full version, including alpha/beta/rc tags
release = '1.11.0.dev0'
release = '1.11.0.dev1'
version = '1.11'


Expand Down
19 changes: 19 additions & 0 deletions grid2op/Backend/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -2245,3 +2245,22 @@ def assert_grid_correct_after_powerflow(self) -> None:
raise EnvError(
'Some components of "backend.get_topo_vect()" are not finite. This should be integer.'
)

def get_class_added_name(self) -> str:
"""
.. versionadded: 1.11.0
This function allows to customize the name added in the generated classes
by default.
It can be usefull for example if multiple instance of your backend can have different
ordering even if they are loaded with the same backend class.
This should not be modified except if you code a specific backend class.
Returns
-------
``str``:
The added name added to the class
"""
return type(self).__name__
67 changes: 43 additions & 24 deletions grid2op/Backend/pandaPowerBackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,47 @@ def _aux_run_pf_init(self):
raise pp.powerflow.LoadflowNotConverged
except pp.powerflow.LoadflowNotConverged:
self._aux_runpf_pp(True)


def _init_big_topo_to_bk(self):
self._big_topo_to_backend = [(None, None, None) for _ in range(self.dim_topo)]
for load_id, pos_big_topo in enumerate(self.load_pos_topo_vect):
self._big_topo_to_backend[pos_big_topo] = (load_id, load_id, 0)
for gen_id, pos_big_topo in enumerate(self.gen_pos_topo_vect):
self._big_topo_to_backend[pos_big_topo] = (gen_id, gen_id, 1)
for l_id, pos_big_topo in enumerate(self.line_or_pos_topo_vect):
if l_id < self.__nb_powerline:
self._big_topo_to_backend[pos_big_topo] = (l_id, l_id, 2)
else:
self._big_topo_to_backend[pos_big_topo] = (
l_id,
l_id - self.__nb_powerline,
3,
)
for l_id, pos_big_topo in enumerate(self.line_ex_pos_topo_vect):
if l_id < self.__nb_powerline:
self._big_topo_to_backend[pos_big_topo] = (l_id, l_id, 4)
else:
self._big_topo_to_backend[pos_big_topo] = (
l_id,
l_id - self.__nb_powerline,
5,
)

def _init_topoid_objid(self):
self._big_topo_to_obj = [(None, None) for _ in range(self.dim_topo)]
nm_ = "load"
for load_id, pos_big_topo in enumerate(self.load_pos_topo_vect):
self._big_topo_to_obj[pos_big_topo] = (load_id, nm_)
nm_ = "gen"
for gen_id, pos_big_topo in enumerate(self.gen_pos_topo_vect):
self._big_topo_to_obj[pos_big_topo] = (gen_id, nm_)
nm_ = "lineor"
for l_id, pos_big_topo in enumerate(self.line_or_pos_topo_vect):
self._big_topo_to_obj[pos_big_topo] = (l_id, nm_)
nm_ = "lineex"
for l_id, pos_big_topo in enumerate(self.line_ex_pos_topo_vect):
self._big_topo_to_obj[pos_big_topo] = (l_id, nm_)

def _init_private_attrs(self) -> None:
# number of elements per substation
self.sub_info = np.zeros(self.n_sub, dtype=dt_int)
Expand Down Expand Up @@ -740,6 +780,7 @@ def _init_private_attrs(self) -> None:
self._nb_bus_before = None

# store the topoid -> objid
self._init_topoid_objid()
self._big_topo_to_obj = [(None, None) for _ in range(self.dim_topo)]
nm_ = "load"
for load_id, pos_big_topo in enumerate(self.load_pos_topo_vect):
Expand All @@ -755,29 +796,7 @@ def _init_private_attrs(self) -> None:
self._big_topo_to_obj[pos_big_topo] = (l_id, nm_)

# store the topoid -> objid
self._big_topo_to_backend = [(None, None, None) for _ in range(self.dim_topo)]
for load_id, pos_big_topo in enumerate(self.load_pos_topo_vect):
self._big_topo_to_backend[pos_big_topo] = (load_id, load_id, 0)
for gen_id, pos_big_topo in enumerate(self.gen_pos_topo_vect):
self._big_topo_to_backend[pos_big_topo] = (gen_id, gen_id, 1)
for l_id, pos_big_topo in enumerate(self.line_or_pos_topo_vect):
if l_id < self.__nb_powerline:
self._big_topo_to_backend[pos_big_topo] = (l_id, l_id, 2)
else:
self._big_topo_to_backend[pos_big_topo] = (
l_id,
l_id - self.__nb_powerline,
3,
)
for l_id, pos_big_topo in enumerate(self.line_ex_pos_topo_vect):
if l_id < self.__nb_powerline:
self._big_topo_to_backend[pos_big_topo] = (l_id, l_id, 4)
else:
self._big_topo_to_backend[pos_big_topo] = (
l_id,
l_id - self.__nb_powerline,
5,
)
self._init_big_topo_to_bk()

self.theta_or = np.full(self.n_line, fill_value=np.NaN, dtype=dt_float)
self.theta_ex = np.full(self.n_line, fill_value=np.NaN, dtype=dt_float)
Expand Down
12 changes: 6 additions & 6 deletions grid2op/Environment/baseEnv.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
HighResSimCounter)
from grid2op.Backend import Backend
from grid2op.dtypes import dt_int, dt_float, dt_bool
from grid2op.Space import GridObjects, RandomObject
from grid2op.Space import GridObjects, RandomObject, GRID2OP_CLASSES_ENV_FOLDER
from grid2op.Exceptions import (Grid2OpException,
EnvError,
InvalidRedispatching,
Expand Down Expand Up @@ -353,7 +353,7 @@ def __init__(
self._local_dir_cls = _local_dir_cls # suppose it's the second path to the environment, so the classes are already in the files
self._read_from_local_dir = _read_from_local_dir
if self._read_from_local_dir is not None:
if os.path.split(self._read_from_local_dir)[1] == "_grid2op_classes":
if os.path.split(self._read_from_local_dir)[1] == GRID2OP_CLASSES_ENV_FOLDER:
# legacy behaviour (using experimental_read_from_local_dir kwargs in env.make)
self._do_not_erase_local_dir_cls = True
else:
Expand Down Expand Up @@ -4081,7 +4081,7 @@ def _aux_gen_classes(cls_other, sys_path, _add_class_output=False):
sys.path.append(sub_repo)

sub_repo_mod = None
if tmp_nm == "_grid2op_classes":
if tmp_nm == GRID2OP_CLASSES_ENV_FOLDER:
# legacy "experimental_read_from_local_dir"
# issue was the module "_grid2op_classes" had the same name
# regardless of the environment, so grid2op was "confused"
Expand Down Expand Up @@ -4118,7 +4118,7 @@ def _aux_gen_classes(cls_other, sys_path, _add_class_output=False):
cls_res = getattr(module, cls_other.__name__)
return str_import, cls_res

def generate_classes(self, *, local_dir_id=None, _guard=None, _is_base_env__=True, sys_path=None):
def generate_classes(self, *, local_dir_id=None, _guard=None, sys_path=None, _is_base_env__=True):
"""
Use with care, but can be incredibly useful !
Expand Down Expand Up @@ -4203,9 +4203,9 @@ def generate_classes(self, *, local_dir_id=None, _guard=None, _is_base_env__=Tru
"(eg no the top level env) if I don't know the path of "
"the top level environment.")
if local_dir_id is not None:
sys_path = os.path.join(self.get_path_env(), "_grid2op_classes", local_dir_id)
sys_path = os.path.join(self.get_path_env(), GRID2OP_CLASSES_ENV_FOLDER, local_dir_id)
else:
sys_path = os.path.join(self.get_path_env(), "_grid2op_classes")
sys_path = os.path.join(self.get_path_env(), GRID2OP_CLASSES_ENV_FOLDER)

if _is_base_env__:
if os.path.exists(sys_path):
Expand Down
4 changes: 2 additions & 2 deletions grid2op/Environment/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ def __init__(
# this means that the "make" call is issued from the
# creation of a MultiMix.
# So I use the base name instead.
self.name = "".join(_overload_name_multimix[2:])
self.multimix_mix_name = name
self.name = _overload_name_multimix.name_env + _overload_name_multimix.add_to_name
self.multimix_mix_name = None # set in creation of the MultiMixEnv instead
self._overload_name_multimix = _overload_name_multimix
else:
self.name = name
Expand Down
Loading

0 comments on commit 26e8e33

Please sign in to comment.