building-agents/genetic_gpu_all.py

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