Skip to content

Commit 3b61cc3

Browse files
author
yassine abdou
committed
feat : use defaultprotection in place of next_grid function
1 parent 3f82d56 commit 3b61cc3

File tree

9 files changed

+122
-101
lines changed

9 files changed

+122
-101
lines changed

grid2op/Backend/thermalLimits.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1-
from loguru import logger
21
from typing import Union, List, Optional, Dict
2+
try:
3+
from typing import Self
4+
except ImportError:
5+
from typing_extensions import Self
6+
7+
from loguru import logger
38
import numpy as np
9+
import copy
410

511
import grid2op
612
from grid2op.dtypes import dt_float
@@ -126,6 +132,8 @@ def limits(self, new_limits: Union[np.ndarray, Dict[str, float]]):
126132
self._thermal_limit_a[i] = tmp
127133

128134
def env_limits(self, thermal_limit):
135+
"""
136+
"""
129137
if isinstance(thermal_limit, dict):
130138
tmp = np.full(self.n_line, fill_value=np.NaN, dtype=dt_float)
131139
for key, val in thermal_limit.items():
@@ -179,7 +187,7 @@ def env_limits(self, thermal_limit):
179187
self._thermal_limit_a = tmp
180188
logger.info("Env thermal limits successfully set.")
181189

182-
def update_limits(self, thermal_limit_a: np.ndarray) -> None:
190+
def update_limits_from_vector(self, thermal_limit_a: np.ndarray) -> None:
183191
"""
184192
Updates the thermal limits using a numpy array.
185193
@@ -188,4 +196,16 @@ def update_limits(self, thermal_limit_a: np.ndarray) -> None:
188196
"""
189197
thermal_limit_a = np.array(thermal_limit_a).astype(dt_float)
190198
self._thermal_limit_a = thermal_limit_a
191-
logger.info("Thermal limits updated from vector.")
199+
logger.info("Thermal limits updated from vector.")
200+
201+
def update_limits(self, env : "grid2op.Environment.BaseEnv") -> None:
202+
pass
203+
204+
def copy(self) -> Self:
205+
"""
206+
Creates a deep copy of the current ThermalLimits instance.
207+
208+
:return: ThermalLimits
209+
A new instance with the same attributes.
210+
"""
211+
return copy.deepcopy(self)

