Source code for grid2op.Space.RandomObject

# Copyright (c) 2019-2020, RTE (https://www.rte-france.com)
# See AUTHORS.txt
# This Source Code Form is subject to the terms of the Mozilla Public License, version 2.0.
# If a copy of the Mozilla Public License, version 2.0 was not distributed with this file,
# you can obtain one at http://mozilla.org/MPL/2.0/.
# SPDX-License-Identifier: MPL-2.0
# This file is part of Grid2Op, Grid2Op a testbed platform to model sequential decision making in power systems.

import copy
import numpy as np
from typing import Optional


[docs]class RandomObject(object): """ Utility class to deal with randomness in some aspect of the game (chronics, action_space, observation_space for examples. Attributes ---------- space_prng: ``numpy.random.RandomState`` The random state of the observation (in case of non deterministic observations or BaseAction. This should not be used at the moment) seed_used: ``int`` The seed used throughout the episode in case of non deterministic observations or action. Notes ----- In order to be reproducible, and to make proper use of the :func:`BaseAgent.seed` capabilities, you must absolutely NOT use the `random` python module (which will not be seeded) nor the `np.random` module and avoid any other "sources" of pseudo random numbers. You can adapt your code the following way. Instead of using `np.random` use `self.space_prng`. For example, if you wanted to write `np.random.randint(1,5)` replace it by `self.space_prng.randint(1,5)`. It is the same for `np.random.normal()` that is replaced by `self.space_prng.normal()`. You have an example of such usage in :func:`RandomAgent.my_act`. If you really need other sources of randomness (for example if you use tensorflow or torch) we strongly recommend you to overload the :func:`BaseAgent.seed` accordingly so that the neural networks are always initialized in the same order using the same weights. Examples --------- If you don't use any :class:`grid2op.Runner.Runner` we recommend using this method twice: 1. to set the seed of the :class:`grid2op.Environment.Environment` 2. to set the seed of your :class:`grid2op.Agent.BaseAgent` .. code-block:: python import grid2op from grid2op.Agent import RandomAgent # or any other agent of course. It might also be a custom you developed # create the environment env = grid2op.make("l2rpn_case14_sandbox") agent = RandomAgent(env.action_space) # and now set the seed env_seed = 42 agent_seed = 12345 env.seed(env_seed) agent.seed(agent_seed) # continue your experiments If you are using a :class:`grid2op.Runner.Runner` we recommend using the "env_seeds" and "agent_seeds" when calling the function :func:`grid2op.Runner.Runner.run` like this: .. code-block:: python import grid2op import numpy as np from grid2op.dtypes import dt_int from grid2op.Agent import RandomAgent # or any other agent of course. It might also be a custom you developed from grid2op.Runner import Runner np.random.seed(42) # or any other seed of course :-) # create the environment env = grid2op.make("l2rpn_case14_sandbox") # NB setting a seed in this environment will have absolutely no effect on the runner # and now set the seed runner = Runner(**env.get_params_for_runner(), agentClass=RandomAgent) # and now start your experiments nb_episode = 2 maximum_int_poss = np.iinfo(dt_int).max # this will be the maximum integer your computer can represent res = runner.run(nb_episode=nb_episode, # generate the seeds for the agent agent_seeds=[np.random.randint(0, maximum_int_poss) for _ in range(nb_episode)], # generate the seeds for the environment env_seeds=[np.random.randint(0, maximum_int_poss) for _ in range(nb_episode)] ) # NB for fully reproducible expriment you have to have called "np.random.seed" before using this method. """
[docs] def __init__(self): self.space_prng : np.random.RandomState = np.random.RandomState() self.seed_used : Optional[int] = None
[docs] def seed(self, seed): """ INTERNAL .. warning:: /!\\\\ Internal, do not use unless you know what you are doing /!\\\\ We do not recommend to use this function outside of the two examples given in the description of this class. Set the seed of the source of pseudo random number used for this RandomObject. Parameters ---------- seed: ``int`` The seed to be set. Returns ------- res: ``tuple`` The associated tuple of seeds used. Tuples are returned because in some cases, multiple objects are seeded with the same call to :func:`RandomObject.seed` """ self.seed_used = seed if self.seed_used is not None: # in this case i have specific seed set. So i force the seed to be deterministic. self.space_prng.seed(seed=self.seed_used) return (self.seed_used,)
def _custom_deepcopy_for_copy(self, new_obj): # RandomObject new_obj.space_prng = copy.deepcopy(self.space_prng) new_obj.seed_used = copy.deepcopy(self.seed_used)