Giter Site home page Giter Site logo

rte-france / grid2op Goto Github PK

View Code? Open in Web Editor NEW
276.0 19.0 114.0 87.46 MB

Grid2Op a testbed platform to model sequential decision making in power systems.

Home Page: https://grid2op.readthedocs.io/

License: Mozilla Public License 2.0

Makefile 0.01% Python 89.90% Jupyter Notebook 10.06% Dockerfile 0.02% Shell 0.01%
grid2op reinforcement-learning reinforcement-learning-environments powergrid powergrid-operation gym-environments

grid2op's Issues

Thermal limits in trafos

Please be aware when you modify the 'sn_mva' you are altering the impedance of the element because (I am almost sure) pandapower uses this value to get the impedance in the t model and also treats as overloaded when the result of the power flow is above this value.

Runner multi proc in 0.8.0

grid2op.Runner has broken multi processor execution in 0.8.0:

from grid2op import make
from grid2op.Runner import Runner
from grid2op.Agent import DoNothingAgent

env = make("rte_case14_realistic", test=True)
runner_params = env.get_params_for_runner()
runner = Runner(**runner_params, agentClass=DoNothingAgent)
res = runner.run(path_save=logs_path,
                 nb_episode=nb_episode, nb_process=4,
                 max_iter=-1, pbar=True)

Multi process running fails with the following:

python3.6/site-packages/grid2op/Runner/Runner.py", line 814, in run_parrallel
    [(self, pn, i, path_save) for i, pn in enumerate(process_ids)])
  File "/usr/lib/python3.6/multiprocessing/pool.py", line 274, in starmap
    return self._map_async(func, iterable, starmapstar, chunksize).get()
  File "/usr/lib/python3.6/multiprocessing/pool.py", line 644, in get
    raise self._value
  File "/usr/lib/python3.6/multiprocessing/pool.py", line 424, in _handle_tasks
    put(task)
  File "/usr/lib/python3.6/multiprocessing/connection.py", line 206, in send
    self._send_bytes(_ForkingPickler.dumps(obj))
  File "/usr/lib/python3.6/multiprocessing/reduction.py", line 51, in dumps
    cls(buf, protocol).dump(obj)
AttributeError: Can't pickle local object 'GridObjects.init_grid.<locals>.res'

Parrallel powerlines not displayed

The parrallel powelines are not displayed properly, the will overlap in the plot helper.

reproduce it:

import grid2op
env = grid2op.make("rte_case5_example", test=True)
obs = env.reset()
_ = env.render()

image

There are actually 2 powerlines going from substation 2 to substations 3

Unable to reconnect powerline

Thanks for releasing new version 0.6.0.

By the way, it seems that reconnection of powerline doesn't work now.
Here is a reproducing code as following.

env = grid2op.make('case5_example')
obs = env.reset()
obs, _, done, info = env.step(env.action_space.disconnect_powerline(2))
print(info)
print(obs.line_status)

It gives the following output as normal.

{'disc_lines': array([False, False, False, False, False, False, False, False]), 'is_illegal': False, 'is_ambiguous': False, 'is_dispatching_illegal': False, 'is_illegal_reco': False, 'exception': [], 'rewards': {}}
[ True True False True True True True True]

Then,

obs, _, done, info = env.step(env.action_space.reconnect_powerline(2, 1, 1))
print(info)
print(obs.line_status)

It gives the illegal action sign as the following.

{'disc_lines': array([False, False, False, False, False, False, False, False]), 'is_illegal': True, 'is_ambiguous': False, 'is_dispatching_illegal': False, 'is_illegal_reco': False, 'exception': [Grid2OpException IllegalAction IllegalAction('BaseAction illegal')], 'rewards': {}}
[ True True False True True True True True]

It seems that it is legal action above situation, but the output tells it is illegal action.
Is it intended outcome?

Best
Sunghoon

EpisodeData len overload

In any version, getting the length of an Episode loaded from disk crashes:

from grid2op.Episode import EpisodeData

logs_path = "./my_runner_output_dir"
episode_id = "0001" 
episode_data = EpisodeData.from_disk(agent_path=logs_path, name=episode_id)
n_steps = len(episode_data)

Overloading __len__ should return an integer type. Instead we have the following:

TypeError: 'str' object cannot be interpreted as an integer

Improve documentation

It would be very helpful if the physical units were added to the relevant variables (e.g. in the Observation description). I am sometimes unclear about the units (e.g. observation.rho - these are values all around 0.01).

Minor other issues:

  • It would be helpful if the current timestep was part of the Observation object too

Line Status Issue

Hi,

