Skip to content

Commit c9de7aa

Browse files
authored
Merge pull request #610 from BDonnot/master
Ready for version 1.10.2
2 parents 0183478 + 2acffe9 commit c9de7aa

File tree

6 files changed

+177
-27
lines changed

6 files changed

+177
-27
lines changed

CHANGELOG.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@ Change Log
3131
- [???] "asynch" multienv
3232
- [???] properly model interconnecting powerlines
3333

34-
[1.10.2] - 2024-xx-yy
34+
[1.10.2] - 2024-05-27
3535
-------------------------
3636
- [BREAKING] the `runner.run_one_episode` now returns an extra first argument:
3737
`chron_id, chron_name, cum_reward, timestep, max_ts = runner.run_one_episode()` which
3838
is consistant with `runner.run(...)` (previously it returned only
3939
`chron_name, cum_reward, timestep, max_ts = runner.run_one_episode()`)
4040
- [BREAKING] the runner now has no `chronics_handler` attribute (`runner.chronics_handler`
4141
is not defined)
42+
- [BREAKING] now grid2op forces everything to be connected at busbar 1 if
43+
`param.IGNORE_INITIAL_STATE_TIME_SERIE == True` (**NOT** the default) and
44+
no initial state is provided in `env.reset(..., options={"init state": ...})`
4245
- [ADDED] it is now possible to call `change_reward` directly from
4346
an observation (no need to do it from the Observation Space)
4447
- [ADDED] method to change the reward from the observation (observation_space
@@ -55,6 +58,11 @@ Change Log
5558
- [ADDED] some more type hints in the `GridObject` class
5659
- [ADDED] Possibility to deactive the support of shunts if subclassing `PandaPowerBackend`
5760
(and add some basic tests)
61+
- [ADDED] a parameters (`param.IGNORE_INITIAL_STATE_TIME_SERIE`) which defaults to
62+
`False` that tells the environment whether it should ignore the
63+
initial state of the grid provided in the time series.
64+
By default it is NOT ignored, it is taken into account
65+
(for the environment that supports this feature)
5866
- [FIXED] a small issue that could lead to having
5967
"redispatching_unit_commitment_availble" flag set even if the redispatching
6068
data was not loaded correctly

grid2op/Chronics/gridValue.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,11 @@ def get_init_action(self, names_chronics_to_backend: Dict[Literal["loads", "prod
833833
For later version, we let the possibility to set, in the "time series folder" (or time series generators)
834834
the possibility to change the initial condition of the grid.
835835
836+
Notes
837+
-----
838+
If the environment parameters :attr:`grid2op.Parameters.Parameters.IGNORE_INITIAL_STATE_TIME_SERIE`
839+
is set to `True` (not its default value) then this is ignored.
840+
836841
Returns
837842
-------
838843
grid2op.Action.playableAction.PlayableAction

grid2op/Environment/environment.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -834,11 +834,22 @@ def reset_grid(self,
834834

835835
self._backend_action = self._backend_action_class()
836836
self.nb_time_step = -1 # to have init obs at step 1 (and to prevent 'setting to proper state' "action" to be illegal)
837-
init_action : BaseAction = self.chronics_handler.get_init_action(self._names_chronics_to_backend)
837+
init_action = None
838+
if not self._parameters.IGNORE_INITIAL_STATE_TIME_SERIE:
839+
# load the initial state from the time series (default)
840+
# TODO logger: log that
841+
init_action : BaseAction = self.chronics_handler.get_init_action(self._names_chronics_to_backend)
842+
else:
843+
# do as if everything was connected to busbar 1
844+
# TODO logger: log that
845+
init_action = self._helper_action_env({"set_bus": np.ones(type(self).dim_topo, dtype=dt_int)})
846+
if type(self).shunts_data_available:
847+
init_action += self._helper_action_env({"shunt": {"set_bus": np.ones(type(self).n_shunt, dtype=dt_int)}})
838848
if init_action is None:
839849
# default behaviour for grid2op < 1.10.2
840850
init_action = self._helper_action_env({})
841851
else:
852+
# remove the "change part" of the action
842853
init_action.remove_change()
843854

844855
if init_act_opt is not None:

grid2op/Parameters.py

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,19 @@ class Parameters:
148148
MAX_SIMULATE_PER_EPISODE: ``int``
149149
Maximum number of calls to `obs.simuate(...)` allowed per episode (reset each "env.simulate(...)"). Defaults to -1 meaning "as much as you want".
150150
151+
IGNORE_INITIAL_STATE_TIME_SERIE: ``bool``
152+
If set to True (which is NOT the default), then the initial state of the grid
153+
will always be "everything connected" and "everything connected to busbar 1"
154+
regardless of the information present in the time series (see
155+
:func:`grid2op.Chronics.GridValue.get_init_action`)
156+
157+
.. versionadded:: 1.10.2
158+
159+
.. note::
160+
This flag has no impact if an initial state is set through a call to
161+
`env.reset(options={"init state": ...})` (see doc of :func:`grid2op.Environment.Environment.reset`
162+
for more information)
163+
151164
"""
152165

153166
def __init__(self, parameters_path=None):
@@ -227,6 +240,8 @@ def __init__(self, parameters_path=None):
227240
else:
228241
warn_msg = "Parameters: the file {} is not found. Continuing with default parameters."
229242
warnings.warn(warn_msg.format(parameters_path))
243+
244+
self.IGNORE_INITIAL_STATE_TIME_SERIE = False
230245

231246
@staticmethod
232247
def _isok_txt(arg):
@@ -368,6 +383,11 @@ def init_from_dict(self, dict_):
368383
if "MAX_SIMULATE_PER_EPISODE" in dict_:
369384
self.MAX_SIMULATE_PER_EPISODE = dt_int(dict_["MAX_SIMULATE_PER_EPISODE"])
370385

386+
if "IGNORE_INITIAL_STATE_TIME_SERIE" in dict_:
387+
self.IGNORE_INITIAL_STATE_TIME_SERIE = Parameters._isok_txt(
388+
dict_["IGNORE_INITIAL_STATE_TIME_SERIE"]
389+
)
390+
371391
authorized_keys = set(self.__dict__.keys())
372392
authorized_keys = authorized_keys | {
373393
"NB_TIMESTEP_POWERFLOW_ALLOWED",
@@ -416,6 +436,7 @@ def to_dict(self):
416436
res["ALERT_TIME_WINDOW"] = int(self.ALERT_TIME_WINDOW)
417437
res["MAX_SIMULATE_PER_STEP"] = int(self.MAX_SIMULATE_PER_STEP)
418438
res["MAX_SIMULATE_PER_EPISODE"] = int(self.MAX_SIMULATE_PER_EPISODE)
439+
res["IGNORE_INITIAL_STATE_TIME_SERIE"] = int(self.IGNORE_INITIAL_STATE_TIME_SERIE)
419440
return res
420441

421442
def init_from_json(self, json_path):
@@ -470,16 +491,18 @@ def check_valid(self):
470491
471492
Raises
472493
-------
473-
An exception if the parameter is not valid
494+
An exception (`RuntimeError`) if the parameter is not valid
495+
474496
"""
497+
475498
try:
476499
if not isinstance(self.NO_OVERFLOW_DISCONNECTION, (bool, dt_bool)):
477500
raise RuntimeError("NO_OVERFLOW_DISCONNECTION should be a boolean")
478501
self.NO_OVERFLOW_DISCONNECTION = dt_bool(self.NO_OVERFLOW_DISCONNECTION)
479502
except Exception as exc_:
480503
raise RuntimeError(
481504
f'Impossible to convert NO_OVERFLOW_DISCONNECTION to bool with error \n:"{exc_}"'
482-
)
505+
) from exc_
483506

484507
try:
485508
self.NB_TIMESTEP_OVERFLOW_ALLOWED = int(
@@ -491,7 +514,7 @@ def check_valid(self):
491514
except Exception as exc_:
492515
raise RuntimeError(
493516
f'Impossible to convert NB_TIMESTEP_OVERFLOW_ALLOWED to int with error \n:"{exc_}"'
494-
)
517+
) from exc_
495518

496519
if self.NB_TIMESTEP_OVERFLOW_ALLOWED < 0:
497520
raise RuntimeError(
@@ -505,7 +528,7 @@ def check_valid(self):
505528
except Exception as exc_:
506529
raise RuntimeError(
507530
f'Impossible to convert NB_TIMESTEP_RECONNECTION to int with error \n:"{exc_}"'
508-
)
531+
) from exc_
509532
if self.NB_TIMESTEP_RECONNECTION < 0:
510533
raise RuntimeError("NB_TIMESTEP_RECONNECTION < 0., this should be >= 0.")
511534
try:
@@ -514,7 +537,7 @@ def check_valid(self):
514537
except Exception as exc_:
515538
raise RuntimeError(
516539
f'Impossible to convert NB_TIMESTEP_COOLDOWN_LINE to int with error \n:"{exc_}"'
517-
)
540+
) from exc_
518541
if self.NB_TIMESTEP_COOLDOWN_LINE < 0:
519542
raise RuntimeError("NB_TIMESTEP_COOLDOWN_LINE < 0., this should be >= 0.")
520543
try:
@@ -525,7 +548,7 @@ def check_valid(self):
525548
except Exception as exc_:
526549
raise RuntimeError(
527550
f'Impossible to convert NB_TIMESTEP_COOLDOWN_SUB to int with error \n:"{exc_}"'
528-
)
551+
) from exc_
529552
if self.NB_TIMESTEP_COOLDOWN_SUB < 0:
530553
raise RuntimeError("NB_TIMESTEP_COOLDOWN_SUB < 0., this should be >= 0.")
531554
try:
@@ -536,7 +559,7 @@ def check_valid(self):
536559
except Exception as exc_:
537560
raise RuntimeError(
538561
f'Impossible to convert HARD_OVERFLOW_THRESHOLD to float with error \n:"{exc_}"'
539-
)
562+
) from exc_
540563
if self.HARD_OVERFLOW_THRESHOLD < 1.0:
541564
raise RuntimeError(
542565
"HARD_OVERFLOW_THRESHOLD < 1., this should be >= 1. (use env.set_thermal_limit "
@@ -551,7 +574,7 @@ def check_valid(self):
551574
except Exception as exc_:
552575
raise RuntimeError(
553576
f'Impossible to convert SOFT_OVERFLOW_THRESHOLD to float with error \n:"{exc_}"'
554-
)
577+
) from exc_
555578
if self.SOFT_OVERFLOW_THRESHOLD < 1.0:
556579
raise RuntimeError(
557580
"SOFT_OVERFLOW_THRESHOLD < 1., this should be >= 1. (use env.set_thermal_limit "
@@ -570,14 +593,14 @@ def check_valid(self):
570593
except Exception as exc_:
571594
raise RuntimeError(
572595
f'Impossible to convert ENV_DC to bool with error \n:"{exc_}"'
573-
)
596+
) from exc_
574597
try:
575598
self.MAX_SUB_CHANGED = int(self.MAX_SUB_CHANGED) # to raise if numpy array
576599
self.MAX_SUB_CHANGED = dt_int(self.MAX_SUB_CHANGED)
577600
except Exception as exc_:
578601
raise RuntimeError(
579602
f'Impossible to convert MAX_SUB_CHANGED to int with error \n:"{exc_}"'
580-
)
603+
) from exc_
581604
if self.MAX_SUB_CHANGED < 0:
582605
raise RuntimeError(
583606
"MAX_SUB_CHANGED should be >=0 (or -1 if you want to be able to change every "
@@ -591,7 +614,7 @@ def check_valid(self):
591614
except Exception as exc_:
592615
raise RuntimeError(
593616
f'Impossible to convert MAX_LINE_STATUS_CHANGED to int with error \n:"{exc_}"'
594-
)
617+
) from exc_
595618
if self.MAX_LINE_STATUS_CHANGED < 0:
596619
raise RuntimeError(
597620
"MAX_LINE_STATUS_CHANGED should be >=0 "
@@ -604,7 +627,7 @@ def check_valid(self):
604627
except Exception as exc_:
605628
raise RuntimeError(
606629
f'Impossible to convert IGNORE_MIN_UP_DOWN_TIME to bool with error \n:"{exc_}"'
607-
)
630+
) from exc_
608631
try:
609632
if not isinstance(self.ALLOW_DISPATCH_GEN_SWITCH_OFF, (bool, dt_bool)):
610633
raise RuntimeError("ALLOW_DISPATCH_GEN_SWITCH_OFF should be a boolean")
@@ -614,7 +637,7 @@ def check_valid(self):
614637
except Exception as exc_:
615638
raise RuntimeError(
616639
f'Impossible to convert ALLOW_DISPATCH_GEN_SWITCH_OFF to bool with error \n:"{exc_}"'
617-
)
640+
) from exc_
618641
try:
619642
if not isinstance(
620643
self.LIMIT_INFEASIBLE_CURTAILMENT_STORAGE_ACTION, (bool, dt_bool)
@@ -628,7 +651,7 @@ def check_valid(self):
628651
except Exception as exc_:
629652
raise RuntimeError(
630653
f'Impossible to convert LIMIT_INFEASIBLE_CURTAILMENT_STORAGE_ACTION to bool with error \n:"{exc_}"'
631-
)
654+
) from exc_
632655

