Grid2op/grid2op

Error regarding forecast while evaluating PowerLineSwitch agent using `FromOneEpisodeData`

Closed this issue · 3 comments

AvisP commented

I am trying to use the newly created FromOneEpisodeData and following some previous discussions regarding how to test different agents by replaying the environment actions for 36 bus I am doing 3 things

  • Generate Logs by setting overflow disconnection to false
  • Create an environment with FromOneEpisodeData class and see how a DoNothing agent performs
  • Create an environment with FromOneEpisodeData class and see how a PowerLineSwitch performs

However it is giving me the following error. I set the with_forecast to False into the third runner because without it was getting a separate error message regarding forecasts. Any help to resolve would be appreciated

Impossible to compute next grid state with error "Grid2OpException "Attempt to retrieve the forecasts when they are not available.""
Traceback (most recent call last):
  File "/Users/paula/Desktop/Projects/RL Practice/RLLIB_Practice4/multi_episode_36bus_DN_test5.py", line 167, in <module>
    res3 = runner.run(#path_save=logs_path,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/paula/Desktop/Projects/venvs/L2RPN_080_RLLIB_261_Grid2OP_195/lib/python3.11/site-packages/grid2op/Runner/runner.py", line 1227, in run
    res = self._run_sequential(
          ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/paula/Desktop/Projects/venvs/L2RPN_080_RLLIB_261_Grid2OP_195/lib/python3.11/site-packages/grid2op/Runner/runner.py", line 846, in _run_sequential
    ) = self.run_one_episode(
        ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/paula/Desktop/Projects/venvs/L2RPN_080_RLLIB_261_Grid2OP_195/lib/python3.11/site-packages/grid2op/Runner/runner.py", line 737, in run_one_episode
    with self.init_env() as env:
         ^^^^^^^^^^^^^^^
  File "/Users/paula/Desktop/Projects/venvs/L2RPN_080_RLLIB_261_Grid2OP_195/lib/python3.11/site-packages/grid2op/Runner/runner.py", line 676, in init_env
    env, self.agent = self._new_env(self.chronics_handler, self.parameters)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/paula/Desktop/Projects/venvs/L2RPN_080_RLLIB_261_Grid2OP_195/lib/python3.11/site-packages/grid2op/Runner/runner.py", line 616, in _new_env
    res = self.envClass.init_obj_from_kwargs(
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/paula/Desktop/Projects/venvs/L2RPN_080_RLLIB_261_Grid2OP_195/lib/python3.11/site-packages/grid2op/Environment/environment.py", line 1759, in init_obj_from_kwargs
    res = Environment(init_env_path=init_env_path,
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/paula/Desktop/Projects/venvs/L2RPN_080_RLLIB_261_Grid2OP_195/lib/python3.11/site-packages/grid2op/Environment/environment.py", line 169, in __init__
    self._init_backend(
  File "/Users/paula/Desktop/Projects/venvs/L2RPN_080_RLLIB_261_Grid2OP_195/lib/python3.11/site-packages/grid2op/Environment/environment.py", line 420, in _init_backend
    raise Grid2OpException(
grid2op.Exceptions.Grid2OpException.Grid2OpException: Grid2OpException "Impossible to initialize the powergrid, the powerflow diverge at iteration 0. Available information are: {'disc_lines': array([-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1], dtype=int32), 'is_illegal': False, 'is_ambiguous': False, 'is_dispatching_illegal': False, 'is_illegal_reco': False, 'reason_alarm_illegal': None, 'reason_alert_illegal': None, 'opponent_attack_line': None, 'opponent_attack_sub': None, 'opponent_attack_duration': 0, 'exception': [Grid2OpException Grid2OpException('Attempt to retrieve the forecasts when they are not available.')], 'rewards': {}}"

Here is the sample code

import grid2op
from grid2op.Runner import Runner
from grid2op.Agent import RecoPowerlineAgent, TopologyGreedy, RandomAgent, DoNothingAgent
from lightsim2grid import LightSimBackend
from grid2op.Chronics import MultifolderWithCache
import re
import numpy as np
from datetime import datetime, timedelta
from grid2op.Agent import PowerLineSwitch as greedy

path_agent = "./saved_multiepisode_agent_36bus_DN_4/"
nb_episode = 1
env_name = "l2rpn_neurips_2020_track1_small"  # or any other name

add_msg = "\n"

 env = grid2op.make(env_name,
                    backend=LightSimBackend(),
                    chronics_class=MultifolderWithCache)

 env.chronics_handler.real_data.set_filter(lambda x: re.match(".*july.*", x) is not None)
 env.chronics_handler.real_data.reset()

# # optional (change the parameters to allow the )
 param = env.parameters
 param.NO_OVERFLOW_DISCONNECTION = True
 env.change_parameters(param)
 env.reset()
# # end optional

 runner = Runner(**env.get_params_for_runner(),
                 #agentClass=RecoPowerlineAgent),
                 # agentClass=RandomAgent
                 )
 res = runner.run(nb_episode=4,
            path_save=path_agent)

 print("DoNtohing Agent")
 for _, chron_name, cum_reward, nb_time_step, max_ts in res:
     msg_tmp = "chronics at: {}".format(chron_name)
     msg_tmp += "\ttotal score: {:.6f}".format(cum_reward)
     msg_tmp += "\ttime steps: {:.0f}/{:.0f}".format(nb_time_step, max_ts)
     print(msg_tmp)
add_msg += msg_tmp

env.close()

###### Compare two different agents from previously generated episode #######

from grid2op.Chronics import FromMultiEpisodeData, FromOneEpisodeData
from grid2op.Opponent import FromEpisodeDataOpponent
from grid2op.Episode import EpisodeData

li_episode = EpisodeData.list_episode(path_agent)
for each_episode in li_episode[:3]:

    full_path, episode_studied = each_episode

    env2 = grid2op.make(env_name,
                        backend=LightSimBackend(),
                        chronics_class=FromOneEpisodeData,
                        data_feeding_kwargs={"ep_data": each_episode},
                        opponent_class=FromEpisodeDataOpponent,
                        opponent_attack_cooldown=1,
                        )

    runner_params = env2.get_params_for_runner()
    runner = Runner(**runner_params,)

    res2 = runner.run(nb_episode=nb_episode,
                        # path_save="./saved_multiepisode_agent_36bus_DN_overload_trip/" 
                        )
    print("Do Nothing Agent")
    for _, chron_name, cum_reward, nb_time_step, max_ts in res2:
        msg_tmp = "\tchronics at: {}".format(episode_studied)#.format(chron_name)
        msg_tmp += "\ttotal score: {:.6f}".format(cum_reward)
        msg_tmp += "\ttime steps: {:.0f}/{:.0f}".format(nb_time_step, max_ts)
        print(msg_tmp)

    add_msg += msg_tmp + "\n"
    env2.close()
    
    env3 = grid2op.make(env_name,
                        backend=LightSimBackend(),
                        chronics_class=FromOneEpisodeData,
                        data_feeding_kwargs={"ep_data": each_episode},
                                        # "start_datetime": datetime(year=2019, month=7, day=start_day),
                                        # "chunk_size": 288},
                        opponent_class=FromEpisodeDataOpponent,
                        opponent_attack_cooldown=1,
              )

    runner_params = env3.get_params_for_runner()
    runner_params["verbose"] = "True"
    runner = Runner(**runner_params,
                    agentClass=greedy,
                    with_forecast=False
                    )
    
    res3 = runner.run(#path_save=logs_path,
                     nb_episode=nb_episode,
                     nb_process=1,
                     )

    
    for _, chron_name, cum_reward, nb_time_step, max_ts in res3:
        msg_tmp = "\tchronics at: {}".format(episode_studied)#.format(chron_name)
        msg_tmp += "\ttotal score: {:.6f}".format(cum_reward)
        msg_tmp += "\ttime steps: {:.0f}/{:.0f}".format(nb_time_step, max_ts)
        print(msg_tmp)
    add_msg += msg_tmp + "\n"

    env3.close()

print(add_msg)

I have verified that when I don't pass the FromMultiEpisodeData and FromOneEpisodeData then the issue don't happen.

Hello,

Remember when posting error message to give a minimal working example.

In your case this could mean:

  • using "test=True" when making the environment
  • using the runner for 1 episode and not 4
  • only give the error for a single agent and not 2
  • and most importantly not having a code of 100+ lines

I'll see what I can do but won't have lot of time to spend on this unfortunately. If the could was smaller and executed faster I would spend less time on it and this would increase the odd to find the solution.

The above state is true for me but applies also to every other person, including you

Sometimes I really wonder what I can do to document stuff that are "tricky" / not straightforward.

But first:

  • why you used the MultiFolderWithCache for this example ? => no reason, remove it
  • why you do all the steps => no reason, remove it and limit it with "max_iter=10" or something
  • lightsim2grid is not the issue, remove it
  • why you implement 3 runners, you can reproduce the bug with only 2...

If you did that, you could have focused the bug on the forecast (which is already in the error message by the way, but completely polluted by everything else). And then realised that using with_forecast=False is probably a bad idea when you use an agent that... performs "obs.simulate" (read the doc)

So you could have removed the with_forecast=False

Then, you could have wondered why there were no forecast in the FromOneEpisodeData. From there, a good place to find a solution is the doc. And in the doc, it's written:

If you want to include perfect forecast (unfortunately you cannot retrieve the original forecasts) you can do:

# same as above

env = grid2op.make(env_name,
            chronics_class=FromOneEpisodeData,
            data_feeding_kwargs={"ep_data": ep_data},
            opponent_class=FromEpisodeDataOpponent,
            opponent_attack_cooldown=1,
            list_perfect_forecasts=(5, 10, 15)
        )
# it creates an environment with perfect forecasts available for the next step (5),
# the step afterwards (10) and again the following one (15)

I honestly don't know how I can be more explicit than this. (ok there is a typo there, the real answer is:

env = grid2op.make(env_name,
            chronics_class=FromOneEpisodeData,
            data_feeding_kwargs={"ep_data": ep_data,
            "list_perfect_forecasts": (5, 10, 15), 
},
            opponent_class=FromEpisodeDataOpponent,
            opponent_attack_cooldown=1,
        )

But beside that everything is written.

AvisP commented

Thanks for your prompt response and taking your time in investigating the issue. I will keep the advice you provided in mind and reduce the code as much as possible before submitting an issue. The reason I provided 3 runners was to show it was working with DoNothing agent but not with rule based agent.

However I can provide some comments and walk you through on why I was not able to find the solution in the documentation. When I had this issue I went to the documentation and looked up FromOneEpisodeData. The Chronics page is too long so I opened up the search bar and this is what appeared
Screenshot 2023-11-29 at 1 29 40 PM
Screenshot 2023-11-29 at 1 30 02 PM

As you can see there is no mention of the forecast in these two examples. I scrolled down further till I reached the function forecasts(). On a high level I understood what it does but I was not sure if this is something I should use to resolve my problem. I proceeded to click on the source link and it took me to code, that I tried to understand but with no avail. So at this point I am not even on the Chronics page anymore and confused what to do to debug the issue, other than look up similar issues in past in github and submit one. I was not even sure if the issue is with the make or runner and looking at the grid2op github runner code I tried using with_forecasts but now I understand why it is wrong.

After reading your messages I find that in the detailed documentation by class section the example that you provided. But even if I did find that I would not be convinced that it would resolve my problem. All this to say is that I do consult the documentation and even the github repo to find some way to resolve it. But at least I know now that there are two different places to look for examples in the documentation page. Also the search bar in the documentation page never gives result
Screenshot 2023-11-29 at 1 45 55 PM