There is one confusing situation for me in the Line Status. For example,
In step 1
I printed the line status and time_before_line_reconnectable attribute as follows:
Line Status: [ True True True True True True True True True True True True
True True True True True True True True]
time_before_line_reconnectable: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
In step 2
It becomes:
Line Status: [ True True True Fasle True True True True True True True True
True True True True True True True Fasle]
time_before_line_reconnectable: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]

I noticed that the time_before_line_reconnectable attribute will not change even if the line has been removed. And I can not reconnected the power line in this situation. Is there anything I can do about it?

Thanks

Issue while installing Grid2op 0.5.8

Note : The issue is not present with 0.5.7

I have the following error when running either pipenv install or pip install :

    Complete output (15 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\mjothy\AppData\Local\Temp\pip-install-jee8j02w\grid2op\setup.py", line 19, in <module>
        import numba
      File "c:\users\mjothy\.virtualenvs\chronix2grid-finrbh4i\lib\site-packages\numba\__init__.py", line 15, in <module>
        from . import config, errors, _runtests as runtests, types
      File "c:\users\mjothy\.virtualenvs\chronix2grid-finrbh4i\lib\site-packages\numba\config.py", line 18, in <module>
        import llvmlite.binding as ll
      File "c:\users\mjothy\.virtualenvs\chronix2grid-finrbh4i\lib\site-packages\llvmlite\binding\__init__.py", line 6, in <module>
        from .dylib import *
      File "c:\users\mjothy\.virtualenvs\chronix2grid-finrbh4i\lib\site-packages\llvmlite\binding\dylib.py", line 4, in <module>
        from . import ffi
      File "c:\users\mjothy\.virtualenvs\chronix2grid-finrbh4i\lib\site-packages\llvmlite\binding\ffi.py", line 154, in <module>
        raise OSError("Could not load shared object file: {}".format(_lib_name))
    OSError: Could not load shared object file: llvmlite.dll

numba/llvmlite#498
This issue seems to indicate that "The wheels may have been built with the wrong ABI setting." I have no idea what it means, but the issue is clearly related to the numba link.

Maybe grid2op requires a specific version of numba ?

Thank you.

Reward function does not reflect gen cost values

In the reward, the marginal cost is defined as the maximum costs of any active generator:

marginal_cost = np.max(env.gen_cost_per_MW[env.gen_activeprod_t > 0.])

However, the gen_cost_per_MW is not equal for all controllable generators:

array([40., 70., 0., 0., 70.])

For an economic optimum, using the generator with costs of 40 would be preferential. This is currently not reflected in the reward function. Is this intentional?

Since the generator with costs of 40 can likely not be used exclusively (while the 70 cost generators are shut down), the reward function would always have marginal costs of 70.

I could set all costs to 70 and not have any disadvantages regarding the reward. Or does this have other unintended consequences?

An example: Maybe the system losses are minimized when only the cost 70 generators are used. However, due to the cost functions, it may be economically preferential to use the 40 cost generator too and thus the result of an OPF. This is not reflected in the reward.

Retrieving the forecast

It would be good to have the ability to access the approximate forecast for the next step time step. This is possible at the moment by using obs.simulate(act) and viewing attributes of the observation, but it would be great if this was more accessible!

Add a 'cache' method when reading the chronics

For now, in case where chronics are read from file, the whole file is read each time the environment is reset, or created.

This behaviour is fine for agents performing really well (eg with few game overs) but can rapidly decrease the performances for early stages of training, where lots of game over are expected (most of the time is actually spend reading whole part of files that will never be used).

Access to the information on the objects from their names

An option should be added to access or modify the variables of objects in the grid (powerlines / loads / generator) from the names of the objects instead of their ID.

For example instead of the following :

change_status = action_space.get_change_line_status_vect()
change_status[0] = True

, it should be possible to do :

change_status = action_space.get_change_line_status_vect()
change_status["0_3_0"] = True

Maybe with something like:

class CallableVector(np.ndarray):
    def __getitem__(self, x):
        try:
            return super().__getitem__(x)
        except KeyError: # x is a string
            idx = np.argmin(env.name_line == x) # env has to be defined in order to get the names
            return super().__getitem__(idx)

And this wouldn't add anything to the computation time.

The same goes for the vectors in the Observation objects.

Numba Req on Ubuntu

Fresh command line install of Grid2Op on Ubuntu 18.04 resulted in numba package not being found. Following error occurred when running python -m grid2op.main with python-3.6.9:

numba cannot be imported and numba functions are disabled.
Probably the execution is slow.
Please install numba to gain a massive speedup.
(or if you prefer slow execution, set the flag numba=False to avoid this warning!)

Will include numba to install_requires in setup.py and submit PR.

Plausible values for transformer's rated power

Currently, all transformers have a rated power of 9900 MVA in the pandapower backend grid.
Parsing

grid.trafo["max_i_ka"] = obs._obs_env._thermal_limit_a[len(self.grid.line):] / 1000.

and using the following formula to generate a more plausible sn_mva

np.sqrt(3) * self.grid.bus.loc[self.grid.trafo.hv_bus, "vn_kv"].values * self.grid.trafo["max_i_ka"].values

i get:

Name: sn_mva, dtype: float64
0 92.000000
1 55.200000
2 40.825000
3 82.500000
4 117.857143

This seems much more realistic, however, transformer 2 is overloaded in the first timestep (44 MW vs. 40.8 MVA limit). The max_i_ka value is very low:

0 0.384900
1 0.230940
2 0.170799
3 3.402243
4 3.402243
Name: max_i_ka, dtype: float64

I noticed the issue comes from the vk_percent value of the transformers, which are much too high. Typical values are below 1 %, however the initial values are > 1000 %. After normalizing them somewhat by

self.grid.trafo["vk_percent"] /= 1e4

the power flow converges. But now, the loading percent is still much too high:

0 252.237821
1 89.102943
2 389.214114
3 233.745565
4 36.207367
Name: loading_percent, dtype: float64

How were the thermal limits chosen? Can they be integrated into the pandapower grid more naturally?

The initial problem was the Backend says a transformer is overloaded in timestep 801 (set_id(0)), but the agent's pandapower results showed no overloading.

If i adjust the sn_mva values to more realistic values and increase them to not have transformer overloading, then the grid's power flow characteristics change completely.
As a second option, i can calculate if a transformer is overloaded manually by using the resulting transformer currents and dividng by the backend's thermal limits. I can get plausible values this way, however, then transformer loading cannot be used while performing optimal power flow.

Exception resulting from illegal action is not propagated in obs.simulate

While running an environment the simulation stopped abruptly without any apparent errors.
Only after some tedious debugging it became clear that an action is illegal:

File "", line 1, in
action()
File "/home/jmenke/Documents/PythonProjects/Grid2Op/grid2op/Action.py", line 1605, in call
self._check_for_ambiguity()
File "/home/jmenke/Documents/PythonProjects/Grid2Op/grid2op/Action.py", line 1136, in _check_for_ambiguity
" which bus.".format(q_id))
grid2op.Exceptions.InvalidLineStatus: Grid2OpException AmbiguousAction InvalidLineStatus "You ask to reconnect powerline 5 yet didn't tell on which bus."

