Haushaltsgeräte wie z.B. Spülmaschine

flask / Optimierung besser getrennt
Optimierung Bug, bei mehrfahcen neustart
This commit is contained in:
Bla Bla 2024-04-02 16:46:16 +02:00
parent db747e6d24
commit be5a99f86a
6 changed files with 199 additions and 299 deletions

View File

@ -18,221 +18,46 @@ import matplotlib.pyplot as plt
import string import string
from datetime import datetime from datetime import datetime
from deap import base, creator, tools, algorithms from deap import base, creator, tools, algorithms
from modules.class_optimize import *
import numpy as np import numpy as np
import random import random
import os import os
# if ist_dst_wechsel(datetime.now()):
# prediction_hours = 23 # Anpassung auf 23 Stunden für DST-Wechseltage
# else:
# prediction_hours = 24 # Standardwert für Tage ohne DST-Wechsel
prediction_hours = 24
start_hour = datetime.now().hour
hohe_strafe = 10.0
# print(prediction_hours)
# sys.exit()
def isfloat(num):
try:
float(num)
return True
except:
return False
def evaluate_inner(individual, ems):
discharge_hours_bin = individual[0::2]
eautocharge_hours_float = individual[1::2]
#print(discharge_hours_bin)
#print(len(eautocharge_hours_float))
ems.reset()
ems.set_akku_discharge_hours(discharge_hours_bin)
ems.set_eauto_charge_hours(eautocharge_hours_float)
o = ems.simuliere(start_hour)
return o
# Fitness-Funktion (muss Ihre EnergieManagementSystem-Logik integrieren)
def evaluate(individual,ems,parameter):
o = evaluate_inner(individual,ems)
gesamtbilanz = o["Gesamtbilanz_Euro"]
# Überprüfung, ob der Mindest-SoC erreicht wird
final_soc = ems.eauto.ladezustand_in_prozent() # Nimmt den SoC am Ende des Optimierungszeitraums
strafe = 0.0
strafe = max(0,(parameter['eauto_min_soc']-ems.eauto.ladezustand_in_prozent()) * hohe_strafe )
# print(ems.eauto.charge_array)
# print(ems.eauto.ladezustand_in_prozent())
# print(strafe)
gesamtbilanz += strafe
gesamtbilanz += o["Gesamt_Verluste"]/1000.0
return (gesamtbilanz,)
# 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_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("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
toolbox.register("select", tools.selTournament, tournsize=3)
# Genetischer Algorithmus
def optimize(start_solution=None):
population = toolbox.population(n=100)
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)
print("Start:",start_solution)
if start_solution is not None and start_solution != -1:
population.insert(0, creator.Individual(start_solution))
#algorithms.eaMuPlusLambda(population, toolbox, 100, 200, cxpb=0.3, mutpb=0.3, ngen=500, stats=stats, halloffame=hof, verbose=True)
algorithms.eaSimple(population, toolbox, cxpb=0.8, mutpb=0.8, ngen=400, stats=stats, halloffame=hof, verbose=True)
return hof[0]
app = Flask(__name__) app = Flask(__name__)
# Dummy-Funktion für die Durchführung der Simulation/Optimierung
# Ersetzen Sie diese Logik durch Ihren eigentlichen Optimierungscode
def durchfuehre_simulation(parameter):
start_hour = datetime.now().hour opt_class = optimization_problem(prediction_hours=24, strafe=10)
############
# Parameter
############
date = (datetime.now().date() + timedelta(hours = prediction_hours)).strftime("%Y-%m-%d")
date_now = datetime.now().strftime("%Y-%m-%d")
akku_size = parameter['pv_akku_cap'] # Wh
year_energy = parameter['year_energy'] #2000*1000 #Wh
einspeiseverguetung_euro_pro_wh = np.full(prediction_hours, parameter["einspeiseverguetung_euro_pro_wh"]) #= # € / Wh 7/(1000.0*100.0)
max_heizleistung = parameter['max_heizleistung'] #1000 # 5 kW Heizleistung
wp = Waermepumpe(max_heizleistung,prediction_hours)
pv_forecast_url = parameter['pv_forecast_url'] #"https://api.akkudoktor.net/forecast?lat=52.52&lon=13.405&power=5000&azimuth=-10&tilt=7&powerInvertor=10000&horizont=20,27,22,20&power=4800&azimuth=-90&tilt=7&powerInvertor=10000&horizont=30,30,30,50&power=1400&azimuth=-40&tilt=60&powerInvertor=2000&horizont=60,30,0,30&power=1600&azimuth=5&tilt=45&powerInvertor=1400&horizont=45,25,30,60&past_days=5&cellCoEff=-0.36&inverterEfficiency=0.8&albedo=0.25&timezone=Europe%2FBerlin&hourly=relativehumidity_2m%2Cwindspeed_10m"
akku = PVAkku(kapazitaet_wh=akku_size,hours=prediction_hours,start_soc_prozent=parameter["pv_soc"])
discharge_array = np.full(prediction_hours,1) #np.array([1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 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])
eauto = PVAkku(kapazitaet_wh=parameter["eauto_cap"], hours=prediction_hours, lade_effizienz=parameter["eauto_charge_efficiency"], entlade_effizienz=1.0, max_ladeleistung_w=parameter["eauto_charge_power"] ,start_soc_prozent=parameter["eauto_soc"]) @app.route('/optimize', methods=['POST'])
eauto.set_charge_per_hour(laden_moeglich) def flask_optimize():
min_soc_eauto = parameter['eauto_min_soc']
start_params = parameter['start_solution']
gesamtlast = Gesamtlast()
###############
# Load Forecast
###############
lf = LoadForecast(filepath=r'load_profiles.npz', year_energy=year_energy)
#leistung_haushalt = lf.get_daily_stats(date)[0,...] # Datum anpassen
leistung_haushalt = lf.get_stats_for_date_range(date_now,date)[0,...].flatten()
gesamtlast.hinzufuegen("Haushalt", leistung_haushalt)
###############
# PV Forecast
###############
#PVforecast = PVForecast(filepath=os.path.join(r'test_data', r'pvprognose.json'))
PVforecast = PVForecast(prediction_hours = prediction_hours, url=pv_forecast_url)
#print("PVPOWER",parameter['pvpowernow'])
if isfloat(parameter['pvpowernow']):
PVforecast.update_ac_power_measurement(date_time=datetime.now(), ac_power_measurement=float(parameter['pvpowernow']))
#PVforecast.print_ac_power_and_measurement()
pv_forecast = PVforecast.get_pv_forecast_for_date_range(date_now,date) #get_forecast_for_date(date)
temperature_forecast = PVforecast.get_temperature_for_date_range(date_now,date)
###############
# Strompreise
###############
filepath = os.path.join (r'test_data', r'strompreise_akkudokAPI.json') # Pfad zur JSON-Datei anpassen
#price_forecast = HourlyElectricityPriceForecast(source=filepath)
price_forecast = HourlyElectricityPriceForecast(source="https://api.akkudoktor.net/prices?start="+date_now+"&end="+date+"")
specific_date_prices = price_forecast.get_price_for_daterange(date_now,date)
###############
# WP
##############
leistung_wp = wp.simulate_24h(temperature_forecast)
gesamtlast.hinzufuegen("Heatpump", leistung_wp)
ems = EnergieManagementSystem(akku=akku, gesamtlast = gesamtlast, pv_prognose_wh=pv_forecast, strompreis_euro_pro_wh=specific_date_prices, einspeiseverguetung_euro_pro_wh=einspeiseverguetung_euro_pro_wh, eauto=eauto)
o = ems.simuliere(start_hour)
def evaluate_wrapper(individual):
return evaluate(individual, ems, parameter)
toolbox.register("evaluate", evaluate_wrapper)
print()
print("START:",start_params)
print()
start_solution = optimize(start_params)
best_solution = start_solution
o = evaluate_inner(best_solution, ems)
eauto = ems.eauto.to_dict()
discharge_hours_bin = best_solution[0::2]
eautocharge_hours_float = best_solution[1::2]
#print(o)
visualisiere_ergebnisse(gesamtlast, pv_forecast, specific_date_prices, o,best_solution[0::2],best_solution[1::2] , temperature_forecast, start_hour, prediction_hours,einspeiseverguetung_euro_pro_wh)
os.system("scp visualisierungsergebnisse.pdf andreas@192.168.1.135:")
#print(eauto)
return {"discharge_hours_bin":discharge_hours_bin, "eautocharge_hours_float":eautocharge_hours_float ,"result":o ,"eauto_obj":eauto,"start_solution":best_solution}
@app.route('/simulation', methods=['POST'])
def simulation():
if request.method == 'POST': if request.method == 'POST':
parameter = request.json parameter = request.json
# Erforderliche Parameter prüfen # Erforderliche Parameter prüfen
erforderliche_parameter = [ 'pv_akku_cap', 'year_energy',"einspeiseverguetung_euro_pro_wh", 'max_heizleistung', 'pv_forecast_url', 'eauto_min_soc', "eauto_cap","eauto_charge_efficiency","eauto_charge_power","eauto_soc","pv_soc","start_solution","pvpowernow"] erforderliche_parameter = [ 'pv_akku_cap', 'year_energy',"einspeiseverguetung_euro_pro_wh", 'max_heizleistung', 'pv_forecast_url', 'eauto_min_soc', "eauto_cap","eauto_charge_efficiency","eauto_charge_power","eauto_soc","pv_soc","start_solution","pvpowernow","haushaltsgeraet_dauer","haushaltsgeraet_wh"]
for p in erforderliche_parameter: for p in erforderliche_parameter:
if p not in parameter: if p not in parameter:
return jsonify({"error": f"Fehlender Parameter: {p}"}), 400 return jsonify({"error": f"Fehlender Parameter: {p}"}), 400
# Simulation durchführen # Simulation durchführen
ergebnis = durchfuehre_simulation(parameter) ergebnis = opt_class.optimierung_ems(parameter=parameter, start_hour=datetime.now().hour)
return jsonify(ergebnis)
@app.route('/optimize_worst_case', methods=['POST'])
def flask_optimize_worst_case():
if request.method == 'POST':
parameter = request.json
# Erforderliche Parameter prüfen
erforderliche_parameter = [ 'pv_akku_cap', 'year_energy',"einspeiseverguetung_euro_pro_wh", 'max_heizleistung', 'pv_forecast_url', 'eauto_min_soc', "eauto_cap","eauto_charge_efficiency","eauto_charge_power","eauto_soc","pv_soc","start_solution","pvpowernow","haushaltsgeraet_dauer","haushaltsgeraet_wh"]
for p in erforderliche_parameter:
if p not in parameter:
return jsonify({"error": f"Fehlender Parameter: {p}"}), 400
# Simulation durchführen
ergebnis = opt_class.optimierung_ems(parameter=parameter, start_hour=datetime.now().hour, worst_case=True)
return jsonify(ergebnis) return jsonify(ergebnis)

