Skip to content

Commit a9d6ff0

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

File tree

9 files changed

+121
-100
lines changed

9 files changed

+121
-100
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
@@ -116,7 +116,6 @@ def __init__(
116116
self.current_obs_init = None
117117
self.current_obs = None
118118

119-
self._init_thermal_limit()
120119

121120
self._init_backend(
122121
chronics_handler=_ObsCH(),
@@ -128,7 +127,6 @@ def __init__(
128127
legalActClass=legalActClass,
129128
)
130129

131-
self.ts_manager = copy.deepcopy(self._observation_space.ts_manager)
132130

133131
self.delta_time_seconds = delta_time_seconds
134132
####

grid2op/Environment/baseEnv.py

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

572572
# Thermal limit and protection
573-
self.ts_manager : thermalLimits.ThermalLimits = None
574-
self.protection = protectionScheme.NoProtection = None
573+
self._init_thermal_limit()
574+
self.protection : protectionScheme.DefaultProtection = None
575575

576576
# to change the parameters
577577
self.__new_param = None
@@ -673,18 +673,8 @@ def __init__(
673673

674674

675675
def _init_thermal_limit(self):
676-
677-
if self._thermal_limit_a is None:
678-
if hasattr(self.ts_manager, '_thermal_limit_a') and isinstance(self.ts_manager.limits, np.ndarray):
679-
_thermal_limits = self.ts_manager.limits.astype(dt_float)
680-
else:
681-
raise ValueError("Thermal limits not provided and 'self.ts_manager.limits' is unavailable or invalid.")
682-
else:
683-
_thermal_limits = self._thermal_limit_a
684-
685-
# Update the thermal limits manager for protection scheme
686676
self.ts_manager = thermalLimits.ThermalLimits(
687-
_thermal_limit_a = _thermal_limits,
677+
_thermal_limit_a = self._thermal_limit_a,
688678
n_line=self.n_line,
689679
line_names=self.name_line
690680
)
@@ -770,6 +760,7 @@ def _custom_deepcopy_for_copy(self, new_obj, dict_=None):
770760
new_obj._backend_action = copy.deepcopy(self._backend_action)
771761

772762
# specific to Basic Env, do not change
763+
new_obj.backend = self.backend.copy()
773764
new_obj.ts_manager = self.ts_manager.copy()
774765
if self._thermal_limit_a is not None:
775766
new_obj.ts_manager.limits = self._thermal_limit_a
@@ -1878,52 +1869,51 @@ def _init_backend(
18781869
"""
18791870
pass
18801871

1881-
def set_thermal_limit(self, thermal_limit):
1882-
"""
1883-
Set the thermal limit effectively.
1872+
# def set_thermal_limit(self, thermal_limit):
1873+
# """
1874+
# Set the thermal limit effectively.
18841875

1885-
Parameters
1886-
----------
1887-
thermal_limit: ``numpy.ndarray``
1888-
The new thermal limit. It must be a numpy ndarray vector (or convertible to it). For each powerline it
1889-
gives the new thermal limit.
1876+
# Parameters
1877+
# ----------
1878+
# thermal_limit: ``numpy.ndarray``
1879+
# The new thermal limit. It must be a numpy ndarray vector (or convertible to it). For each powerline it
1880+
# gives the new thermal limit.
18901881

1891-
Alternatively, this can be a dictionary mapping the line names (keys) to its thermal limits (values). In
1892-
that case, all thermal limits for all powerlines should be specified (this is a safety measure
1893-
to reduce the odds of misuse).
1882+
# Alternatively, this can be a dictionary mapping the line names (keys) to its thermal limits (values). In
1883+
# that case, all thermal limits for all powerlines should be specified (this is a safety measure
1884+
# to reduce the odds of misuse).
18941885

1895-
Examples
1896-
---------
1886+
# Examples
1887+
# ---------
18971888

1898-
This function can be used like this:
1889+
# This function can be used like this:
18991890

1900-
.. code-block:: python
1891+
# .. code-block:: python
19011892

1902-
import grid2op
1893+
# import grid2op
19031894

1904-
# I create an environment
1905-
env = grid2op.make(""l2rpn_case14_sandbox"", test=True)
1895+
# # I create an environment
1896+
# env = grid2op.make(""l2rpn_case14_sandbox"", test=True)
19061897

1907-
# i set the thermal limit of each powerline to 20000 amps
1908-
env.set_thermal_limit([20000 for _ in range(env.n_line)])
1898+
# # i set the thermal limit of each powerline to 20000 amps
1899+
# env.set_thermal_limit([20000 for _ in range(env.n_line)])
19091900

1910-
Notes
1911-
-----
1912-
As of grid2op > 1.5.0, it is possible to set the thermal limit by using a dictionary with the keys being
1913-
the name of the powerline and the values the thermal limits.
1901+
# Notes
1902+
# -----
1903+
# As of grid2op > 1.5.0, it is possible to set the thermal limit by using a dictionary with the keys being
1904+
# the name of the powerline and the values the thermal limits.
19141905

1915-
"""
1916-
if self.__closed:
1917-
raise EnvError("This environment is closed, you cannot use it.")
1918-
if not self.__is_init:
1919-
raise Grid2OpException(
1920-
"Impossible to set the thermal limit to a non initialized Environment. "
1921-
"Have you called `env.reset()` after last game over ?"
1922-
)
1923-
# update n_line and name_line of ts_manager (old : self.ts_manager.n_line = -1 and self.ts_manager.name_line = None)
1924-
self.ts_manager.env_limits(thermal_limit=thermal_limit)
1925-
self.ts_manager.limits = self._thermal_limit_a
1926-
self.observation_space.set_thermal_limit(self._thermal_limit_a)
1906+
# """
1907+
# if self.__closed:
1908+
# raise EnvError("This environment is closed, you cannot use it.")
1909+
# if not self.__is_init:
1910+
# raise Grid2OpException(
1911+
# "Impossible to set the thermal limit to a non initialized Environment. "
1912+
# "Have you called `env.reset()` after last game over ?"
1913+
# )
1914+
# # update n_line and name_line of ts_manager (old : self.ts_manager.n_line = -1 and self.ts_manager.name_line = None)
1915+
# self.ts_manager.env_limits(thermal_limit=thermal_limit)
1916+
# self.observation_space.set_thermal_limit(thermal_limit=thermal_limit)
19271917

19281918
def _reset_redispatching(self):
19291919
# redispatching
@@ -2588,33 +2578,33 @@ def get_obs(self, _update_state=True, _do_copy=True):
25882578
else:
25892579
return self._last_obs
25902580

2591-
def get_thermal_limit(self):
2592-
"""
2593-
Get the current thermal limit in amps registered for the environment.
2581+
# def get_thermal_limit(self):
2582+
# """
2583+
# Get the current thermal limit in amps registered for the environment.
25942584

2595-
Examples
2596-
---------
2585+
# Examples
2586+
# ---------
25972587

2598-
It can be used like this:
2588+
# It can be used like this:
25992589

2600-
.. code-block:: python
2590+
# .. code-block:: python
26012591

2602-
import grid2op
2592+
# import grid2op
26032593

2604-
# I create an environment
2605-
env = grid2op.make("l2rpn_case14_sandbox")
2594+
# # I create an environment
2595+
# env = grid2op.make("l2rpn_case14_sandbox")
26062596

2607-
thermal_limits = env.get_thermal_limit()
2597+
# thermal_limits = env.get_thermal_limit()
26082598

2609-
"""
2610-
if self.__closed:
2611-
raise EnvError("This environment is closed, you cannot use it.")
2612-
if not self.__is_init:
2613-
raise EnvError(
2614-
"This environment is not initialized. It has no thermal limits. "
2615-
"Have you called `env.reset()` after last game over ?"
2616-
)
2617-
return 1.0 * self._thermal_limit_a
2599+
# """
2600+
# if self.__closed:
2601+
# raise EnvError("This environment is closed, you cannot use it.")
2602+
# if not self.__is_init:
2603+
# raise EnvError(
2604+
# "This environment is not initialized. It has no thermal limits. "
2605+
# "Have you called `env.reset()` after last game over ?"
2606+
# )
2607+
# return 1.0 * self._thermal_limit_a
26182608

26192609
def _withdraw_storage_losses(self):
26202610
"""
@@ -3155,7 +3145,7 @@ def _update_alert_properties(self, action, lines_attacked, subs_attacked):
31553145
def _aux_register_env_converged(self, disc_lines, action, init_line_status, new_p) -> Optional[Grid2OpException]:
31563146
beg_res = time.perf_counter()
31573147
# update the thermal limit, for DLR for example
3158-
self.ts_manager.update_limits(thermal_limit_a=self._thermal_limit_a) # old code : self.backend.update_thermal_limit(self)
3148+
self.ts_manager.update_limits(self) # old code : self.backend.update_thermal_limit(self)
31593149

31603150
overflow_lines = self.backend.get_line_overflow()
31613151
# save the current topology as "last" topology (for connected powerlines)
@@ -3252,11 +3242,10 @@ def _aux_register_env_converged(self, disc_lines, action, init_line_status, new_
32523242
self._time_extract_obs += time.perf_counter() - beg_res
32533243
return None
32543244

3255-
def _backend_next_grid_state(self):
3245+
def _protection_next_grid_state(self):
32563246
"""overlaoded in MaskedEnv"""
32573247
self._init_thermal_limit()
32583248
self._init_protection()
3259-
return self.protection.next_grid_state()
32603249

32613250
def _aux_run_pf_after_state_properly_set(
32623251
self, action, init_line_status, new_p, except_
@@ -3286,7 +3275,8 @@ def _aux_run_pf_after_state_properly_set(
32863275
try:
32873276
# compute the next _grid state
32883277
beg_pf = time.perf_counter()
3289-
disc_lines, detailed_info, conv_ = self._backend_next_grid_state()
3278+
self._protection_next_grid_state()
3279+
disc_lines, detailed_info, conv_ = self.protection.next_grid_state()
32903280
self._disc_lines[:] = disc_lines
32913281
self._time_powerflow += time.perf_counter() - beg_pf
32923282
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
@@ -85,6 +85,7 @@ def __init__(
8585
chronics_handler,
8686
backend,
8787
parameters,
88+
ts_manager: thermalLimits.ThermalLimits = None,
8889
name="unknown",
8990
n_busbar:N_BUSBAR_PER_SUB_TYPING=DEFAULT_N_BUSBAR_PER_SUB,
9091
allow_detachment:bool=DEFAULT_ALLOW_DETACHMENT,
@@ -207,19 +208,19 @@ def __init__(
207208
self._init_backend(
208209
chronics_handler,
209210
backend,
211+
ts_manager,
210212
names_chronics_to_backend,
211213
actionClass,
212214
observationClass,
213215
rewardClass,
214216
legalActClass,
215217
)
216-
self.ts_manager : thermalLimits.ThermalLimits = copy.deepcopy(self.ts_manager)
217-
self.protection : protectionScheme.DefaultProtection = copy.deepcopy(self.protection)
218218

219219
def _init_backend(
220220
self,
221221
chronics_handler,
222222
backend,
223+
ts_manager,
223224
names_chronics_to_backend,
224225
actionClass,
225226
observationClass,
@@ -249,7 +250,13 @@ def _init_backend(
249250
type(rewardClass)
250251
)
251252
)
252-
253+
#thermalLimits:
254+
ts_manager = ts_manager or self.ts_manager
255+
if not isinstance(ts_manager, thermalLimits.ThermalLimits):
256+
raise Grid2OpException(
257+
'Parameter "ts_manager" used to build the Environment should derived form the '
258+
'grid2op.Backend.thermalLimits class, type provided is "{}"'.format(type(ts_manager))
259+
)
253260
# backend
254261
if not isinstance(backend, Backend):
255262
raise Grid2OpException(
@@ -326,11 +333,13 @@ def _init_backend(
326333
self._line_status = np.ones(shape=self.n_line, dtype=dt_bool)
327334
self._disc_lines = np.zeros(shape=self.n_line, dtype=dt_int) - 1
328335

336+
self.ts_manager.n_line = self.n_line
337+
self.ts_manager.name_line = self.name_line
329338
if self._thermal_limit_a is None:
330-
self._thermal_limit_a = self.backend.thermal_limit_a.astype(dt_float)
339+
self.ts_manager.limits = self.backend.thermal_limit_a.astype(dt_float)
340+
self._thermal_limit_a = self.ts_manager.limits
331341
else:
332-
self.backend.set_thermal_limit(self._thermal_limit_a.astype(dt_float))
333-
342+
self.ts_manager.limits = self._thermal_limit_a.astype(dt_float)
334343
*_, tmp = self.backend.generators_info()
335344

336345
# rules of the game
@@ -1582,7 +1591,8 @@ def get_kwargs(self,
15821591
res["legalActClass"] = self._legalActClass
15831592
res["epsilon_poly"] = self._epsilon_poly
15841593
res["tol_poly"] = self._tol_poly
1585-
res["thermal_limit_a"] = self._thermal_limit_a
1594+
# res["thermal_limit_a"] = self._thermal_limit_a
1595+
res["ts_manager"] = self.ts_manager
15861596
res["voltagecontrolerClass"] = self._voltagecontrolerClass
15871597
res["other_rewards"] = {k: v.rewardClass for k, v in self.other_rewards.items()}
15881598
res["name"] = self.name
@@ -2204,7 +2214,8 @@ def get_params_for_runner(self):
22042214
if self.chronics_handler.max_iter is not None:
22052215
res["max_iter"] = self.chronics_handler.max_iter
22062216
res["gridStateclass_kwargs"] = dict_
2207-
res["thermal_limit_a"] = self._thermal_limit_a
2217+
# res["thermal_limit_a"] = self._thermal_limit_a
2218+
res["ts_manager"] = self.ts_manager
22082219
res["voltageControlerClass"] = self._voltagecontrolerClass
22092220
res["other_rewards"] = {k: v.rewardClass for k, v in self.other_rewards.items()}
22102221
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: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,8 +1069,9 @@ def make_from_dataset_path(
10691069
env._do_not_erase_local_dir_cls = do_not_erase_cls
10701070
# Update the thermal limit if any
10711071
if thermal_limits is not None:
1072-
env.set_thermal_limit(thermal_limits)
1073-
1072+
env.ts_manager.env_limits(thermal_limits)
1073+
env.observation_space.ts_manager.env_limits(env.ts_manager.limits)
1074+
10741075
# Set graph layout if not None and not an empty dict
10751076
if graph_layout is not None and graph_layout:
10761077
try:

0 commit comments

Comments
 (0)