grid2op/Environment/_obsEnv.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ def __init__(
123123
self.current_obs_init = None
124124
self.current_obs = None
125125

126-
self._init_thermal_limit()
127126

128127
self._init_backend(
129128
chronics_handler=_ObsCH(),
@@ -135,7 +134,6 @@ def __init__(
135134
legalActClass=legalActClass,
136135
)
137136

138-
self.ts_manager = copy.deepcopy(self._observation_space.ts_manager)
139137

140138
self.delta_time_seconds = delta_time_seconds
141139
####

grid2op/Environment/baseEnv.py

Lines changed: 63 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,8 @@ def __init__(
550550
self.debug_dispatch = False
551551

552552
# Thermal limit and protection
553-
self.ts_manager : thermalLimits.ThermalLimits = None
554-
self.protection = protectionScheme.NoProtection = None
553+
self._init_thermal_limit()
554+
self.protection : protectionScheme.DefaultProtection = None
555555

556556
# to change the parameters
557557
self.__new_param = None
@@ -637,18 +637,8 @@ def __init__(
637637
self._reward_to_obs = {}
638638

639639
def _init_thermal_limit(self):
640-
641-
if self._thermal_limit_a is None:
642-
if hasattr(self.ts_manager, '_thermal_limit_a') and isinstance(self.ts_manager.limits, np.ndarray):
643-
_thermal_limits = self.ts_manager.limits.astype(dt_float)
644-
else:
645-
raise ValueError("Thermal limits not provided and 'self.ts_manager.limits' is unavailable or invalid.")
646-
else:
647-
_thermal_limits = self._thermal_limit_a
648-
649-
# Update the thermal limits manager for protection scheme
650640
self.ts_manager = thermalLimits.ThermalLimits(
651-
_thermal_limit_a = _thermal_limits,
641+
_thermal_limit_a = self._thermal_limit_a,
652642
n_line=self.n_line,
653643
line_names=self.name_line
654644
)
@@ -733,6 +723,7 @@ def _custom_deepcopy_for_copy(self, new_obj, dict_=None):
733723
new_obj._backend_action = copy.deepcopy(self._backend_action)
734724

735725
# specific to Basic Env, do not change
726+
new_obj.backend = self.backend.copy()
736727
new_obj.ts_manager = self.ts_manager.copy()
737728
if self._thermal_limit_a is not None:
738729
new_obj.ts_manager.limits = self._thermal_limit_a
@@ -1792,52 +1783,51 @@ def _init_backend(
17921783
"""
17931784
pass
17941785

1795-
def set_thermal_limit(self, thermal_limit):
1796-
"""
1797-
Set the thermal limit effectively.
1786+
# def set_thermal_limit(self, thermal_limit):
1787+
# """
1788+
# Set the thermal limit effectively.
17981789

1799-
Parameters
1800-
----------
1801-
thermal_limit: ``numpy.ndarray``
1802-
The new thermal limit. It must be a numpy ndarray vector (or convertible to it). For each powerline it
1803-
gives the new thermal limit.
1790+
# Parameters
1791+
# ----------
1792+
# thermal_limit: ``numpy.ndarray``
1793+
# The new thermal limit. It must be a numpy ndarray vector (or convertible to it). For each powerline it
1794+
# gives the new thermal limit.
18041795

1805-
Alternatively, this can be a dictionary mapping the line names (keys) to its thermal limits (values). In
1806-
that case, all thermal limits for all powerlines should be specified (this is a safety measure
1807-
to reduce the odds of misuse).
1796+
# Alternatively, this can be a dictionary mapping the line names (keys) to its thermal limits (values). In
1797+
# that case, all thermal limits for all powerlines should be specified (this is a safety measure
1798+
# to reduce the odds of misuse).
18081799

1809-
Examples
1810-
---------
1800+
# Examples
1801+
# ---------
18111802

1812-
This function can be used like this:
1803+
# This function can be used like this:
18131804

1814-
.. code-block:: python
1805+
# .. code-block:: python
18151806

1816-
import grid2op
1807+
# import grid2op
18171808

1818-
# I create an environment
1819-
env = grid2op.make(""l2rpn_case14_sandbox"", test=True)
1809+
# # I create an environment
1810+
# env = grid2op.make(""l2rpn_case14_sandbox"", test=True)
18201811

1821-
# i set the thermal limit of each powerline to 20000 amps
1822-
env.set_thermal_limit([20000 for _ in range(env.n_line)])
1812+
# # i set the thermal limit of each powerline to 20000 amps
1813+
# env.set_thermal_limit([20000 for _ in range(env.n_line)])
18231814

1824-
Notes
1825-
-----
1826-
As of grid2op > 1.5.0, it is possible to set the thermal limit by using a dictionary with the keys being
1827-
the name of the powerline and the values the thermal limits.
1815+
# Notes
1816+
# -----
1817+
# As of grid2op > 1.5.0, it is possible to set the thermal limit by using a dictionary with the keys being
1818+
# the name of the powerline and the values the thermal limits.
18281819

1829-
"""
1830-
if self.__closed:
1831-
raise EnvError("This environment is closed, you cannot use it.")
1832-
if not self.__is_init:
1833-
raise Grid2OpException(
1834-
"Impossible to set the thermal limit to a non initialized Environment. "
1835-
"Have you called `env.reset()` after last game over ?"
1836-
)
1837-
# update n_line and name_line of ts_manager (old : self.ts_manager.n_line = -1 and self.ts_manager.name_line = None)
1838-
self.ts_manager.env_limits(thermal_limit=thermal_limit)
1839-
self.ts_manager.limits = self._thermal_limit_a
1840-
self.observation_space.set_thermal_limit(self._thermal_limit_a)
1820+
# """
1821+
# if self.__closed:
1822+
# raise EnvError("This environment is closed, you cannot use it.")
1823+
# if not self.__is_init:
1824+
# raise Grid2OpException(
1825+
# "Impossible to set the thermal limit to a non initialized Environment. "
1826+
# "Have you called `env.reset()` after last game over ?"
1827+
# )
1828+
# # update n_line and name_line of ts_manager (old : self.ts_manager.n_line = -1 and self.ts_manager.name_line = None)
1829+
# self.ts_manager.env_limits(thermal_limit=thermal_limit)
1830+
# self.observation_space.set_thermal_limit(thermal_limit=thermal_limit)
18411831

18421832
def _reset_redispatching(self):
18431833
# redispatching
@@ -2492,33 +2482,33 @@ def get_obs(self, _update_state=True, _do_copy=True):
24922482
else:
24932483
return self._last_obs
24942484

2495-
def get_thermal_limit(self):
2496-
"""
2497-
Get the current thermal limit in amps registered for the environment.
2485+
# def get_thermal_limit(self):
2486+
# """
2487+
# Get the current thermal limit in amps registered for the environment.
24982488

2499-
Examples
2500-
---------
2489+
# Examples
2490+
# ---------
25012491

2502-
It can be used like this:
2492+
# It can be used like this:
25032493

2504-
.. code-block:: python
2494+
# .. code-block:: python
25052495

2506-
import grid2op
2496+
# import grid2op
25072497

2508-
# I create an environment
2509-
env = grid2op.make("l2rpn_case14_sandbox")
2498+
# # I create an environment
2499+
# env = grid2op.make("l2rpn_case14_sandbox")
25102500

2511-
thermal_limits = env.get_thermal_limit()
2501+
# thermal_limits = env.get_thermal_limit()
25122502

2513-
"""
2514-
if self.__closed:
2515-
raise EnvError("This environment is closed, you cannot use it.")
2516-
if not self.__is_init:
2517-
raise EnvError(
2518-
"This environment is not initialized. It has no thermal limits. "
2519-
"Have you called `env.reset()` after last game over ?"
2520-
)
2521-
return 1.0 * self._thermal_limit_a
2503+
# """
2504+
# if self.__closed:
2505+
# raise EnvError("This environment is closed, you cannot use it.")
2506+
# if not self.__is_init:
2507+
# raise EnvError(
2508+
# "This environment is not initialized. It has no thermal limits. "
2509+
# "Have you called `env.reset()` after last game over ?"
2510+
# )
2511+
# return 1.0 * self._thermal_limit_a
25222512

25232513
def _withdraw_storage_losses(self):
25242514
"""
@@ -3053,7 +3043,7 @@ def _update_alert_properties(self, action, lines_attacked, subs_attacked):
30533043
def _aux_register_env_converged(self, disc_lines, action, init_line_status, new_p):
30543044
beg_res = time.perf_counter()
30553045
# update the thermal limit, for DLR for example
3056-
self.ts_manager.update_limits(thermal_limit_a=self._thermal_limit_a) # old code : self.backend.update_thermal_limit(self)
3046+
self.ts_manager.update_limits(self) # old code : self.backend.update_thermal_limit(self)
30573047

30583048
overflow_lines = self.backend.get_line_overflow()
30593049
# save the current topology as "last" topology (for connected powerlines)
@@ -3116,11 +3106,10 @@ def _aux_register_env_converged(self, disc_lines, action, init_line_status, new_
31163106
# TODO is non zero and disconnected, this should be ok.
31173107
self._time_extract_obs += time.perf_counter() - beg_res
31183108

3119-
def _backend_next_grid_state(self):
3109+
def _protection_next_grid_state(self):
31203110
"""overlaoded in MaskedEnv"""
31213111
self._init_thermal_limit()
31223112
self._init_protection()
3123-
return self.protection.next_grid_state()
31243113

31253114
def _aux_run_pf_after_state_properly_set(
31263115
self, action, init_line_status, new_p, except_
@@ -3130,7 +3119,8 @@ def _aux_run_pf_after_state_properly_set(
31303119
try:
31313120
# compute the next _grid state
31323121
beg_pf = time.perf_counter()
3133-
disc_lines, detailed_info, conv_ = self._backend_next_grid_state()
3122+
self._protection_next_grid_state()
3123+
disc_lines, detailed_info, conv_ = self.protection.next_grid_state()
31343124
self._disc_lines[:] = disc_lines
31353125
self._time_powerflow += time.perf_counter() - beg_pf
31363126
if conv_ is None:

grid2op/Environment/environment.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from grid2op.Observation import CompleteObservation, ObservationSpace, BaseObservation
2727
from grid2op.Reward import FlatReward, RewardHelper, BaseReward
2828
from grid2op.Rules import RulesChecker, AlwaysLegal, BaseRules
29-
from grid2op.Backend import Backend, protectionScheme, thermalLimits
29+
from grid2op.Backend import Backend, thermalLimits
3030
from grid2op.Chronics import ChronicsHandler
3131
from grid2op.VoltageControler import ControlVoltageFromFile, BaseVoltageController
3232
from grid2op.Environment.baseEnv import BaseEnv
@@ -84,6 +84,7 @@ def __init__(
8484
chronics_handler,
8585
backend,
8686
parameters,
87+
ts_manager: thermalLimits.ThermalLimits = None,
8788
name="unknown",
8889
n_busbar : N_BUSBAR_PER_SUB_TYPING=DEFAULT_N_BUSBAR_PER_SUB,
8990
names_chronics_to_backend=None,
@@ -204,19 +205,19 @@ def __init__(
204205
self._init_backend(
205206
chronics_handler,
206207
backend,
208+
ts_manager,
207209
names_chronics_to_backend,
208210
actionClass,
209211
observationClass,
210212
rewardClass,
211213
legalActClass,
212214
)
213-
self.ts_manager : thermalLimits.ThermalLimits = copy.deepcopy(self.ts_manager)
214-
self.protection : protectionScheme.DefaultProtection = copy.deepcopy(self.protection)
215215

216216
def _init_backend(
217217
self,
218218
chronics_handler,
219219
backend,
220+
ts_manager,
220221
names_chronics_to_backend,
221222
actionClass,
222223
observationClass,
@@ -246,7 +247,13 @@ def _init_backend(
246247
type(rewardClass)
247248
)
248249
)
249-
250+
#thermalLimits:
251+
ts_manager = ts_manager or self.ts_manager
252+
if not isinstance(ts_manager, thermalLimits.ThermalLimits):
253+
raise Grid2OpException(
254+
'Parameter "ts_manager" used to build the Environment should derived form the '
255+
'grid2op.Backend.thermalLimits class, type provided is "{}"'.format(type(ts_manager))
256+
)
250257
# backend
251258
if not isinstance(backend, Backend):
252259
raise Grid2OpException(
@@ -318,11 +325,13 @@ def _init_backend(
318325
self._line_status = np.ones(shape=self.n_line, dtype=dt_bool)
319326
self._disc_lines = np.zeros(shape=self.n_line, dtype=dt_int) - 1
320327

328+
self.ts_manager.n_line = self.n_line
329+
self.ts_manager.name_line = self.name_line
321330
if self._thermal_limit_a is None:
322-
self._thermal_limit_a = self.backend.thermal_limit_a.astype(dt_float)
331+
self.ts_manager.limits = self.backend.thermal_limit_a.astype(dt_float)
332+
self._thermal_limit_a = self.ts_manager.limits
323333
else:
324-
self.backend.set_thermal_limit(self._thermal_limit_a.astype(dt_float))
325-
334+
self.ts_manager.limits = self._thermal_limit_a.astype(dt_float)
326335
*_, tmp = self.backend.generators_info()
327336

328337
# rules of the game
@@ -1517,7 +1526,8 @@ def get_kwargs(self,
15171526
res["legalActClass"] = self._legalActClass
15181527
res["epsilon_poly"] = self._epsilon_poly
15191528
res["tol_poly"] = self._tol_poly
1520-
res["thermal_limit_a"] = self._thermal_limit_a
1529+
# res["thermal_limit_a"] = self._thermal_limit_a
1530+
res["ts_manager"] = self.ts_manager
15211531
res["voltagecontrolerClass"] = self._voltagecontrolerClass
15221532
res["other_rewards"] = {k: v.rewardClass for k, v in self.other_rewards.items()}
15231533
res["name"] = self.name
@@ -2139,7 +2149,8 @@ def get_params_for_runner(self):
21392149
if self.chronics_handler.max_iter is not None:
21402150
res["max_iter"] = self.chronics_handler.max_iter
21412151
res["gridStateclass_kwargs"] = dict_
2142-
res["thermal_limit_a"] = self._thermal_limit_a
2152+
# res["thermal_limit_a"] = self._thermal_limit_a
2153+
res["ts_manager"] = self.ts_manager
21432154
res["voltageControlerClass"] = self._voltagecontrolerClass
21442155
res["other_rewards"] = {k: v.rewardClass for k, v in self.other_rewards.items()}
21452156
res["grid_layout"] = self.grid_layout

grid2op/Episode/EpisodeReboot.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,7 @@ def _assign_state(self, obs):
244244
# # TODO check that the "stored" "last bus for when the powerline were connected" are
245245
# # kept there (I might need to do a for loop)
246246
self.env.backend.update_from_obs(obs)
247-
disc_lines, detailed_info, conv_ = self.env.backend.next_grid_state(
248-
env=self.env
249-
)
247+
disc_lines, detailed_info, conv_ = self.env.protection.next_grid_state()
250248
if conv_ is None:
251249
self.env._backend_action.update_state(disc_lines)
252250
self.env._backend_action.reset()

grid2op/MakeEnv/MakeFromPath.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,11 +1039,12 @@ def make_from_dataset_path(
10391039
kwargs_observation=kwargs_observation,
10401040
observation_bk_class=observation_backend_class,
10411041
observation_bk_kwargs=observation_backend_kwargs
1042-
)
1042+
)
10431043
# Update the thermal limit if any
10441044
if thermal_limits is not None:
1045-
env.set_thermal_limit(thermal_limits)
1046-
1045+
env.ts_manager.env_limits(thermal_limits)
1046+
env.observation_space.ts_manager.env_limits(env.ts_manager.limits)
1047+
10471048
# Set graph layout if not None and not an empty dict
10481049
if graph_layout is not None and graph_layout:
10491050
try:

0 commit comments

Comments
 (0)