EAuto mit unterschiedlicher Ladeleistung (auch Optimierung)

2 stufige Optimierung, erst binär, dann mit float
This commit is contained in:
Bla Bla 2024-03-04 12:37:47 +01:00
parent 8fffec91f3
commit 4baf758ef2
4 changed files with 107 additions and 31 deletions

View File

@ -30,8 +30,9 @@ class EAuto:
return return
for moeglich in self.laden_moeglich: for moeglich in self.laden_moeglich:
if moeglich == 1 and self.soc < 100: if moeglich > 0.0 and self.soc < 100:
geladene_energie = min(self.ladegeschwindigkeit, (100 - self.soc) / 100 * self.akku_kapazitaet) # Berechnung der geladenen Energie basierend auf dem Anteil der Lademöglichkeit
geladene_energie = min(self.ladegeschwindigkeit * moeglich, (100 - self.soc) / 100 * self.akku_kapazitaet)
self.soc += geladene_energie / self.akku_kapazitaet * 100 self.soc += geladene_energie / self.akku_kapazitaet * 100
self.soc = min(100, self.soc) self.soc = min(100, self.soc)
self.stuendliche_last.append(geladene_energie) self.stuendliche_last.append(geladene_energie)
@ -42,6 +43,24 @@ class EAuto:
# Umwandlung der stündlichen Last in ein NumPy-Array # Umwandlung der stündlichen Last in ein NumPy-Array
self.stuendliche_last = np.array(self.stuendliche_last) self.stuendliche_last = np.array(self.stuendliche_last)
# def berechne_ladevorgang(self):
# if self.laden_moeglich is None:
# print("Lademöglichkeit wurde nicht gesetzt.")
# return
# for moeglich in self.laden_moeglich:
# if moeglich > 1 and self.soc < 100:
# geladene_energie = min(self.ladegeschwindigkeit, (100 - self.soc) / 100 * self.akku_kapazitaet)
# self.soc += geladene_energie / self.akku_kapazitaet * 100
# self.soc = min(100, self.soc)
# self.stuendliche_last.append(geladene_energie)
# else:
# self.stuendliche_last.append(0) # Keine Ladung in dieser Stunde
# self.stuendlicher_soc.append(self.soc)
# # Umwandlung der stündlichen Last in ein NumPy-Array
# self.stuendliche_last = np.array(self.stuendliche_last)
def get_stuendliche_last(self): def get_stuendliche_last(self):
"""Gibt das NumPy-Array mit der stündlichen Last zurück.""" """Gibt das NumPy-Array mit der stündlichen Last zurück."""
return self.stuendliche_last return self.stuendliche_last

View File

@ -4,9 +4,10 @@ import numpy as np
from pprint import pprint from pprint import pprint
class Gesamtlast: class Gesamtlast:
def __init__(self): def __init__(self, prediction_hours=24):
self.lasten = {} # Enthält Namen und Lasten-Arrays für verschiedene Quellen self.lasten = {} # Enthält Namen und Lasten-Arrays für verschiedene Quellen
self.prediction_hours=prediction_hours
def hinzufuegen(self, name, last_array): def hinzufuegen(self, name, last_array):
""" """
Fügt ein Array von Lasten für eine bestimmte Quelle hinzu. Fügt ein Array von Lasten für eine bestimmte Quelle hinzu.
@ -14,8 +15,11 @@ class Gesamtlast:
:param name: Name der Lastquelle (z.B. "Haushalt", "Wärmepumpe") :param name: Name der Lastquelle (z.B. "Haushalt", "Wärmepumpe")
:param last_array: Array von Lasten, wobei jeder Eintrag einer Stunde entspricht :param last_array: Array von Lasten, wobei jeder Eintrag einer Stunde entspricht
""" """
if(len(last_array) != self.prediction_hours):
raise ValueError(f"Gesamtlast Inkonsistente Längen bei den Arrays: ", name," ", len(last_array) )
self.lasten[name] = last_array self.lasten[name] = last_array
def gesamtlast_berechnen(self): def gesamtlast_berechnen(self):
""" """
Berechnet die gesamte Last für jede Stunde und gibt ein Array der Gesamtlasten zurück. Berechnet die gesamte Last für jede Stunde und gibt ein Array der Gesamtlasten zurück.

View File

