mirror of
https://github.com/Akkudoktor-EOS/EOS.git
synced 2025-04-19 08:55:15 +00:00
EV possible currents -> Work now (new Mutate Function)
-> Some Penalties are removed (deprecated) AC Charge -> Parameter in Optimization -1,0,1 -> Missing integration in class_ems
This commit is contained in:
parent
141257f514
commit
2807ec7978
@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
# Import necessary modules from the project
|
# Import necessary modules from the project
|
||||||
from akkudoktoreos.class_optimize import optimization_problem
|
from akkudoktoreos.class_optimize import optimization_problem
|
||||||
@ -241,7 +242,7 @@ parameter = {
|
|||||||
# Electricity price forecast (48 hours)
|
# Electricity price forecast (48 hours)
|
||||||
"strompreis_euro_pro_wh": strompreis_euro_pro_wh,
|
"strompreis_euro_pro_wh": strompreis_euro_pro_wh,
|
||||||
# Minimum SOC for electric car
|
# Minimum SOC for electric car
|
||||||
"eauto_min_soc": 80,
|
"eauto_min_soc": 20,
|
||||||
# Electric car battery capacity (Wh)
|
# Electric car battery capacity (Wh)
|
||||||
"eauto_cap": 60000,
|
"eauto_cap": 60000,
|
||||||
# Charging efficiency of the electric car
|
# Charging efficiency of the electric car
|
||||||
@ -262,6 +263,9 @@ parameter = {
|
|||||||
"min_soc_prozent": 15,
|
"min_soc_prozent": 15,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Startzeit nehmen
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
# Initialize the optimization problem
|
# Initialize the optimization problem
|
||||||
opt_class = optimization_problem(
|
opt_class = optimization_problem(
|
||||||
prediction_hours=48, strafe=10, optimization_hours=24, verbose=True, fixed_seed=42
|
prediction_hours=48, strafe=10, optimization_hours=24, verbose=True, fixed_seed=42
|
||||||
@ -270,8 +274,16 @@ opt_class = optimization_problem(
|
|||||||
# Perform the optimisation based on the provided parameters and start hour
|
# Perform the optimisation based on the provided parameters and start hour
|
||||||
ergebnis = opt_class.optimierung_ems(parameter=parameter, start_hour=start_hour)
|
ergebnis = opt_class.optimierung_ems(parameter=parameter, start_hour=start_hour)
|
||||||
|
|
||||||
|
# Endzeit nehmen
|
||||||
|
end_time = time.time()
|
||||||
|
|
||||||
|
# Berechnete Zeit ausgeben
|
||||||
|
elapsed_time = end_time - start_time
|
||||||
|
print(f"Elapsed time: {elapsed_time:.4f} seconds")
|
||||||
|
|
||||||
|
|
||||||
# Print or visualize the result
|
# Print or visualize the result
|
||||||
# pprint(ergebnis)
|
# pprint(ergebnis)
|
||||||
|
|
||||||
json_data = json.dumps(ergebnis)
|
#json_data = json.dumps(ergebnis)
|
||||||
print(json_data)
|
#print(json_data)
|
||||||
|
@ -84,7 +84,7 @@ class PVAkku:
|
|||||||
return (self.soc_wh / self.kapazitaet_wh) * 100
|
return (self.soc_wh / self.kapazitaet_wh) * 100
|
||||||
|
|
||||||
def energie_abgeben(self, wh, hour):
|
def energie_abgeben(self, wh, hour):
|
||||||
if self.discharge_array[hour] == 0:
|
if self.discharge_array[hour] == 0 and self.discharge_array[hour] == -1:
|
||||||
return 0.0, 0.0 # No energy discharge and no losses
|
return 0.0, 0.0 # No energy discharge and no losses
|
||||||
|
|
||||||
# Calculate the maximum energy that can be discharged considering min_soc and efficiency
|
# Calculate the maximum energy that can be discharged considering min_soc and efficiency
|
||||||
|
@ -28,6 +28,7 @@ class EnergieManagementSystem:
|
|||||||
self.akku.set_discharge_per_hour(ds)
|
self.akku.set_discharge_per_hour(ds)
|
||||||
|
|
||||||
def set_eauto_charge_hours(self, ds: List[int]) -> None:
|
def set_eauto_charge_hours(self, ds: List[int]) -> None:
|
||||||
|
|
||||||
self.eauto.set_charge_per_hour(ds)
|
self.eauto.set_charge_per_hour(ds)
|
||||||
|
|
||||||
def set_haushaltsgeraet_start(self, ds: List[int], global_start_hour: int = 0) -> None:
|
def set_haushaltsgeraet_start(self, ds: List[int], global_start_hour: int = 0) -> None:
|
||||||
|
@ -39,7 +39,7 @@ class optimization_problem:
|
|||||||
) -> Tuple[List[int], List[float], Optional[int]]:
|
) -> Tuple[List[int], List[float], Optional[int]]:
|
||||||
"""
|
"""
|
||||||
Split the individual solution into its components:
|
Split the individual solution into its components:
|
||||||
1. Discharge hours (binary),
|
1. Discharge hours (-1 (Charge),0 (Nothing),1 (Discharge)),
|
||||||
2. Electric vehicle charge hours (float),
|
2. Electric vehicle charge hours (float),
|
||||||
3. Dishwasher start time (integer if applicable).
|
3. Dishwasher start time (integer if applicable).
|
||||||
"""
|
"""
|
||||||
@ -69,8 +69,8 @@ class optimization_problem:
|
|||||||
|
|
||||||
# Initialize toolbox with attributes and operations
|
# Initialize toolbox with attributes and operations
|
||||||
self.toolbox = base.Toolbox()
|
self.toolbox = base.Toolbox()
|
||||||
self.toolbox.register("attr_bool", random.randint, 0, 1)
|
self.toolbox.register("attr_discharge_state", random.randint, -1, 1)
|
||||||
self.toolbox.register("attr_float", random.uniform, 0, 1)
|
self.toolbox.register("attr_ev_charge_index", random.randint, 0, len(moegliche_ladestroeme_in_prozent) - 1)
|
||||||
self.toolbox.register("attr_int", random.randint, start_hour, 23)
|
self.toolbox.register("attr_int", random.randint, start_hour, 23)
|
||||||
|
|
||||||
# Register individual creation method based on household appliance parameter
|
# Register individual creation method based on household appliance parameter
|
||||||
@ -78,8 +78,8 @@ class optimization_problem:
|
|||||||
self.toolbox.register(
|
self.toolbox.register(
|
||||||
"individual",
|
"individual",
|
||||||
lambda: creator.Individual(
|
lambda: creator.Individual(
|
||||||
[self.toolbox.attr_bool() for _ in range(self.prediction_hours)]
|
[self.toolbox.attr_discharge_state() for _ in range(self.prediction_hours)]
|
||||||
+ [self.toolbox.attr_float() for _ in range(self.prediction_hours)]
|
+ [self.toolbox.attr_ev_charge_index() for _ in range(self.prediction_hours)]
|
||||||
+ [self.toolbox.attr_int()]
|
+ [self.toolbox.attr_int()]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -87,15 +87,48 @@ class optimization_problem:
|
|||||||
self.toolbox.register(
|
self.toolbox.register(
|
||||||
"individual",
|
"individual",
|
||||||
lambda: creator.Individual(
|
lambda: creator.Individual(
|
||||||
[self.toolbox.attr_bool() for _ in range(self.prediction_hours)]
|
[self.toolbox.attr_discharge_state() for _ in range(self.prediction_hours)]
|
||||||
+ [self.toolbox.attr_float() for _ in range(self.prediction_hours)]
|
+ [self.toolbox.attr_ev_charge_index() for _ in range(self.prediction_hours)]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Register population, mating, mutation, and selection functions
|
# Register population, mating, mutation, and selection functions
|
||||||
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.1)
|
#self.toolbox.register("mutate", tools.mutFlipBit, indpb=0.1)
|
||||||
|
# Register separate mutation functions for each type of value:
|
||||||
|
# - Discharge state mutation (-1, 0, 1)
|
||||||
|
self.toolbox.register("mutate_discharge", tools.mutUniformInt, low=0, up=1, indpb=0.1)
|
||||||
|
# - Float mutation for EV charging values
|
||||||
|
self.toolbox.register("mutate_ev_charge_index", tools.mutUniformInt, low=0, up=len(moegliche_ladestroeme_in_prozent) - 1, indpb=0.1)
|
||||||
|
# - Start hour mutation for household devices
|
||||||
|
self.toolbox.register("mutate_hour", tools.mutUniformInt, low=start_hour, up=23, indpb=0.3)
|
||||||
|
|
||||||
|
# Custom mutation function that applies type-specific mutations
|
||||||
|
def mutate(individual):
|
||||||
|
# Mutate the discharge state genes (-1, 0, 1)
|
||||||
|
individual[:self.prediction_hours], = self.toolbox.mutate_discharge(
|
||||||
|
individual[:self.prediction_hours]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Mutate the EV charging indices
|
||||||
|
ev_charge_part = individual[self.prediction_hours : self.prediction_hours * 2]
|
||||||
|
ev_charge_part_mutated, = self.toolbox.mutate_ev_charge_index(ev_charge_part)
|
||||||
|
individual[self.prediction_hours : self.prediction_hours * 2] = ev_charge_part_mutated
|
||||||
|
|
||||||
|
# Mutate the appliance start hour if present
|
||||||
|
if len(individual) > self.prediction_hours * 2:
|
||||||
|
appliance_part = [individual[-1]]
|
||||||
|
appliance_part_mutated, = self.toolbox.mutate_hour(appliance_part)
|
||||||
|
individual[-1] = appliance_part_mutated[0]
|
||||||
|
|
||||||
|
return (individual,)
|
||||||
|
|
||||||
|
|
||||||
|
# Register custom mutation function
|
||||||
|
self.toolbox.register("mutate", mutate)
|
||||||
|
|
||||||
|
|
||||||
self.toolbox.register("select", tools.selTournament, tournsize=3)
|
self.toolbox.register("select", tools.selTournament, tournsize=3)
|
||||||
|
|
||||||
def evaluate_inner(
|
def evaluate_inner(
|
||||||
@ -106,16 +139,22 @@ class optimization_problem:
|
|||||||
using the provided individual solution.
|
using the provided individual solution.
|
||||||
"""
|
"""
|
||||||
ems.reset()
|
ems.reset()
|
||||||
discharge_hours_bin, eautocharge_hours_float, spuelstart_int = self.split_individual(
|
discharge_hours_bin, eautocharge_hours_index, spuelstart_int = self.split_individual(
|
||||||
individual
|
individual
|
||||||
)
|
)
|
||||||
if self.opti_param.get("haushaltsgeraete", 0) > 0:
|
if self.opti_param.get("haushaltsgeraete", 0) > 0:
|
||||||
ems.set_haushaltsgeraet_start(spuelstart_int, global_start_hour=start_hour)
|
ems.set_haushaltsgeraet_start(spuelstart_int, global_start_hour=start_hour)
|
||||||
|
|
||||||
ems.set_akku_discharge_hours(discharge_hours_bin)
|
ems.set_akku_discharge_hours(discharge_hours_bin)
|
||||||
eautocharge_hours_float[self.prediction_hours - self.fixed_eauto_hours :] = [
|
eautocharge_hours_index[self.prediction_hours - self.fixed_eauto_hours :] = [
|
||||||
0.0
|
0
|
||||||
] * self.fixed_eauto_hours
|
] * self.fixed_eauto_hours
|
||||||
|
|
||||||
|
eautocharge_hours_float = [
|
||||||
|
moegliche_ladestroeme_in_prozent[i] for i in eautocharge_hours_index
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
ems.set_eauto_charge_hours(eautocharge_hours_float)
|
ems.set_eauto_charge_hours(eautocharge_hours_float)
|
||||||
return ems.simuliere(start_hour)
|
return ems.simuliere(start_hour)
|
||||||
|
|
||||||
@ -136,10 +175,11 @@ class optimization_problem:
|
|||||||
return (100000.0,) # Return a high penalty in case of an exception
|
return (100000.0,) # Return a high penalty in case of an exception
|
||||||
|
|
||||||
gesamtbilanz = o["Gesamtbilanz_Euro"] * (-1.0 if worst_case else 1.0)
|
gesamtbilanz = o["Gesamtbilanz_Euro"] * (-1.0 if worst_case else 1.0)
|
||||||
|
|
||||||
discharge_hours_bin, eautocharge_hours_float, _ = self.split_individual(individual)
|
discharge_hours_bin, eautocharge_hours_float, _ = self.split_individual(individual)
|
||||||
max_ladeleistung = np.max(moegliche_ladestroeme_in_prozent)
|
max_ladeleistung = np.max(moegliche_ladestroeme_in_prozent)
|
||||||
|
|
||||||
# Penalty for not discharging
|
# Small Penalty for not discharging
|
||||||
gesamtbilanz += sum(
|
gesamtbilanz += sum(
|
||||||
0.01 for i in range(self.prediction_hours) if discharge_hours_bin[i] == 0.0
|
0.01 for i in range(self.prediction_hours) if discharge_hours_bin[i] == 0.0
|
||||||
)
|
)
|
||||||
@ -151,13 +191,6 @@ class optimization_problem:
|
|||||||
if eautocharge_hours_float[i] != 0.0
|
if eautocharge_hours_float[i] != 0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
# Penalty for exceeding maximum charge power
|
|
||||||
gesamtbilanz += sum(
|
|
||||||
self.strafe * 10
|
|
||||||
for ladeleistung in eautocharge_hours_float
|
|
||||||
if ladeleistung > max_ladeleistung
|
|
||||||
)
|
|
||||||
|
|
||||||
# Penalty for not meeting the minimum SOC (State of Charge) requirement
|
# Penalty for not meeting the minimum SOC (State of Charge) requirement
|
||||||
if parameter["eauto_min_soc"] - ems.eauto.ladezustand_in_prozent() <= 0.0:
|
if parameter["eauto_min_soc"] - ems.eauto.ladezustand_in_prozent() <= 0.0:
|
||||||
gesamtbilanz += sum(
|
gesamtbilanz += sum(
|
||||||
@ -205,7 +238,7 @@ class optimization_problem:
|
|||||||
self.toolbox,
|
self.toolbox,
|
||||||
mu=100,
|
mu=100,
|
||||||
lambda_=200,
|
lambda_=200,
|
||||||
cxpb=0.5,
|
cxpb=0.7,
|
||||||
mutpb=0.3,
|
mutpb=0.3,
|
||||||
ngen=ngen,
|
ngen=ngen,
|
||||||
stats=stats,
|
stats=stats,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user