def __init__(self, detailed_infos_for_cascading_failures=False): """ Initialize an instance of Backend. This does nothing per se. Only the call to :func:`Backend.load_grid` should guarantee the backend is properly configured. :param detailed_infos_for_cascading_failures: Whether to be detailed (but slow) when computing cascading failures :type detailed_infos_for_cascading_failures: :class:`bool` """ # lazy loading from grid2op.Action import CompleteAction from grid2op.Action._BackendAction import _BackendAction GridObjects.__init__(self) # the following parameter is used to control the amount of verbosity when computing a cascading failure # if it's set to true, it returns all intermediate _grid states. This can slow down the computation! self.detailed_infos_for_cascading_failures = detailed_infos_for_cascading_failures # the power _grid manipulated. One powergrid per backend. self._grid = None # thermal limit setting, in ampere, at the same "side" of the powerline than self.get_line_overflow self.thermal_limit_a = None # action to set me self.my_bk_act_class = _BackendAction self._complete_action_class = CompleteAction # for the shunt (only if supported) self._sh_vnkv = None # for each shunt gives the nominal value at the bus at which it is connected
def __init__(self): GridObjects.__init__(self) # last connected registered self.last_topo_registered = ValueStore(self.dim_topo, dtype=dt_int) # topo at time t self.current_topo = ValueStore(self.dim_topo, dtype=dt_int) # injection at time t self.prod_p = ValueStore(self.n_gen, dtype=dt_float) self.prod_v = ValueStore(self.n_gen, dtype=dt_float) self.load_p = ValueStore(self.n_load, dtype=dt_float) self.load_q = ValueStore(self.n_load, dtype=dt_float) self.activated_bus = np.full((self.n_sub, 2), dtype=dt_bool, fill_value=False) self.big_topo_to_subid = np.repeat(list(range(self.n_sub)), repeats=self.sub_info) # shunts if self.shunts_data_available: self.shunt_p = ValueStore(self.n_shunt, dtype=dt_float) self.shunt_q = ValueStore(self.n_shunt, dtype=dt_float) self.shunt_bus = ValueStore(self.n_shunt, dtype=dt_int)
def __init__(self, envs): GridObjects.__init__(self) self.envs = envs for env in envs: if not isinstance(env, Environment): raise MultiEnvException( "You provided environment of type \"{}\" which is not supported." "Please only provide a grid2op.Environment.Environment class." "".format(type(env))) self.nb_env = len(envs) max_int = np.iinfo(dt_int).max self._remotes, self._work_remotes = zip( *[Pipe() for _ in range(self.nb_env)]) env_params = [ envs[e].get_kwargs(with_backend=False) for e in range(self.nb_env) ] self._ps = [ RemoteEnv(env_params=env_, remote=work_remote, parent_remote=remote, name="{}_subprocess_{}".format(envs[i].name, i), seed=envs[i].space_prng.randint(max_int)) for i, (work_remote, remote, env_) in enumerate( zip(self._work_remotes, self._remotes, env_params)) ] for p in self._ps: p.daemon = True # if the main process crashes, we should not cause things to hang p.start() for remote in self._work_remotes: remote.close() self._waiting = True
def __init__(self, nb_env, env): GridObjects.__init__(self) self.imported_env = env self.nb_env = nb_env self._remotes, self._work_remotes = zip( *[Pipe() for _ in range(self.nb_env)]) env_params = [env.get_kwargs() for _ in range(self.nb_env)] for el in env_params: el["backendClass"] = type(env.backend) self._ps = [ RemoteEnv(env_params=env_, remote=work_remote, parent_remote=remote, name="env: {}".format(i), seed=np.random.randint(np.iinfo(dt_int).max)) for i, (work_remote, remote, env_) in enumerate( zip(self._work_remotes, self._remotes, env_params)) ] for p in self._ps: p.daemon = True # if the main process crashes, we should not cause things to hang p.start() for remote in self._work_remotes: remote.close() self._waiting = True
def __init__( self, envs_dir, _add_to_name="", # internal, for test only, do not use ! **kwargs): GridObjects.__init__(self) RandomObject.__init__(self) self.current_env = None self.env_index = None self.mix_envs = [] # Special case handling for backend backendClass = None if "backend" in kwargs: backendClass = type(kwargs["backend"]) del kwargs["backend"] # Inline import to prevent cyclical import from grid2op.MakeEnv.Make import make try: for env_dir in sorted(os.listdir(envs_dir)): env_path = os.path.join(envs_dir, env_dir) if not os.path.isdir(env_path): continue # Special case for backend if backendClass is not None: env = make(env_path, backend=backendClass(), _add_to_name=_add_to_name, **kwargs) else: env = make(env_path, **kwargs) self.mix_envs.append(env) except Exception as e: err_msg = "MultiMix environment creation failed: {}".format(e) raise EnvError(err_msg) if len(self.mix_envs) == 0: err_msg = "MultiMix envs_dir did not contain any valid env" raise EnvError(err_msg) self.env_index = 0 self.current_env = self.mix_envs[self.env_index] # Make sure GridObject class attributes are set from first env # Should be fine since the grid is the same for all envs multi_env_name = os.path.basename( os.path.abspath(envs_dir)) + _add_to_name save_env_name = self.current_env.env_name self.current_env.env_name = multi_env_name self.__class__ = self.init_grid(self.current_env) self.current_env.env_name = save_env_name
def __init__(self, detailed_infos_for_cascading_failures=False): """ Initialize an instance of Backend. This does nothing per se. Only the call to :func:`Backend.load_grid` should guarantee the backend is properly configured. :param detailed_infos_for_cascading_failures: Whether to be detailed (but slow) when computing cascading failures :type detailed_infos_for_cascading_failures: :class:`bool` """ GridObjects.__init__(self) # the following parameter is used to control the amount of verbosity when computing a cascading failure # if it's set to true, it returns all intermediate _grid states. This can slow down the computation! self.detailed_infos_for_cascading_failures = detailed_infos_for_cascading_failures # the power _grid manipulated. One powergrid per backend. self._grid = None # thermal limit setting, in ampere, at the same "side" of the powerline than self.get_line_overflow self.thermal_limit_a = None
def __init__(self, obs_env=None, action_helper=None, seed=None): GridObjects.__init__(self) self.action_helper = action_helper # time stamp information self.year = 1970 self.month = 0 self.day = 0 self.hour_of_day = 0 self.minute_of_hour = 0 self.day_of_week = 0 # for non deterministic observation that would not use default np.random module self.seed = None # handles the forecasts here self._forecasted_grid_act = {} self._forecasted_inj = [] self.timestep_overflow = np.zeros(shape=(self.n_line, ), dtype=dt_int) # 0. (line is disconnected) / 1. (line is connected) self.line_status = np.ones(shape=self.n_line, dtype=dt_bool) # topological vector self.topo_vect = np.full(shape=self.dim_topo, dtype=dt_int, fill_value=0) # generators information self.prod_p = np.full(shape=self.n_gen, dtype=dt_float, fill_value=np.NaN) self.prod_q = np.full(shape=self.n_gen, dtype=dt_float, fill_value=np.NaN) self.prod_v = np.full(shape=self.n_gen, dtype=dt_float, fill_value=np.NaN) # loads information self.load_p = np.full(shape=self.n_load, dtype=dt_float, fill_value=np.NaN) self.load_q = np.full(shape=self.n_load, dtype=dt_float, fill_value=np.NaN) self.load_v = np.full(shape=self.n_load, dtype=dt_float, fill_value=np.NaN) # lines origin information self.p_or = np.full(shape=self.n_line, dtype=dt_float, fill_value=np.NaN) self.q_or = np.full(shape=self.n_line, dtype=dt_float, fill_value=np.NaN) self.v_or = np.full(shape=self.n_line, dtype=dt_float, fill_value=np.NaN) self.a_or = np.full(shape=self.n_line, dtype=dt_float, fill_value=np.NaN) # lines extremity information self.p_ex = np.full(shape=self.n_line, dtype=dt_float, fill_value=np.NaN) self.q_ex = np.full(shape=self.n_line, dtype=dt_float, fill_value=np.NaN) self.v_ex = np.full(shape=self.n_line, dtype=dt_float, fill_value=np.NaN) self.a_ex = np.full(shape=self.n_line, dtype=dt_float, fill_value=np.NaN) # lines relative flows self.rho = np.full(shape=self.n_line, dtype=dt_float, fill_value=np.NaN) # cool down and reconnection time after hard overflow, soft overflow or cascading failure self.time_before_cooldown_line = np.full(shape=self.n_line, dtype=dt_int, fill_value=-1) self.time_before_cooldown_sub = np.full(shape=self.n_sub, dtype=dt_int, fill_value=-1) self.time_next_maintenance = np.full(shape=self.n_line, dtype=dt_int, fill_value=-1) self.duration_next_maintenance = np.full(shape=self.n_line, dtype=dt_int, fill_value=-1) # calendar data self.year = dt_int(1970) self.month = dt_int(0) self.day = dt_int(0) self.hour_of_day = dt_int(0) self.minute_of_hour = dt_int(0) self.day_of_week = dt_int(0) # forecasts self._forecasted_inj = [] self._forecasted_grid = [] self._obs_env = obs_env # redispatching self.target_dispatch = np.full(shape=self.n_gen, dtype=dt_float, fill_value=np.NaN) self.actual_dispatch = np.full(shape=self.n_gen, dtype=dt_float, fill_value=np.NaN) # value to assess if two observations are equal self._tol_equal = 5e-1 self.attr_list_vect = None
def __init__(self, parameters, thermal_limit_a=None, epsilon_poly=1e-2, tol_poly=1e-6, other_rewards={}): GridObjects.__init__(self) # specific to power system if not isinstance(parameters, Parameters): raise Grid2OpException( "Parameter \"parameters\" used to build the Environment should derived form the " "grid2op.Parameters class, type provided is \"{}\"".format( type(parameters))) self.parameters = parameters # some timers self._time_apply_act = 0 self._time_powerflow = 0 self._time_extract_obs = 0 self._time_opponent = 0 # data relative to interpolation self._epsilon_poly = epsilon_poly self._tol_poly = tol_poly # define logger self.logger = None # and calendar data self.time_stamp = None self.nb_time_step = 0 # observation self.current_obs = None # type of power flow to play # if True, then it will not disconnect lines above their thermal limits self.no_overflow_disconnection = self.parameters.NO_OVERFLOW_DISCONNECTION self.timestep_overflow = None self.nb_timestep_overflow_allowed = None # store actions "cooldown" self.times_before_line_status_actionable = None self.max_timestep_line_status_deactivated = self.parameters.NB_TIMESTEP_LINE_STATUS_REMODIF self.times_before_topology_actionable = None self.max_timestep_topology_deactivated = self.parameters.NB_TIMESTEP_TOPOLOGY_REMODIF # for maintenance operation self.time_next_maintenance = None self.duration_next_maintenance = None # hazard (not used outside of this class, information is given in `time_remaining_before_line_reconnection` self._hazard_duration = None # hard overflow part self.hard_overflow_threshold = self.parameters.HARD_OVERFLOW_THRESHOLD self.time_remaining_before_line_reconnection = None self.env_dc = self.parameters.ENV_DC # redispatching data self.target_dispatch = None self.actual_dispatch = None self.gen_uptime = None self.gen_downtime = None self.gen_activeprod_t = None self._thermal_limit_a = thermal_limit_a # maintenance / hazards self.time_next_maintenance = None self.duration_next_maintenance = None self.time_remaining_before_reconnection = None # store environment modifications self._injection = None self._maintenance = None self._hazards = None self.env_modification = None # to use the data self.done = False self.current_reward = None self.helper_action_env = None self.chronics_handler = None self.game_rules = None self.helper_action_player = None self.rewardClass = None self.actionClass = None self.observationClass = None self.legalActClass = None self.helper_observation = None self.names_chronics_to_backend = None self.reward_helper = None self.reward_range = None, None # other rewards self.other_rewards = {} for k, v in other_rewards.items(): if not issubclass(v, BaseReward): raise Grid2OpException( "All keys of \"rewards\" key word argument should be classes that inherit from " "\"grid2op.BaseReward\"") self.other_rewards[k] = RewardHelper(v) # opponent self.opponent_action_class = DontAct # class of the action of the opponent self.opponent_class = BaseOpponent # class of the opponent self.opponent_init_budget = 0 ## below initialized by _create_env, above: need to be called self.opponent_action_space = None # ActionSpace(gridobj=) self.compute_opp_budg = None # UnlimitedBudget(self.opponent_act_space) self.opponent = None # OpponentSpace() self.oppSpace = None # voltage self.voltage_controler = None # backend self.init_grid_path = None # specific to Basic Env, do not change self.backend = None self.__is_init = False
def __init__(self, observation_space, substation_layout=None, radius_sub=20., load_prod_dist=70., bus_radius=6.): if substation_layout is None: if observation_space.grid_layout is None: # if no layout is provided, and observation_space has no layout, then it fails raise PlotError( "Impossible to use plotting abilities without specifying a layout (coordinates) " "of the substations.") # if no layout is provided, use the one in the observation_space substation_layout = [] for el in observation_space.name_sub: substation_layout.append(observation_space.grid_layout[el]) if len(substation_layout) != observation_space.n_sub: raise PlotError( "You provided a layout with {} elements while there are {} substations on the powergrid. " "Your layout is invalid".format(len(substation_layout), observation_space.n_sub)) GridObjects.__init__(self) self.init_grid(observation_space) self.observation_space = observation_space self._layout = {} self._layout["substations"] = self._get_sub_layout(substation_layout) self.radius_sub = radius_sub self.load_prod_dist = load_prod_dist # distance between load and generator to the center of the substation self.bus_radius = bus_radius self.subs_elements = [None for _ in self.observation_space.sub_info] # get the element in each substation for sub_id in range(self.observation_space.sub_info.shape[0]): this_sub = {} objs = self.observation_space.get_obj_connect_to( substation_id=sub_id) for c_id in objs["loads_id"]: c_nm = self._get_load_name(sub_id, c_id) this_load = {} this_load["type"] = "load" this_load["sub_pos"] = self.observation_space.load_to_sub_pos[ c_id] this_sub[c_nm] = this_load for g_id in objs["generators_id"]: g_nm = self._get_gen_name(sub_id, g_id) this_gen = {} this_gen["type"] = "gen" this_gen["sub_pos"] = self.observation_space.gen_to_sub_pos[ g_id] this_sub[g_nm] = this_gen for lor_id in objs["lines_or_id"]: ext_id = self.observation_space.line_ex_to_subid[lor_id] l_nm = self._get_line_name(sub_id, ext_id, lor_id) this_line = {} this_line["type"] = "line" this_line[ "sub_pos"] = self.observation_space.line_or_to_sub_pos[ lor_id] this_sub[l_nm] = this_line for lex_id in objs["lines_ex_id"]: or_id = self.observation_space.line_or_to_subid[lex_id] l_nm = self._get_line_name(or_id, sub_id, lex_id) this_line = {} this_line["type"] = "line" this_line[ "sub_pos"] = self.observation_space.line_ex_to_sub_pos[ lex_id] this_sub[l_nm] = this_line self.subs_elements[sub_id] = this_sub self._compute_layout()
def __init__(self, obs_env=None, action_helper=None, seed=None): GridObjects.__init__(self) self.action_helper = action_helper # time stamp information self.year = 1970 self.month = 0 self.day = 0 self.hour_of_day = 0 self.minute_of_hour = 0 self.day_of_week = 0 # for non deterministic observation that would not use default np.random module self.seed = None # handles the forecasts here self._forecasted_grid_act = {} self._forecasted_inj = [] self._obs_env = obs_env self.timestep_overflow = np.zeros(shape=(self.n_line,), dtype=dt_int) # 0. (line is disconnected) / 1. (line is connected) self.line_status = np.ones(shape=self.n_line, dtype=dt_bool) # topological vector self.topo_vect = np.zeros(shape=self.dim_topo, dtype=dt_int) # generators information self.prod_p = np.full(shape=self.n_gen, dtype=dt_float, fill_value=np.NaN) self.prod_q = 1.0 * self.prod_p self.prod_v = 1.0 * self.prod_p # loads information self.load_p = np.full(shape=self.n_load, dtype=dt_float, fill_value=np.NaN) self.load_q = 1.0 * self.load_p self.load_v = 1.0 * self.load_p # lines origin information self.p_or = np.full(shape=self.n_line, dtype=dt_float, fill_value=np.NaN) self.q_or = 1.0 * self.p_or self.v_or = 1.0 * self.p_or self.a_or = 1.0 * self.p_or # lines extremity information self.p_ex = 1.0 * self.p_or self.q_ex = 1.0 * self.p_or self.v_ex = 1.0 * self.p_or self.a_ex = 1.0 * self.p_or # lines relative flows self.rho = 1.0 * self.p_or # cool down and reconnection time after hard overflow, soft overflow or cascading failure self.time_before_cooldown_line = np.full(shape=self.n_line, dtype=dt_int, fill_value=-1) self.time_before_cooldown_sub = np.full(shape=self.n_sub, dtype=dt_int, fill_value=-1) self.time_next_maintenance = 1 * self.time_before_cooldown_line self.duration_next_maintenance = 1 * self.time_before_cooldown_line # calendar data self.year = dt_int(1970) self.month = dt_int(0) self.day = dt_int(0) self.hour_of_day = dt_int(0) self.minute_of_hour = dt_int(0) self.day_of_week = dt_int(0) # redispatching self.target_dispatch = 1.0 * self.prod_p self.actual_dispatch = 1.0 * self.prod_p # to save some computation time self._connectivity_matrix_ = None self._bus_connectivity_matrix_ = None self._dictionnarized = None # for shunt (these are not stored!) if self.shunts_data_available: self._shunt_p = np.full(shape=self.n_shunt, dtype=dt_float, fill_value=np.NaN) self._shunt_q = 1.0 * self._shunt_p self._shunt_v = 1.0 * self._shunt_p self._shunt_bus = np.full(shape=self.n_shunt, dtype=dt_int, fill_value=1)
def __init__(self, gridobj, obs_env=None, action_helper=None, seed=None): GridObjects.__init__(self) self.init_grid(gridobj) self.action_helper = action_helper # time stamp information self.year = 1970 self.month = 0 self.day = 0 self.hour_of_day = 0 self.minute_of_hour = 0 self.day_of_week = 0 # for non deterministic observation that would not use default np.random module self.seed = None # handles the forecasts here self._forecasted_grid = [] self._forecasted_inj = [] self._obs_env = obs_env self.timestep_overflow = None # 0. (line is disconnected) / 1. (line is connected) self.line_status = None # topological vector self.topo_vect = None # generators information self.prod_p = None self.prod_q = None self.prod_v = None # loads information self.load_p = None self.load_q = None self.load_v = None # lines origin information self.p_or = None self.q_or = None self.v_or = None self.a_or = None # lines extremity information self.p_ex = None self.q_ex = None self.v_ex = None self.a_ex = None # lines relative flows self.rho = None # cool down and reconnection time after hard overflow, soft overflow or cascading failure self.time_before_cooldown_line = None self.time_before_cooldown_sub = None self.time_before_line_reconnectable = None self.time_next_maintenance = None self.duration_next_maintenance = None # matrices self.connectivity_matrix_ = None self.bus_connectivity_matrix_ = None self.vectorized = None # redispatching self.target_dispatch = None self.actual_dispatch = None # value to assess if two observations are equal self._tol_equal = 5e-1 self.attr_list_vect = None self.reset()
def __init__( self, envs_dir, experimental_read_from_local_dir=False, _add_to_name="", # internal, for test only, do not use ! _compat_glop_version=None, # internal, for test only, do not use ! _test=False, **kwargs): GridObjects.__init__(self) RandomObject.__init__(self) self.current_env = None self.env_index = None self.mix_envs = [] self._env_dir = os.path.abspath(envs_dir) # Special case handling for backend # TODO: with backend.copy() instead ! backendClass = None if "backend" in kwargs: backendClass = type(kwargs["backend"]) del kwargs["backend"] # Inline import to prevent cyclical import from grid2op.MakeEnv.Make import make # TODO reuse same observation_space and action_space in all the envs maybe ? try: for env_dir in sorted(os.listdir(envs_dir)): env_path = os.path.join(envs_dir, env_dir) if not os.path.isdir(env_path): continue # Special case for backend if backendClass is not None: env = make(env_path, backend=backendClass(), _add_to_name=_add_to_name, _compat_glop_version=_compat_glop_version, test=_test, experimental_read_from_local_dir= experimental_read_from_local_dir, **kwargs) else: env = make(env_path, _add_to_name=_add_to_name, _compat_glop_version=_compat_glop_version, test=_test, experimental_read_from_local_dir= experimental_read_from_local_dir, **kwargs) self.mix_envs.append(env) except Exception as exc_: err_msg = "MultiMix environment creation failed: {}".format(exc_) raise EnvError(err_msg) if len(self.mix_envs) == 0: err_msg = "MultiMix envs_dir did not contain any valid env" raise EnvError(err_msg) self.env_index = 0 self.current_env = self.mix_envs[self.env_index] # Make sure GridObject class attributes are set from first env # Should be fine since the grid is the same for all envs multi_env_name = os.path.basename( os.path.abspath(envs_dir)) + _add_to_name save_env_name = self.current_env.env_name self.current_env.env_name = multi_env_name self.__class__ = self.init_grid(self.current_env) self.current_env.env_name = save_env_name