Space

This page is organized as follow:

Objectives

This module exposes the action space definition, the observation space definition (both depend on the underlying power grid and on the type of Action / Observation chosen).

It also define a dedicated representation of the powergrid, that is “powerflow agnostic” (does not depends on the implementation of the grid2op.Backend) and from which inherit most of grid2op objects: the GridObjects

More information about the modeling can be found in the Creating a new backend page more especially in the Grid description section.

Detailed Documentation by class

Classes:

GridObjects()

INTERNAL

RandomObject()

Utility class to deal with randomness in some aspect of the game (chronics, action_space, observation_space for examples.

SerializableSpace(gridobj[, subtype, _init_grid])

INTERNAL

class grid2op.Space.GridObjects[source]

Bases: object

INTERNAL

Warning

/!\ Internal, do not use unless you know what you are doing /!\ Almost every class inherit from this class, so they have its methods and attributes. Do not attempt to use it outside of grid2op environment.

This class stores in a “Backend agnostic” way some information about the powergrid. All these attributes are constant throughout an episode and are defined when the backend is loaded by the environment.

It stores information about numbers of objects, and which objects are where, their names, etc.

The classes grid2op.Action.BaseAction, grid2op.Action.ActionSpace, grid2op.Observation.BaseObservation, grid2op.Observation.ObservationSpace and grid2op.Backend.Backend all inherit from this class. This means that each of the above has its own representation of the powergrid.

Before diving into the technical details on the implementation, you might want to have a look at this page of the documentation How the graph of the grid is encoded in grid2op that details why this representation is suitable.

The modeling adopted for describing a powergrid is the following:

  • only the main objects of a powergrid are represented. An “object” is either a load (consumption) a generator (production), an end of a powerline (each powerline have exactly two extremities: “origin” (or) and “extremity” (ext)).

  • every “object” (see above) is connected to a unique substation. Each substation then counts a given (fixed) number of objects connected to it. [in this platform we don’t consider the possibility to build new “objects” as of today]

For each object, the bus to which it is connected is given in the *_to_subid (for example GridObjects.load_to_subid gives, for each load, the id of the substation to which it is connected)

We suppose that, at every substation, each object (if connected) can be connected to either “busbar” 1 or “busbar” 2. This means that, at maximum, there are 2 independent buses for each substation.

With this hypothesis, we can represent (thought experiment) each substation by a vector. This vector has as many components than the number of objects in the substation (following the previous example, the vector representing the first substation would have 5 components). And each component of this vector would represent a fixed element in it. For example, if say, the load with id 1 is connected to the first element, there would be a unique component saying if the load with id 1 is connected to busbar 1 or busbar 2. For the generators, this id in this (fictive) vector is indicated in the GridObjects.gen_to_sub_pos vector. For example the first position of GridObjects.gen_to_sub_pos indicates on which component of the (fictive) vector representing the substation 1 to look to know on which bus the first generator is connected.

We define the “topology” as the busbar to which each object is connected: each object being connected to either busbar 1 or busbar 2, this topology can be represented by a vector of fixed size (and it actually is in grid2op.Observation.BaseObservation.topo_vect or in grid2op.Backend.Backend.get_topo_vect()). There are multiple ways to make such a vector. We decided to concatenate all the (fictive) vectors described above. This concatenation represents the actual topology of this powergrid at a given timestep. This class doesn’t store this information (see grid2op.Observation.BaseObservation for such purpose). This entails that:

  • the bus to which each object on a substation will be stored in consecutive components of such a vector. For example, if the first substation of the grid has 5 elements connected to it, then the first 5 elements of grid2op.Observation.BaseObservation.topo_vect will represent these 5 elements. The number of elements in each substation is given in grid2op.Space.GridObjects.sub_info.

  • the substation are stored in “order”: objects of the first substations are represented, then this is the objects of the second substation etc. So in the example above, the 6th element of grid2op.Observation.BaseObservation.topo_vect is an object connected to the second substation.

  • to know on which position of this “topology vector” we can find the information relative a specific element it is possible to:

    • method 1 (not recommended):

      1. retrieve the substation to which this object is connected (for example looking at GridObjects.line_or_to_subid [l_id] to know on which substation is connected the origin of powerline with id $l_id$.)

      2. once this substation id is known, compute which are the components of the topological vector that encodes information about this substation. For example, if the substation id sub_id is 4, we a) count the number of elements in substations with id 0, 1, 2 and 3 (say it’s 42) we know, by definition that the substation 4 is encoded in ,:attr:grid2op.Observation.BaseObservation.topo_vect starting at component 42 and b) this substations has GridObjects.sub_info [sub_id] elements (for the sake of the example say it’s 5) then the end of the vector for substation 4 will be 42+5 = 47. Finally, we got the representation of the “local topology” of the substation 4 by looking at grid2op.Observation.BaseObservation.topo_vect [42:47].

      3. retrieve which component of this vector of dimension 5 (remember we assumed substation 4 had 5 elements) encodes information about the origin end of the line with id l_id. This information is given in GridObjects.line_or_to_sub_pos [l_id]. This is a number between 0 and 4, say it’s 3. 3 being the index of the object in the substation)

    • method 2 (not recommended): all of the above is stored (for the same powerline) in the GridObjects.line_or_pos_topo_vect [l_id]. In the example above, we will have: GridObjects.line_or_pos_topo_vect [l_id] = 45 (=42+3: 42 being the index on which the substation started and 3 being the index of the object in the substation)

    • method 3 (recommended): use any of the function that computes it for you: grid2op.Observation.BaseObservation.state_of() is such an interesting method. The two previous methods “method 1” and “method 2” were presented as a way to give detailed and “concrete” example on how the modeling of the powergrid work.