I would expect that this exception would be propagated and raised properly with the default settings.

Reuse Name on the grid instead of creating new ones

For now the default behavior is, when using the pandapower backend, to creat new names when the powergrid is loaded instead of reusing the one in the description of the powergrid.

This should be changed to ensure a better understanding of what's happening.

Add parrallel processing

For now, a Runner can be executed in parallel using the python default "multiprocessing" framework.

It has two main drawbacks:

  • multiprocessing works efficiently solely on a single machine
  • the runner is not suited to train an Agent, but rather to evaluate its performance on given scenarios.

It would then be a great addition to add the possibility for executing distributed environments (computing multiple environment in parallel) that ideally can be run on a HPC cluster. Few possibilities are possible:

  • synchronous actions: an agent submit an ordered list of actions, each being implemented in its own environment
  • asynchronous actions: an agent would submit an ID of the environment as well as an action that will be executed on this environment.

Multiple technologies can be used for such a purpose, for example:

Any contributions are welcome on this topic.

Deviation between observation's a_or and power flow results based on same observation

Hi, it would be awesome if someone could clarify the following:

Using the backend grid as follows:

        self.grid = deepcopy(obs._obs_env.backend._grid)
        drop_buses(self.grid, self.grid.bus.loc[~self.grid.bus.in_service].index)
        self.grid.load["p_mw"] = obs.load_p
        self.grid.load["q_mvar"] = obs.load_q
        self.grid.line["in_service"] = obs.line_status[:len(self.grid.line)]
        self.grid.trafo["in_service"] = obs.line_status[-len(self.grid.trafo):]
        self.grid.ext_grid.vm_pu = obs.v_or[0] / self.grid.bus.loc[self.grid.ext_grid.bus, "vn_kv"].values
        self.grid.gen.loc[self.grid.gen.slack, "vm_pu"] = self.grid.ext_grid.vm_pu.values
        self.grid.gen["p_mw"] = obs.prod_p
        pp.runpp(self.grid)

I set the observation load and gen values and also the observed ext_grid voltage and then perform a power flow calculation with the original backend grid.