633656
try:
634657
self.INIT_STORAGE_CAPACITY = float(
@@ -638,16 +661,16 @@ def check_valid(self):
638661
except Exception as exc_:
639662
raise RuntimeError(
640663
f'Impossible to convert INIT_STORAGE_CAPACITY to float with error \n:"{exc_}"'
641-
)
664+
) from exc_
642665

643666
if self.INIT_STORAGE_CAPACITY < 0.0:
644667
raise RuntimeError(
645668
"INIT_STORAGE_CAPACITY < 0., this should be within range [0., 1.]"
646-
)
669+
) from exc_
647670
if self.INIT_STORAGE_CAPACITY > 1.0:
648671
raise RuntimeError(
649672
"INIT_STORAGE_CAPACITY > 1., this should be within range [0., 1.]"
650-
)
673+
) from exc_
651674

652675
try:
653676
if not isinstance(self.ACTIVATE_STORAGE_LOSS, (bool, dt_bool)):
@@ -656,26 +679,26 @@ def check_valid(self):
656679
except Exception as exc_:
657680
raise RuntimeError(
658681
f'Impossible to convert ACTIVATE_STORAGE_LOSS to bool with error \n:"{exc_}"'
659-
)
682+
) from exc_
660683

661684
try:
662685
self.ALARM_WINDOW_SIZE = dt_int(self.ALARM_WINDOW_SIZE)
663686
except Exception as exc_:
664687
raise RuntimeError(
665688
f'Impossible to convert ALARM_WINDOW_SIZE to int with error \n:"{exc_}"'
666-
)
689+
) from exc_
667690
try:
668691
self.ALARM_BEST_TIME = dt_int(self.ALARM_BEST_TIME)
669692
except Exception as exc_:
670693
raise RuntimeError(
671694
f'Impossible to convert ALARM_BEST_TIME to int with error \n:"{exc_}"'
672-
)
695+
) from exc_
673696
try:
674697
self.ALERT_TIME_WINDOW = dt_int(self.ALERT_TIME_WINDOW)
675698
except Exception as exc_:
676699
raise RuntimeError(
677700
f'Impossible to convert ALERT_TIME_WINDOW to int with error \n:"{exc_}"'
678-
)
701+
) from exc_
679702