For a given powergrid, this object should be initialized once in the grid2op.Backend.Backend when the first call to grid2op.Backend.Backend.load_grid() is performed. In particular the following attributes must necessarily be defined (see above for a detailed description of some of the attributes):

Optionally, to have more control on the internal grid2op representation, you can also set:

A call to the function GridObjects._compute_pos_big_topo_cls() allow to compute the *_pos_topo_vect attributes (for example GridObjects.line_ex_pos_topo_vect) can be computed from the above data:

Note that if you want to model an environment with unit commitment or redispatching capabilities, you also need to provide the following attributes:

These information are loaded using the grid2op.Backend.Backend.load_redispacthing_data() method.

NB it does not store any information about the current state of the powergrid. It stores information that cannot be modified by the BaseAgent, the Environment or any other entity.

n_line

number of powerlines in the powergrid [class attribute]

Type

int

n_gen

number of generators in the powergrid [class attribute]

Type

int

n_load

number of loads in the powergrid. [class attribute]

Type

int

n_sub

number of substations in the powergrid. [class attribute]

Type

int

n_storage

number of storage units in the powergrid. [class attribute]

Type

int

dim_topo

The total number of objects in the powergrid. This is also the dimension of the “topology vector” defined above. [class attribute]

Type

int

sub_info

for each substation, gives the number of elements connected to it [class attribute]

Type

numpy.ndarray, dtype:int

load_to_subid

for each load, gives the id the substation to which it is connected. For example, GridObjects.load_to_subid [load_id] gives the id of the substation to which the load of id load_id is connected. [class attribute]

Type

numpy.ndarray, dtype:int

gen_to_subid

for each generator, gives the id the substation to which it is connected [class attribute]

Type

numpy.ndarray, dtype:int

line_or_to_subid

for each line, gives the id the substation to which its “origin” end is connected [class attribute]

Type

numpy.ndarray, dtype:int

line_ex_to_subid

for each line, gives the id the substation to which its “extremity” end is connected [class attribute]

Type

numpy.ndarray, dtype:int

storage_to_subid

for each storage unit, gives the id the substation to which it is connected [class attribute]

Type

numpy.ndarray, dtype:int

load_to_sub_pos

Suppose you represent the topoology of the substation s with a vector (each component of this vector will represent an object connected to this substation). This vector has, by definition the size GridObject.sub_info [s]. load_to_sub_pos tells which component of this vector encodes the current load. Suppose that load of id l is connected to the substation of id s (this information is stored in GridObjects.load_to_subid [l]), then if you represent the topology of the substation s with a vector sub_topo_vect, then “sub_topo_vect [ GridObjects.load_to_subid [l] ]” will encode on which bus the load of id l is stored. [class attribute]

Type

numpy.ndarray, dtype:int

gen_to_sub_pos

same as GridObjects.load_to_sub_pos but for generators. [class attribute]

Type

numpy.ndarray, dtype:int

line_or_to_sub_pos

same as GridObjects.load_to_sub_pos but for “origin” end of powerlines. [class attribute]

Type

numpy.ndarray, dtype:int

line_ex_to_sub_pos

same as GridObjects.load_to_sub_pos but for “extremity” end of powerlines. [class attribute]

Type

numpy.ndarray, dtype:int

storage_to_sub_pos

same as GridObjects.load_to_sub_pos but for storage units. [class attribute]

Type

numpy.ndarray, dtype:int

load_pos_topo_vect

The topology if the entire grid is given by a vector, say topo_vect of size GridObjects.dim_topo. For a given load of id l, GridObjects.load_to_sub_pos [l] is the index of the load l in the vector grid2op.BaseObservation.BaseObservation.topo_vect . This means that, if “topo_vect [ GridObjects.load_pos_topo_vect [l] ]=2” then load of id l is connected to the second bus of the substation. [class attribute]

Type

numpy.ndarray, dtype:int

gen_pos_topo_vect

same as GridObjects.load_pos_topo_vect but for generators. [class attribute]

Type

numpy.ndarray, dtype:int

line_or_pos_topo_vect

same as GridObjects.load_pos_topo_vect but for “origin” end of powerlines. [class attribute]

Type

numpy.ndarray, dtype:int

line_ex_pos_topo_vect

same as GridObjects.load_pos_topo_vect but for “extremity” end of powerlines. [class attribute]

Type

numpy.ndarray, dtype:int

storage_pos_topo_vect

same as GridObjects.load_pos_topo_vect but for storage units. [class attribute]

Type

numpy.ndarray, dtype:int

name_load

ordered names of the loads in the grid. [class attribute]

Type

numpy.ndarray, dtype:str

name_gen