View File

@ -3,7 +3,7 @@ from pprint import pprint
class EnergieManagementSystem: class EnergieManagementSystem:
def __init__(self, akku=None, pv_prognose_wh=None, strompreis_euro_pro_wh=None, einspeiseverguetung_euro_pro_wh=None, eauto=None, gesamtlast=None): def __init__(self, akku=None, pv_prognose_wh=None, strompreis_euro_pro_wh=None, einspeiseverguetung_euro_pro_wh=None, eauto=None, gesamtlast=None, haushaltsgeraet=None):
self.akku = akku self.akku = akku
#self.lastkurve_wh = lastkurve_wh #self.lastkurve_wh = lastkurve_wh
self.gesamtlast = gesamtlast self.gesamtlast = gesamtlast
@ -11,6 +11,8 @@ class EnergieManagementSystem:
self.strompreis_euro_pro_wh = strompreis_euro_pro_wh # Strompreis in Cent pro Wh self.strompreis_euro_pro_wh = strompreis_euro_pro_wh # Strompreis in Cent pro Wh
self.einspeiseverguetung_euro_pro_wh = einspeiseverguetung_euro_pro_wh # Einspeisevergütung in Cent pro Wh self.einspeiseverguetung_euro_pro_wh = einspeiseverguetung_euro_pro_wh # Einspeisevergütung in Cent pro Wh
self.eauto = eauto self.eauto = eauto
self.haushaltsgeraet = haushaltsgeraet
def set_akku_discharge_hours(self, ds): def set_akku_discharge_hours(self, ds):
self.akku.set_discharge_per_hour(ds) self.akku.set_discharge_per_hour(ds)
@ -18,6 +20,9 @@ class EnergieManagementSystem:
def set_eauto_charge_hours(self, ds): def set_eauto_charge_hours(self, ds):
self.eauto.set_charge_per_hour(ds) self.eauto.set_charge_per_hour(ds)
def set_haushaltsgeraet_start(self, ds, global_start_hour=0):
self.haushaltsgeraet.set_startzeitpunkt(ds,global_start_hour=global_start_hour)
def reset(self): def reset(self):
self.eauto.reset() self.eauto.reset()
self.akku.reset() self.akku.reset()
@ -43,24 +48,27 @@ class EnergieManagementSystem:
akku_soc_pro_stunde = [] akku_soc_pro_stunde = []
eauto_soc_pro_stunde = [] eauto_soc_pro_stunde = []
verluste_wh_pro_stunde = [] verluste_wh_pro_stunde = []
haushaltsgeraet_wh_pro_stunde = []
lastkurve_wh = self.gesamtlast.gesamtlast_berechnen() lastkurve_wh = self.gesamtlast.gesamtlast_berechnen()
assert len(lastkurve_wh) == len(self.pv_prognose_wh) == len(self.strompreis_euro_pro_wh), f"Arraygrößen stimmen nicht überein: Lastkurve = {len(lastkurve_wh)}, PV-Prognose = {len(self.pv_prognose_wh)}, Strompreis = {len(self.strompreis_euro_pro_wh)}" assert len(lastkurve_wh) == len(self.pv_prognose_wh) == len(self.strompreis_euro_pro_wh), f"Arraygrößen stimmen nicht überein: Lastkurve = {len(lastkurve_wh)}, PV-Prognose = {len(self.pv_prognose_wh)}, Strompreis = {len(self.strompreis_euro_pro_wh)}"
ende = min( len(lastkurve_wh),len(self.pv_prognose_wh), len(self.strompreis_euro_pro_wh)) ende = min( len(lastkurve_wh),len(self.pv_prognose_wh), len(self.strompreis_euro_pro_wh))
# print(len(lastkurve_wh), " ",len(self.pv_prognose_wh)," ", len(self.strompreis_euro_pro_wh))
# sys.exit()
# Berechnet das Ende basierend auf der Länge der Lastkurve # Berechnet das Ende basierend auf der Länge der Lastkurve
for stunde in range(start_stunde, ende): for stunde in range(start_stunde, ende):
# Anpassung, um sicherzustellen, dass Indizes korrekt sind # Anpassung, um sicherzustellen, dass Indizes korrekt sind
verbrauch = lastkurve_wh[stunde] verbrauch = lastkurve_wh[stunde]
if self.haushaltsgeraet != None:
verbrauch = verbrauch + self.haushaltsgeraet.get_last_fuer_stunde(stunde)
haushaltsgeraet_wh_pro_stunde.append(self.haushaltsgeraet.get_last_fuer_stunde(stunde))
else:
haushaltsgeraet_wh_pro_stunde.append(0)
erzeugung = self.pv_prognose_wh[stunde] erzeugung = self.pv_prognose_wh[stunde]
strompreis = self.strompreis_euro_pro_wh[stunde] if stunde < len(self.strompreis_euro_pro_wh) else self.strompreis_euro_pro_wh[-1] strompreis = self.strompreis_euro_pro_wh[stunde] if stunde < len(self.strompreis_euro_pro_wh) else self.strompreis_euro_pro_wh[-1]
verluste_wh_pro_stunde.append(0.0) verluste_wh_pro_stunde.append(0.0)
#eauto_soc = self.eauto.get_stuendlicher_soc()[stunde]
# Logik für die E-Auto-Ladung bzw. Entladung # Logik für die E-Auto-Ladung bzw. Entladung
@ -68,16 +76,14 @@ class EnergieManagementSystem:
geladene_menge_eauto, verluste_eauto = self.eauto.energie_laden(None,stunde) geladene_menge_eauto, verluste_eauto = self.eauto.energie_laden(None,stunde)
verbrauch = verbrauch + geladene_menge_eauto verbrauch = verbrauch + geladene_menge_eauto
verluste_wh_pro_stunde[-1] += verluste_eauto verluste_wh_pro_stunde[-1] += verluste_eauto
#print("verluste_eauto:",verluste_eauto) eauto_soc = self.eauto.ladezustand_in_prozent()
#eauto_soc_pro_stunde.append(eauto_soc)
# Fügen Sie hier zusätzliche Logik für E-Auto ein, z.B. Ladung über Nacht
stündlicher_netzbezug_wh = 0 stündlicher_netzbezug_wh = 0
stündliche_kosten_euro = 0 stündliche_kosten_euro = 0
stündliche_einnahmen_euro = 0 stündliche_einnahmen_euro = 0
eauto_soc = self.eauto.ladezustand_in_prozent()
if erzeugung > verbrauch: if erzeugung > verbrauch:
überschuss = erzeugung - verbrauch überschuss = erzeugung - verbrauch
@ -102,8 +108,9 @@ class EnergieManagementSystem:
eigenverbrauch_wh_pro_stunde.append(erzeugung+aus_akku) eigenverbrauch_wh_pro_stunde.append(erzeugung+aus_akku)
stündliche_kosten_euro = stündlicher_netzbezug_wh * strompreis stündliche_kosten_euro = stündlicher_netzbezug_wh * strompreis
#print(self.akku.ladezustand_in_prozent()) if self.eauto:
eauto_soc_pro_stunde.append(eauto_soc) eauto_soc_pro_stunde.append(eauto_soc)
akku_soc_pro_stunde.append(self.akku.ladezustand_in_prozent()) akku_soc_pro_stunde.append(self.akku.ladezustand_in_prozent())
kosten_euro_pro_stunde.append(stündliche_kosten_euro) kosten_euro_pro_stunde.append(stündliche_kosten_euro)
einnahmen_euro_pro_stunde.append(stündliche_einnahmen_euro) einnahmen_euro_pro_stunde.append(stündliche_einnahmen_euro)
@ -132,7 +139,8 @@ class EnergieManagementSystem:
'Gesamteinnahmen_Euro': sum(einnahmen_euro_pro_stunde), 'Gesamteinnahmen_Euro': sum(einnahmen_euro_pro_stunde),
'Gesamtkosten_Euro': sum(kosten_euro_pro_stunde), 'Gesamtkosten_Euro': sum(kosten_euro_pro_stunde),
"Verluste_Pro_Stunde":verluste_wh_pro_stunde, "Verluste_Pro_Stunde":verluste_wh_pro_stunde,
"Gesamt_Verluste":sum(verluste_wh_pro_stunde) "Gesamt_Verluste":sum(verluste_wh_pro_stunde),
"Haushaltsgeraet_wh_pro_stunde":haushaltsgeraet_wh_pro_stunde
} }
return out return out