680703
if self.ALARM_WINDOW_SIZE <= 0:
681704
raise RuntimeError("self.ALARM_WINDOW_SIZE should be a positive integer !")
@@ -692,7 +715,7 @@ def check_valid(self):
692715
except Exception as exc_:
693716
raise RuntimeError(
694717
f'Impossible to convert MAX_SIMULATE_PER_STEP to int with error \n:"{exc_}"'
695-
)
718+
) from exc_
696719
if self.MAX_SIMULATE_PER_STEP <= -2:
697720
raise RuntimeError(
698721
f"self.MAX_SIMULATE_PER_STEP should be a positive integer or -1, we found {self.MAX_SIMULATE_PER_STEP}"
@@ -706,8 +729,15 @@ def check_valid(self):
706729
except Exception as exc_:
707730
raise RuntimeError(
708731
f'Impossible to convert MAX_SIMULATE_PER_EPISODE to int with error \n:"{exc_}"'
709-
)
732+
) from exc_
710733
if self.MAX_SIMULATE_PER_EPISODE <= -2:
711734
raise RuntimeError(
712735
f"self.MAX_SIMULATE_PER_EPISODE should be a positive integer or -1, we found {self.MAX_SIMULATE_PER_EPISODE}"
713736
)
737+
738+
try:
739+
self.IGNORE_INITIAL_STATE_TIME_SERIE = dt_bool(self.IGNORE_INITIAL_STATE_TIME_SERIE)
740+
except Exception as exc_:
741+
raise RuntimeError(
742+
f'Impossible to convert IGNORE_INITIAL_STATE_TIME_SERIE to bool with error \n:"{exc_}"'
743+
) from exc_

grid2op/tests/test_Observation.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2975,6 +2975,7 @@ def setUp(self):
29752975
"educ_case14_storage", test=True, action_class=PlayableAction,
29762976
_add_to_name=type(self).__name__
29772977
)
2978+
self.env.reset(seed=0, options={"time serie id": 0})
29782979
self.obs = self._make_forecast_perfect(self.env)
29792980
self.sim_obs = None
29802981
self.step_obs = None

0 commit comments

Comments
 (0)