ordered names of the productions in the grid. [class attribute]

Type

numpy.ndarray, dtype:str

name_line

ordered names of the powerline in the grid. [class attribute]

Type

numpy.ndarray, dtype:str

name_sub

ordered names of the substation in the grid [class attribute]

Type

numpy.ndarray, dtype:str

name_storage

ordered names of the storage units in the grid [class attribute]

Type

numpy.ndarray, dtype:str

attr_list_vect

List of string. It represents the attributes that will be stored to/from vector when the BaseObservation is converted to/from it. This parameter is also used to compute automatically GridObjects.dtype() and GridObjects.shape() as well as GridObjects.size(). If this class is derived, then it’s really important that this vector is properly set. All the attributes with the name on this vector should have consistently the same size and shape, otherwise, some methods will not behave as expected. [class attribute]

Type

list, static

_vectorized

The representation of the GridObject as a vector. See the help of GridObjects.to_vect() and GridObjects.from_vect() for more information. NB for performance reason, the conversion of the internal representation to a vector is not performed at any time. It is only performed when GridObjects.to_vect() is called the first time. Otherwise, this attribute is set to None. [class attribute]

Type

numpy.ndarray, dtype:float

gen_type

Type of the generators, among: “solar”, “wind”, “hydro”, “thermal” and “nuclear”. Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:str

gen_pmin

Minimum active power production needed for a generator to work properly. Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:float

gen_pmax

Maximum active power production needed for a generator to work properly. Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:float

gen_redispatchable

For each generator, it says if the generator is dispatchable or not. Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:bool

gen_max_ramp_up

Maximum active power variation possible between two consecutive timestep for each generator: a redispatching action on generator g_id cannot be above GridObjects.gen_ramp_up_max [g_id]. Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:float

gen_max_ramp_down

Minimum active power variationpossible between two consecutive timestep for each generator: a redispatching action on generator g_id cannot be below GridObjects.gen_ramp_down_min [g_id]. Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:float

gen_min_uptime

The minimum time (expressed in the number of timesteps) a generator needs to be turned on: it’s not possible to turn off generator gen_id that has been turned on less than gen_min_time_on [gen_id] timesteps ago. Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:float

gen_min_downtime

The minimum time (expressed in the number of timesteps) a generator needs to be turned off: it’s not possible to turn on generator gen_id that has been turned off less than gen_min_time_on [gen_id] timesteps ago. Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:float

gen_cost_per_MW

For each generator, it gives the “operating cost”, eg the cost, in terms of “used currency” for the production of one MW with this generator, if it is already turned on. It’s a positive real number. It’s the marginal cost for each MW. Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:float

gen_startup_cost

The cost to start a generator. It’s a positive real number. Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:float

gen_shutdown_cost

The cost to shut down a generator. It’s a positive real number. Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:float

gen_renewable

Whether each generator is from a renewable energy sources (=can be curtailed). Optional. Used for unit commitment problems or redispacthing action. [class attribute]

Type

numpy.ndarray, dtype:bool

redispatching_unit_commitment_availble

Does the current grid allow for redispatching and / or unit commit problem. If not, any attempt to use it will raise a grid2op.Exceptions.UnitCommitorRedispachingNotAvailable error. [class attribute] For an environment to be compatible with this feature, you need to set up, when loading the backend:

Type

bool

grid_layout

The layout of the powergrid in a form of a dictionnary with keys the substation name, and value a tuple of the coordinate of this substation. If no layout are provided, it defaults to None [class attribute]

Type

dict or None

shunts_data_available

Whether or not the backend support the shunt data. [class attribute]

Type

bool

n_shunt

Number of shunts on the grid. It might be None if the backend does not support shunts. [class attribute]

Type

int or None

name_shunt

Name of each shunt on the grid, or None if the backend does not support shunts. [class attribute]

Type

numpy.ndarray, dtype:str or None

shunt_to_subid

for each shunt (if supported), gives the id the substation to which it is connected [class attribute]

Type

numpy.ndarray, dtype:int

storage_type

type of each storage units, one of “battery” or “pumped storage”

storage_Emax

maximum energy the storage unit can store, in MWh

storage_Emin

minimum energy in the storage unit, in MWh

storage_max_p_prod

maximum power the storage unit can produce (in MW)

storage_max_p_absorb

maximum power the storage unit can absorb (in MW)

storage_marginal_cost

Cost of usage of the storage unit, when charged or discharged, in $/MWh produced (or absorbed)

storage_loss

The self discharged loss of each storage unit (in MW)

storage_charging_efficiency

The efficiency when the storage unit is charging (how much will the capacity increase when the unit is charging) between 0. and 1.

storage_discharging_efficiency

The efficiency when the storage unit is discharging (how much will the capacity decrease to generate a 1MWh of energy on the grid side) between 0. and 1.

grid_objects_types

Give the information about each element of the “topo_vect” vector. It is an “easy” way to retrieve at which element (side of a power, load, generator, storage units) a given component of the “topology vector” is referring to. For more information, you can consult the How the graph of the grid is encoded in grid2op of the documentation or the getting started notebook about the observation and the action for more information.

Type

matrix