View File

@ -0,0 +1,57 @@
import numpy as np
class Haushaltsgeraet:
def __init__(self, hours=None, verbrauch_kwh=None, dauer_h=None):
self.hours = hours # Gesamtzeitraum, für den die Planung erfolgt
self.verbrauch_kwh = verbrauch_kwh # Gesamtenergieverbrauch des Geräts in kWh
self.dauer_h = dauer_h # Dauer der Nutzung in Stunden
self.lastkurve = np.zeros(self.hours) # Initialisiere die Lastkurve mit Nullen
def set_startzeitpunkt(self, start_hour,global_start_hour=0):
"""
Setzt den Startzeitpunkt des Geräts und generiert eine entsprechende Lastkurve.
:param start_hour: Die Stunde, zu der das Gerät starten soll.
"""
self.reset()
# Überprüfe, ob die Dauer der Nutzung innerhalb des verfügbaren Zeitraums liegt
if start_hour + self.dauer_h > self.hours:
raise ValueError("Die Nutzungsdauer überschreitet den verfügbaren Zeitraum.")
if start_hour < global_start_hour:
raise ValueError("Die Nutzungsdauer unterschreitet den verfügbaren Zeitraum.")
# Berechne die Leistung pro Stunde basierend auf dem Gesamtverbrauch und der Dauer
leistung_pro_stunde = (self.verbrauch_kwh / self.dauer_h) # Umwandlung in Wattstunde
#print(start_hour," ",leistung_pro_stunde)
# Setze die Leistung für die Dauer der Nutzung im Lastkurven-Array
self.lastkurve[start_hour:start_hour + self.dauer_h] = leistung_pro_stunde
def reset(self):
"""
Setzt die Lastkurve zurück.
"""
self.lastkurve = np.zeros(self.hours)
def get_lastkurve(self):
"""
Gibt die aktuelle Lastkurve zurück.
"""
return self.lastkurve
def get_last_fuer_stunde(self, hour):
"""
Gibt die Last für eine spezifische Stunde zurück.
:param hour: Die Stunde, für die die Last abgefragt wird.
:return: Die Last in Watt für die angegebene Stunde.
"""
if hour < 0 or hour >= self.hours:
raise ValueError("Angegebene Stunde liegt außerhalb des verfügbaren Zeitraums.")
return self.lastkurve[hour]
def spaetestmoeglicher_startzeitpunkt(self):
"""
Gibt den spätestmöglichen Startzeitpunkt zurück, an dem das Gerät noch vollständig laufen kann.
"""
return self.hours - self.dauer_h

