184 lines
7.3 KiB
Python
184 lines
7.3 KiB
Python
import json
|
|
import os
|
|
import time
|
|
import numpy as np
|
|
import pandas as pd
|
|
import torch
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
from deap import base, creator, tools, algorithms
|
|
|
|
|
|
def fitness_torch(individuals, price, load, temperature, irradiance, wind_speed, device):
|
|
individuals_torch = torch.tensor(individuals, device=device)
|
|
num_individuals = individuals_torch.shape[0]
|
|
Ac, Ag1, Ag2, Ag3, Av = [individuals_torch[:, i * period:(i + 1) * period] for i in range(5)]
|
|
|
|
soc = torch.zeros((num_individuals, period), device=device)
|
|
Pg1, Pg2, Pg3 = [torch.zeros((num_individuals, period), device=device) for _ in range(3)]
|
|
Cb, Cg1, Cg2, Cg3, Cs, Cw, Rs, Cp, Pe, Ps, Ee, Es = [torch.zeros((num_individuals, period), device=device) for _ in
|
|
range(12)]
|
|
|
|
price_torch = torch.tensor(price, device=device)
|
|
load_torch = torch.tensor(load, device=device)
|
|
temperature_torch = torch.tensor(temperature, device=device)
|
|
irradiance_torch = torch.tensor(irradiance, device=device)
|
|
wind_speed_torch = torch.tensor(wind_speed, device=device)
|
|
|
|
for t in range(period):
|
|
if t > 0:
|
|
soc[:, t] = torch.clamp(soc[:, t - 1] + 0.2 * Ac[:, t] * 0.9, 0.2, 0.8)
|
|
Pg1[:, t] = torch.clamp(Pg1[:, t - 1] + 100 * Ag1[:, t], min=0, max=150)
|
|
Pg2[:, t] = torch.clamp(Pg2[:, t - 1] + 100 * Ag2[:, t], min=0, max=375)
|
|
Pg3[:, t] = torch.clamp(Pg3[:, t - 1] + 200 * Ag3[:, t], min=0, max=500)
|
|
else:
|
|
soc[:, t] = 0.4
|
|
Pg1[:, t] = torch.clamp(100 * Ag1[:, t], min=0, max=150)
|
|
Pg2[:, t] = torch.clamp(100 * Ag2[:, t], min=0, max=375)
|
|
Pg3[:, t] = torch.clamp(200 * Ag3[:, t], min=0, max=500)
|
|
|
|
Pso = torch.clamp((0.2 * irradiance_torch[t] + 0.05 * temperature_torch[t] - 9.25) * (1 + Av[:, t]), min=0)
|
|
|
|
Pw = torch.where(
|
|
(wind_speed_torch[t] >= 3) & (wind_speed_torch[t] < 8),
|
|
wind_speed_torch[t] ** 3 * 172.2625 / 1000,
|
|
torch.where(
|
|
(wind_speed_torch[t] >= 8) & (wind_speed_torch[t] < 12),
|
|
64 * 172.2625 / 125,
|
|
torch.zeros_like(wind_speed_torch[t])
|
|
)
|
|
)
|
|
|
|
P = Ac[:, t] + Pg1[:, t] + Pg2[:, t] + Pg3[:, t] + Pso + Pw
|
|
|
|
Ee[:, t] = torch.where(P >= load_torch[t], P - load_torch[t], torch.zeros_like(P))
|
|
Es[:, t] = torch.where(P < load_torch[t], load_torch[t] - P, torch.zeros_like(P))
|
|
|
|
Cb[:, t] = 0.01 * Ac[:, t] + 0.1 * soc[:, t]
|
|
Cg1[:, t] = 0.0034 * Pg1[:, t] ** 2 + 3 * Pg1[:, t] + 30
|
|
Cg2[:, t] = 0.001 * Pg2[:, t] ** 2 + 10 * Pg2[:, t] + 40
|
|
Cg3[:, t] = 0.001 * Pg3[:, t] ** 2 + 15 * Pg3[:, t] + 70
|
|
Cs[:, t] = 0.01 * Pso
|
|
Cw[:, t] = 0.01 * Pw
|
|
Rs[:, t] = 0.5 * price_torch[t] * Ee[:, t]
|
|
Cp[:, t] = price_torch[t] * Es[:, t]
|
|
Pe[:, t] = torch.where(Ee[:, t] > 100, (Ee[:, t] - 100) * 50, torch.zeros_like(Ee[:, t]))
|
|
Ps[:, t] = torch.where(Es[:, t] > 100, (Es[:, t] - 100) * 50, torch.zeros_like(Es[:, t]))
|
|
|
|
total_cost = torch.sum(Cb + Cg1 + Cg2 + Cg3 + Cs + Cw + Pe + Ps - Rs + Cp, dim=1)
|
|
reward = -total_cost / 1000
|
|
|
|
return reward.cpu().numpy()
|
|
|
|
|
|
def check_bounds(func):
|
|
def wrapper(*args, **kwargs):
|
|
offspring = func(*args, **kwargs)
|
|
for individual in offspring:
|
|
for i in range(len(individual)):
|
|
individual[i] = np.clip(individual[i], -1, 1)
|
|
return offspring
|
|
return wrapper
|
|
|
|
|
|
def save_progress(population, gen, filename='ga_progress.json'):
|
|
data = {
|
|
'population': [[list(ind), ind.fitness.values[0]] for ind in population],
|
|
'generation': gen
|
|
}
|
|
with open(filename, 'w') as f:
|
|
json.dump(data, f)
|
|
print(f"进度已保存到第 {gen} 代到 '{filename}'。")
|
|
|
|
|
|
def load_progress(filename='ga_progress.json'):
|
|
if os.path.exists(filename):
|
|
with open(filename, 'r') as f:
|
|
data = json.load(f)
|
|
population = []
|
|
for ind_data in data['population']:
|
|
ind = creator.Individual(ind_data[0])
|
|
ind.fitness.values = (ind_data[1],)
|
|
population.append(ind)
|
|
gen = data['generation']
|
|
print(f"从第 {gen} 代加载进度。")
|
|
return population, gen
|
|
else:
|
|
return None, 0
|
|
|
|
|
|
def save_decision_values(best_ind, period, file_suffix):
|
|
decision_values = [
|
|
{"x1": best_ind[i], "x2": best_ind[i + period], "x3": best_ind[i + 2 * period], "x4": best_ind[i + 3 * period],
|
|
"x5": best_ind[i + 4 * period]} for i in range(period)]
|
|
filename = f'./decision_values_{file_suffix}.json'
|
|
with open(filename, 'w') as f:
|
|
json.dump(decision_values, f)
|
|
print(f"周期 {file_suffix}:决策值已保存到 '{filename}'。")
|
|
|
|
|
|
def main():
|
|
data = pd.read_csv('./data.csv')
|
|
# period = len(data)
|
|
period = 2
|
|
price, load, temperature, irradiance, wind_speed = [data[col].values for col in
|
|
['price', 'load', 'temperature', 'irradiance', 'wind_speed']]
|
|
|
|
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
|
|
creator.create("Individual", list, fitness=creator.FitnessMax)
|
|
|
|
toolbox = base.Toolbox()
|
|
toolbox.register("attr_float", np.random.uniform, -1, 1)
|
|
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_float, n=5 * period)
|
|
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
|
|
|
|
toolbox.register("mate", check_bounds(tools.cxBlend), alpha=0.5)
|
|
toolbox.register("mutate", check_bounds(tools.mutGaussian), mu=0, sigma=0.1, indpb=0.2)
|
|
toolbox.register("select", tools.selTournament, tournsize=3)
|
|
toolbox.register("evaluate", fitness_torch)
|
|
|
|
population, start_gen = load_progress()
|
|
if population is None:
|
|
population = toolbox.population(n=500)
|
|
start_gen = 0
|
|
|
|
NGEN, CXPB, MUTPB = 500, 0.7, 0.2
|
|
batch_size = 500
|
|
|
|
for gen in range(start_gen, NGEN):
|
|
start_time = time.time()
|
|
offspring = algorithms.varAnd(population, toolbox, cxpb=CXPB, mutpb=MUTPB)
|
|
num_individuals = len(offspring)
|
|
|
|
with ThreadPoolExecutor() as executor:
|
|
futures = []
|
|
for i in range(0, num_individuals, batch_size):
|
|
batch = offspring[i:i + batch_size]
|
|
individuals = [ind[:] for ind in batch]
|
|
futures.append(
|
|
executor.submit(toolbox.evaluate, individuals, price, load, temperature, irradiance, wind_speed, 0))
|
|
|
|
for future in futures:
|
|
fitnesses = future.result()
|
|
for ind, fitness in zip(offspring, fitnesses):
|
|
ind.fitness.values = (fitness,)
|
|
|
|
population = toolbox.select(offspring, k=len(population))
|
|
end_time = time.time()
|
|
elapsed_time = end_time - start_time
|
|
print(f"第 {gen + 1} 代完成于 {elapsed_time:.2f} 秒")
|
|
|
|
if (gen + 1) % 100 == 0:
|
|
best_ind = tools.selBest(population, 1)[0]
|
|
save_decision_values(best_ind, period, gen + 1)
|
|
save_progress(population, gen + 1)
|
|
|
|
best_ind = tools.selBest(population, 1)[0]
|
|
print('最佳个体:', best_ind)
|
|
print('适应度:', best_ind.fitness.values)
|
|
save_decision_values(best_ind, period, NGEN)
|
|
save_progress(population, NGEN)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|