dim_alarms = 0  # TODO
alarms_area_names = []  # name of each area  # TODO
alarms_lines_area = {}  # for each lines of the grid, gives on which area(s) it is  # TODO
alarms_area_lines = []  # for each area in the grid, gives which powerlines it contains # TODO
# TODO specify the unit of redispatching data MWh, $/MW etc.

Methods:

__init__()

__reduce__()

It here to avoid issue with pickle.

assert_grid_correct_cls()

INTERNAL

attach_layout(grid_layout)

INTERNAL

cls_to_dict()

INTERNAL

dtype()

The types of the components of the GridObjects, mainly used for gym compatibility is the shape of all part of the action.

from_dict(dict_)

INTERNAL

from_json(dict_)

TODO doc and example

from_vect(vect[, check_legit])

Convert a GridObjects, represented as a vector, into an GridObjects object.

get_generators_id(sub_id)

Returns the list of all generators id in the backend connected to the substation sub_id

get_lines_id([_sentinel, from_, to_])

Returns the list of all the powerlines id in the backend going from from_ to to_

get_loads_id(sub_id)

Returns the list of all loads id in the backend connected to the substation sub_id

get_obj_connect_to([_sentinel, substation_id])

Get all the object connected to a given substation.

get_obj_substations([_sentinel, substation_id])

Return the object connected as a substation in form of a numpy array instead of a dictionary (as opposed to GridObjects.get_obj_connect_to()).

get_storages_id(sub_id)

Returns the list of all storages element (battery or damp) id in the grid connected to the substation sub_id

init_grid(gridobj[, force, extra_name, …])

INTERNAL

init_grid_from_dict_for_pickle(name_res, …)

This function is used internally for pickle to build the classes of the objects instead of loading them from the module (which is impossible as most classes are defined on the fly in grid2op)

process_grid2op_compat()

This function can be overloaded.

same_grid_class(other_cls)

return whether the two classes have the same grid

set_env_name(name)

INTERNAL

set_no_storage()

this function is used to set all necessary parameters when the grid do not contain any storage element.

shape()

The shapes of all the components of the action, mainly used for gym compatibility is the shape of all part of the action.

size()

When the action / observation is converted to a vector, this method return its size.

to_json()

Convert this instance of GridObjects to a dictionary that can be json serialized.

to_vect()

Convert this instance of GridObjects to a numpy ndarray.

Attributes:

__weakref__

list of weak references to the object (if defined)

__init__()[source]
__reduce__()[source]

It here to avoid issue with pickle. But the problem is that it’s also used by deepcopy… So its implementation is used a lot

__weakref__

list of weak references to the object (if defined)

classmethod assert_grid_correct_cls()[source]

INTERNAL

Warning

/!\ Internal, do not use unless you know what you are doing /!\

This is used at the initialization of the environment.

Performs some checking on the loaded grid to make sure it is consistent.

It also makes sure that the vector such as sub_info, load_to_subid or gen_to_sub_pos are of the right type eg. numpy.ndarray with dtype: dt_int

It is called after the grid has been loaded.

These function is by default called by the grid2op.Environment class after the initialization of the environment. If these tests are not successfull, no guarantee are given that the backend will return consistent computations.

In order for the backend to fully understand the structure of actions, it is strongly advised NOT to override this method.

Returns

None

Raise

grid2op.EnvError and possibly all of its derived class.

classmethod attach_layout(grid_layout)[source]

INTERNAL

Warning

/!\ Internal, do not use unless you know what you are doing /!\ We do not recommend to “attach layout” outside of the environment. Please refer to the function grid2op.Environment.BaseEnv.attach_layout() for more information.

grid layout is a dictionary with the keys the name of the substations, and the value the tuple of coordinates of each substations. No check are made it to ensure it is correct.

Parameters

grid_layout (dict) – See definition of GridObjects.grid_layout for more information.

classmethod cls_to_dict()[source]

INTERNAL

Warning

/!\ Internal, do not use unless you know what you are doing /!\ This is used internally only to save action_space or observation_space for example. Do not attempt to use it in a different context.

Convert the object as a dictionary. Note that unless this method is overridden, a call to it will only output the

Returns

res – The representation of the object as a dictionary that can be json serializable.

Return type

dict

dtype()[source]

The types of the components of the GridObjects, mainly used for gym compatibility is the shape of all part of the action.

It is mainly used to know of which types each “sub spaces” the action space and observation space are made of, but you can also directly use it on an observation or an action.

It is a numpy array of objects.

The dtype vector must have the same number of components as the return value of the GridObjects.shape() vector.

NB: in case the class GridObjects is derived,

either GridObjects.attr_list_vect is properly defined for the derived class, or this function must be redefined.

Returns

res – The dtype of the GridObjects

Return type

numpy.ndarray

Examples

It is mainly used to know of which “sub spaces the action space and observation space are made of.

import grid2op
env = grid2op.make()

# for an observation:
obs_space_types = env.observation_space.dtype()

# for an action
act_space_types = env.action_space.dtype()
staticmethod from_dict(dict_)[source]

INTERNAL

Warning

/!\ Internal, do not use unless you know what you are doing /!\ This is used internally only to restore action_space or observation_space if they have been saved by to_dict. Do not attempt to use it in a different context.

