Skip to content

Commit 0ee6867

Browse files
committed
The Benchmarking platforme (Preliminary version)
1 parent 647afde commit 0ee6867

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+5984
-0
lines changed

.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,11 @@ dmypy.json
127127

128128
# Pyre type checker
129129
.pyre/
130+
131+
#custom ignore folders
132+
.vscode
133+
lips/Outputs/Scenario1/Data/*
134+
lips/Outputs/Scenario1/Benchmarks/*
135+
lips/Outputs/Scenario1_old
136+
lips/Outputs/Scenario2
137+
lips/Outputs/Scenario5

AUTHORS.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Lead author :
2+
Milad LEYLI ABADI
3+
4+
other contributors :
5+
Benjamin Donnot
6+
Jérôme Picault

Notebook_Benchmark1.ipynb

+2,492
Large diffs are not rendered by default.

img/Benchmarking.png

54.2 KB
Loading

img/Benchmarking_scheme.png

53.5 KB
Loading

img/DataGeneration.png

53.6 KB
Loading

img/Evaluation.png

53.6 KB
Loading

lips/__init__.py

Whitespace-only changes.

lips/agents/AgentTC1.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import numpy as np
2+
import grid2op
3+
from grid2op.Agent import BaseAgent
4+
5+
class AgentTC1(BaseAgent):
6+
"""
7+
The Topological Change One (TC1) agent will randomly switch the buses of one of the indicated elements.
8+
Only one substation is affected by the topological action returned after each call to the act function.
9+
Contrary to RandomTC1, it does not reconnect the elements which are not affected by the topological change
10+
to the first bus !
11+
12+
params
13+
______
14+
action_space : Grid2op ``Environment`` ``action_space``
15+
16+
subsid_list : ``list``
17+
a list of substation identifiers for which we would perform topological changes
18+
19+
20+
"""
21+
def __init__(self, action_space, subsid_list):
22+
super(AgentTC1, self).__init__(action_space)
23+
if not "set_bus" in action_space.subtype.authorized_keys:
24+
raise NotImplementedError("Impossible to have a TopoChange agent if you cannot set the bus")
25+
#self.subsid_list = [1,3,4,5,8,12]
26+
27+
self.act_space = grid2op.Converter.IdToAct(action_space)
28+
# generate only "set_topo" type of actions
29+
self.act_space.init_converter(set_line_status=False, change_line_status=False, change_bus_vect=False, redispatch=False)
30+
31+
# filter only the action at the relevant substations
32+
def filter_fun(g2op_act):
33+
l_imp, s_imp = g2op_act.get_topological_impact()
34+
res = False
35+
if np.any(s_imp[subsid_list]):
36+
res = True
37+
return res
38+
39+
self.act_space.filter_action(filter_fun)
40+
41+
self.bus_switch_action_space_as_list = []
42+
# generate bus switching actions that impact only one substation.
43+
for act_ in self.act_space.all_actions:
44+
self.bus_switch_action_space_as_list.append(act_)
45+
self.actions_size = len(self.bus_switch_action_space_as_list)
46+
47+
def act(self, obs, reward, done):
48+
# select and return randomly an action (at one substation) in the topological action list
49+
id_ = self.space_prng.choice(self.actions_size)
50+
# adding the reset action with an action which will change the buses at one substation
51+
return self.bus_switch_action_space_as_list[id_]

lips/agents/AgentTC2.py

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import numpy as np
2+
import grid2op
3+
from grid2op.Agent import BaseAgent
4+
5+
class AgentTC2(BaseAgent):
6+
"""
7+
The Topological Change Two (TC2) agent will randomly switch the buses of two of the indicated elements.
8+
Two substations are affected by the topological action returned after each call to the act function.
9+
Contrary to RandomTC2, it does not reconnect the elements which are not affected by the topological change
10+
to the first bus !
11+
12+
params
13+
______
14+
action_space : Grid2op ``Environment`` ``action_space``
15+
16+
subsid_list : ``list``
17+
a list of substation identifiers for which we would perform topological changes
18+
19+
returns
20+
-------
21+
action : Grid2Op ``action``
22+
an action which modifies the topology configuration of the network
23+
24+
25+
"""
26+
def __init__(self, action_space, subsid_list):
27+
super(AgentTC2, self).__init__(action_space)
28+
if not "set_bus" in action_space.subtype.authorized_keys:
29+
raise NotImplementedError("Impossible to have a TopoChange agent if you cannot set the bus vector")
30+
#self.subsid_list = [1,3,4,5,8,12]
31+
32+
self.act_space = grid2op.Converter.IdToAct(action_space)
33+
# generate only "set_topo" type of actions
34+
self.act_space.init_converter(set_line_status=False, change_line_status=False, change_bus_vect=False, redispatch=False)
35+
36+
# filter only the action at the relevant substations
37+
def filter_fun(g2op_act):
38+
l_imp, s_imp = g2op_act.get_topological_impact()
39+
res = False
40+
if np.any(s_imp[subsid_list]):
41+
res = True
42+
return res
43+
44+
self.act_space.filter_action(filter_fun)
45+
46+
self.bus_switch_action_space_as_list = []
47+
48+
for act1 in self.act_space.all_actions:
49+
_, s_imp1 = act1.get_topological_impact()
50+
s_id1 = np.where(s_imp1)[0]
51+
if not s_id1:
52+
# this is the do nothing action
53+
continue
54+
for act2 in self.act_space.all_actions:
55+
_, s_imp2 = act2.get_topological_impact()
56+
s_id2 = np.where(s_imp2)[0]
57+
if not s_id2:
58+
# this is the do nothing action
59+
continue
60+
if s_id2 <= s_id1: # To avoid duplicate actions.
61+
continue
62+
63+
act_saved = action_space()
64+
act_saved += act1
65+
act_saved += act2
66+
self.bus_switch_action_space_as_list.append(act_saved)
67+
self.actions_size = len(self.bus_switch_action_space_as_list)
68+
69+
def act(self, obs, reward, done):
70+
# select and return randomly an action (at two substations) in the topological action list
71+
id_ = self.space_prng.choice(self.actions_size)
72+
return self.bus_switch_action_space_as_list[id_]

lips/agents/DoNothingAgent.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from grid2op.Agent.BaseAgent import BaseAgent
2+
3+
4+
class DoNothingAgent(BaseAgent):
5+
"""
6+
This is the most basic BaseAgent. It is purely passive, and does absolutely nothing.
7+
8+
As opposed to most reinforcement learning environments, in grid2op, doing nothing is often
9+
the best solution.
10+
11+
"""
12+
def __init__(self, action_space):
13+
BaseAgent.__init__(self, action_space)
14+
15+
def act(self, observation, reward, done=False):
16+
"""
17+
As better explained in the document of :func:`grid2op.BaseAction.update` or
18+
:func:`grid2op.BaseAction.ActionSpace.__call__`.
19+
20+
The preferred way to make an object of type action is to call :func:`grid2op.BaseAction.ActionSpace.__call__`
21+
with the dictionary representing the action. In this case, the action is "do nothing" and it is represented by
22+
the empty dictionary.
23+
24+
Parameters
25+
----------
26+
observation: :class:`grid2op.Observation.Observation`
27+
The current observation of the :class:`grid2op.Environment.Environment`
28+
29+
reward: ``float``
30+
The current reward. This is the reward obtained by the previous action
31+
32+
done: ``bool``
33+
Whether the episode has ended or not. Used to maintain gym compatibility
34+
35+
Returns
36+
-------
37+
res: :class:`grid2op.Action.Action`
38+
The action chosen by the bot / controller / agent.
39+
40+
"""
41+
res = self.action_space({})
42+
return res

lips/agents/RandomN1.py

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Copyright (c) 2019-2020, RTE (https://www.rte-france.com)
2+
# See AUTHORS.txt
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 leap_net, leap_net a keras implementation of the LEAP Net model.
8+
9+
import numpy as np
10+
from grid2op.Agent import BaseAgent
11+
from grid2op.dtypes import dt_int, dt_float
12+
13+
14+
class RandomN1(BaseAgent):
15+
"""
16+
This "agent" will randomly disconnect exactly 1 powerline from the grid.
17+
18+
**NB** Every powerline that is not chosen at random to be disconnected will be reconnected by force.
19+
"""
20+
21+
def __init__(self, action_space):
22+
super(RandomN1, self).__init__(action_space)
23+
if not "set_line_status" in action_space.subtype.authorized_keys:
24+
raise NotImplementedError("Impossible to have a RandomN1 agent if you cannot set the status or powerline")
25+
26+
# represent the action "exactly one powerline is disconnected
27+
self.powerline_actions = 1 - 2 * np.eye(action_space.n_line, dtype=dt_int)
28+
29+
def act(self, obs, reward, done):
30+
id_ = self.space_prng.choice(self.action_space.n_line)
31+
arr_ = self.powerline_actions[id_, :]
32+
li_bus = [(i, el) for i, el in enumerate(arr_)]
33+
return self.action_space({"set_line_status": arr_,
34+
"set_bus": {"lines_or_id": li_bus,
35+
"lines_ex_id": li_bus},
36+
}
37+
)

lips/agents/RandomN2.py

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Copyright (c) 2019-2020, RTE (https://www.rte-france.com)
2+
# See AUTHORS.txt
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 leap_net, leap_net a keras implementation of the LEAP Net model.
8+
9+
import numpy as np
10+
from grid2op.Agent import BaseAgent
11+
from grid2op.dtypes import dt_int, dt_float
12+
13+
14+
class RandomN2(BaseAgent):
15+
"""
16+
This "agent" will randomly disconnect exactly 1 powerline from the grid.
17+
18+
**NB** Every powerline that is not chosen at random to be disconnected will be reconnected by force.
19+
20+
This agent will modify the status of all powerlines at every steps!
21+
"""
22+
23+
def __init__(self, action_space):
24+
super(RandomN2, self).__init__(action_space)
25+
if not "set_line_status" in action_space.subtype.authorized_keys:
26+
raise NotImplementedError("Impossible to have a RandomN1 agent if you cannot set the status or powerline")
27+
28+
# represent the action "exactly one powerline is disconnected
29+
self.powerline_actions = np.ones(action_space.n_line, dtype=dt_int)
30+
self.tmp_arr = np.ones(action_space.n_line, dtype=dt_int)
31+
32+
def act(self, obs, reward, done):
33+
id_1 = self.space_prng.choice(self.action_space.n_line)
34+
id_2 = self.space_prng.choice(self.action_space.n_line - 1)
35+
if id_2 >= id_1:
36+
# this procedure is to be sure not to "disconnect twice" the same powerline
37+
id_2 += 1
38+
self.tmp_arr[:] = self.powerline_actions
39+
self.tmp_arr[id_1] = -1
40+
self.tmp_arr[id_2] = -1
41+
li_bus = [(i, el) for i, el in enumerate(self.tmp_arr)]
42+
act = self.action_space({"set_line_status": self.tmp_arr,
43+
"set_bus": {"lines_or_id": li_bus,
44+
"lines_ex_id": li_bus},
45+
}
46+
)
47+
return act

lips/agents/RandomNN1.py

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright (c) 2019-2020, RTE (https://www.rte-france.com)
2+
# See AUTHORS.txt
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 leap_net, leap_net a keras implementation of the LEAP Net model.
8+
9+
import numpy as np
10+
from grid2op.Agent import BaseAgent
11+
from grid2op.dtypes import dt_int, dt_float
12+
import pdb
13+
14+
15+
class RandomNN1(BaseAgent):
16+
"""
17+
This "agent" will randomly disconnect 0 or 1 powerline with probability 1-p to disconnect 1 powerline
18+
and with probability p to disconnect randomly one powerline.
19+
20+
**NB** the output distribution is heavily biased: all the powerline are connected with proba `1-p`, but if you
21+
consider the odds of having powerline line `l` disconnected it's equal to `p / (nb_line)`.
22+
"""
23+
def __init__(self, action_space, p):
24+
super(RandomNN1, self).__init__(action_space)
25+
if not "set_line_status" in action_space.subtype.authorized_keys:
26+
raise NotImplementedError("Impossible to have a RandomN1 agent if you cannot set the status or powerline")
27+
if p <= 0.:
28+
raise RuntimeError("Impossible to have p lower than 0.")
29+
self.p = dt_float(p)
30+
self._1_p = 1. - self.p
31+
# represent the action "no powerline are disconnected
32+
self.reset_all = np.ones(action_space.n_line, dtype=dt_int)
33+
# represent the action "exactly one powerline is disconnected
34+
self.powerline_actions = 1 - 2*np.eye(action_space.n_line, dtype=dt_int)
35+
36+
def act(self, obs, reward, done):
37+
ur = self.space_prng.uniform()
38+
if ur < self._1_p:
39+
arr_ = self.reset_all
40+
else:
41+
id_ = self.space_prng.choice(self.action_space.n_line)
42+
arr_ = self.powerline_actions[id_, :]
43+
li_bus = [(i, el) for i, el in enumerate(arr_)]
44+
act = self.action_space({"set_line_status": arr_,
45+
"set_bus": {"lines_or_id": li_bus,
46+
"lines_ex_id": li_bus},
47+
})
48+
return act

lips/agents/RandomTC1.py

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import numpy as np
2+
import grid2op
3+
from grid2op.Agent import BaseAgent
4+
5+
class RandomTC1(BaseAgent):
6+
"""
7+
This agent will randomly switch the buses of some indicated elements.
8+
Only one substation is affected by the topological action returned after each call to the act function.
9+
Contrary to the previous version, it will also ensure that all the elements are connected to the first bus before performing a new action
10+
"""
11+
def __init__(self, action_space, subsid_list):
12+
super(RandomTC1, self).__init__(action_space)
13+
if not "set_bus" in action_space.subtype.authorized_keys:
14+
raise NotImplementedError("Impossible to have a TopoChange agent if you cannot set the bus")
15+
#self.subsid_list = [1,3,4,5,8,12]
16+
17+
# reset all the connections and connect all the elements to bus 1
18+
self.set_buses = action_space({"set_bus": [(i,1) for i in range(action_space.dim_topo)]})
19+
20+
self.act_space = grid2op.Converter.IdToAct(action_space)
21+
# generate only "set_topo" type of actions
22+
self.act_space.init_converter(set_line_status=False, change_line_status=False, change_bus_vect=False, redispatch=False)
23+
24+
# filter only the action at the relevant substations
25+
def filter_fun(g2op_act):
26+
l_imp, s_imp = g2op_act.get_topological_impact()
27+
res = False
28+
if np.any(s_imp[subsid_list]):
29+
res = True
30+
return res
31+
32+
self.act_space.filter_action(filter_fun)
33+
34+
self.bus_switch_action_space_as_list = []
35+
# generate bus switching actions that impact only one substation.
36+
for act_ in self.act_space.all_actions:
37+
self.bus_switch_action_space_as_list.append(act_)
38+
self.actions_size = len(self.bus_switch_action_space_as_list)
39+
40+
def act(self, obs, reward, done):
41+
# select and return randomly an action (at one substation) in the topological action list
42+
id_ = self.space_prng.choice(self.actions_size)
43+
# adding the reset action with an action which will change the buses at one substation
44+
return self.set_buses + self.bus_switch_action_space_as_list[id_]

0 commit comments

Comments
 (0)