View File

@ -1,61 +0,0 @@
import numpy as np
class OptimizableLoad:
def __init__(self, name=None, power=0, duration=0, schedule=None):
"""
Initialisiert eine neue optimierbare Last.
:param name: Eindeutiger Name der Last
:param power: Leistung der Last in kW
:param duration: Dauer, für die die Last aktiv ist, in Stunden
:param schedule: Ein 24-Stunden-Array (0/1), das angibt, wann die Last gestartet werden kann
"""
self.name = name
self.power = power
self.duration = duration
self.optimal_start_time = None
if schedule is None:
self.schedule = [1] * 24
else:
self.schedule = schedule
def set_schedule(self, new_schedule):
"""
Aktualisiert den Zeitplan, wann die Last gestartet werden kann.
:param new_schedule: Ein 24-Stunden-Array (0/1)
"""
self.schedule = new_schedule
def set_optimal_start_time(self, start_time):
"""
Setzt die optimale Startzeit für die Last.
:param start_time: Die Stunde des Tages (0-23), zu der die Last starten soll
"""
if 0 <= start_time < 24 and self.is_activatable(start_time):
self.optimal_start_time = start_time
def is_active_at_hour(self, hour):
"""
Überprüft, ob die Last zu einer bestimmten Stunde aktiv ist, basierend auf ihrem Startzeitpunkt und der Dauer.
:param hour: Stunde des Tages (0-23)
:return: True, wenn die Last aktiv ist, sonst False
"""
if self.optimal_start_time is None:
return False
return self.optimal_start_time <= hour < self.optimal_start_time + self.duration
def power_at_hour(self, hour):
"""
Gibt die Leistung der Last zu einer bestimmten Stunde zurück.
:param hour: Stunde des Tages (0-23)
:return: Leistung der Last in kW, wenn sie aktiv ist, sonst 0
"""
if self.is_active_at_hour(hour):
return self.power
return 0
def __str__(self):
return f"OptimizableLoad(Name: {self.name}, Power: {self.power}kW, Duration: {self.duration}h, Schedule: {self.schedule})"

