Skip to content

Commit

Permalink
Cleanup: parameters: extra=forbid, optimize: battery, inverter optional
Browse files Browse the repository at this point in the history
 * Don't allow extra fields for parameters/REST-API (at least for now while
   changing API).
 * Allow both battery and inverter to be set optionally (atm optional
   battery not implemented, no API constraints).
 * inverter: Remove default max_power_wh
 * single_test_optimization: Add more cli-parameters
 * Docker: Fix entrypoint
  • Loading branch information
Lasall committed Jan 10, 2025
1 parent 34d8e88 commit 270fabf
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 107 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ ENTRYPOINT []

EXPOSE 8503

CMD ["python", "-m", "akkudoktoreos.server.fastapi_server"]
CMD ["python", "-m", "akkudoktoreos.server.eos"]

VOLUME ["${MPLCONFIGDIR}", "${EOS_CACHE_DIR}", "${EOS_OUTPUT_DIR}", "${EOS_CONFIG_DIR}"]
35 changes: 28 additions & 7 deletions openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -6108,6 +6108,7 @@
"default": 100
}
},
"additionalProperties": false,
"type": "object",
"required": [
"capacity_wh"
Expand Down Expand Up @@ -6231,6 +6232,7 @@
"description": "An array of floats representing the total load (consumption) in watts for different time intervals."
}
},
"additionalProperties": false,
"type": "object",
"required": [
"pv_prognose_wh",
Expand Down Expand Up @@ -6326,6 +6328,7 @@
"description": "An integer representing the usage duration of a household device in hours."
}
},
"additionalProperties": false,
"type": "object",
"required": [
"consumption_wh",
Expand All @@ -6338,11 +6341,14 @@
"max_power_wh": {
"type": "number",
"exclusiveMinimum": 0.0,
"title": "Max Power Wh",
"default": 10000
"title": "Max Power Wh"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"max_power_wh"
],
"title": "InverterParameters"
},
"OptimizationParameters": {
Expand All @@ -6351,13 +6357,24 @@
"$ref": "#/components/schemas/EnergieManagementSystemParameters"
},
"pv_akku": {
"$ref": "#/components/schemas/SolarPanelBatteryParameters"
"anyOf": [
{
"$ref": "#/components/schemas/SolarPanelBatteryParameters"
},
{
"type": "null"
}
]
},
"inverter": {
"$ref": "#/components/schemas/InverterParameters",
"default": {
"max_power_wh": 10000.0
}
"anyOf": [
{
"$ref": "#/components/schemas/InverterParameters"
},
{
"type": "null"
}
]
},
"eauto": {
"anyOf": [
Expand Down Expand Up @@ -6417,10 +6434,12 @@
"description": "Can be `null` or contain a previous solution (if available)."
}
},
"additionalProperties": false,
"type": "object",
"required": [
"ems",
"pv_akku",
"inverter",
"eauto"
],
"title": "OptimizationParameters"
Expand Down Expand Up @@ -6507,6 +6526,7 @@
"description": "Can be `null` or contain an object representing the start of washing (if applicable)."
}
},
"additionalProperties": false,
"type": "object",
"required": [
"ac_charge",
Expand Down Expand Up @@ -8917,6 +8937,7 @@
"default": 100
}
},
"additionalProperties": false,
"type": "object",
"required": [
"capacity_wh"
Expand Down
48 changes: 39 additions & 9 deletions single_test_optimization.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import argparse
import cProfile
import json
import pstats
import sys
import time
from typing import Any

import numpy as np

Expand Down Expand Up @@ -292,7 +294,9 @@ def prepare_optimization_parameters() -> OptimizationParameters:
)


def run_optimization(real_world: bool = False, start_hour: int = 0, verbose: bool = False) -> dict:
def run_optimization(
real_world: bool, start_hour: int, verbose: bool, seed: int, parameters_file: str, ngen: int
) -> Any:
"""Run the optimization problem.
Args:
Expand All @@ -303,7 +307,10 @@ def run_optimization(real_world: bool = False, start_hour: int = 0, verbose: boo
dict: Optimization result as a dictionary
"""
# Prepare parameters
if real_world:
if parameters_file:
with open(parameters_file, "r") as f:
parameters = OptimizationParameters(**json.load(f))
elif real_world:
parameters = prepare_optimization_real_parameters()
else:
parameters = prepare_optimization_parameters()
Expand All @@ -315,12 +322,12 @@ def run_optimization(real_world: bool = False, start_hour: int = 0, verbose: boo
# Initialize the optimization problem using the default configuration
config_eos = get_config()
config_eos.merge_settings_from_dict({"prediction_hours": 48, "optimization_hours": 48})
opt_class = optimization_problem(verbose=verbose, fixed_seed=42)
opt_class = optimization_problem(verbose=verbose, fixed_seed=seed)

# Perform the optimisation based on the provided parameters and start hour
result = opt_class.optimierung_ems(parameters=parameters, start_hour=start_hour)
result = opt_class.optimierung_ems(parameters=parameters, start_hour=start_hour, ngen=ngen)

return result.model_dump()
return result.model_dump_json()


def main():
Expand All @@ -336,6 +343,19 @@ def main():
parser.add_argument(
"--start-hour", type=int, default=0, help="Starting hour for optimization (default: 0)"
)
parser.add_argument(
"--parameters-file",
type=str,
default="",
help="Load optimization parameters from json file (default: unset)",
)
parser.add_argument("--seed", type=int, default=42, help="Use fixed random seed (default: 42)")
parser.add_argument(
"--ngen",
type=int,
default=400,
help="Number of generations during optimization process (default: 400)",
)

args = parser.parse_args()

Expand All @@ -348,12 +368,16 @@ def main():
real_world=args.real_world,
start_hour=args.start_hour,
verbose=args.verbose,
seed=args.seed,
parameters_file=args.parameters_file,
ngen=args.ngen,
)
# Print profiling statistics
stats = pstats.Stats(profiler)
stats.strip_dirs().sort_stats("cumulative").print_stats(200)
# Print result
print("\nOptimization Result:")
if args.verbose:
print("\nOptimization Result:")
print(result)