Create a valid GridObject (or one of its derived class if this method is overide) from a dictionnary (usually read from a json file)

Parameters

dict (dict) – The representation of the GridObject as a dictionary.

Returns

res – The object of the proper class that were initially represented as a dictionary.

Return type

GridObject

from_json(dict_)[source]

TODO doc and example

Parameters

dict

from_vect(vect, check_legit=True)[source]

Convert a GridObjects, represented as a vector, into an GridObjects object.

NB: in case the class GridObjects is derived, either GridObjects.attr_list_vect is properly defined for the derived class, or this function must be redefined.

It is recommended to use it from the action_space and the observation_space exclusively.

Only the size is checked. If it does not match, an grid2op.Exceptions.AmbiguousAction is thrown. Otherwise the component of the vector are coerced into the proper type silently.

It may results in an non deterministic behaviour if the input vector is not a real action, or cannot be converted to one.

Parameters

vect (numpy.ndarray) – A vector representing an BaseAction.

Examples

It is mainly used for converting back vector representing action or observation into “grid2op” action or observation. NB You should use it only with the “env.action_space” and “env.observation_space”

import grid2op
env = grid2op.make()

# get the vector representation of an observation:
obs = env.reset()
obs_as_vect = obs.to_vect()

# convert it back to an observation (which will be equal to the first one)
obs_cpy = env.observation_space.from_vect(obs_as_vect)

# get the vector representation of an action:
act = env.action_space.sample()
act_as_vect = act.to_vec()

# convert it back to an action (which will be equal to the first one)
act_cpy = env.action_space.from_vect(act_as_vect)
get_generators_id(sub_id)[source]

Returns the list of all generators id in the backend connected to the substation sub_id

Parameters

sub_id (int) – The substation to which we look for the generator

Returns

res – Id of the generators looked for.

Return type

list

Raises

grid2op.Exceptions.BackendError

Examples

It can be used like:

import numpy as np
import grid2op
env = grid2op.make()

g_ids = env.get_generators_id(sub_id=1)
print("The generators connected to substation 1 have for ids: {}".format(g_ids))
get_lines_id(_sentinel=None, from_=None, to_=None)[source]

Returns the list of all the powerlines id in the backend going from from_ to to_

Parameters
  • _sentinel (None) – Internal, do not use

  • from (int) – Id the substation to which the origin end of the powerline to look for should be connected to

  • to (int) – Id the substation to which the extremity end of the powerline to look for should be connected to

Returns

res – Id of the powerline looked for.

Return type

list

Raises

grid2op.Exceptions.BackendError

Examples

It can be used like:

import numpy as np
import grid2op
env = grid2op.make()

l_ids = env.get_lines_id(from_=0, to_=1)
print("The powerlines connecting substation 0 to substation 1 have for ids: {}".format(l_ids))
get_loads_id(sub_id)[source]

Returns the list of all loads id in the backend connected to the substation sub_id

Parameters

sub_id (int) – The substation to which we look for the generator

Returns

res – Id of the loads looked for.

Return type

list

Raises

grid2op.Exceptions.BackendError

Examples

It can be used like:

import numpy as np
import grid2op
env = grid2op.make()

c_ids = env.get_loads_id(sub_id=1)
print("The loads connected to substation 1 have for ids: {}".format(c_ids))
classmethod get_obj_connect_to(_sentinel=None, substation_id=None)[source]

Get all the object connected to a given substation. This is particularly usefull if you want to know the names of the generator / load connected to a given substation, or which extremity etc.

Parameters
  • _sentinel (None) – Used to prevent positional parameters. Internal, do not use.

  • substation_id (int) – ID of the substation we want to inspect

Returns

res

A dictionary with keys:

  • ”loads_id”: a vector giving the id of the loads connected to this substation, empty if none

  • ”generators_id”: a vector giving the id of the generators connected to this substation, empty if none

  • ”lines_or_id”: a vector giving the id of the origin side of the powerlines connected to this substation, empty if none

  • ”lines_ex_id”: a vector giving the id of the extermity side of the powerlines connected to this substation, empty if none.

  • ”storages_id”: a vector giving the id of the storage units connected at this substation.

  • ”nb_elements” : number of elements connected to this substation

Return type

dict

Examples

import grid2op
env = grid2op.make()

# get the vector representation of an observation:
sub_id = 1
dict_ = env.get_obj_connect_to(substation_id=sub_id)
print("There are {} elements connected to this substation (not counting shunt)".format(
      dict_["nb_elements"]))
print("The names of the loads connected to substation {} are: {}".format(
       sub_id, env.name_load[dict_["loads_id"]]))
print("The names of the generators connected to substation {} are: {}".format(
       sub_id, env.name_gen[dict_["generators_id"]]))
print("The powerline whose origin end is connected to substation {} are: {}".format(
       sub_id, env.name_line[dict_["lines_or_id"]]))
print("The powerline whose extremity end is connected to substation {} are: {}".format(
       sub_id, env.name_line[dict_["lines_ex_id"]]))
print("The storage units connected to substation {} are: {}".format(
       sub_id, env.name_line[dict_["storages_id"]]))
classmethod get_obj_substations(_sentinel=None, substation_id=None)[source]