View File

@ -9,6 +9,7 @@ from modules.class_heatpump import *
from modules.class_load_container import * from modules.class_load_container import *
from modules.class_sommerzeit import * from modules.class_sommerzeit import *
from modules.visualize import * from modules.visualize import *
from modules.class_haushaltsgeraet import *
import os import os
from flask import Flask, send_from_directory from flask import Flask, send_from_directory
from pprint import pprint from pprint import pprint
@ -32,52 +33,93 @@ def isfloat(num):
class optimization_problem: class optimization_problem:
def __init__(self, prediction_hours=24, strafe = 10): def __init__(self, prediction_hours=24, strafe = 10):
# Werkzeug-Setup
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)
self.toolbox = base.Toolbox()
self.prediction_hours = prediction_hours# self.prediction_hours = prediction_hours#
self.strafe = strafe self.strafe = strafe
self.opti_param = None
def setup_deap_environment(self,opti_param):
self.opti_param = opti_param
if "FitnessMin" in creator.__dict__:
del creator.FitnessMin
if "Individual" in creator.__dict__:
del creator.Individual
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)
# PARAMETER # PARAMETER
self.toolbox = base.Toolbox()
self.toolbox.register("attr_bool", random.randint, 0, 1) self.toolbox.register("attr_bool", random.randint, 0, 1)
self.toolbox.register("attr_bool", random.randint, 0, 1) self.toolbox.register("attr_int", random.randint, 0, 23)
self.toolbox.register("individual", tools.initCycle, creator.Individual, (self.toolbox.attr_bool,self.toolbox.attr_bool), n=self.prediction_hours)
###################
# Haushaltsgeraete
if opti_param["haushaltsgeraete"]>0:
def create_individual():
attrs = [self.toolbox.attr_bool() for _ in range(2*self.prediction_hours)] + [self.toolbox.attr_int()]
return creator.Individual(attrs)
else:
def create_individual():
attrs = [self.toolbox.attr_bool() for _ in range(2*self.prediction_hours)]
return creator.Individual(attrs)
self.toolbox.register("individual", create_individual)#tools.initCycle, creator.Individual, (self.toolbox.attr_bool,self.toolbox.attr_bool), n=self.prediction_hours+1)
self.toolbox.register("population", tools.initRepeat, list, self.toolbox.individual) self.toolbox.register("population", tools.initRepeat, list, self.toolbox.individual)
self.toolbox.register("mate", tools.cxTwoPoint) self.toolbox.register("mate", tools.cxTwoPoint)
self.toolbox.register("mutate", tools.mutFlipBit, indpb=0.05) self.toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
self.toolbox.register("select", tools.selTournament, tournsize=3) self.toolbox.register("select", tools.selTournament, tournsize=3)
return
def evaluate_inner(self,individual, ems,start_hour): def evaluate_inner(self,individual, ems,start_hour):
ems.reset()
# Haushaltsgeraete
if self.opti_param["haushaltsgeraete"]>0:
spuelstart_int = individual[-1]
individual = individual[:-1]
ems.set_haushaltsgeraet_start(spuelstart_int,global_start_hour=start_hour)
discharge_hours_bin = individual[0::2] discharge_hours_bin = individual[0::2]
eautocharge_hours_float = individual[1::2] eautocharge_hours_float = individual[1::2]
ems.reset()
ems.set_akku_discharge_hours(discharge_hours_bin) ems.set_akku_discharge_hours(discharge_hours_bin)
ems.set_eauto_charge_hours(eautocharge_hours_float) ems.set_eauto_charge_hours(eautocharge_hours_float)
o = ems.simuliere(start_hour) o = ems.simuliere(start_hour)
return o return o
# Fitness-Funktion (muss Ihre EnergieManagementSystem-Logik integrieren) # Fitness-Funktion (muss Ihre EnergieManagementSystem-Logik integrieren)
def evaluate(self,individual,ems,parameter,start_hour): def evaluate(self,individual,ems,parameter,start_hour,worst_case):
o = self.evaluate_inner(individual,ems,start_hour) try:
o = self.evaluate_inner(individual,ems,start_hour)
except:
return (100000.0,)
gesamtbilanz = o["Gesamtbilanz_Euro"] gesamtbilanz = o["Gesamtbilanz_Euro"]
if worst_case:
gesamtbilanz = gesamtbilanz * -1.0
# Überprüfung, ob der Mindest-SoC erreicht wird # Überprüfung, ob der Mindest-SoC erreicht wird
final_soc = ems.eauto.ladezustand_in_prozent() # Nimmt den SoC am Ende des Optimierungszeitraums final_soc = ems.eauto.ladezustand_in_prozent() # Nimmt den SoC am Ende des Optimierungszeitraums
strafe = 0.0 strafe = 0.0
strafe = max(0,(parameter['eauto_min_soc']-ems.eauto.ladezustand_in_prozent()) * self.strafe ) if worst_case:
strafe = abs(parameter['eauto_min_soc']-ems.eauto.ladezustand_in_prozent()) * self.strafe
gesamtbilanz += strafe
gesamtbilanz += strafe gesamtbilanz -= o["Gesamt_Verluste"]/1000.0
gesamtbilanz += o["Gesamt_Verluste"]/1000.0 else:
strafe = max(0,(parameter['eauto_min_soc']-ems.eauto.ladezustand_in_prozent()) * self.strafe )
gesamtbilanz += strafe
gesamtbilanz += o["Gesamt_Verluste"]/1000.0
return (gesamtbilanz,) return (gesamtbilanz,)
@ -104,7 +146,7 @@ class optimization_problem:
return hof[0] return hof[0]
def optimierung_ems(self,parameter=None, start_hour=None): def optimierung_ems(self,parameter=None, start_hour=None,worst_case=False):
############ ############
# Parameter # Parameter
@ -130,11 +172,19 @@ class optimization_problem:
eauto = PVAkku(kapazitaet_wh=parameter["eauto_cap"], hours=self.prediction_hours, lade_effizienz=parameter["eauto_charge_efficiency"], entlade_effizienz=1.0, max_ladeleistung_w=parameter["eauto_charge_power"] ,start_soc_prozent=parameter["eauto_soc"]) eauto = PVAkku(kapazitaet_wh=parameter["eauto_cap"], hours=self.prediction_hours, lade_effizienz=parameter["eauto_charge_efficiency"], entlade_effizienz=1.0, max_ladeleistung_w=parameter["eauto_charge_power"] ,start_soc_prozent=parameter["eauto_soc"])
eauto.set_charge_per_hour(laden_moeglich) eauto.set_charge_per_hour(laden_moeglich)
min_soc_eauto = parameter['eauto_min_soc'] min_soc_eauto = parameter['eauto_min_soc']
start_params = parameter['start_solution'] start_params = parameter['start_solution']
gesamtlast = Gesamtlast() gesamtlast = Gesamtlast()
###############
# spuelmaschine
##############
if parameter["haushaltsgeraet_dauer"] >0:
spuelmaschine = Haushaltsgeraet(hours=self.prediction_hours, verbrauch_kwh=parameter["haushaltsgeraet_wh"], dauer_h=parameter["haushaltsgeraet_dauer"])
spuelmaschine.set_startzeitpunkt(start_hour) # Startet jetzt
else:
spuelmaschine = None
############### ###############
# Load Forecast # Load Forecast
############### ###############
@ -173,29 +223,49 @@ class optimization_problem:
leistung_wp = wp.simulate_24h(temperature_forecast) leistung_wp = wp.simulate_24h(temperature_forecast)
gesamtlast.hinzufuegen("Heatpump", leistung_wp) gesamtlast.hinzufuegen("Heatpump", leistung_wp)
ems = EnergieManagementSystem(akku=akku, gesamtlast = gesamtlast, pv_prognose_wh=pv_forecast, strompreis_euro_pro_wh=specific_date_prices, einspeiseverguetung_euro_pro_wh=einspeiseverguetung_euro_pro_wh, eauto=eauto) ems = EnergieManagementSystem(akku=akku, gesamtlast = gesamtlast, pv_prognose_wh=pv_forecast, strompreis_euro_pro_wh=specific_date_prices, einspeiseverguetung_euro_pro_wh=einspeiseverguetung_euro_pro_wh, eauto=eauto, haushaltsgeraet=spuelmaschine)
o = ems.simuliere(start_hour) o = ems.simuliere(start_hour)
###############
# Optimizer Init
##############
opti_param = {}
opti_param["haushaltsgeraete"] = 0
if spuelmaschine != None:
opti_param["haushaltsgeraete"] = 1
self.setup_deap_environment(opti_param)
def evaluate_wrapper(individual): def evaluate_wrapper(individual):
return self.evaluate(individual, ems, parameter,start_hour) return self.evaluate(individual, ems, parameter,start_hour,worst_case)
self.toolbox.register("evaluate", evaluate_wrapper) self.toolbox.register("evaluate", evaluate_wrapper)
start_solution = self.optimize(start_params) start_solution = self.optimize(start_params)
best_solution = start_solution best_solution = start_solution
o = self.evaluate_inner(best_solution, ems,start_hour) o = self.evaluate_inner(best_solution, ems,start_hour)
eauto = ems.eauto.to_dict() eauto = ems.eauto.to_dict()
spuelstart_int = None
# Haushaltsgeraete
if self.opti_param["haushaltsgeraete"]>0:
spuelstart_int = best_solution[-1]
best_solution = best_solution[:-1]
discharge_hours_bin = best_solution[0::2] discharge_hours_bin = best_solution[0::2]
eautocharge_hours_float = best_solution[1::2] eautocharge_hours_float = best_solution[1::2]
#print(o)
visualisiere_ergebnisse(gesamtlast, pv_forecast, specific_date_prices, o,best_solution[0::2],best_solution[1::2] , temperature_forecast, start_hour, self.prediction_hours,einspeiseverguetung_euro_pro_wh)
os.system("scp visualisierungsergebnisse.pdf andreas@192.168.1.135:")
print(o)
if worst_case:
visualisiere_ergebnisse(gesamtlast, pv_forecast, specific_date_prices, o,best_solution[0::2],best_solution[1::2] , temperature_forecast, start_hour, self.prediction_hours,einspeiseverguetung_euro_pro_wh,filename="visualisierungsergebnisse_worst.pdf")
os.system("scp visualisierungsergebnisse_worst.pdf andreas@192.168.1.135:")
else:
visualisiere_ergebnisse(gesamtlast, pv_forecast, specific_date_prices, o,best_solution[0::2],best_solution[1::2] , temperature_forecast, start_hour, self.prediction_hours,einspeiseverguetung_euro_pro_wh)
os.system("scp visualisierungsergebnisse.pdf andreas@192.168.1.135:")
#print(eauto) #print(eauto)
return {"discharge_hours_bin":discharge_hours_bin, "eautocharge_hours_float":eautocharge_hours_float ,"result":o ,"eauto_obj":eauto,"start_solution":best_solution} return {"discharge_hours_bin":discharge_hours_bin, "eautocharge_hours_float":eautocharge_hours_float ,"result":o ,"eauto_obj":eauto,"start_solution":best_solution,"spuelstart":spuelstart_int}

