1717from grid2op .Action .baseAction import BaseAction
1818from grid2op .Exceptions import AmbiguousAction
1919from grid2op .Action import CompleteAction
20+ from grid2op .Backend import PandaPowerBackend
2021from grid2op .Parameters import Parameters
2122from grid2op .Action ._backendAction import _BackendAction
2223
2324
25+ class _BackendNoDetach (PandaPowerBackend ):
26+ @classmethod
27+ def set_detachment_is_allowed (cls , detachment_is_allowed : bool ) -> None :
28+ cls .detachment_is_allowed = False
29+
30+ def load_grid (self , path , filename = None ):
31+ self .cannot_handle_detachment ()
32+ return super ().load_grid (path , filename )
33+
34+
2435class TestShedding (unittest .TestCase ):
2536
2637 def setUp (self ) -> None :
@@ -494,44 +505,52 @@ def test_storage(self):
494505class TestDetachmentRedisp (unittest .TestCase ):
495506 def setUp (self ):
496507 super ().setUp ()
497- p = Parameters ()
498- p .MAX_SUB_CHANGED = 999999
508+ param = Parameters ()
509+ param .MAX_SUB_CHANGED = 999999
499510 with warnings .catch_warnings ():
500511 warnings .filterwarnings ("ignore" )
501512 self .env = grid2op .make ("educ_case14_storage" ,
502- param = p ,
513+ param = param ,
503514 action_class = CompleteAction ,
504515 allow_detachment = True ,
505516 test = True ,
506517 _add_to_name = type (self ).__name__ )
507- type(self .env ).gen_pmax = 3. * np .array ([140. , 120. , 70. , 70. , 40. , 100. ])
508- type(self .env ).gen_max_ramp_down = type (self .env ).gen_pmax
509- type(self .env ).gen_max_ramp_up = type (self .env ).gen_pmax
518+ # assign new limits not to get limited by it
519+ new_vals = 3. * np .array ([140. , 120. , 70. , 70. , 40. , 100. ])
520+ li_all_cls = [type (self .env ),
521+ type (self .env .action_space ),
522+ self .env .action_space .actionClass ]
523+ for this_cls in li_all_cls :
524+ this_cls .gen_pmax = new_vals
525+ this_cls .gen_max_ramp_down = new_vals
526+ this_cls .gen_max_ramp_up = new_vals
527+ self .tol_redisp = max (self .env ._epsilon_poly , 1e-5 )
510528 obs = self .env .reset (seed = 0 , options = {"time serie id" : 0 }) # Reproducibility
511529 return super ().setUp ()
512530
513531 def tearDown (self ):
514532 self .env .close ()
515533 return super ().tearDown ()
516534
517- def test_no_redisp_no_detach (self ):
535+ def test_no_redisp_no_detach (self , tol = 1e-5 ):
518536 # just a basic test to get the values not modified
519537 obs , reward , done , info = self .env .step (self .env .action_space ())
520- assert abs (obs .gen_p [0 ] - 83.6 ) <= 1e-6 , f'{ obs .gen_p [0 ]} vs 83.6'
538+ assert abs (obs .gen_p [0 ] - 83.6 ) <= tol , f'{ obs .gen_p [0 ]} vs 83.6'
521539 obs , reward , done , info = self .env .step (self .env .action_space ())
522- assert abs (obs .gen_p [0 ] - 83.4 ) <= 1e-6 , f'{ obs .gen_p [0 ]} vs 83.4'
540+ assert abs (obs .gen_p [0 ] - 83.4 ) <= tol , f'{ obs .gen_p [0 ]} vs 83.4'
523541 obs , reward , done , info = self .env .step (self .env .action_space ())
524- assert abs (obs .gen_p [0 ] - 83.9 ) <= 1e-6 , f'{ obs .gen_p [0 ]} vs 83.9'
542+ assert abs (obs .gen_p [0 ] - 83.9 ) <= tol , f'{ obs .gen_p [0 ]} vs 83.9'
525543
526544 def test_detached_no_redisp_0 (self ):
527- gen_id = 1
545+ amount_redisp = 10.
528546 # first test: apply redispatch, then disco
529- act = self .env .action_space ({"redispatch" : [(0 , 1. )]})
547+ act = self .env .action_space ({"redispatch" : [(0 , amount_redisp )]})
530548 # act = self.env.action_space()
531549 obs , reward , done , info = self .env .step (act )
532550 assert not done
533- assert np .abs (obs .actual_dispatch [0 ] - 1. ) <= 1e-8 , f"{ obs .actual_dispatch [0 ]} vs 1."
534- assert np .abs (obs .actual_dispatch .sum () - 0. ) <= 1e-5 , f"{ obs .actual_dispatch .sum ()} vs 0."
551+ assert not info ["exception" ], info ["exception" ]
552+ assert np .abs (obs .actual_dispatch [0 ] - amount_redisp ) <= 1e-8 , f"{ obs .actual_dispatch [0 ]} vs { amount_redisp } "
553+ assert np .abs (obs .actual_dispatch .sum () - 0. ) <= self .tol_redisp , f"{ obs .actual_dispatch .sum ()} vs 0."
535554 # does not work, env chronics are not precise (even without redisp it's 2.9 MW or something)
536555 # assert abs(obs.gen_p_delta.sum() - 0.) <= 1., f"{obs.gen_p_delta.sum()}" # gen_p delta should be bellow 1 MW
537556
@@ -540,8 +559,8 @@ def test_detached_no_redisp_0(self):
540559 assert not done2 , info2 ["exception" ]
541560 assert np .abs (obs2 .gen_p [0 ] - 0. ) <= 1e-8 , f"{ obs2 .gen_p [0 ]} vs 0."
542561 assert np .abs (obs2 .actual_dispatch [0 ]) <= 1e-8 , f"{ obs2 .actual_dispatch [0 ]} vs 0."
543- # dispatch should compensate the 83.4 MW (base) and the +1 (of the dispatch)
544- assert np .abs (obs2 .actual_dispatch .sum () + (83.4 + 1 )) <= 1e-5 , f"{ obs2 .actual_dispatch .sum ()} vs { (83.4 + 1 )} "
562+ # dispatch should compensate the 83.4 MW (base)
563+ assert np .abs (obs2 .actual_dispatch .sum () - (83.4 )) <= self . tol_redisp , f"{ obs2 .actual_dispatch .sum ()} vs { (83.4 )} "
545564 # does not work, env chronics are not precise (even without redisp it's 2.9 MW or something)
546565 # assert abs(obs2.gen_p_delta.sum() - 0.) <= 1., f"{obs2.gen_p_delta.sum()}" # gen_p delta should be bellow 1 MW
547566
@@ -551,36 +570,100 @@ def test_detached_no_redisp_0(self):
551570 assert np .abs (obs3 .gen_p [0 ] - 0. ) <= 1e-8 , f"{ obs3 .gen_p [0 ]} vs 0."
552571 assert np .abs (obs3 .actual_dispatch [0 ]) <= 1e-8 , f"{ obs3 .actual_dispatch [0 ]} vs 0."
553572 # dispatch should compensate the 83.4 MW (base) and the +1 (of the dispatch)
554- assert np .abs (obs3 .actual_dispatch .sum () + (83.9 + 1 )) <= 1e-5 , f"{ obs3 .actual_dispatch .sum ()} vs { (83.9 + 1 )} "
573+ assert np .abs (obs3 .actual_dispatch .sum () - (83.9 )) <= self . tol_redisp , f"{ obs3 .actual_dispatch .sum ()} vs { (83.9 )} "
555574 # does not work, env chronics are not precise (even without redisp it's 2.9 MW or something)
556575
557576 def test_detached_no_redisp_1 (self ):
558577 # second test: apply disconnect, then redispatch
559578 act_redisp = self .env .action_space ({"redispatch" : [(0 , 1. )]})
560579 act_disc = self .env .action_space ({"set_bus" : {"generators_id" : [(0 , - 1 )]}})
561-
562580 obs , reward , done , info = self .env .step (act_disc )
563581 assert not done
564582 assert np .abs (obs .actual_dispatch [0 ] - 0. ) <= 1e-8 , f"{ obs .actual_dispatch [0 ]} vs 0."
565- assert np .abs (obs .actual_dispatch .sum () - 0. ) <= 1e-5 , f"{ obs .actual_dispatch .sum ()} vs 0. "
583+ assert np .abs (obs .actual_dispatch .sum () - 83.6 ) <= self . tol_redisp , f"{ obs .actual_dispatch .sum ()} vs 83.6 "
566584 assert np .abs (obs .gen_p [0 ] - 0. ) <= 1e-8 , f"{ obs .gen_p [0 ]} vs 0."
567585
568586 obs2 , r2 , done2 , info2 = self .env .step (act_redisp )
569587 assert not done2 , info2 ["exception" ]
570588 assert np .abs (obs2 .actual_dispatch [0 ]) <= 1e-8 , f"{ obs2 .actual_dispatch [0 ]} vs 0."
571- assert np .abs (obs2 .actual_dispatch .sum () - 0. ) <= 1e-5 , f"{ obs2 .actual_dispatch .sum ()} vs 0. "
589+ assert np .abs (obs2 .actual_dispatch .sum () - 83.4 ) <= self . tol_redisp , f"{ obs2 .actual_dispatch .sum ()} vs 83.4 "
572590
591+ obs3 , r3 , done3 , info3 = self .env .step (self .env .action_space ())
592+ assert not done3 , info3 ["exception" ]
593+ assert np .abs (obs3 .actual_dispatch [0 ]) <= 1e-8 , f"{ obs3 .actual_dispatch [0 ]} vs 0."
594+ assert abs (obs3 .gen_p [0 ]) <= 1e-8 , f"{ obs3 .gen_p [0 ]} vs 0."
595+ assert np .abs (obs3 .actual_dispatch .sum () - 83.9 ) <= self .tol_redisp , f"{ obs3 .actual_dispatch .sum ()} vs 83.9"
596+
597+ def test_detached_reattached (self ):
598+ # second test: apply redisp, then disco, then reco
599+ act_redisp = self .env .action_space ({"redispatch" : [(0 , 1. )]})
600+ act_disc = self .env .action_space ({"set_bus" : {"generators_id" : [(0 , - 1 )]}})
601+ act_reco = self .env .action_space ({"set_bus" : {"generators_id" : [(0 , 1 )]}})
602+ obs , reward , done , info = self .env .step (act_redisp )
603+ assert not done
604+ assert np .abs (obs .actual_dispatch [0 ] - 1. ) <= 1e-8 , f"{ obs .actual_dispatch [0 ]} vs 0."
605+ assert np .abs (obs .actual_dispatch .sum () - 0. ) <= self .tol_redisp , f"{ obs .actual_dispatch .sum ()} vs 0."
606+
607+ obs2 , r2 , done2 , info2 = self .env .step (act_disc )
608+ assert not done2 , info2 ["exception" ]
609+ assert np .abs (obs2 .actual_dispatch [0 ]) <= 1e-8 , f"{ obs2 .actual_dispatch [0 ]} vs 0."
610+ assert np .abs (obs2 .actual_dispatch .sum () - 83.4 ) <= self .tol_redisp , f"{ obs2 .actual_dispatch .sum ()} vs 83.4"
611+
612+ obs3 , r3 , done3 , info3 = self .env .step (act_reco )
613+ assert not done3 , info3 ["exception" ]
614+ assert np .abs (obs3 .actual_dispatch [0 ] - 1. ) <= self .tol_redisp , f"{ obs3 .actual_dispatch [0 ]} vs 1."
615+ assert abs (obs3 .gen_p [0 ] - (83.9 + 1. ) ) <= self .tol_redisp , f"{ obs3 .gen_p [0 ]} vs 84.9"
616+ assert np .abs (obs3 .actual_dispatch .sum () - 0. ) <= self .tol_redisp , f"{ obs3 .actual_dispatch .sum ()} vs 83.9"
617+
618+
619+ class TestSheddingcorrectlySet (unittest .TestCase ):
620+ def test_shedding_env1_bk1 (self ):
621+ with warnings .catch_warnings ():
622+ warnings .filterwarnings ("ignore" )
623+ env = grid2op .make ("educ_case14_storage" ,
624+ action_class = CompleteAction ,
625+ allow_detachment = True ,
626+ test = True ,
627+ _add_to_name = type (self ).__name__ + "test_shedding_env1_bk1" )
628+ assert type (env ).detachment_is_allowed
629+
630+ def test_shedding_env0_bk1 (self ):
631+ with warnings .catch_warnings ():
632+ warnings .filterwarnings ("ignore" )
633+ env = grid2op .make ("educ_case14_storage" ,
634+ action_class = CompleteAction ,
635+ allow_detachment = False ,
636+ test = True ,
637+ _add_to_name = type (self ).__name__ + "test_shedding_env0_bk1" )
638+ assert not type (env ).detachment_is_allowed
639+
640+ def test_shedding_env1_bk0 (self ):
641+ with warnings .catch_warnings ():
642+ warnings .filterwarnings ("ignore" )
643+ env = grid2op .make ("educ_case14_storage" ,
644+ action_class = CompleteAction ,
645+ allow_detachment = True ,
646+ test = True ,
647+ backend = _BackendNoDetach (),
648+ _add_to_name = type (self ).__name__ + "test_shedding_env1_bk1" )
649+ assert not type (env ).detachment_is_allowed
650+
651+ def test_shedding_env0_bk0 (self ):
652+ with warnings .catch_warnings ():
653+ warnings .filterwarnings ("ignore" )
654+ env = grid2op .make ("educ_case14_storage" ,
655+ action_class = CompleteAction ,
656+ allow_detachment = False ,
657+ test = True ,
658+ backend = _BackendNoDetach (),
659+ _add_to_name = type (self ).__name__ + "test_shedding_env0_bk1" )
660+ assert not type (env ).detachment_is_allowed
573661
574662# TODO with the env parameters STOP_EP_IF_GEN_BREAK_CONSTRAINTS and ENV_DOES_REDISPATCHING
575- # TODO when something is "re attached" on the grid
576- # TODO check gen detached does not participate in redisp
577663
578664# TODO shedding in simulate
579665# TODO shedding in Simulator !
580666
581- # TODO Shedding: test when backend does not support it is not set
582- # TODO shedding: test when user deactivates it it is not set
583-
584667# TODO Shedding: Runner
585668
586669# TODO Shedding: environment copied
0 commit comments