Return the object connected as a substation in form of a numpy array instead of a dictionary (as opposed to GridObjects.get_obj_connect_to()).

This format is particularly useful for example if you want to know the number of generator connected to a given substation for example (see section examples).

Parameters
  • _sentinel (None) – Used to prevent positional parameters. Internal, do not use.

  • substation_id (int) – ID of the substation we want to inspect

Returns

res

A matrix with as many rows as the number of element of the substation and 6 columns:

  1. column 0: the id of the substation

  2. column 1: -1 if this object is not a load, or LOAD_ID if this object is a load (see example)

  3. column 2: -1 if this object is not a generator, or GEN_ID if this object is a generator (see example)

  4. column 3: -1 if this object is not the origin end of a line, or LOR_ID if this object is the origin end of a powerline(see example)

  5. column 4: -1 if this object is not a extremity end, or LEX_ID if this object is the extremity end of a powerline

  6. column 5: -1 if this object is not a storage unit, or STO_ID if this object is one

Return type

numpy.ndarray

Examples

import numpy as np
import grid2op
env = grid2op.make()

# get the vector representation of an observation:
sub_id = 1
mat = env.get_obj_substations(substation_id=sub_id)

# the first element of the substation is:
mat[0,:]
# array([ 1, -1, -1, -1,  0, -1], dtype=int32)
# we know it's connected to substation 1... no kidding...
# we can also get that:
# 1. this is not a load (-1 at position 1 - so 2nd component)
# 2. this is not a generator (-1 at position 2 - so 3rd component)
# 3. this is not the origin end of a powerline (-1 at position 3)
# 4. this is the extremity end of powerline 0 (there is a 0 at position 4)
# 5. this is not a storage unit (-1 at position 5 - so last component)

# likewise, the second element connected at this substation is:
mat[1,:]
# array([ 1, -1, -1,  2, -1, -1], dtype=int32)
# it represents the origin end of powerline 2

# the 5th element connected at this substation is:
mat[4,:]
# which is equal to  array([ 1, -1,  0, -1, -1, -1], dtype=int32)
# so it's represents a generator, and this generator has the id 0

# the 6th element connected at this substation is:
mat[5,:]
# which is equal to  array([ 1, 0,  -1, -1, -1, -1], dtype=int32)
# so it's represents a generator, and this generator has the id 0

# and, last example, if you want to count the number of generator connected at this
# substation you can
is_gen = mat[:,env.GEN_COL] != -1  # a boolean vector saying ``True`` if the object is a generator
nb_gen_this_substation = np.sum(is_gen)
get_storages_id(sub_id)[source]

Returns the list of all storages element (battery or damp) id in the grid connected to the substation sub_id

Parameters

sub_id (int) – The substation to which we look for the storage unit

Returns

res – Id of the storage elements looked for.

Return type

list

Raises

grid2op.Exceptions.BackendError

Examples

It can be used like:

import numpy as np
import grid2op
env = grid2op.make()

sto_ids = env.get_storages_id(sub_id=1)
print("The loads connected to substation 1 have for ids: {}".format(c_ids))
classmethod init_grid(gridobj, force=False, extra_name=None, force_module=None)[source]

INTERNAL

Warning

/!\ Internal, do not use unless you know what you are doing /!\ This is done at the creation of the environment. Use of this class outside of this particular use is really dangerous and will lead to undefined behaviours. Do not use this function.

Initialize this GridObjects subclass with a provided class.

It does not perform any check on the validity of the gridobj parameters, but it guarantees that if gridobj is a valid grid, then the initialization will lead to a valid grid too.

Parameters
  • gridobj (GridObjects) – The representation of the powergrid

  • force (bool) – force the initialization of the class. By default if a class with the same name exists in globals() it does not initialize it. Setting “force=True” will bypass this check and update it accordingly.

staticmethod init_grid_from_dict_for_pickle(name_res, orig_cls, cls_attr)[source]

This function is used internally for pickle to build the classes of the objects instead of loading them from the module (which is impossible as most classes are defined on the fly in grid2op)

It is expected to create an object of the correct type. This object will then be “filled” with the proper content automatically by python, because i provided the “state” of the object in the __reduce__ method.

classmethod process_grid2op_compat()[source]

This function can be overloaded.

This is called when the class is initialized, with init_grid to broadcast grid2op compatibility feature.

classmethod same_grid_class(other_cls) bool[source]

return whether the two classes have the same grid

Notes

Two environments can have different name, but representing the same grid. This is why this function is agnostic to the “env_name” class attribute.

In order for two grid to be equal, they must have everything in common, including the presence / absence of shunts or storage units for example.

classmethod set_env_name(name)[source]

INTERNAL

Warning

/!\ Internal, do not use unless you know what you are doing /!\ Do not attempt in any case to modify the name of the environment once it has been loaded. If you do that, you might experience undefined behaviours, notably with the multi processing but not only.

classmethod set_no_storage()[source]

this function is used to set all necessary parameters when the grid do not contain any storage element.

shape()[source]

The shapes of all the components of the action, mainly used for gym compatibility is the shape of all part of the action.

It is mainly used to know of which “sub spaces the action space and observation space are made of, but you can also directly use it on an observation or an action.

