import gym import pandas as pd from data_manager import * from module import * from parameters import * class WgzGym(gym.Env): def __init__(self, **kwargs): super(WgzGym, self).__init__() self.excess = None self.shedding = None self.unbalance = None self.real_unbalance = None self.operation_cost = None self.current_output = None self.final_step_outputs = None self.data_manager = DataManager() self._load_year_data() self.month = 1 self.day = 1 self.TRAIN = True self.current_time = None self.episode_length = 24 self.penalty_coefficient = 50 # 约束惩罚系数 self.sell_coefficient = 0.1 # 售出利润系数 self.EC_parameters = kwargs.get('EC_parameters', EC_parameters) # 电解水制氢器 self.HST_parameters = kwargs.get('dg_parameters', dg_parameters) # 储氢罐 self.grid = Grid() self.EC = EC(self.EC_parameters) self.HST = HST(self.HST_parameters) self.action_space = gym.spaces.Box(low=-1, high=1, shape=(3,), dtype=np.float32) ''' 时间 光伏 温度(湿度暂未考虑) 电需 热需(转化为对应热水所需瓦数) 人数 电价 7 电解水制氢功率 市电功率 储氢罐容量占比 3 ''' self.state_space = gym.spaces.Box(low=0, high=1, shape=(10,), dtype=np.float32) def reset(self, *args): self.month = np.random.randint(1, 13) # choose 12 month if self.TRAIN: self.day = np.random.randint(1, 20) else: self.day = np.random.randint(20, Constant.MONTHS_LEN[self.month - 1]) self.current_time = 0 self.EC.reset() self.HST.reset() return self._build_state() def _build_state(self): soc = self.HST.SOC() ec_output = self.EC.current_output time_step = self.current_time price = self.data_manager.get_price_data(self.month, self.day, self.current_time) temper = self.data_manager.get_temperature_data(self.month, self.day, self.current_time) solar = self.data_manager.get_solar_data(self.month, self.day, self.current_time) load = self.data_manager.get_load_data(self.month, self.day, self.current_time) heat = self.data_manager.get_heat_data(self.month, self.day, self.current_time) people = self.data_manager.get_people_data(self.month, self.day, self.current_time) obs = np.concatenate((np.float32(time_step), np.float32(soc), np.float32(price), np.float32(netload), np.float32(dg1_output), np.float32(dg2_output), np.float32(dg3_output), np.float32(temperature), np.float32(irradiance), np.float32(windspeed)), axis=None) return obs def step(self, action): # state transition: current_obs->take_action->get_reward->get_finish->next_obs # 在每个组件中添加动作 current_obs = self._build_state() temperature = current_obs[7] irradiance = current_obs[8] self.wind.current_power = current_obs[9] self.battery.step(action[0]) # 执行状态转换,电池当前容量也改变 self.dg1.step(action[1]) self.dg2.step(action[2]) self.dg3.step(action[3]) self.solar.step(temperature, irradiance, action[4]) self.current_output = np.array((self.dg1.current_output, self.dg2.current_output, self.dg3.current_output, -self.battery.energy_change, self.solar.current_power, self.wind.current_power)) actual_production = sum(self.current_output) price = current_obs[1] netload = current_obs[3] - self.solar.output_change unbalance = actual_production - netload # reward = 0.0 excess_penalty = 0 deficient_penalty = 0 sell_benefit, buy_cost = 0, 0 self.excess, self.shedding = 0, 0 if unbalance >= 0: # 过剩 if unbalance <= self.grid.exchange_ability: sell_benefit = self.grid.get_cost(price, unbalance) * self.sell_coefficient else: sell_benefit = self.grid.get_cost(price, self.grid.exchange_ability) * self.sell_coefficient # real unbalance:超电网限值 self.excess = unbalance - self.grid.exchange_ability excess_penalty = self.excess * self.penalty_coefficient else: # unbalance <0, 缺少惩罚 if abs(unbalance) <= self.grid.exchange_ability: buy_cost = self.grid.get_cost(price, abs(unbalance)) else: buy_cost = self.grid.get_cost(price, self.grid.exchange_ability) self.shedding = abs(unbalance) - self.grid.exchange_ability deficient_penalty = self.shedding * self.penalty_coefficient battery_cost = self.battery.get_cost(self.battery.energy_change) dg1_cost = self.dg1.get_cost(self.dg1.current_output) dg2_cost = self.dg2.get_cost(self.dg2.current_output) dg3_cost = self.dg3.get_cost(self.dg3.current_output) solar_cost = self.solar.get_cost(self.solar.current_power) wind_cost = self.wind.gen_cost(self.wind.current_power) self.operation_cost = (battery_cost + dg1_cost + dg2_cost + dg3_cost + solar_cost + wind_cost + excess_penalty + deficient_penalty - sell_benefit + buy_cost) reward = - self.operation_cost / 1e3 self.unbalance = unbalance self.real_unbalance = self.shedding + self.excess final_step_outputs = [self.dg1.current_output, self.dg2.current_output, self.dg3.current_output, self.battery.current_capacity, self.solar.current_power, self.wind.current_power] self.current_time += 1 finish = (self.current_time == self.episode_length) if finish: self.final_step_outputs = final_step_outputs self.current_time = 0 next_obs = self.reset() else: next_obs = self._build_state() return current_obs, next_obs, float(reward), finish def _load_year_data(self): data_df = pd.read_csv('data/all_data.csv', sep=',') solar = data_df['solar_power'].to_numpy(dtype=float) temper = data_df['temper'].to_numpy(dtype=float) energy = data_df['energy_demand'].to_numpy(dtype=float) water = data_df['water_demand'].to_numpy(dtype=float) people = data_df['people_count'].to_numpy(dtype=float) price = data_df['price'].to_numpy(dtype=float) '''可根据需求重新设计训练数据大小''' def process_elements(elements, transform_function, add_function): for e in elements: transformed_e = transform_function(e) add_function(transformed_e) process_elements(solar, lambda x: x, self.data_manager.add_load_element) process_elements(temper, lambda x: x, self.data_manager.add_load_element) process_elements(energy, lambda x: x, self.data_manager.add_irradiance_element) process_elements(water, lambda x: x, self.data_manager.add_temperature_element) process_elements(people, lambda x: x, self.data_manager.add_wind_element) process_elements(price, lambda x: x, self.data_manager.add_price_element)