@ -63,11 +63,11 @@ def visualisiere_ergebnisse(gesamtlast,leistung_haushalt,leistung_wp, pv_forecas
ax1 = plt.subplot(3, 2, 5) ax1 = plt.subplot(3, 2, 5)
for hour, value in enumerate(discharge_hours): for hour, value in enumerate(discharge_hours):
if value == 1: #if value == 1:
ax1.axvspan(hour, hour+1, color='red', alpha=0.3, label='Entlademöglichkeit' if hour == 0 else "") ax1.axvspan(hour, hour+1, color='red',ymax=value, alpha=0.3, label='Entlademöglichkeit' if hour == 0 else "")
for hour, value in enumerate(laden_moeglich): for hour, value in enumerate(laden_moeglich):
if value == 1: #if value == 1:
ax1.axvspan(hour, hour+1, color='green', alpha=0.3, label='Lademöglichkeit' if hour == 0 else "") ax1.axvspan(hour, hour+1, color='green',ymax=value, alpha=0.3, label='Lademöglichkeit' if hour == 0 else "")
ax1.legend(loc='upper left') ax1.legend(loc='upper left')

99
test.py
View File

@ -37,7 +37,7 @@ discharge_array = np.full(prediction_hours,1) #np.array([1, 0, 1, 0, 1, 1, 1, 1,
laden_moeglich = np.full(prediction_hours,1) # np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0]) laden_moeglich = np.full(prediction_hours,1) # np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0])
#np.full(prediction_hours,1) #np.full(prediction_hours,1)
eauto = EAuto(soc=10, capacity = 60000, power_charge = 7000, load_allowed = laden_moeglich) eauto = EAuto(soc=10, capacity = 60000, power_charge = 7000, load_allowed = laden_moeglich)
min_soc_eauto = 20 min_soc_eauto = 100
hohe_strafe = 10.0 hohe_strafe = 10.0
@ -102,13 +102,18 @@ o = ems.simuliere(0)#ems.simuliere_ab_jetzt()
# Optimierung # Optimierung
# Fitness-Funktion (muss Ihre EnergieManagementSystem-Logik integrieren) def evaluate_inner(individual):
def evaluate(individual): #print(individual)
discharge_hours_bin = individual[0::2]
eautocharge_hours_float = individual[1::2]
#print(discharge_hours_bin)
#print(len(eautocharge_hours_float))
ems.reset() ems.reset()
eauto.reset() eauto.reset()
ems.set_akku_discharge_hours(individual[:prediction_hours]) ems.set_akku_discharge_hours(discharge_hours_bin)
eauto.set_laden_moeglich(individual[prediction_hours:]) eauto.set_laden_moeglich(eautocharge_hours_float)
eauto.berechne_ladevorgang() eauto.berechne_ladevorgang()
leistung_eauto = eauto.get_stuendliche_last() leistung_eauto = eauto.get_stuendliche_last()
gesamtlast.hinzufuegen("eauto", leistung_eauto) gesamtlast.hinzufuegen("eauto", leistung_eauto)
@ -116,6 +121,11 @@ def evaluate(individual):
ems.set_gesamtlast(gesamtlast.gesamtlast_berechnen()) ems.set_gesamtlast(gesamtlast.gesamtlast_berechnen())
o = ems.simuliere(0) o = ems.simuliere(0)
return o, eauto
# Fitness-Funktion (muss Ihre EnergieManagementSystem-Logik integrieren)
def evaluate(individual):
o,eauto = evaluate_inner(individual)
gesamtbilanz = o["Gesamtbilanz_Euro"] gesamtbilanz = o["Gesamtbilanz_Euro"]
# Überprüfung, ob der Mindest-SoC erreicht wird # Überprüfung, ob der Mindest-SoC erreicht wird
@ -124,20 +134,25 @@ def evaluate(individual):
#if final_soc < min_soc_eauto: #if final_soc < min_soc_eauto:
# Fügt eine Strafe hinzu, wenn der Mindest-SoC nicht erreicht wird # Fügt eine Strafe hinzu, wenn der Mindest-SoC nicht erreicht wird
strafe = max(0,(min_soc_eauto - final_soc) * hohe_strafe ) # `hohe_strafe` ist ein vorher festgelegter Strafwert strafe = max(0,(min_soc_eauto - final_soc) * hohe_strafe ) # `hohe_strafe` ist ein vorher festgelegter Strafwert
gesamtbilanz += strafe gesamtbilanz += strafe
#if strafe > 0.0:
# print(min_soc_eauto," - ",final_soc,"*10 = ",strafe)
return (gesamtbilanz,) return (gesamtbilanz,)
# Werkzeug-Setup # Werkzeug-Setup
creator.create("FitnessMin", base.Fitness, weights=(-1.0,)) creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin) creator.create("Individual", list, fitness=creator.FitnessMin)
toolbox = base.Toolbox() toolbox = base.Toolbox()
toolbox.register("attr_bool", random.randint, 0, 1) toolbox.register("attr_bool", random.randint, 0, 1)
toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_bool, prediction_hours*2) toolbox.register("attr_bool", random.randint, 0, 1)
toolbox.register("individual", tools.initCycle, creator.Individual, (toolbox.attr_bool,toolbox.attr_bool), n=prediction_hours)
toolbox.register("population", tools.initRepeat, list, toolbox.individual) toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register("evaluate", evaluate) toolbox.register("evaluate", evaluate)
@ -155,31 +170,69 @@ def optimize():
stats.register("min", np.min) stats.register("min", np.min)
stats.register("max", np.max) stats.register("max", np.max)
algorithms.eaSimple(population, toolbox, cxpb=0.4, mutpb=0.3, ngen=100, algorithms.eaMuPlusLambda(population, toolbox, 50, 100, cxpb=0.5, mutpb=0.5, ngen=500, stats=stats, halloffame=hof, verbose=True)
stats=stats, halloffame=hof, verbose=True) #algorithms.eaSimple(population, toolbox, cxpb=0.2, mutpb=0.2, ngen=1000, stats=stats, halloffame=hof, verbose=True)
return hof[0]
start_solution = optimize()
print("Start Lösung:", start_solution)
# Werkzeug-Setup
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)
toolbox = base.Toolbox()
toolbox.register("attr_bool", random.randint, 0, 1)
toolbox.register("attr_float", random.uniform, 0.0, 1.0)
toolbox.register("individual", tools.initCycle, creator.Individual, (toolbox.attr_bool,toolbox.attr_float), n=prediction_hours)
start_individual = toolbox.individual()
start_individual[:] = start_solution
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register("evaluate", evaluate)
toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
toolbox.register("select", tools.selTournament, tournsize=3)
# Genetischer Algorithmus
def optimize():
population = toolbox.population(n=1000)
population[0] = start_individual
hof = tools.HallOfFame(1)
stats = tools.Statistics(lambda ind: ind.fitness.values)
stats.register("avg", np.mean)
stats.register("min", np.min)
stats.register("max", np.max)
algorithms.eaMuPlusLambda(population, toolbox, 100, 200, cxpb=0.5, mutpb=0.2, ngen=1000, stats=stats, halloffame=hof, verbose=True)
#algorithms.eaSimple(population, toolbox, cxpb=0.2, mutpb=0.2, ngen=1000, stats=stats, halloffame=hof, verbose=True)
return hof[0] return hof[0]
best_solution = optimize() best_solution = optimize()
print("Beste Lösung:", best_solution) print("Beste Lösung:", best_solution)
#ems.set_akku_discharge_hours(best_solution) #ems.set_akku_discharge_hours(best_solution)
ems.reset() o,eauto = evaluate_inner(best_solution)
eauto.reset()
ems.set_akku_discharge_hours(best_solution[:prediction_hours])
eauto.set_laden_moeglich(best_solution[prediction_hours:])
eauto.berechne_ladevorgang()
leistung_eauto = eauto.get_stuendliche_last()
gesamtlast.hinzufuegen("eauto", leistung_eauto)
ems.set_gesamtlast(gesamtlast.gesamtlast_berechnen())
o = ems.simuliere(0)
soc_eauto = eauto.get_stuendlicher_soc() soc_eauto = eauto.get_stuendlicher_soc()
print(soc_eauto) print(soc_eauto)
pprint(o) pprint(o)
pprint(eauto.get_stuendlicher_soc()) pprint(eauto.get_stuendlicher_soc())
visualisiere_ergebnisse(gesamtlast,leistung_haushalt,leistung_wp, pv_forecast, specific_date_prices, o,soc_eauto,best_solution[:prediction_hours],best_solution[prediction_hours:] ) visualisiere_ergebnisse(gesamtlast,leistung_haushalt,leistung_wp, pv_forecast, specific_date_prices, o,soc_eauto,best_solution[0::2],best_solution[1::2] )
# for data in forecast.get_forecast_data(): # for data in forecast.get_forecast_data():