Skip to content

Commit d1586d3

Browse files
committed
adding test for issue 616
1 parent 017128d commit d1586d3

File tree

1 file changed

+362
-0
lines changed

1 file changed

+362
-0
lines changed

grid2op/tests/test_issue_616.py

Lines changed: 362 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,362 @@
1+
# Copyright (c) 2024, RTE (https://www.rte-france.com)
2+
# See AUTHORS.txt and https://github.com/rte-france/Grid2Op/pull/319
3+
# This Source Code Form is subject to the terms of the Mozilla Public License, version 2.0.
4+
# If a copy of the Mozilla Public License, version 2.0 was not distributed with this file,
5+
# you can obtain one at http://mozilla.org/MPL/2.0/.
6+
# SPDX-License-Identifier: MPL-2.0
7+
# This file is part of Grid2Op, Grid2Op a testbed platform to model sequential decision making in power systems.
8+
9+
import unittest
10+
import grid2op
11+
import tempfile
12+
import numpy as np
13+
import re
14+
import os
15+
import json
16+
import warnings
17+
18+
from grid2op.Chronics import (MultifolderWithCache,
19+
GridStateFromFileWithForecastsWithMaintenance,
20+
FromHandlers)
21+
from grid2op.Chronics.handlers import (CSVHandler,
22+
NoisyForecastHandler,
23+
LoadQFromPHandler,
24+
JSONMaintenanceHandler)
25+
26+
from grid2op.Runner import Runner
27+
28+
class Issue616Tester(unittest.TestCase):
29+
def setUp(self):
30+
self.env_name = "l2rpn_case14_sandbox"
31+
# create first env
32+
with warnings.catch_warnings():
33+
warnings.filterwarnings("ignore")
34+
env = grid2op.make(self.env_name,
35+
test=True)
36+
37+
# hack for adding maintenance
38+
dict_maint = {
39+
"maintenance_starting_hour": 1,
40+
"maintenance_ending_hour": 2,
41+
"line_to_maintenance": ["1_2_2", "1_4_4", "9_10_12", "12_13_14"],
42+
"daily_proba_per_month_maintenance": [0.7 for _ in range(12)],
43+
"max_daily_number_per_month_maintenance": [1 for _ in range(12)],
44+
"maintenance_day_of_week": list(range(7))
45+
}
46+
self.tmp_files = [os.path.join(env.get_path_env(),
47+
"chronics", "0000", "maintenance_meta.json"),
48+
os.path.join(env.get_path_env(),
49+
"chronics", "0001", "maintenance_meta.json"),
50+
os.path.join(env.get_path_env(),
51+
"chronics", "0000", "maintenance_meta.json"),
52+
]
53+
for path in self.tmp_files:
54+
with open(path, "w", encoding="utf-8") as f:
55+
json.dump(fp=f, obj=dict_maint)
56+
env.close()
57+
# create the env with the maintenance
58+
with warnings.catch_warnings():
59+
warnings.filterwarnings("ignore")
60+
self.env_bug = grid2op.make(self.env_name,
61+
chronics_class=MultifolderWithCache,
62+
data_feeding_kwargs={"gridvalueClass": GridStateFromFileWithForecastsWithMaintenance},
63+
test=True
64+
)
65+
self.env_bug.chronics_handler.reset()
66+
67+
# store the normal maintenance schedule:
68+
self.maint_ref = (np.array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
69+
11, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
70+
298, 299]) + 12,
71+
np.array([4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2,
72+
2, 2, 2, 2, 2, 2]))
73+
74+
def tearDown(self) -> None:
75+
self.env_bug.close()
76+
for el in self.tmp_files:
77+
if os.path.exists(el):
78+
os.remove(el)
79+
return super().tearDown()
80+
81+
def test_reset(self):
82+
"""test that the seed is used correctly in env.reset"""
83+
obs = self.env_bug.reset(seed=0, options={"time serie id": 0})
84+
maint_ref = 1. * self.env_bug.chronics_handler.real_data.data.maintenance
85+
86+
obs = self.env_bug.reset(seed=1, options={"time serie id": 0})
87+
maint_1 = 1. * self.env_bug.chronics_handler.real_data.data.maintenance
88+
89+
obs = self.env_bug.reset(seed=0, options={"time serie id": 0})
90+
maint_0 = 1. * self.env_bug.chronics_handler.real_data.data.maintenance
91+
92+
assert (maint_ref == maint_0).all()
93+
assert (maint_ref != maint_1).any()
94+
assert (maint_ref.nonzero()[0] == self.maint_ref[0]).all()
95+
assert (maint_ref.nonzero()[1] == self.maint_ref[1]).all()
96+
97+
def test_runner(self):
98+
"""test the runner behaves correctly"""
99+
with warnings.catch_warnings():
100+
warnings.filterwarnings("ignore")
101+
runner = Runner(**self.env_bug.get_params_for_runner())
102+
res = runner.run(nb_episode=3,
103+
env_seeds=[0, 1, 0],
104+
max_iter=5,
105+
add_detailed_output=True)
106+
107+
maint_ref = np.array([ -1, -1, 300, -1, 12, -1, -1, -1, -1, -1,
108+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
109+
dtype=np.int32)
110+
assert (res[0][-1].observations[0].time_next_maintenance == maint_ref).all()
111+
assert (res[0][-1].observations[0].time_next_maintenance != res[1][-1].observations[0].time_next_maintenance).any()
112+
assert (res[0][-1].observations[0].time_next_maintenance == res[2][-1].observations[0].time_next_maintenance).all()
113+
114+
def test_chronics_handler_twice_reset(self):
115+
"""test the same results is obtained if the chronics handler is reset twice"""
116+
obs = self.env_bug.reset(seed=0, options={"time serie id": 0})
117+
maint_ref = 1. * self.env_bug.chronics_handler.real_data.data.maintenance
118+
assert (maint_ref.nonzero()[0] == self.maint_ref[0]).all()
119+
assert (maint_ref.nonzero()[1] == self.maint_ref[1]).all()
120+
121+
self.env_bug.chronics_handler.reset()
122+
maint_ref = 1. * self.env_bug.chronics_handler.real_data.data.maintenance
123+
assert (maint_ref.nonzero()[0] == self.maint_ref[0]).all()
124+
assert (maint_ref.nonzero()[1] == self.maint_ref[1]).all()
125+
126+
127+
class Issue616WithHandlerTester(unittest.TestCase):
128+
def setUp(self):
129+
self.env_name = "l2rpn_case14_sandbox"
130+
hs_ = [5*(i+1) for i in range(12)]
131+
132+
# create first env
133+
with warnings.catch_warnings():
134+
warnings.filterwarnings("ignore")
135+
env = grid2op.make(self.env_name,
136+
test=True)
137+
138+
# hack for adding maintenance
139+
dict_maint = {
140+
"maintenance_starting_hour": 1,
141+
"maintenance_ending_hour": 2,
142+
"line_to_maintenance": ["1_2_2", "1_4_4", "9_10_12", "12_13_14"],
143+
"daily_proba_per_month_maintenance": [0.7 for _ in range(12)],
144+
"max_daily_number_per_month_maintenance": [1 for _ in range(12)],
145+
"maintenance_day_of_week": list(range(7))
146+
}
147+
self.tmp_json = tempfile.NamedTemporaryFile(dir=os.path.join(env.get_path_env(), "chronics", "0000"),
148+
prefix="maintenance_meta",
149+
suffix=".json")
150+
with open(self.tmp_json.name, "w", encoding="utf-8") as f:
151+
json.dump(fp=f, obj=dict_maint)
152+
153+
# uses the default noise: sqrt(horizon) * 0.01 : error of 8% 1h ahead
154+
with warnings.catch_warnings():
155+
warnings.filterwarnings("ignore")
156+
self.env_bug = grid2op.make(self.env_name,
157+
chronics_class=MultifolderWithCache,
158+
data_feeding_kwargs={"gridvalueClass": FromHandlers,
159+
"gen_p_handler": CSVHandler("prod_p"),
160+
"load_p_handler": CSVHandler("load_p"),
161+
"gen_v_handler": CSVHandler("prod_v"),
162+
"load_q_handler": LoadQFromPHandler("load_q"),
163+
"h_forecast": hs_,
164+
"maintenance_handler": JSONMaintenanceHandler(json_file_name=self.tmp_json.name),
165+
"gen_p_for_handler": NoisyForecastHandler("prod_p_forecasted"),
166+
"load_p_for_handler": NoisyForecastHandler("load_p_forecasted"),
167+
"load_q_for_handler": NoisyForecastHandler("load_q_forecasted"),
168+
}
169+
)
170+
self.env_bug.chronics_handler.reset()
171+
172+
# store the normal maintenance schedule:
173+
self.maint_ref = (np.array([ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
174+
23, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309,
175+
310, 311, 588, 589, 590, 591, 592, 593, 594, 595, 596,
176+
597, 598, 599, 876, 877, 878, 879, 880, 881, 882, 883,
177+
884, 885, 886, 887, 1164, 1165, 1166, 1167, 1168, 1169, 1170,
178+
1171, 1172, 1173, 1174, 1175, 1452, 1453, 1454, 1455, 1456, 1457,
179+
1458, 1459, 1460, 1461, 1462, 1463, 1740, 1741, 1742, 1743, 1744,
180+
1745, 1746, 1747, 1748, 1749, 1750, 1751, 2028, 2029, 2030, 2031,
181+
2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2316, 2317, 2318,
182+
2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2604, 2605,
183+
2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2892,
184+
2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903,
185+
3180, 3181, 3182, 3183, 3184, 3185, 3186, 3187, 3188, 3189, 3190,
186+
3191, 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477,
187+
3478, 3479, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764,
188+
3765, 3766, 3767, 4044, 4045, 4046, 4047, 4048, 4049, 4050, 4051,
189+
4052, 4053, 4054, 4055, 4332, 4333, 4334, 4335, 4336, 4337, 4338,
190+
4339, 4340, 4341, 4342, 4343, 4620, 4621, 4622, 4623, 4624, 4625,
191+
4626, 4627, 4628, 4629, 4630, 4631, 4908, 4909, 4910, 4911, 4912,
192+
4913, 4914, 4915, 4916, 4917, 4918, 4919, 5196, 5197, 5198, 5199,
193+
5200, 5201, 5202, 5203, 5204, 5205, 5206, 5207, 5484, 5485, 5486,
194+
5487, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495, 5772, 5773,
195+
5774, 5775, 5776, 5777, 5778, 5779, 5780, 5781, 5782, 5783, 6060,
196+
6061, 6062, 6063, 6064, 6065, 6066, 6067, 6068, 6069, 6070, 6071,
197+
6348, 6349, 6350, 6351, 6352, 6353, 6354, 6355, 6356, 6357, 6358,
198+
6359, 6636, 6637, 6638, 6639, 6640, 6641, 6642, 6643, 6644, 6645,
199+
6646, 6647, 6924, 6925, 6926, 6927, 6928, 6929, 6930, 6931, 6932,
200+
6933, 6934, 6935, 7212, 7213, 7214, 7215, 7216, 7217, 7218, 7219,
201+
7220, 7221, 7222, 7223, 7500, 7501, 7502, 7503, 7504, 7505, 7506,
202+
7507, 7508, 7509, 7510, 7511, 7788, 7789, 7790, 7791, 7792, 7793,
203+
7794, 7795, 7796, 7797, 7798, 7799]),
204+
np.array([12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 14, 14, 14, 14, 14,
205+
14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
206+
12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2, 2,
207+
2, 2, 2, 2, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14,
208+
14, 14, 14, 14, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
209+
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
210+
12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
211+
2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2,
212+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
213+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 12,
214+
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2,
215+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
216+
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2,
217+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
218+
2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2,
219+
2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4,
220+
4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4,
221+
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 14, 14, 14, 14, 14, 14,
222+
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
223+
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14]))
224+
225+
self.load_p_ref = np.array([[22. , 87. , 45.79999924, 7. , 12. ,
226+
28.20000076, 8.69999981, 3.5 , 5.5 , 12.69999981,
227+
14.80000019],
228+
[22.44357109, 90.38361359, 46.61357117, 7.00726891, 12.49121857,
229+
28.84151268, 8.93680668, 3.45285726, 5.58550406, 13.10054588,
230+
15.43630219],
231+
[22.48419762, 89.22782135, 45.57607269, 6.98833132, 12.35618019,
232+
28.45972633, 9.01393414, 3.44352579, 5.57040882, 12.96386147,
233+
15.2933054 ],
234+
[21.85004234, 86.51035309, 44.29330063, 6.82195902, 11.86427689,
235+
28.2765255 , 8.79933834, 3.36154509, 5.33892441, 12.65522861,
236+
14.92921543],
237+
[21.61282349, 86.64777374, 44.50276947, 6.68032742, 11.88705349,
238+
27.90019035, 8.84160995, 3.34016371, 5.30496597, 12.57473373,
239+
14.63777542],
240+
[23.22621727, 92.27429962, 47.29320145, 7.25162458, 12.71661758,
241+
30.16255379, 9.24844837, 3.57326436, 5.57008839, 13.34719276,
242+
15.97459316],
243+
[20.23793983, 81.04374695, 42.03972244, 6.25536346, 10.85489559,
244+
26.03334999, 8.0951767 , 3.12768173, 5.05948496, 11.49882984,
245+
13.89058685],
246+
[19.92967606, 81.96430206, 41.73068237, 6.54965878, 11.13441944,
247+
26.10506821, 8.04672432, 3.08769631, 4.95902777, 11.50868607,
248+
13.94141674],
249+
[20.64870644, 83.94567871, 42.16581726, 6.56127167, 11.38573551,
250+
27.0170002 , 8.39456749, 3.1841464 , 5.21042156, 11.96467113,
251+
14.37690353],
252+
[19.72007751, 79.25064087, 40.82889175, 6.11044645, 10.83215523,
253+
25.83052444, 7.77693176, 3.05522323, 4.814291 , 11.5728159 ,
254+
13.9799614 ],
255+
[21.79347801, 87.17391205, 42.77978897, 6.76001358, 11.70390511,
256+
28.14990807, 8.67703247, 3.32955885, 5.24657774, 12.30927849,
257+
14.83167171],
258+
[19.81615639, 78.61643982, 40.09531021, 6.11152506, 10.64886951,
259+
25.27948952, 7.87090397, 2.96316385, 4.72254229, 11.20446301,
260+
13.88982964],
261+
[19.3391819 , 77.26506805, 39.22829056, 6.04922247, 10.44865608,
262+
24.83847427, 7.8823204 , 2.93295646, 4.76605368, 11.18189621,
263+
13.19830322]])
264+
265+
self.load_q_ref = np.array([15.4 , 60.899998 , 32.059998 , 4.9 , 8.4 ,
266+
19.74 , 6.0899997, 2.45 , 3.85 , 8.889999 ,
267+
10.36 ], dtype=np.float32)
268+
269+
270+
271+
def tearDown(self) -> None:
272+
self.env_bug.close()
273+
self.tmp_json.close()
274+
return super().tearDown()
275+
276+
def test_reset(self):
277+
"""test that the seed is used correctly in env.reset"""
278+
obs = self.env_bug.reset(seed=0, options={"time serie id": 0})
279+
maint_ref = 1. * self.env_bug.chronics_handler.real_data.data.maintenance_handler.maintenance
280+
load_q_ref = 1. * obs.load_q
281+
load_p_ref = 1. * obs.get_forecast_arrays()[0]
282+
283+
obs = self.env_bug.reset(seed=1, options={"time serie id": 0})
284+
maint_1 = 1. * self.env_bug.chronics_handler.real_data.data.maintenance_handler.maintenance
285+
load_q_1 = 1. * obs.load_q
286+
load_p_1= 1. * obs.get_forecast_arrays()[0]
287+
288+
obs = self.env_bug.reset(seed=0, options={"time serie id": 0})
289+
maint_0 = 1. * self.env_bug.chronics_handler.real_data.data.maintenance_handler.maintenance
290+
load_q_0 = 1. * obs.load_q
291+
load_p_0 = 1. * obs.get_forecast_arrays()[0]
292+
293+
# maintenance, so JSONMaintenanceHandler
294+
assert (maint_ref == maint_0).all()
295+
assert (maint_ref != maint_1).any()
296+
assert (maint_ref.nonzero()[0] == self.maint_ref[0]).all()
297+
assert (maint_ref.nonzero()[1] == self.maint_ref[1]).all()
298+
299+
# load_q, so LoadQFromPHandler
300+
assert (load_q_ref == load_q_0).all()
301+
# assert (load_q_ref != load_q_1).any() # it's normal it works as this is not random !
302+
assert (load_q_ref == self.load_q_ref).all()
303+
304+
# load_p_forecasted, so NoisyForecastHandler
305+
assert (load_p_ref == load_p_0).all()
306+
assert (load_p_ref != load_p_1).any()
307+
assert (np.abs(load_p_ref - self.load_p_ref) <= 1e-6).all()
308+
309+
def test_runner(self):
310+
"""test the runner behaves correctly"""
311+
with warnings.catch_warnings():
312+
warnings.filterwarnings("ignore")
313+
runner = Runner(**self.env_bug.get_params_for_runner())
314+
res = runner.run(nb_episode=3,
315+
env_seeds=[0, 1, 0],
316+
max_iter=5,
317+
add_detailed_output=True)
318+
obs = res[0][-1].observations[0]
319+
maint_ref = 1. * obs.time_next_maintenance
320+
load_q_ref = 1. * obs.load_q
321+
# load_p_ref = 1. * obs.get_forecast_arrays()[0] not present in episodeData
322+
323+
obs = res[1][-1].observations[0]
324+
maint_1 = 1. * obs.time_next_maintenance
325+
load_q_1 = 1. * obs.load_q
326+
# load_p_1 = 1. * obs.get_forecast_arrays()[0] not present in episodeData
327+
328+
obs = res[2][-1].observations[0]
329+
maint_0 = 1. * obs.time_next_maintenance
330+
load_q_0 = 1. * obs.load_q
331+
# load_p_0 = 1. * obs.get_forecast_arrays()[0] not present in episodeData
332+
333+
# maintenance, so JSONMaintenanceHandler
334+
assert (maint_ref == maint_0).all()
335+
assert (maint_ref != maint_1).any()
336+
# TODO test against a reference data stored in the file
337+
338+
# load_q, so LoadQFromPHandler
339+
assert (load_q_ref == load_q_0).all()
340+
# assert (load_q_ref != load_q_1).any() # it's normal it works as this is not random !
341+
assert (load_q_ref == self.load_q_ref).all()
342+
343+
# load_p_forecasted, so NoisyForecastHandler
344+
# assert (load_p_ref == load_p_0).all()
345+
# assert (load_p_ref != load_p_1).any()
346+
# TODO test that with an agent
347+
348+
def test_chronics_handler_twice_reset(self):
349+
"""test the same results is obtained if the chronics handler is reset twice"""
350+
obs = self.env_bug.reset(seed=0, options={"time serie id": 0})
351+
maint_ref = 1. * obs.time_next_maintenance
352+
load_q_ref = 1. * obs.load_q
353+
load_p_ref = 1. * obs.get_forecast_arrays()[0]
354+
355+
self.env_bug.chronics_handler.reset()
356+
maint_1 = 1. * obs.time_next_maintenance
357+
load_q_1 = 1. * obs.load_q
358+
load_p_1 = 1. * obs.get_forecast_arrays()[0]
359+
360+
assert (np.abs(maint_ref - maint_1) <= 1e-6).all()
361+
assert (np.abs(load_q_ref - load_q_1) <= 1e-6).all()
362+
assert (np.abs(load_p_ref - load_p_1) <= 1e-6).all()

0 commit comments

Comments
 (0)