I would expect the line and transformer currents to be similar at least to the observation values in obs.a_or. However, both have a significant deviation. There is also a bias that exists for all time steps.

The maximum difference of self.grid.res_line.i_ka / self.grid.res_trafo.i_hv_ka and obs.a_or (converted to kA) is about 60 A which fluctuates slightly over time steps (e.g. 55 A, 63 A, ...).

Is this intentional? Did i forget to update some values before the power flow?
Thanks!

Enhance notebook "2_Action_GridManipulation" to make it clear some actions presented are ambiguous

Notebook 2_Action_GridManipulation.ipynb provides the following notation for changes of line status:

the_same_act = action_space({"set_line_status": [(3,1), (4,1), (5,-1), (6,-1)],
                             "change_line_status": [0,1,2]
                            })
print(the_same_act)

If one prints this, then the description says that the statuses of lines 3,4, 5, 6 will be set accordingly. However, nothing will actually happen as the reward is the same as the one received with a do nothing action. What instead works is to have a vector with the same length as the number of lines as the value of "set_line_status".
Setting 1/-1 at the corresponding line positions will be parsed correctly.

This seems to be a bug.

the_same_act = self.action_space({"set_line_status": [(3,1), (4,1), (5,-1), (6,-1)], "change_line_status": [0,1,2]})
observation.simulate(the_same_act)
Out[13]:
(<grid2op.Observation.CompleteObservation at 0x7fba9cc42f10>,
14.59234479485048,
False,
{})
observation.simulate(self.action_space({}))
Out[14]:
(<grid2op.Observation.CompleteObservation at 0x7fba9bd58090>,
14.59234479485048,
False,
{})

Distinguish score and reward files

Currently there is only one common .py script that is used to specify either the reward or the score.
What we are interested in when analyzing an agent, is to analyze the score of this agent. But when training the agent, we must give him a reward from which he should learn from. So we cannot define and compute the score currently when it is training.
To analyze the agent performance when he is training, it would be good to be able to compute the score at the same time. One possible solution is to explicitly separate the script .py file of score and reward.

[FIXED] wrong layout for l2rpn_case14_sandbox..

The layout for the cas14 sandbox competition is wrong on some platform, but not on other.

import grid2op
env = grid2op.make("l2rpn_case14_sandbox")
env.render()

And this is what i got:
image

EDIT If the problem persists, remove the dataset from the cache and try to download it again. grid2op cache location is accessible through

import grid2op
grid2op.get_current_local_dir()

Update documentation of Make / MakeEnv

The documentation mention make_new / make instead of make / make_old and does not mention the utils function to list the cache, change the cache etc.

5 bus example showing unusual behaviour

The 5 bus example shows unusual behaviour while deploying the do-nothing-agent. Load 3's voltage, after some amount of time, does not have a value, and becomes 'NaN'. This occurs in the main episode as well as most of the provided scenarios. In all these scenarios however, the do-nothing-agent does not fail. Attached is a code snippet to reproduce this issue. The code shows 3 plots: Load 3's voltage, Line 4 extremity's voltage, Line 8 extremity's voltage.
The plot produced by the code shows that even though the scenario is longer (the length is 2016) the load 3's voltage does not have a curve after index 100 (approximately). With each of the scenarios, this occurs, though this "failure" occurs at different timesteps.
Other information:
Pandapower version: 2.2.0
Grid2op version: 0.5.2

Scenario numbers that have a similar output:
00, 01, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 14, 15, 16, 17, 18, 19

Scenarios that had normal behaviour:
13

Scenarios where the agent failed:
02
code_snippet_5bus_network.txt

Downloading additional chronics

I am a little confused about how to download additional chronics. From the getting started notebook 0 (basic functionalities) it seems to suggest I can pass local=False to make_new() when creating the environment then it will download chronics, but this is not a valid keyword argument at the moment.

I was familiar with the old approach to downloading chronics from the command line but now I don't know the URL for this download! (I am trying to download the extra chronics for rte_case14_realistic.)

Incidentally, is there a preferred function out of make() make2() and make_new()?

Making gif and matplotlib "canva"

There is a problem when trying to make the gif of the episode (episode replay) due to a weird error in matplotlib:

Traceback (most recent call last):
  File "evaluate.py", line 104, in <module>
    evaluate(env,
  File "evaluate.py", line 86, in evaluate
    save_log_gif(logs_path, res)
  File "/home/benjamin/Documents/l2rpn-baselines/l2rpn_baselines/utils/save_log_gif.py", line 36, in save_log_gif
    ep_replay.replay_episode(episode_id=chron_name, gif_name=gif_name, display=False)
  File "/home/benjamin/Documents/grid2op_dev/grid2op/Episode/EpisodeReplay.py", line 110, in replay_episode
    frames.append(plot_runner.convert_figure_to_numpy_HWC(figure))
  File "/home/benjamin/Documents/grid2op_dev/grid2op/PlotGrid/PlotMatplot.py", line 156, in convert_figure_to_numpy_HWC
    figure.canvas.print_raw(buf)
  File "/home/benjamin/.local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py", line 447, in print_raw
    FigureCanvasAgg.draw(self)
  File "/home/benjamin/.local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py", line 390, in draw
    with RendererAgg.lock, \
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/home/benjamin/.local/lib/python3.8/site-packages/matplotlib/backend_bases.py", line 2788, in _wait_cursor_for_draw_cm
    self.set_cursor(self._lastCursor)
  File "/home/benjamin/.local/lib/python3.8/site-packages/matplotlib/backends/backend_gtk3.py", line 468, in set_cursor
    self.canvas.get_property("window").set_cursor(cursord[cursor])
AttributeError: 'NoneType' object has no attribute 'set_cursor'

Probably the way to make gif should be set up differently.

PlotGrid rho values > 1.0 crash

When using gridop2.PloGrid with rho values > 1.0
In case of Parameters.NO_OVERFLOW_DISCONNECTION = True, for example.

Will cause the renderes to throw list index out of range

Should clip values to [0.0;1.0] for powerlines color gradient selection

Issue of case14_redisp

Hi,

I am running the "case14_redisp" with "env = grid2op.make("case14_redisp", chronics_path="PATH\YOU\WANT\DATA\SAVED\TO\case14_redisp" )"
I found some issues in the data file of "case14_redisp" and could you please help to check?
First, the time information is missing, which might be a minor problem.
Second, the definition of the thermal limit is confusing for us. I think the thermal limit is defined as apparent power in the previous version. Now it is defined as follows with significantly different magnitude. Even if I change this to the previous value, it will be changed again during the calculation. Similarly, the state.rho values also become very strange. I think it might be a bug in the program.
Third, the most important issue is the setting point of generation. The setpoint of the latest version will lead to the diverge of power flow even when I take no action, which needs to be modified.
Finally, I found the reward definition of "case14_redisp" is different from L2RPN, could you please provide some materials to explain the meaning of the new reward definition?

Thanks,

Some issues on Observation and Action

I played with “case5_example” environment, and I found some cases that I can not understand.

Firstly, observation dimension is not same as Grid2Op documentation. The documentation says there are 31 vectors that consist Completeobservation (1 the year, 2 the month, 3 the day …. 31 actual_dispatch). Howerver when I type “env.observation_space.shape”, there are 32 vectors. I think there is a strange vector between 25(time_before_cooldown_line) and 26 (time_before_cooldown_sub), because there is a vector of size #powerlines between them, which is not mentioned in the documentation.

Secondly, an action that assign origin and extremity to bus 2 at the same time always gives game over. Initially, all the components in a grid are connected to bus 1. Therefore, for example, if I command :

action_space.reconnect_powerline(line_id=5,bus_or=2,bus_ex=2),

it makes the line 5 being isolated, and I thought it is same as disconnecting the line 5, since electricity does not flow through the line 5. However, it gives game over. I tried line_id 1 to 7 but all results were same.

Furthermore, if I disconnect the line 5 first, and then reconnect origin and extremity of the line 5 to bus 2, it works. Is this what you intended?

Finally, what is exactly Observation.time_before_cooldown_line and Observation.time_before_cooldown_sub ? Those values do not change all the time. If I disconnect the line, or the line is disconnected because of overflow, those value always give zeros.

ChronicsError: Grid2OpException ChronicsError "Path "c:\users\username\miniconda3\envs\grid2op\lib\site-packages\grid2op\data\test_multi_chronics" doesn't exists."

I had to reinstall everything for the setup I had for Grid2Op. I am using windows machine.

I ran the basic functionality ipynb and got the above error. I made sure the virtual environment is added as the kernel for the jupyter notebook. The problem is that my git pull saved all the downloaded code from github repo to my D drive and the missing folder in the above error is located at the following location i.e., D:\Grid2Op\grid2op\data\test_multi_chronics. However, when I do "pip install -U ." in the grid2op folder, the grid2op package is installed in my C drive where miniconda libraries folder is present as a package. When it installs, it does not copy the data folder (from my D drive) to the package installed location (C drive).

To run basic functionality ipynb without error, I had to manually copy the "data" folder from D drive to the desired location in C drive. I am running the virtual environment from my Grid2Op folder and call jupyter notebook from there.

MultiEnvironment not working on windows based machine

Windows does not handle the multi processing the same way as linux / macos.

Unfortunately, this cause issues with grid2op MultiEnvironment.
We are working to solve this issue.

NB we have trouble making tests on windows machines. If you encounter any other bugs let us know.

One way to make sure you can use grid2op on windows is to use the "windows subsystem for linux" and to install your favorite linux distribution there.

Misleading error message when redispatching action is not performed correctly

So i have likely found another bug.

My redispatch action looks like this:

action_space["redispatch"]
Out[2]: [(0, 4.9999784936326535), (1, 4.78524395611872), (4, -9.999591852954794)]

This is translated into the following print action:

print(action)
This action will:
	 - NOT change anything to the injections
	 - perform the following redispatching action: [ 4.99997849  4.78524396  0.          0.         -9.99959185]
	 - NOT force any line status
	 - NOT switch any line status
	 - NOT switch anything in the topology
	 - NOT force any particular bus configuration

Not that indices 2,3 are not redispatched (0.) - this is correct as they are not controllable.

However, in BasicEnv.py in line 435:

if np.any(redisp_act_orig[new_p == 0.]):

this will evaluate to True because redisp_act_orig has two zeros as per the action print (nothing should be changed on the generators). This is the bug, because now a InvalidRedispatching("Impossible to dispatched a turned off generator") is thrown and the reward is -5.

Even if this was fixed, afterwards there would be

redisp_act_orig[new_p == 0.] = 0.

which would reset all redispatch. For some reason, new_p is completely 0, which would mean that all generators are shut off. I don't think this is correct as the first observation has most generators active.

Thanks for looking into it and best regards

How to define path_save in grid2op.make?

I am using the grid2op.make function to generator a runner with an environment. How is it possible to define the path where the logs are saved in this function?

InvalidRedispatching exception: target redispatching below pmin for generators

My understanding of env.target_dispatch is that it represents the amount of redispatching, not the 'absolute' dispatch (which is given by env.gen_prod_t).

However, I notice that the below exception seems to suggest that an action is illegal if any of the target dispatches go below pmin. Of course this means that if, for instance, I run:

env = grid2op.make("case14_redisp")    
act = env.action_space({"redispatch": [0, -1]})
obs, reward, done, info = env.step(act)
print(reward)
act = env.action_space({"redispatch": [0, 0]})
obs, reward, done, info = env.step(act)
print(reward)

Then the second action is illegal, with print(info['exception']) showing:

[Grid2OpException AmbiguousAction InvalidRedispatching InvalidRedispatching('Target redispatching bellow pmin for generators [0]')]

I feel as though the exception should be thrown if np.any(self.active_prod_t < self.gen_pmin) (or similar)?

Grid2Op/grid2op/BasicEnv.py

Lines 428 to 432 in ceecb56

if np.any(self.target_dispatch < self.gen_pmin):
# action is invalid, the target redispatching would be below pmin for at least a generator
except_ = InvalidRedispatching("Target redispatching bellow pmin for generators "
"{}".format(np.where(self.target_dispatch < self.gen_pmin)[0]))
return except_

Isolating load issue

I played with “case5_example” environment, and I found a strange situation.
Initially, all loads, generators, and powerlines are connected to bus1. If I change bus of a load, which means change bus connection 1 to 2, the load is isolated, and therefore, I think it must lead to the game over. However, the game was not over. I changed the bus of two loads, and the game still was not over (‘done’ keeps giving ‘false’). Is it legal action or bug?
image

If I try to change the bus of last load, I found

{'disc_lines': array([False, False, False, False, False, False, False, False]), 'is_illegal': False, 'is_ambiguous': False, 'is_dispatching_illegal': True, 'is_illegal_reco': False, 'exception': [Grid2OpException Grid2OpException('Impossible to solve for this equilibrium, not enough production')]}

from ‘info’. After this step, all actions did not work, but ‘done’ gave ‘false’.

Best regards,
Thank you

Improve clarity in parameter attribute names

Some attributes names in the Parameters are obscure, for example NB_TIMESTEP_POWERFLOW_ALLOWED which should be NB_TIMESTEP_OVERFLOW_ALLOWED.

We can also improve names of the NB_TIMESTEP_TOPOLOGY_REMODIF and NB_TIMESTEP_LINE_STATUS_REMODIF to match the "cooldown" terminology adopted in observation for example.

To this regard, observation attribute time_before_cooldown_line and time_before_cooldown_sub are not that clear.

Also NB_TIMESTEP_RECONNECTION means something like "number of time step i have to wait if i disconnect a powerline that has been deconnected because of an overflow". The name is not clear.

Wrong voltages for disconnected powerline

The default pandapower backend does not output 0.0 to v_or when a powerline is disconnected.

Code to reproduce:

import grid2op
env = grid2op.make("rte_case5_example", test=True)
line_id = 1
act = env.action_space( {"set_line_status": [(line_id, -1)]})
obs, *_ = env.step(act)
obs.v_or[line_id] # is not 0 however line is not connected

Error in the "Power_Grid_101_notebook.ipynb"

In the "Power_Grid_101_notebook.ipynb" file the cell 17 is giving an error:

id_l2_ingrid, *_ = environment.backend.get_lines_id(from_=0, to_=sub_id)

it should be:

id_l2_ingrid, *_ = environment.observation_space.get_lines_id(from_=0, to_=sub_id)

And more generally, some tests should be made on these notebooks in the "tests" section to make sure there are no regressions at least on the code part.

(this notebook is on the competition starting kit, and NOT on this package)

Beside, on this notebook, and more generally, it's not clear whether the id start at 1 or at 0, so it's really confusing for people looking at it. This need to be fix as soon as possible.

Scaling of the "rho" value in renderer are not correct

The renderer / plot helper is drawing some really nice plots, however the scaling, when the rho values are plotted is not the correct one.

Indeed it shows something like "0.35%" instead of "35%". We have to multiply them by 100 (-:

Add settings of the previous competitions

Some competitions, like the L2RPN (Learning To Run a Power Network - https://l2rpn.chalearn.org/) competition series, used the grid2op platform to emulate the behavior of powergrids.

It would be a nice addition here to add the settings of these past competition: how to set up the "main" function, the "runner" or the "environment" from gri2op that are used in these function.

These settings could include a tool to directly download the training samples available for the 2019 participants, as well as all the tools to evaluate locally the performances of their agents.

Not working line reconnection rule properly

Hello, I've got a new issue.

From the documentation,
BaseObservation.time_before_line_reconnectable
(number of timestep to wait before a powerline can be reconnected (it is disconnected due to maintenance, cascading failure or overflow))

I observed that time_before_line_reconnectableis properly given in my obs, after the powerline was disconnected by overflow.
However, it seems that the disabling reconnection of the powerline (by the default rule) does not work.
That is, when I try to reconnect the powerline before the time_before_line_reconnectable is done, it still work.
Even in the information from env.step(), there is not any exception or illegalAction.

I would like to inform you this issue!

Best Regards

BasePlot - Text formatting

Running a dummy example outputs a grid visualization with poor text formatting. After investigating the matter, I figured that the method BasePlot._get_text_unit is not formatting the float values, since the condition isinstance(number, float) or isinstance(number, np.float) is always False. This happens since my machine uses np.float32 as a default data type for floats. Thus the issue can be fixed by adding an additional clause to the condition: isinstance(number, float) or isinstance(number, np.float) or isinstance(number, np.float32). This efficiently solves the problem.

Best,

Improve Gym integration

I think it's now time to add a full gym integration (and dependency) for the environment (that is almost done already) but also for observation and action spaces.

This would mean introducing the gym framework as a dependency and check for license first.

This would also make some use of other RL methods easier.

L2RPNSandBoxReward crashes

In 0.8.0, using the grid2op.Reward.L2RPNSandBoxReward causes the framework to fail with:

python3.6/site-packages/grid2op/Reward/L2RPNSandBoxScore.py", line 35, in __call__
    p_t = np.max(env.gen_cost_per_MW[env.gen_activeprod_t > 0.], dtype=dt_float)
  File "<__array_function__ internals>", line 4, in amax
TypeError: _amax_dispatcher() got an unexpected keyword argument 'dtype'

Should remove dtype from np.max call and add a unit tests that call rewards instances to prevent this from happening

ChronicsError in notebook 0_basic_functionalities in 0.5.5

I get the following error when running the notebook 0_basic_functionalities.

image

Steps to reproduce:

conda create -n myenv 
conda activate myenv
pip install grid2op  #-> Installs version 0.5.5
run 0_basic_functionalities.ipynb

Stacktrace:

---------------------------------------------------------------------------
ChronicsError                             Traceback (most recent call last)
<ipython-input-9-493abc591523> in <module>
      1 from grid2op.Environment import Environment
----> 2 env = Environment(init_grid_path=powergrid_path,
      3                  chronics_handler=data_feeding,
      4                  backend=backend,
      5                  parameters=param,

D:\Users\hx\miniconda3\envs\test\lib\site-packages\grid2op\Environment\Environment.py in __init__(self, init_grid_path, chronics_handler, backend, parameters, names_chronics_to_backend, actionClass, observationClass, rewardClass, legalActClass, voltagecontrolerClass, other_rewards, thermal_limit_a, epsilon_poly, tol_poly, opponent_action_class, opponent_class, opponent_init_budget)
    154 
    155         # for plotting
--> 156         self.init_backend(init_grid_path, chronics_handler, backend,
    157                           names_chronics_to_backend, actionClass, observationClass,
    158                           rewardClass, legalActClass)

D:\Users\hx\miniconda3\envs\test\lib\site-packages\grid2op\Environment\Environment.py in init_backend(self, init_grid_path, chronics_handler, backend, names_chronics_to_backend, actionClass, observationClass, rewardClass, legalActClass)
    275                     type(chronics_handler)))
    276         self.chronics_handler = chronics_handler
--> 277         self.chronics_handler.initialize(self.name_load, self.name_gen,
    278                                          self.name_line, self.name_sub,
    279                                          names_chronics_to_backend=names_chronics_to_backend)

D:\Users\hx\miniconda3\envs\test\lib\site-packages\grid2op\Chronics\ChronicsHandler.py in initialize(self, order_backend_loads, order_backend_prods, order_backend_lines, order_backend_subs, names_chronics_to_backend)
     84 
     85         """
---> 86         self.real_data.initialize(order_backend_loads, order_backend_prods, order_backend_lines, order_backend_subs,
     87                                   names_chronics_to_backend)
     88 

D:\Users\hx\miniconda3\envs\test\lib\site-packages\grid2op\Chronics\MultiFolder.py in initialize(self, order_backend_loads, order_backend_prods, order_backend_lines, order_backend_subs, names_chronics_to_backend)
    102                                         max_iter=self.max_iter,
    103                                         chunk_size=self.chunk_size)
--> 104         self.data.initialize(order_backend_loads, order_backend_prods, order_backend_lines, order_backend_subs,
    105                              names_chronics_to_backend=names_chronics_to_backend)
    106 

D:\Users\hx\miniconda3\envs\test\lib\site-packages\grid2op\Chronics\GridStateFromFileWithForecasts.py in initialize(self, order_backend_loads, order_backend_prods, order_backend_lines, order_backend_subs, names_chronics_to_backend)
    104 
    105         """
--> 106         super().initialize(order_backend_loads, order_backend_prods, order_backend_lines, order_backend_subs,
    107                            names_chronics_to_backend)
    108 

D:\Users\hx\miniconda3\envs\test\lib\site-packages\grid2op\Chronics\GridStateFromFile.py in initialize(self, order_backend_loads, order_backend_prods, order_backend_lines, order_backend_subs, names_chronics_to_backend)
    408         order_backend_prod_p, order_backend_prod_v, \
    409         order_backend_hazards, order_backend_maintenance \
--> 410             = self._get_orders(load_p, load_q, prod_p, prod_v, hazards, maintenance,
    411                                order_backend_loads, order_backend_prods, order_backend_lines)
    412 

D:\Users\hx\miniconda3\envs\test\lib\site-packages\grid2op\Chronics\GridStateFromFile.py in _get_orders(self, load_p, load_q, prod_p, prod_v, hazards, maintenance, order_backend_loads, order_backend_prods, order_backend_lines)
    231 
    232         if load_p is not None:
--> 233             self._assert_correct_second_stage(load_p.columns, self.names_chronics_to_backend, "loads", "active")
    234             order_chronics_load_p = np.array([order_backend_loads[self.names_chronics_to_backend["loads"][el]]
    235                                               for el in load_p.columns]).astype(dt_int)

D:\Users\hx\miniconda3\envs\test\lib\site-packages\grid2op\Chronics\GridStateFromFile.py in _assert_correct_second_stage(self, pandas_name, dict_convert, key, extra)
    160         for i, el in enumerate(pandas_name):
    161             if not el in dict_convert[key]:
--> 162                 raise ChronicsError("Element named {} is found in the data (column {}) but it is not found on the "
    163                                     "powergrid for data of type \"{}\".\nData in files  are: {}\n"
    164                                     "Converter data are: {}".format(el, i+1, key, sorted(list(pandas_name)),

ChronicsError: Grid2OpException ChronicsError "Element named load_1_0 is found in the data (column 1) but it is not found on the powergrid for data of type "loads".
Data in files  are: ['load_10_8', 'load_11_9', 'load_12_10', 'load_13_2', 'load_1_0', 'load_2_1', 'load_3_3', 'load_4_4', 'load_5_5', 'load_8_6', 'load_9_7']
Converter data are: ['10_C228.66', '11_C-138.89', '12_C-27.88', '13_C-13.33', '14_C63.6', 

'2_C-10.61', '3_C151.15', '4_C-9.47', '5_C201.84', '6_C-6.27', '9_C130.49']"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.