It returns a numpy integer array.

This function must return a vector from which the sum is equal to the return value of “size()”.

The shape vector must have the same number of components as the return value of the GridObjects.dtype() vector.

NB: in case the class GridObjects is derived,

either GridObjects.attr_list_vect is properly defined for the derived class, or this function must be redefined.

Returns

res – The shape of the GridObjects

Return type

numpy.ndarray

Examples

It is mainly used to know of which “sub spaces the action space and observation space are made of.

import grid2op
env = grid2op.make()

# for an observation:
obs_space_shapes = env.observation_space.shape()

# for an action
act_space_shapes = env.action_space.shape()
size()[source]

When the action / observation is converted to a vector, this method return its size.

NB that it is a requirement that converting an GridObjects gives a vector of a fixed size throughout a training.

The size of an object if constant, but more: for a given environment the size of each action or the size of each observations is constant. This allows us to also define the size of the “action_space” and “observation_space”: this method also applies to these spaces (see the examples bellow).

NB: in case the class GridObjects is derived, either GridObjects.attr_list_vect is properly defined for the derived class, or this function must be redefined.

Returns

size – The size of the GridObjects if it’s converted to a flat vector.

Return type

int

Examples

It is mainly used to know the size of the vector that would represent these objects

import grid2op
env = grid2op.make()

# get the vector representation of an observation:
obs = env.reset()
print("The size of this observation is {}".format(obs.size()))

# get the vector representation of an action:
act = env.action_space.sample()
print("The size of this action is {}".format(act.size()))

# it can also be used with the action_space and observation_space
print("The size of the observation space is {}".format(env.observation_space.size()))
print("The size of the action space is {}".format(env.action_space.size()))
to_json()[source]

Convert this instance of GridObjects to a dictionary that can be json serialized.

TODO doc and example

to_vect()[source]

Convert this instance of GridObjects to a numpy ndarray. The size of the array is always the same and is determined by the GridObject.size() method.

NB: in case the class GridObjects is derived,

either GridObjects.attr_list_vect is properly defined for the derived class, or this function must be redefined.

Returns

res – The representation of this action as a flat numpy ndarray

Return type

numpy.ndarray

Examples

It is mainly used for converting Observation of Action to vector:

import grid2op
env = grid2op.make()

# for an observation:
obs = env.reset()
obs_as_vect = obs.to_vect()

# for an action
act = env.action_space.sample()
ac_as_vect = act.to_vec()
class grid2op.Space.RandomObject[source]

Bases: object