except Exception as e:
Expand All @@ -364,12 +388,18 @@ def main():
try:
start_time = time.time()
result = run_optimization(
real_world=args.real_world, start_hour=args.start_hour, verbose=args.verbose
real_world=args.real_world,
start_hour=args.start_hour,
verbose=args.verbose,
seed=args.seed,
parameters_file=args.parameters_file,
ngen=args.ngen,
)
end_time = time.time()
elapsed_time = end_time - start_time
print(f"\nElapsed time: {elapsed_time:.4f} seconds.")
print("\nOptimization Result:")
if args.verbose:
print(f"\nElapsed time: {elapsed_time:.4f} seconds.")
print("\nOptimization Result:")
print(result)

except Exception as e:
Expand Down
64 changes: 0 additions & 64 deletions src/akkudoktoreos/class_home_appliance.py

This file was deleted.

6 changes: 3 additions & 3 deletions src/akkudoktoreos/core/ems.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from akkudoktoreos.core.coreabc import ConfigMixin, PredictionMixin, SingletonMixin
from akkudoktoreos.core.logging import get_logger
from akkudoktoreos.core.pydantic import PydanticBaseModel
from akkudoktoreos.core.pydantic import ParametersBaseModel, PydanticBaseModel
from akkudoktoreos.devices.battery import Battery
from akkudoktoreos.devices.generic import HomeAppliance
from akkudoktoreos.devices.inverter import Inverter
Expand All @@ -18,7 +18,7 @@
logger = get_logger(__name__)


class EnergieManagementSystemParameters(PydanticBaseModel):
class EnergieManagementSystemParameters(ParametersBaseModel):
pv_prognose_wh: list[float] = Field(
description="An array of floats representing the forecasted photovoltaic output in watts for different time intervals."
)
Expand Down Expand Up @@ -50,7 +50,7 @@ def validate_list_length(self) -> Self:
return self


class SimulationResult(PydanticBaseModel):
class SimulationResult(ParametersBaseModel):
"""This object contains the results of the simulation and provides insights into various parameters over the entire forecast period."""

Last_Wh_pro_Stunde: list[Optional[float]] = Field(description="TBD")
Expand Down
4 changes: 4 additions & 0 deletions src/akkudoktoreos/core/pydantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,3 +478,7 @@ def from_series(cls, series: pd.Series, tz: Optional[str] = None) -> "PydanticDa
dtype=str(series.dtype),
tz=tz,
)


class ParametersBaseModel(PydanticBaseModel):
model_config = ConfigDict(extra="forbid")
3 changes: 2 additions & 1 deletion src/akkudoktoreos/devices/battery.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pydantic import BaseModel, Field, field_validator

from akkudoktoreos.core.logging import get_logger
from akkudoktoreos.core.pydantic import ParametersBaseModel
from akkudoktoreos.devices.devicesabc import DeviceBase
from akkudoktoreos.utils.utils import NumpyEncoder

Expand All @@ -24,7 +25,7 @@ def initial_soc_percentage_field(description: str) -> int:
return Field(default=0, ge=0, le=100, description=description)


class BaseBatteryParameters(BaseModel):
class BaseBatteryParameters(ParametersBaseModel):
"""Base class for battery parameters with fields for capacity, efficiency, and state of charge."""

capacity_wh: int = Field(
Expand Down
5 changes: 3 additions & 2 deletions src/akkudoktoreos/devices/generic.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from typing import Optional

import numpy as np
from pydantic import BaseModel, Field
from pydantic import Field

from akkudoktoreos.core.logging import get_logger
from akkudoktoreos.core.pydantic import ParametersBaseModel
from akkudoktoreos.devices.devicesabc import DeviceBase

logger = get_logger(__name__)


class HomeApplianceParameters(BaseModel):
class HomeApplianceParameters(ParametersBaseModel):
consumption_wh: int = Field(
gt=0,
description="An integer representing the energy consumption of a household device in watt-hours.",
Expand Down
7 changes: 4 additions & 3 deletions src/akkudoktoreos/devices/inverter.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
from typing import Optional

from pydantic import BaseModel, Field
from pydantic import Field
from scipy.interpolate import RegularGridInterpolator

from akkudoktoreos.core.logging import get_logger
from akkudoktoreos.core.pydantic import ParametersBaseModel
from akkudoktoreos.devices.battery import Battery
from akkudoktoreos.devices.devicesabc import DeviceBase

logger = get_logger(__name__)


class InverterParameters(BaseModel):
max_power_wh: float = Field(default=10000, gt=0)
class InverterParameters(ParametersBaseModel):
max_power_wh: float = Field(gt=0)


class Inverter(DeviceBase):
Expand Down
Loading

0 comments on commit 270fabf

Please sign in to comment.