mirror of
				https://github.com/Akkudoktor-EOS/EOS.git
				synced 2025-10-30 22:36:21 +00:00 
			
		
		
		
	EV Bugs
This commit is contained in:
		| @@ -20,7 +20,7 @@ class PVAkku: | ||||
|         self.soc_wh = (start_soc_prozent / 100) * kapazitaet_wh | ||||
|         self.hours = hours if hours is not None else 24  # Default to 24 hours if not specified | ||||
|         self.discharge_array = np.full(self.hours, 1) | ||||
|         self.charge_array = np.full(self.hours, 1) | ||||
|         self.charge_array = np.full(self.hours, 0) | ||||
|         # Charge and discharge efficiency | ||||
|         self.lade_effizienz = lade_effizienz | ||||
|         self.entlade_effizienz = entlade_effizienz | ||||
| @@ -88,7 +88,7 @@ class PVAkku: | ||||
|         # Ensure no simultaneous charging and discharging in the same hour using NumPy mask | ||||
|         conflict_mask = (self.charge_array > 0) & (self.discharge_array > 0) | ||||
|         # Prioritize discharge by setting charge to 0 where both are > 0 | ||||
|         self.charge_array[conflict_mask] = 0 | ||||
|         self.discharge_array[conflict_mask] = 0 | ||||
|  | ||||
|  | ||||
|     def ladezustand_in_prozent(self): | ||||
|   | ||||
| @@ -92,9 +92,7 @@ class EnergieManagementSystem: | ||||
|  | ||||
|             # AC PV Battery Charge | ||||
|             if self.akku.charge_array[stunde] > 0.0: | ||||
|                 #soc_pre = self.akku.ladezustand_in_prozent() | ||||
|                 geladene_menge, verluste_wh = self.akku.energie_laden(None,stunde) | ||||
|                 #print(self.akku.charge_array[stunde], " ",geladene_menge," ",soc_pre," ",self.akku.ladezustand_in_prozent()) | ||||
|                 verbrauch += geladene_menge | ||||
|                 verluste_wh_pro_stunde[stunde_since_now] += verluste_wh                 | ||||
|              | ||||
|   | ||||
| @@ -59,6 +59,43 @@ class optimization_problem: | ||||
|         discharge = np.where(discharge_hours_bin > 0, discharge_hours_bin, 0) | ||||
|  | ||||
|         return charge, discharge | ||||
|      | ||||
|     # Custom mutation function that applies type-specific mutations | ||||
|     def mutate(self,individual): | ||||
|         # Mutate the discharge state genes (-1, 0, 1) | ||||
|         individual[:self.prediction_hours], = self.toolbox.mutate_discharge( | ||||
|             individual[:self.prediction_hours] | ||||
|         ) | ||||
|  | ||||
|         if self.optimize_ev: | ||||
|             # 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) | ||||
|             ev_charge_part_mutated[self.prediction_hours - self.fixed_eauto_hours :] = [0] * self.fixed_eauto_hours | ||||
|             individual[self.prediction_hours : self.prediction_hours * 2] = ev_charge_part_mutated | ||||
|  | ||||
|         # Mutate the appliance start hour if present | ||||
|         if self.opti_param["haushaltsgeraete"] > 0: | ||||
|             appliance_part = [individual[-1]] | ||||
|             appliance_part_mutated, = self.toolbox.mutate_hour(appliance_part) | ||||
|             individual[-1] = appliance_part_mutated[0] | ||||
|  | ||||
|         return (individual,) | ||||
|  | ||||
|     # Method to create an individual based on the conditions | ||||
|     def create_individual(self): | ||||
|         # Start with discharge states for the individual | ||||
|         individual_components = [self.toolbox.attr_discharge_state() for _ in range(self.prediction_hours)] | ||||
|  | ||||
|         # Add EV charge index values if optimize_ev is True | ||||
|         if self.optimize_ev: | ||||
|             individual_components += [self.toolbox.attr_ev_charge_index() for _ in range(self.prediction_hours)] | ||||
|  | ||||
|         # Add the start time of the household appliance if it's being optimized | ||||
|         if self.opti_param["haushaltsgeraete"] > 0: | ||||
|             individual_components += [self.toolbox.attr_int()] | ||||
|  | ||||
|         return creator.Individual(individual_components) | ||||
|  | ||||
|     def split_individual( | ||||
|         self, individual: List[float] | ||||
| @@ -100,43 +137,10 @@ class optimization_problem: | ||||
|             self.toolbox.register("attr_ev_charge_index", random.randint, 0, len(possible_ev_charge_currents) - 1) | ||||
|         self.toolbox.register("attr_int", random.randint, start_hour, 23) | ||||
|  | ||||
|         # Function to create an individual based on the conditions | ||||
|         def create_individual(): | ||||
|             # Start with discharge states for the individual | ||||
|             individual_components = [self.toolbox.attr_discharge_state() for _ in range(self.prediction_hours)] | ||||
|  | ||||
|             # Add EV charge index values if optimize_ev is True | ||||
|             if self.optimize_ev: | ||||
|                 individual_components += [self.toolbox.attr_ev_charge_index() for _ in range(self.prediction_hours)] | ||||
|  | ||||
|             # Add the start time of the household appliance if it's being optimized | ||||
|             if self.opti_param["haushaltsgeraete"] > 0: | ||||
|                 individual_components += [self.toolbox.attr_int()] | ||||
|  | ||||
|             return creator.Individual(individual_components) | ||||
|  | ||||
|         # Register individual creation function | ||||
|         self.toolbox.register("individual", create_individual) | ||||
|  | ||||
|  | ||||
|         # # Register individual creation method based on household appliance parameter | ||||
|         # if opti_param["haushaltsgeraete"] > 0: | ||||
|         #     self.toolbox.register( | ||||
|         #         "individual", | ||||
|         #         lambda: creator.Individual( | ||||
|         #             [self.toolbox.attr_discharge_state() for _ in range(self.prediction_hours)] | ||||
|         #             + [self.toolbox.attr_ev_charge_index() for _ in range(self.prediction_hours)] | ||||
|         #             + [self.toolbox.attr_int()] | ||||
|         #         ), | ||||
|         #     ) | ||||
|         # else: | ||||
|         #     self.toolbox.register( | ||||
|         #         "individual", | ||||
|         #         lambda: creator.Individual( | ||||
|         #             [self.toolbox.attr_discharge_state() for _ in range(self.prediction_hours)] | ||||
|         #             + [self.toolbox.attr_ev_charge_index() for _ in range(self.prediction_hours)] | ||||
|         #         ), | ||||
|         #     ) | ||||
|         self.toolbox.register("individual", self.create_individual) | ||||
|  | ||||
|         # Register population, mating, mutation, and selection functions | ||||
|         self.toolbox.register("population", tools.initRepeat, list, self.toolbox.individual) | ||||
| @@ -150,32 +154,8 @@ class optimization_problem: | ||||
|         # - Start hour mutation for household devices | ||||
|         self.toolbox.register("mutate_hour", tools.mutUniformInt, low=start_hour, up=23, indpb=0.1) | ||||
|  | ||||
|         # 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] | ||||
|             ) | ||||
|  | ||||
|             if self.optimize_ev: | ||||
|                 # 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) | ||||
|                 ev_charge_part_mutated[self.prediction_hours - self.fixed_eauto_hours :] = [0] * self.fixed_eauto_hours | ||||
|                 individual[self.prediction_hours : self.prediction_hours * 2] = ev_charge_part_mutated | ||||
|  | ||||
|             # Mutate the appliance start hour if present | ||||
|             if self.opti_param["haushaltsgeraete"] > 0: | ||||
|                 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("mutate", self.mutate) | ||||
|  | ||||
|         self.toolbox.register("select", tools.selTournament, tournsize=3) | ||||
|  | ||||
| @@ -198,13 +178,13 @@ class optimization_problem: | ||||
|  | ||||
|         ems.set_akku_discharge_hours(discharge) | ||||
|         ems.set_akku_charge_hours(charge) | ||||
|         #print(charge) | ||||
|          | ||||
|         eautocharge_hours_float = [ | ||||
|             possible_ev_charge_currents[i] for i in eautocharge_hours_index | ||||
|         ] | ||||
|  | ||||
|         if self.optimize_ev: | ||||
|             eautocharge_hours_float = [ | ||||
|                 possible_ev_charge_currents[i] for i in eautocharge_hours_index | ||||
|             ]             | ||||
|             ems.set_eauto_charge_hours(eautocharge_hours_float) | ||||
|          | ||||
|         return ems.simuliere(start_hour) | ||||
|  | ||||
|     def evaluate( | ||||
| @@ -226,7 +206,6 @@ class optimization_problem: | ||||
|         gesamtbilanz = o["Gesamtbilanz_Euro"] * (-1.0 if worst_case else 1.0) | ||||
|          | ||||
|         discharge_hours_bin, eautocharge_hours_float, _ = self.split_individual(individual) | ||||
|         #max_ladeleistung = np.max(possible_ev_charge_currents) | ||||
|  | ||||
|         # Small Penalty for not discharging | ||||
|         gesamtbilanz += sum( | ||||
|   | ||||
| @@ -160,39 +160,39 @@ def visualisiere_ergebnisse( | ||||
|         plt.grid(True, which="both", axis="x")  # Grid for every hour | ||||
|  | ||||
|         ax1 = plt.subplot(3, 2, 3) | ||||
|         # Plot für die discharge_hours-Werte | ||||
|         # Plot charge and discharge values | ||||
|         for hour, value in enumerate(discharge_hours): | ||||
|             # Festlegen der Farbe und des Labels basierend auf dem Wert | ||||
|             if value > 0:  # Positive Werte (Entladung) | ||||
|             # Determine color and label based on the value | ||||
|             if value > 0:  # Positive values (discharge) | ||||
|                 color = "red" | ||||
|                 label = "Discharge" if hour == 0 else ""  # Label nur beim ersten Eintrag hinzufügen | ||||
|             elif value < 0:  # Negative Werte (Ladung) | ||||
|                 label = "Discharge" if hour == 0 else "" | ||||
|             elif value < 0:  # Negative values (charge) | ||||
|                 color = "blue" | ||||
|                 label = "Charge" if hour == 0 else "" | ||||
|             else: | ||||
|                 continue  # Überspringe 0-Werte | ||||
|  | ||||
|             # Erstellen der Farbbereiche mit `axvspan` | ||||
|             else: | ||||
|                 continue  # Skip zero values | ||||
|  | ||||
|             # Create colored areas with `axvspan` | ||||
|             ax1.axvspan( | ||||
|                 hour,  # Start der Stunde | ||||
|                 hour + 1,  # Ende der Stunde | ||||
|                 ymin=0,  # Untere Grenze | ||||
|                 ymax=abs(value),  # Obere Grenze: abs(value), um die Höhe richtig darzustellen | ||||
|                 hour,  # Start of the hour | ||||
|                 hour + 1,  # End of the hour | ||||
|                 ymin=0,  # Lower bound | ||||
|                 ymax=abs(value) / 5 if value < 0 else value,  # Adjust height based on the value | ||||
|                 color=color, | ||||
|                 alpha=0.3, | ||||
|                 label=label | ||||
|             ) | ||||
|  | ||||
|             # Annotieren der Werte in der Mitte des Farbbereichs | ||||
|             ax1.text( | ||||
|                 hour + 0.5,  # In der Mitte des Bereichs | ||||
|                 abs(value) / 2,  # In der Mitte der Höhe | ||||
|                 f'{value:.2f}',  # Wert mit zwei Dezimalstellen | ||||
|                 ha='center', | ||||
|                 va='center', | ||||
|                 fontsize=8, | ||||
|                 color='black' | ||||
|             ) | ||||
|  | ||||
|         # Configure the plot | ||||
|         ax1.legend(loc="upper left") | ||||
|         ax1.set_xlim(0, prediction_hours) | ||||
|         ax1.set_xlabel("Hour") | ||||
|         ax1.set_ylabel("Charge/Discharge Level") | ||||
|         ax1.set_title("Charge and Discharge Hours Overview") | ||||
|         ax1.grid(True) | ||||
|  | ||||
|  | ||||
|  | ||||
|         pdf.savefig()  # Save the current figure state to the PDF | ||||
|   | ||||
		Reference in New Issue
	
	Block a user