Utility class to deal with randomness in some aspect of the game (chronics, action_space, observation_space for examples.

space_prng

The random state of the observation (in case of non deterministic observations or BaseAction. This should not be used at the moment)

Type

numpy.random.RandomState

seed_used

The seed used throughout the episode in case of non deterministic observations or action.

Type

int

Notes

In order to be reproducible, and to make proper use of the 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 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 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 grid2op.Runner.Runner we recommend using this method twice:

  1. to set the seed of the grid2op.Environment.Environment

  2. to set the seed of your grid2op.Agent.BaseAgent

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()
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 grid2op.Runner.Runner we recommend using the “env_seeds” and “agent_seeds” when calling the function grid2op.Runner.Runner.run() like this:

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()
# 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.

Methods:

__init__

Initialize self.

Attributes:

__init__()[source]
__weakref__

list of weak references to the object (if defined)

seed(seed)[source]

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 – The associated tuple of seeds used. Tuples are returned because in some cases, multiple objects are seeded with the same call to RandomObject.seed()

Return type

tuple

class grid2op.Space.SerializableSpace(gridobj, subtype=<class 'object'>, _init_grid=True)[source]

Bases: grid2op.Space.GridObjects.GridObjects, grid2op.Space.RandomObject.RandomObject

INTERNAL

Warning

/!\ Internal, do not use unless you know what you are doing /!\ This is a higher level wrapper that allows to avoid code duplicates for the action_space and observation_space. None of the methods here should be used outside of env.action_space or env.observation_space

This class allows to serialize / de serialize the action space or observation space.

It should not be used inside an Environment, as some functions of the action might not be compatible with the serialization, especially the checking of whether or not an BaseAction is legal or not.

subtype

Type use to build the template object SerializableSpace.template_obj. This type should derive from grid2op.BaseAction.BaseAction or grid2op.BaseObservation.BaseObservation.

Type

type

_template_obj

An instance of the “subtype” provided used to provide higher level utilities, such as the size of the action (see grid2op.BaseAction.BaseAction.size()) or to sample a new BaseAction (see grid2op.BaseAction.BaseAction.sample()) for example.

Type

grid2op.GridObjects

n

Size of the space

Type

int

shape

Shape of each of the component of the Object if represented in a flat vector. An instance that derives from a GridObject (for example grid2op.BaseAction.BaseAction or grid2op.BaseObservation.BaseObservation) can be thought of as being concatenation of independant spaces. This vector gives the dimension of all the basic spaces they are made of.

Type

numpy.ndarray, dtype:int

dtype

Data type of each of the component of the Object if represented in a flat vector. An instance that derives from a GridObject (for example grid2op.BaseAction.BaseAction or grid2op.BaseObservation.BaseObservation) can be thought of as being concatenation of independant spaces. This vector gives the type of all the basic spaces they are made of.

Type

numpy.ndarray, dtype:int

Methods:

__init__

Initialize self.

__init__(gridobj, subtype=<class 'object'>, _init_grid=True)[source]
subtype: type

Type of action used to build SerializableActionSpace._template_act. This type should derive from grid2op.BaseAction.BaseAction or grid2op.BaseObservation.BaseObservation .

_init_grid: bool

Whether or not to call ‘init_grid’ in the subtype (to initialize the class). Do not modify unless you are certain of what you want to do

cls_to_dict()[source]

INTERNAL

Warning

/!\ Internal, do not use unless you know what you are doing /!\ This is used internally only to save action_space or observation_space for example. Do not attempt to use it in a different context.

Serialize this object as a dictionary.

Returns

res – A dictionary representing this object content. It can be loaded back with SerializableObservationSpace.cls_from_dict()

Return type

dict

extract_from_vect(obj_as_vect, attr_name)[source]

This method allows you to extract only a given part of the observation / action if this one is represented as a vector.

Parameters
  • obj_as_vect (numpy.ndarray) – the object (action or observation) represented as a vector.

  • attr_name (str) – the name of the attribute you want to extract from the object

Returns

res – The value of the attribute with name attr_name

Return type

numpy.ndarray

Examples

We detail only the process for the observation, but it works the same way for the action too.

import numpy as np
import grid2op
env = grid2op.make()

# get the vector representation of an observation:
obs = env.reset()
obs_as_vect = obs.to_vect()

# and now you can extract for example the load
load_p = env.observation_space.extract_from_vect(obs_as_vect, "load_p")
assert np.all(load_p == obs.load_p)
# and this should assert to True
staticmethod from_dict(dict_)[source]

INTERNAL

Warning

/!\ Internal, do not use unless you know what you are doing /!\ This is used internally only to restore action_space or observation_space if they have been saved by to_dict. Do not attempt to use it in a different context.

Allows the de-serialization of an object stored as a dictionary (for example in the case of json saving).

Parameters

dict (dict) – Representation of an BaseObservation Space (aka grid2op.BaseObservation.ObservartionHelper) or the BaseAction Space (aka grid2op.BaseAction.ActionSpace) as a dictionary.

Returns

res – An instance of an SerializableSpace matching the dictionary.

Return type

SerializableSpace

from_vect(obj_as_vect, check_legit=True)[source]

Convert an space (action space or observation space), represented as a vector to a valid BaseAction instance. It works the same way for observations.

Parameters

obj_as_vect (numpy.ndarray) – A object living in a space represented as a vector (typically an grid2op.BaseAction.BaseAction or an grid2op.BaseObservation.BaseObservation represented as a numpy vector)

Returns

res – The corresponding action (or observation) as an object (and not as a vector). The return type is given by the type of SerializableSpace._template_obj

Return type

grid2op.Action.Action or grid2op.Observation.Observation

Examples

See GridObjects.from_vect() for more information.

get_indx_extract(attr_name)[source]

Retrieve the type, the beginning and the end of a given attribute in the action or observation once it is represented as vector.

[advanced usage] This is particularly useful to avoid parsing of all the observation / action when you want only to extract a subset of them (see example)

Parameters

attr_name (str) – The name of the attribute you want to extract information from

Returns

  • beg_ (int) – The first component of the vector that concerns the attribute

  • end_ (int) – The las component of the vector that concerns the attribute

  • dtype – The type of the attribute

Examples

This is an “advanced” function used to accelerate the study of an agent. Supposes you have an environment and you want to compute a runner from it. Then you want to have a quick look at the “relative flows” that this agent provides:

import grid2op
import os
import numpy as np
from grid2op.Runner import Runner
from grid2op.Episode import EpisodeData

################
# INTRO
# create a runner
env = grid2op.make()
# see the documentation of the Runner if you want to change the agent.
# in this case it will be "do nothing"
runner = Runner(**env.get_params_for_runner())

# execute it a given number of chronics
nb_episode = 2
path_save = "i_saved_the_runner_here"
res = runner.run(nb_episode=nb_episode, path_save=path_save)

# END INTRO
##################

# now let's load only the flows for each of the computed episode
li_episode = EpisodeData.list_episode(path_save)  # retrieve the list of where each episode is stored
beg_, end_, dtype = env.observation_space.get_indx_extract("rho")
observation_space_name = "observations.npz"

for full_episode_path, episode_name in li_episode:
    all_obs = np.load(os.path.join(full_episode_path, observation_space_name))["data"]

    # and you use the function like this:
    all_flows = all_obs[:, beg_:end_].astype(dtype)

    # you can now do something with the computed flows
    # each row will be a time step, each column a powerline
    # you can have "nan" if the episode "game over" before the end.
size()[source]

The size of any action converted to vector.

Returns

n – The size of the action space.

Return type

int

Examples

See GridObjects.size() for more information.

If you still can’t find what you’re looking for, try in one of the following pages:

Still trouble finding the information ? Do not hesitate to send a github issue about the documentation at this link: Documentation issue template