From c911378bee29d4bcda2a23bf40607542a92ffd2b Mon Sep 17 00:00:00 2001 From: Bobby Noelte Date: Thu, 30 Oct 2025 13:26:17 +0100 Subject: [PATCH] fix: ensure genetic common settings available Signed-off-by: Bobby Noelte --- docs/_generated/config.md | 3 ++ openapi.json | 34 ++++++++++++++----- .../optimization/optimization.py | 21 ++++++++++-- tests/testdata/eos_config_minimal_now.json | 7 +++- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/docs/_generated/config.md b/docs/_generated/config.md index f54edcd..1f1727c 100644 --- a/docs/_generated/config.md +++ b/docs/_generated/config.md @@ -873,6 +873,7 @@ Battery SoC, power. | | ---- | -------------------- | ---- | --------- | ------- | ----------- | | horizon_hours | `EOS_OPTIMIZATION__HORIZON_HOURS` | `Optional[int]` | `rw` | `24` | The general time window within which the energy optimization goal shall be achieved [h]. Defaults to 24 hours. | | interval | `EOS_OPTIMIZATION__INTERVAL` | `Optional[int]` | `rw` | `3600` | The optimization interval [sec]. | +| algorithm | `EOS_OPTIMIZATION__ALGORITHM` | `Optional[str]` | `rw` | `GENETIC` | The optimization algorithm. | | genetic | `EOS_OPTIMIZATION__GENETIC` | `Optional[akkudoktoreos.optimization.optimization.GeneticCommonSettings]` | `rw` | `None` | Genetic optimization algorithm configuration. | ::: @@ -885,6 +886,7 @@ Battery SoC, power. | "optimization": { "horizon_hours": 24, "interval": 3600, + "algorithm": "GENETIC", "genetic": { "individuals": 400, "generations": 400, @@ -1886,6 +1888,7 @@ Validators: "optimization": { "horizon_hours": 24, "interval": 3600, + "algorithm": "GENETIC", "genetic": { "individuals": 400, "generations": 400, diff --git a/openapi.json b/openapi.json index 98cbb79..66e6bd7 100644 --- a/openapi.json +++ b/openapi.json @@ -2378,7 +2378,12 @@ "$ref": "#/components/schemas/OptimizationCommonSettings", "default": { "horizon_hours": 24, - "interval": 3600 + "interval": 3600, + "algorithm": "GENETIC", + "genetic": { + "generations": 400, + "individuals": 300 + } } }, "prediction": { @@ -5713,6 +5718,22 @@ 900 ] }, + "algorithm": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Algorithm", + "description": "The optimization algorithm.", + "default": "GENETIC", + "examples": [ + "GENETIC" + ] + }, "genetic": { "anyOf": [ { @@ -5803,13 +5824,9 @@ "title": "Total Costs Amt", "description": "The total costs [money amount]." }, - "prediction": { + "data": { "$ref": "#/components/schemas/PydanticDateTimeDataFrame", - "description": "Datetime data frame with time series prediction data per optimization interval:- pv_energy_wh: PV energy prediction (positive) in wh- elec_price_amt_kwh: Electricity price prediction in money per kwh- feed_in_tariff_amt_kwh: Feed in tariff prediction in money per kwh- weather_temp_air_celcius: Temperature in \u00b0C- load_mean_energy_wh: Load mean energy prediction in wh- load_std_energy_wh: Load energy standard deviation prediction in wh- load_mean_adjusted_energy_w: Adjusted load mean energy prediction in wh" - }, - "solution": { - "$ref": "#/components/schemas/PydanticDateTimeDataFrame", - "description": "Datetime data frame with time series solution data per optimization interval:- load_energy_wh: Load of all energy consumers in wh- grid_energy_wh: Grid energy feed in (negative) or consumption (positive) in wh- costs_amt: Costs in money amount- revenue_amt: Revenue in money amount- losses_energy_wh: Energy losses in wh- _operation_mode_id: Operation mode id of the device.- _operation_mode_factor: Operation mode factor of the device.- _soc_factor: State of charge of a battery/ electric vehicle device as factor of total capacity.- _energy_wh: Energy consumption (positive) of a device in wh." + "description": "Datetime data frame with time series optimization data per optimization interval:- load_energy_wh: Load of all energy consumers in wh- grid_energy_wh: Grid energy feed in (negative) or consumption (positive) in wh- pv_prediction_energy_wh: PV energy prediction (positive) in wh- elec_price_prediction_amt_kwh: Electricity price prediction in money per kwh- costs_amt: Costs in money amount- revenue_amt: Revenue in money amount- losses_energy_wh: Energy losses in wh- _operation_mode_id: Operation mode id of the device.- _operation_mode_factor: Operation mode factor of the device.- _soc_factor: State of charge of a battery/ electric vehicle device as factor of total capacity.- _energy_wh: Energy consumption (positive) of a device in wh." } }, "type": "object", @@ -5819,8 +5836,7 @@ "total_losses_energy_wh", "total_revenues_amt", "total_costs_amt", - "prediction", - "solution" + "data" ], "title": "OptimizationSolution", "description": "General Optimization Solution." diff --git a/src/akkudoktoreos/optimization/optimization.py b/src/akkudoktoreos/optimization/optimization.py index 74cf1ba..82c44ab 100644 --- a/src/akkudoktoreos/optimization/optimization.py +++ b/src/akkudoktoreos/optimization/optimization.py @@ -1,9 +1,12 @@ from typing import Optional, Union -from pydantic import Field +from pydantic import Field, model_validator from akkudoktoreos.config.configabc import SettingsBaseModel -from akkudoktoreos.core.pydantic import PydanticBaseModel, PydanticDateTimeDataFrame +from akkudoktoreos.core.pydantic import ( + PydanticBaseModel, + PydanticDateTimeDataFrame, +) from akkudoktoreos.utils.datetimeutil import DateTime @@ -58,12 +61,26 @@ class OptimizationCommonSettings(SettingsBaseModel): examples=[60 * 60, 15 * 60], ) + algorithm: Optional[str] = Field( + default="GENETIC", + description="The optimization algorithm.", + examples=["GENETIC"], + ) + genetic: Optional[GeneticCommonSettings] = Field( default=None, description="Genetic optimization algorithm configuration.", examples=[{"individuals": 400, "seed": None, "penalties": {"ev_soc_miss": 10}}], ) + @model_validator(mode="after") + def _enforce_algorithm_configuration(self) -> "OptimizationCommonSettings": + """Ensure algorithm default configuration is set.""" + if self.algorithm is not None: + if self.algorithm.lower() == "genetic" and self.genetic is None: + self.genetic = GeneticCommonSettings() + return self + class OptimizationSolution(PydanticBaseModel): """General Optimization Solution.""" diff --git a/tests/testdata/eos_config_minimal_now.json b/tests/testdata/eos_config_minimal_now.json index 3888a75..3caecb2 100644 --- a/tests/testdata/eos_config_minimal_now.json +++ b/tests/testdata/eos_config_minimal_now.json @@ -8,7 +8,12 @@ "hours": 48 }, "optimization": { - "horizon_hours": 48 + "horizon_hours": 48, + "algorithm": "GENETIC", + "genetic": { + "individuals": 300, + "generations": 400 + } }, "general": { "latitude": 52.5,