View File

@ -9,12 +9,12 @@ from matplotlib.backends.backend_pdf import PdfPages
from datetime import datetime from datetime import datetime
def visualisiere_ergebnisse(gesamtlast, pv_forecast, strompreise, ergebnisse, discharge_hours, laden_moeglich, temperature, start_hour, prediction_hours,einspeiseverguetung_euro_pro_wh): def visualisiere_ergebnisse(gesamtlast, pv_forecast, strompreise, ergebnisse, discharge_hours, laden_moeglich, temperature, start_hour, prediction_hours,einspeiseverguetung_euro_pro_wh, filename="visualisierungsergebnisse.pdf"):
##################### #####################
# 24h # 24h
##################### #####################
with PdfPages('visualisierungsergebnisse.pdf') as pdf: with PdfPages(filename) as pdf:
# Last und PV-Erzeugung # Last und PV-Erzeugung
@ -98,6 +98,7 @@ def visualisiere_ergebnisse(gesamtlast, pv_forecast, strompreise, ergebnisse, d
# Eigenverbrauch, Netzeinspeisung und Netzbezug # Eigenverbrauch, Netzeinspeisung und Netzbezug
plt.subplot(3, 2, 1) plt.subplot(3, 2, 1)
plt.plot(stunden, ergebnisse['Eigenverbrauch_Wh_pro_Stunde'], label='Eigenverbrauch (Wh)', marker='o') plt.plot(stunden, ergebnisse['Eigenverbrauch_Wh_pro_Stunde'], label='Eigenverbrauch (Wh)', marker='o')
plt.plot(stunden, ergebnisse['Haushaltsgeraet_wh_pro_stunde'], label='Haushaltsgerät (Wh)', marker='o')
plt.plot(stunden, ergebnisse['Netzeinspeisung_Wh_pro_Stunde'], label='Netzeinspeisung (Wh)', marker='x') plt.plot(stunden, ergebnisse['Netzeinspeisung_Wh_pro_Stunde'], label='Netzeinspeisung (Wh)', marker='x')
plt.plot(stunden, ergebnisse['Netzbezug_Wh_pro_Stunde'], label='Netzbezug (Wh)', marker='^') plt.plot(stunden, ergebnisse['Netzbezug_Wh_pro_Stunde'], label='Netzbezug (Wh)', marker='^')
plt.plot(stunden, ergebnisse['Verluste_Pro_Stunde'], label='Verluste (Wh)', marker='^') plt.plot(stunden, ergebnisse['Verluste_Pro_Stunde'], label='Verluste (Wh)', marker='^')