def __init__(self, grid2op_observation_space, attr_to_keep=ALL_ATTR_OBS, subtract=None, divide=None, functs=None): check_gym_version() if not isinstance(grid2op_observation_space, ObservationSpace): raise RuntimeError( f"Impossible to create a BoxGymObsSpace without providing a " f"grid2op observation. You provided {type(grid2op_observation_space)}" f"as the \"grid2op_observation_space\" attribute.") self._attr_to_keep = sorted(attr_to_keep) ob_sp = grid2op_observation_space tol_redisp = ob_sp.obs_env._tol_poly # add to gen_p otherwise ... well it can crash extra_for_losses = _compute_extra_power_for_losses(ob_sp) self.dict_properties = { "year": (np.zeros(1, dtype=dt_int), np.zeros(1, dtype=dt_int) + 2200, (1, ), dt_int), "month": (np.zeros(1, dtype=dt_int), np.zeros(1, dtype=dt_int) + 12, (1, ), dt_int), "day": (np.zeros(1, dtype=dt_int), np.zeros(1, dtype=dt_int) + 31, (1, ), dt_int), "hour_of_day": (np.zeros(1, dtype=dt_int), np.zeros(1, dtype=dt_int) + 24, (1, ), dt_int), "minute_of_hour": (np.zeros(1, dtype=dt_int), np.zeros(1, dtype=dt_int) + 60, (1, ), dt_int), "day_of_week": (np.zeros(1, dtype=dt_int), np.zeros(1, dtype=dt_int) + 7, (1, ), dt_int), "gen_p": (np.full(shape=(ob_sp.n_gen, ), fill_value=0., dtype=dt_float) - tol_redisp - extra_for_losses, ob_sp.gen_pmax + tol_redisp + extra_for_losses, (ob_sp.n_gen, ), dt_float), "gen_q": (np.full(shape=(ob_sp.n_gen, ), fill_value=-np.inf, dtype=dt_float), np.full(shape=(ob_sp.n_gen, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_gen, ), dt_float), "gen_v": (np.full(shape=(ob_sp.n_gen, ), fill_value=0., dtype=dt_float), np.full(shape=(ob_sp.n_gen, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_gen, ), dt_float), "load_p": (np.full(shape=(ob_sp.n_load, ), fill_value=-np.inf, dtype=dt_float), np.full(shape=(ob_sp.n_load, ), fill_value=+np.inf, dtype=dt_float), (ob_sp.n_load, ), dt_float), "load_q": (np.full(shape=(ob_sp.n_load, ), fill_value=-np.inf, dtype=dt_float), np.full(shape=(ob_sp.n_load, ), fill_value=+np.inf, dtype=dt_float), (ob_sp.n_load, ), dt_float), "load_v": (np.full(shape=(ob_sp.n_load, ), fill_value=0., dtype=dt_float), np.full(shape=(ob_sp.n_load, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_load, ), dt_float), "p_or": (np.full(shape=(ob_sp.n_line, ), fill_value=-np.inf, dtype=dt_float), np.full(shape=(ob_sp.n_line, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_line, ), dt_float), "q_or": (np.full(shape=(ob_sp.n_line, ), fill_value=-np.inf, dtype=dt_float), np.full(shape=(ob_sp.n_line, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_line, ), dt_float), "a_or": (np.full(shape=(ob_sp.n_line, ), fill_value=0., dtype=dt_float), np.full(shape=(ob_sp.n_line, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_line, ), dt_float), "v_or": (np.full(shape=(ob_sp.n_line, ), fill_value=0., dtype=dt_float), np.full(shape=(ob_sp.n_line, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_line, ), dt_float), "p_ex": (np.full(shape=(ob_sp.n_line, ), fill_value=-np.inf, dtype=dt_float), np.full(shape=(ob_sp.n_line, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_line, ), dt_float), "q_ex": (np.full(shape=(ob_sp.n_line, ), fill_value=-np.inf, dtype=dt_float), np.full(shape=(ob_sp.n_line, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_line, ), dt_float), "a_ex": (np.full(shape=(ob_sp.n_line, ), fill_value=0., dtype=dt_float), np.full(shape=(ob_sp.n_line, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_line, ), dt_float), "v_ex": (np.full(shape=(ob_sp.n_line, ), fill_value=0., dtype=dt_float), np.full(shape=(ob_sp.n_line, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_line, ), dt_float), "rho": (np.full(shape=(ob_sp.n_line, ), fill_value=0., dtype=dt_float), np.full(shape=(ob_sp.n_line, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_line, ), dt_float), "line_status": (np.full(shape=(ob_sp.n_line, ), fill_value=0, dtype=dt_int), np.full(shape=(ob_sp.n_line, ), fill_value=1, dtype=dt_int), (ob_sp.n_line, ), dt_int), "timestep_overflow": (np.full(shape=(ob_sp.n_line, ), fill_value=np.iinfo(dt_int).min, dtype=dt_int), np.full(shape=(ob_sp.n_line, ), fill_value=np.iinfo(dt_int).max, dtype=dt_int), (ob_sp.n_line, ), dt_int), "topo_vect": (np.full(shape=(ob_sp.dim_topo, ), fill_value=-1, dtype=dt_int), np.full(shape=(ob_sp.dim_topo, ), fill_value=2, dtype=dt_int), (ob_sp.dim_topo, ), dt_int), "time_before_cooldown_line": (np.full(shape=(ob_sp.n_line, ), fill_value=0, dtype=dt_int), np.full(shape=(ob_sp.n_line, ), fill_value=np.iinfo(dt_int).max, dtype=dt_int), (ob_sp.n_line, ), dt_int), "time_before_cooldown_sub": (np.full(shape=(ob_sp.n_sub, ), fill_value=0, dtype=dt_int), np.full(shape=(ob_sp.n_sub, ), fill_value=np.iinfo(dt_int).max, dtype=dt_int), (ob_sp.n_sub, ), dt_int), "time_next_maintenance": (np.full(shape=(ob_sp.n_line, ), fill_value=-1, dtype=dt_int), np.full(shape=(ob_sp.n_line, ), fill_value=np.iinfo(dt_int).max, dtype=dt_int), (ob_sp.n_line, ), dt_int), "duration_next_maintenance": (np.full(shape=(ob_sp.n_line, ), fill_value=0, dtype=dt_int), np.full(shape=(ob_sp.n_line, ), fill_value=np.iinfo(dt_int).max, dtype=dt_int), (ob_sp.n_line, ), dt_int), "target_dispatch": (np.minimum(ob_sp.gen_pmin, -ob_sp.gen_pmax), np.maximum(-ob_sp.gen_pmin, +ob_sp.gen_pmax), (ob_sp.n_gen, ), dt_float), "actual_dispatch": (np.minimum(ob_sp.gen_pmin, -ob_sp.gen_pmax), np.maximum(-ob_sp.gen_pmin, +ob_sp.gen_pmax), (ob_sp.n_gen, ), dt_float), "storage_charge": (np.full(shape=(ob_sp.n_storage, ), fill_value=0, dtype=dt_float), 1.0 * ob_sp.storage_Emax, (ob_sp.n_storage, ), dt_float), "storage_power_target": (-1.0 * ob_sp.storage_max_p_prod, 1.0 * ob_sp.storage_max_p_absorb, (ob_sp.n_storage, ), dt_float), "storage_power": (-1.0 * ob_sp.storage_max_p_prod, 1.0 * ob_sp.storage_max_p_absorb, (ob_sp.n_storage, ), dt_float), "curtailment": (np.full(shape=(ob_sp.n_gen, ), fill_value=0., dtype=dt_float), np.full(shape=(ob_sp.n_gen, ), fill_value=1.0, dtype=dt_float), (ob_sp.n_gen, ), dt_float), "curtailment_limit": (np.full(shape=(ob_sp.n_gen, ), fill_value=0., dtype=dt_float), np.full(shape=(ob_sp.n_gen, ), fill_value=1.0, dtype=dt_float), (ob_sp.n_gen, ), dt_float), "curtailment_mw": (np.full(shape=(ob_sp.n_gen, ), fill_value=0., dtype=dt_float), 1.0 * ob_sp.gen_pmax, (ob_sp.n_gen, ), dt_float), "curtailment_limit_mw": (np.full(shape=(ob_sp.n_gen, ), fill_value=0., dtype=dt_float), 1.0 * ob_sp.gen_pmax, (ob_sp.n_gen, ), dt_float), "thermal_limit": (np.full(shape=(ob_sp.n_line, ), fill_value=0., dtype=dt_float), np.full(shape=(ob_sp.n_line, ), fill_value=np.inf, dtype=dt_float), (ob_sp.n_line, ), dt_float), } self.dict_properties["prod_p"] = self.dict_properties["gen_p"] self.dict_properties["prod_q"] = self.dict_properties["gen_q"] self.dict_properties["prod_v"] = self.dict_properties["gen_v"] self.dict_properties["gen_p_before_curtail"] = self.dict_properties[ "gen_p"] if functs is None: functs = {} for key in functs.keys(): if key not in self._attr_to_keep: raise RuntimeError( f"The key {key} is present in the \"functs\" dictionary but not in the " f"\"attr_to_keep\". This is not consistent: either ignore this function, " f"in that case remove \"{key}\" from \"functs\" or you want to add " f"something to your observation, in that case add it to \"attr_to_keep\"" ) if subtract is None: subtract = {} self._subtract = subtract if divide is None: divide = {} self._divide = divide # handle the "functional" part self._template_obs = ob_sp._template_obj.copy() self.__func = {} self._dims = None low, high, shape, dtype = self._get_info(functs) # initialize the base container Box.__init__(self, low=low, high=high, shape=shape, dtype=dtype)
def __init__(self, grid2op_action_space, attr_to_keep=ALL_ATTR, add=None, multiply=None, functs=None): if not isinstance(grid2op_action_space, ActionSpace): raise RuntimeError( f"Impossible to create a BoxGymActSpace without providing a " f"grid2op action_space. You provided {type(grid2op_action_space)}" f"as the \"grid2op_action_space\" attribute.") check_gym_version() if attr_to_keep == ALL_ATTR: # by default, i remove all the attributes that are not supported by the action type # i do not do that if the user specified specific attributes to keep. This is his responsibility in # in this case attr_to_keep = { el for el in attr_to_keep if grid2op_action_space.supports_type(el) } for el in ATTR_DISCRETE: if el in attr_to_keep: warnings.warn( f"The class \"BoxGymActSpace\" should mainly be used to consider only continuous " f"actions (eg. redispatch, set_storage or curtail). Though it is possible to use " f"\"{el}\" when building it, be aware that this discrete action will be treated " f"as continuous. Consider using the \"MultiDiscreteActSpace\" for these attributes." ) self._attr_to_keep = sorted(attr_to_keep) act_sp = grid2op_action_space self._act_space = copy.deepcopy(grid2op_action_space) low_gen = -1.0 * act_sp.gen_max_ramp_down high_gen = 1.0 * act_sp.gen_max_ramp_up low_gen[~act_sp.gen_redispatchable] = 0. high_gen[~act_sp.gen_redispatchable] = 0. curtail = np.full(shape=(act_sp.n_gen, ), fill_value=0., dtype=dt_float) curtail[~act_sp.gen_renewable] = 1.0 curtail_mw = np.full(shape=(act_sp.n_gen, ), fill_value=0., dtype=dt_float) curtail_mw[~act_sp.gen_renewable] = act_sp.gen_pmax[~act_sp. gen_renewable] self.dict_properties = { "set_line_status": (np.full(shape=(act_sp.n_line, ), fill_value=-1, dtype=dt_int), np.full(shape=(act_sp.n_line, ), fill_value=1, dtype=dt_int), (act_sp.n_line, ), dt_int), "change_line_status": (np.full(shape=(act_sp.n_line, ), fill_value=0, dtype=dt_int), np.full(shape=(act_sp.n_line, ), fill_value=1, dtype=dt_int), (act_sp.n_line, ), dt_int), "set_bus": (np.full(shape=(act_sp.dim_topo, ), fill_value=-1, dtype=dt_int), np.full(shape=(act_sp.dim_topo, ), fill_value=1, dtype=dt_int), (act_sp.dim_topo, ), dt_int), "change_bus": (np.full(shape=(act_sp.dim_topo, ), fill_value=0, dtype=dt_int), np.full(shape=(act_sp.dim_topo, ), fill_value=1, dtype=dt_int), (act_sp.dim_topo, ), dt_int), "redispatch": (low_gen, high_gen, (act_sp.n_gen, ), dt_float), "set_storage": (-1.0 * act_sp.storage_max_p_prod, 1.0 * act_sp.storage_max_p_absorb, (act_sp.n_storage, ), dt_float), "curtail": (curtail, np.full(shape=(act_sp.n_gen, ), fill_value=1., dtype=dt_float), (act_sp.n_gen, ), dt_float), "curtail_mw": (curtail_mw, 1.0 * act_sp.gen_pmax, (act_sp.n_gen, ), dt_float), } self._key_dict_to_proptype = { "set_line_status": dt_int, "change_line_status": dt_bool, "set_bus": dt_int, "change_bus": dt_bool, "redispatch": dt_float, "set_storage": dt_float, "curtail": dt_float, "curtail_mw": dt_float } if add is not None: self._add = add else: self._add = {} if multiply is not None: self._multiply = multiply else: self._multiply = {} # handle the "functional" part self.__func = {} self._dims = None self._dtypes = None if functs is None: functs = {} low, high, shape, dtype = self._get_info(functs) # initialize the base container Box.__init__(self, low=low, high=high, shape=shape, dtype=dtype)