|
| 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 Grid2Op, Grid2Op a testbed platform to model sequential decision making in power systems. |
| 8 | + |
| 9 | +""" |
| 10 | +This file should be used to assess the performance of grid2op in "runner" mode: the loading time are not studied, |
| 11 | +neither are the import times. |
| 12 | +
|
| 13 | +Data are loaded only once, when the environment is "done" the programm stops. |
| 14 | +
|
| 15 | +This corresponds to the situation: you have a trained agent, you want to assess its performance using the runner |
| 16 | +""" |
| 17 | + |
| 18 | +import os |
| 19 | + |
| 20 | +from grid2op import make |
| 21 | +from grid2op.Action import CompleteAction |
| 22 | +from grid2op.Space import AddDetailedTopoIEEE |
| 23 | +from grid2op.Parameters import Parameters |
| 24 | +from grid2op.Agent import BaseAgent |
| 25 | +from grid2op.Rules import AlwaysLegal |
| 26 | +from grid2op.Backend import PandaPowerBackend |
| 27 | +import cProfile |
| 28 | + |
| 29 | +from utils_benchmark import run_env, str2bool |
| 30 | + |
| 31 | +try: |
| 32 | + from lightsim2grid import LightSimBackend |
| 33 | + light_sim_avail = True |
| 34 | +except ImportError: |
| 35 | + light_sim_avail = False |
| 36 | + |
| 37 | +ENV_NAME = "rte_case5_example" |
| 38 | +ENV_NAME = "rte_case14_realistic" |
| 39 | +MAX_TS = 1000 |
| 40 | +RANDOM_SWITCH_AGENT = False # do not change this |
| 41 | +# for profiling it has no impact. |
| 42 | + |
| 43 | + |
| 44 | +class RandomBusSwitchAgent(BaseAgent): |
| 45 | + def act(self, observation, reward, done=False): |
| 46 | + sub_id = self.space_prng.randint(type(self.action_space).n_sub) |
| 47 | + new_position = self.space_prng.choice([-1, 1], size=1) |
| 48 | + return self.action_space({"set_switch": [(sub_id, new_position)]}) |
| 49 | + |
| 50 | + |
| 51 | +class RandomElSwitchAgent(BaseAgent): |
| 52 | + def act(self, observation, reward, done = False): |
| 53 | + if observation.current_step <= 1: |
| 54 | + # deactivate the connector between busbars |
| 55 | + res = self.action_space({"set_switch": [(sub_id, -1) |
| 56 | + for sub_id in range(type(self.action_space).n_sub)]}) |
| 57 | + else: |
| 58 | + res = self.action_space() |
| 59 | + |
| 60 | + do_act = self.space_prng.choice([0, 1], size=1, p = [0.95, 0.05]) |
| 61 | + if not do_act: |
| 62 | + return res |
| 63 | + |
| 64 | + n_switch = type(self.action_space).detailed_topo_desc.switches.shape[0] |
| 65 | + switch_id = self.space_prng.randint(type(self.action_space).n_sub, |
| 66 | + n_switch, |
| 67 | + size=1) |
| 68 | + new_position = self.space_prng.choice([-1, 1], size=1) |
| 69 | + res.update({"set_switch": [(switch_id, new_position)]}) |
| 70 | + return res |
| 71 | + |
| 72 | +def main(max_ts, name, use_lightsim=False, test_env=True): |
| 73 | + param = Parameters() |
| 74 | + if use_lightsim: |
| 75 | + if light_sim_avail: |
| 76 | + class ThisBackendClass(AddDetailedTopoIEEE, LightSimBackend): |
| 77 | + pass |
| 78 | + else: |
| 79 | + raise RuntimeError("LightSimBackend not available") |
| 80 | + else: |
| 81 | + class ThisBackendClass(AddDetailedTopoIEEE, PandaPowerBackend): |
| 82 | + pass |
| 83 | + |
| 84 | + backend = ThisBackendClass() |
| 85 | + |
| 86 | + param.init_from_dict( |
| 87 | + {"NO_OVERFLOW_DISCONNECTION": True, |
| 88 | + "STOP_EP_IF_GEN_BREAK_CONSTRAINTS": False, |
| 89 | + "ENV_DOES_REDISPATCHING": False}) |
| 90 | + |
| 91 | + env_klu = make(name, |
| 92 | + backend=backend, |
| 93 | + param=param, |
| 94 | + gamerules_class=AlwaysLegal, |
| 95 | + test=test_env, |
| 96 | + action_class=CompleteAction) |
| 97 | + assert type(env_klu).detailed_topo_desc is not None |
| 98 | + agent = RandomBusSwitchAgent(action_space=env_klu.action_space) |
| 99 | + if RANDOM_SWITCH_AGENT: |
| 100 | + agent = RandomElSwitchAgent(action_space=env_klu.action_space) |
| 101 | + agent.seed(4) |
| 102 | + |
| 103 | + cp = cProfile.Profile() |
| 104 | + cp.enable() |
| 105 | + nb_ts_klu, *_, time_step = run_env(env_klu, max_ts, agent) |
| 106 | + cp.disable() |
| 107 | + print(f'Time for {nb_ts_klu} steps: {time_step} => {time_step / nb_ts_klu} s/step or {nb_ts_klu / time_step:.3e} step / s') |
| 108 | + nm_f, ext = os.path.splitext(__file__) |
| 109 | + nm_out = "{}_{}_{}.prof".format(nm_f, "lightsim" if use_ls else "pp", name) |
| 110 | + cp.dump_stats(nm_out) |
| 111 | + print("You can view profiling results with:\n\tsnakeviz {}".format(nm_out)) |
| 112 | + |
| 113 | + |
| 114 | +if __name__ == "__main__": |
| 115 | + import argparse |
| 116 | + parser = argparse.ArgumentParser(description='Benchmark pyKLU and Pandapower Backend for an agent that takes every ' |
| 117 | + 'topological action possible') |
| 118 | + parser.add_argument('--name', default=ENV_NAME, type=str, |
| 119 | + help='Environment name to be used for the benchmark.') |
| 120 | + parser.add_argument('--number', type=int, default=MAX_TS, |
| 121 | + help='Maximum number of time steps for which the benchamark will be run.') |
| 122 | + parser.add_argument("--use_ls", type=str2bool, nargs='?', |
| 123 | + const=True, default=False, |
| 124 | + help="Use the LightSim2Grid Backend.") |
| 125 | + parser.add_argument("--no_test", type=str2bool, nargs='?', |
| 126 | + const=True, default=False, |
| 127 | + help="Do not use a test environment for the profiling (default to False: meaning you use a test env)") |
| 128 | + |
| 129 | + args = parser.parse_args() |
| 130 | + |
| 131 | + max_ts = int(args.number) |
| 132 | + name = str(args.name) |
| 133 | + use_ls = args.use_ls |
| 134 | + test_env = not args.no_test |
| 135 | + main(max_ts, name, use_lightsim=use_ls, test_env=test_env) |
0 commit comments