rtc-tools-interface 0.4.4__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/PKG-INFO +1 -1
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/README.md +13 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtc_tools_interface.egg-info/PKG-INFO +1 -1
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtc_tools_interface.egg-info/SOURCES.txt +1 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/_version.py +3 -3
- rtc-tools-interface-0.5.0/rtctools_interface/optimization/goal_generator_mixin.py +96 -0
- rtc-tools-interface-0.5.0/rtctools_interface/optimization/goal_performance_metrics.py +117 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/plot_goals_mixin.py +38 -99
- rtc-tools-interface-0.4.4/rtctools_interface/optimization/goal_generator_mixin.py +0 -46
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/COPYING.LESSER +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtc_tools_interface.egg-info/dependency_links.txt +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtc_tools_interface.egg-info/requires.txt +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtc_tools_interface.egg-info/top_level.txt +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/__init__.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/__init__.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/base_goal.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/base_optimization_problem.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/goal_table_schema.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/plot_and_goal_schema.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/plot_table_schema.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/plotting/__init__.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/plotting/plot_tools.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/plotting/subplot_classes.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/read_goals.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/read_plot_table.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/type_definitions.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/utils/__init__.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/setup.cfg +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/setup.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/tests/__init__.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/tests/optimization/__init__.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/tests/optimization/get_test.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/tests/optimization/test_base_optimization_problem.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/tests/optimization/test_passing_goals_directly.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/tests/optimization/test_plot_goals_mixin.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/tests/optimization/test_read_goals.py +0 -0
- {rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/versioneer.py +0 -0
|
@@ -96,6 +96,19 @@ See the table below for an example content of the `goal_table.csv`.
|
|
|
96
96
|
| goal_2 | reservoir_2_waterlevel | 1 | range | 0 | 15 | 10 | timeseries | "target_series" | "target_series" | 10 | | |
|
|
97
97
|
| goal_3 | electricity_cost | 1 | minimization_path | | | | | | | 20 | | |
|
|
98
98
|
|
|
99
|
+
## Goal performance metrics
|
|
100
|
+
For all goals defined with the goal generator this rtc-tools-interface module will also calculate performance metrics. By default, these performance metrics are saved to a .csv in the folder `output/perfomance_metrics`, with one csv file per goal. With the class variable `calculate_performance_metrics` this functionality can be disabled (by default it is enabled).
|
|
101
|
+
|
|
102
|
+
The calculated metrics are:
|
|
103
|
+
- `timeseries_sum`: The sum of the state variable over all timesteps.
|
|
104
|
+
- `timeseries_min`: The minimum of the state variable.
|
|
105
|
+
- `timeseries_max`: The maximum of the state variable.
|
|
106
|
+
- `timeseries_avg`: The average of the state variable.
|
|
107
|
+
- `max_difference`: The maximum difference in one timestep.
|
|
108
|
+
- `mean_absolute_percentual_difference`: The mean of the absolute percentual difference per timestep over all timesteps (only for range goals).
|
|
109
|
+
- `mean_absolute_difference`: The mean absolute difference per timestep of the state variable over all timesteps (only for range goals).
|
|
110
|
+
|
|
111
|
+
|
|
99
112
|
## Automatic plotting of results
|
|
100
113
|
With the `PlotGoalsMixin` one can easily make plots of the results of rtc-tools. To utilize this functionality, import the mixin as follows:
|
|
101
114
|
```python
|
{rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtc_tools_interface.egg-info/SOURCES.txt
RENAMED
|
@@ -14,6 +14,7 @@ rtctools_interface/optimization/__init__.py
|
|
|
14
14
|
rtctools_interface/optimization/base_goal.py
|
|
15
15
|
rtctools_interface/optimization/base_optimization_problem.py
|
|
16
16
|
rtctools_interface/optimization/goal_generator_mixin.py
|
|
17
|
+
rtctools_interface/optimization/goal_performance_metrics.py
|
|
17
18
|
rtctools_interface/optimization/goal_table_schema.py
|
|
18
19
|
rtctools_interface/optimization/plot_and_goal_schema.py
|
|
19
20
|
rtctools_interface/optimization/plot_goals_mixin.py
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "2023-10-
|
|
11
|
+
"date": "2023-10-30T13:58:13+0000",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "0.
|
|
14
|
+
"full-revisionid": "34cc7954ac465b9eedd42d7efdea2bf42d26ac19",
|
|
15
|
+
"version": "0.5.0"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""Module for a basic optimization problem."""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Dict, Union
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
from rtctools_interface.optimization.base_goal import BaseGoal
|
|
9
|
+
from rtctools_interface.optimization.goal_performance_metrics import get_performance_metrics
|
|
10
|
+
from rtctools_interface.optimization.helpers.statistics_mixin import StatisticsMixin
|
|
11
|
+
from rtctools_interface.optimization.read_goals import read_goals
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger("rtctools")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def write_performance_metrics(performance_metrics: Dict[str, pd.DataFrame], output_path: Union[str, Path]):
|
|
17
|
+
"""Write the performance metrics for each goal to a csv file."""
|
|
18
|
+
output_path = Path(output_path) / "performance_metrics"
|
|
19
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
20
|
+
for goal_id, performance_metric_table in performance_metrics.items():
|
|
21
|
+
performance_metric_table.to_csv(output_path / f"{goal_id}.csv")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class GoalGeneratorMixin(StatisticsMixin):
|
|
25
|
+
# TODO: remove pylint disable below once we have more public functions.
|
|
26
|
+
# pylint: disable=too-few-public-methods
|
|
27
|
+
"""Add path goals as specified in the goal_table.
|
|
28
|
+
|
|
29
|
+
By default, the mixin looks for the csv in the in the default input
|
|
30
|
+
folder. One can also set the path to the goal_table_file manually
|
|
31
|
+
with the `goal_table_file` class variable.
|
|
32
|
+
"""
|
|
33
|
+
calculate_performance_metrics = True
|
|
34
|
+
|
|
35
|
+
def __init__(self, **kwargs):
|
|
36
|
+
super().__init__(**kwargs)
|
|
37
|
+
self.goals_to_generate = kwargs.get("goals_to_generate", [])
|
|
38
|
+
self.read_from = kwargs.get("read_goals_from", "csv_table")
|
|
39
|
+
if not hasattr(self, "goal_table_file"):
|
|
40
|
+
self.goal_table_file = os.path.join(self._input_folder, "goal_table.csv")
|
|
41
|
+
|
|
42
|
+
self._goal_generator_path_goals = read_goals(
|
|
43
|
+
self.goal_table_file, path_goal=True, read_from=self.read_from, goals_to_generate=self.goals_to_generate
|
|
44
|
+
)
|
|
45
|
+
self._goal_generator_non_path_goals = read_goals(
|
|
46
|
+
self.goal_table_file, path_goal=False, read_from=self.read_from, goals_to_generate=self.goals_to_generate
|
|
47
|
+
)
|
|
48
|
+
self._all_goal_generator_goals = self._goal_generator_path_goals + self._goal_generator_non_path_goals
|
|
49
|
+
|
|
50
|
+
if self.calculate_performance_metrics:
|
|
51
|
+
# A dataframe for each goal defined by the goal generator
|
|
52
|
+
self.performance_metrics = {}
|
|
53
|
+
for goal in self._all_goal_generator_goals:
|
|
54
|
+
self.performance_metrics[goal.goal_id] = pd.DataFrame()
|
|
55
|
+
|
|
56
|
+
def path_goals(self):
|
|
57
|
+
"""Return the list of path goals."""
|
|
58
|
+
goals = super().path_goals()
|
|
59
|
+
new_goals = self._goal_generator_path_goals
|
|
60
|
+
if new_goals:
|
|
61
|
+
goals = goals + [BaseGoal(optimization_problem=self, **goal.__dict__) for goal in new_goals]
|
|
62
|
+
return goals
|
|
63
|
+
|
|
64
|
+
def goals(self):
|
|
65
|
+
"""Return the list of goals."""
|
|
66
|
+
goals = super().goals()
|
|
67
|
+
new_goals = self._goal_generator_non_path_goals
|
|
68
|
+
if new_goals:
|
|
69
|
+
goals = goals + [BaseGoal(optimization_problem=self, **goal.__dict__) for goal in new_goals]
|
|
70
|
+
return goals
|
|
71
|
+
|
|
72
|
+
def store_performance_metrics(self, label):
|
|
73
|
+
"""Calculate and store performance metrics."""
|
|
74
|
+
results = self.extract_results()
|
|
75
|
+
goal_generator_goals = self._all_goal_generator_goals
|
|
76
|
+
targets = self.collect_range_target_values(goal_generator_goals)
|
|
77
|
+
for goal in goal_generator_goals:
|
|
78
|
+
next_row = get_performance_metrics(results, goal, targets.get(goal.goal_id))
|
|
79
|
+
if next_row is not None:
|
|
80
|
+
next_row.rename(label, inplace=True)
|
|
81
|
+
self.performance_metrics[goal.goal_id] = pd.concat(
|
|
82
|
+
[self.performance_metrics[goal.goal_id].T, next_row], axis=1
|
|
83
|
+
).T
|
|
84
|
+
|
|
85
|
+
def priority_completed(self, priority):
|
|
86
|
+
"""Tasks after priority optimization."""
|
|
87
|
+
super().priority_completed(priority)
|
|
88
|
+
if self.calculate_performance_metrics:
|
|
89
|
+
self.store_performance_metrics(priority)
|
|
90
|
+
|
|
91
|
+
def post(self):
|
|
92
|
+
"""Tasks after all optimization steps."""
|
|
93
|
+
super().post()
|
|
94
|
+
if self.calculate_performance_metrics:
|
|
95
|
+
self.store_performance_metrics("final_results")
|
|
96
|
+
write_performance_metrics(self.performance_metrics, self._output_folder)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""This file contains functions to get performance metrics for the BaseGoal."""
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Dict, Optional
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from rtctools_interface.optimization.goal_table_schema import (
|
|
9
|
+
BaseGoalModel,
|
|
10
|
+
MaximizationGoalModel,
|
|
11
|
+
MinimizationGoalModel,
|
|
12
|
+
RangeGoalModel,
|
|
13
|
+
RangeRateOfChangeGoalModel,
|
|
14
|
+
)
|
|
15
|
+
from rtctools_interface.optimization.type_definitions import TargetDict
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger("rtctools")
|
|
19
|
+
|
|
20
|
+
ABS_TOL = 0.001
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_mean_absolute_percentual_difference(timeseries: np.ndarray) -> float:
|
|
24
|
+
"""Calculate the mean absolute percentual difference."""
|
|
25
|
+
differences = np.diff(timeseries)
|
|
26
|
+
mapd = np.mean(np.abs(differences / timeseries[:-1]))
|
|
27
|
+
return mapd
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_absolute_sum_difference(timeseries: np.ndarray) -> float:
|
|
31
|
+
"""Calculate the mean of absolute first-order difference."""
|
|
32
|
+
mad = np.mean(np.abs(np.diff(timeseries)))
|
|
33
|
+
return mad
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_max_difference(timeseries: np.ndarray) -> float:
|
|
37
|
+
"""Get maximum one step difference"""
|
|
38
|
+
return max(np.diff(timeseries))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_basic_metrics(timeseries: np.ndarray) -> dict[str, float]:
|
|
42
|
+
"""Get general metrics applicable for each goal type."""
|
|
43
|
+
metrics = {
|
|
44
|
+
"timeseries_sum": sum(timeseries),
|
|
45
|
+
"timeseries_min": min(timeseries),
|
|
46
|
+
"timeseries_max": max(timeseries),
|
|
47
|
+
"timeseries_avg": np.mean(timeseries),
|
|
48
|
+
"mean_absolute_percentual_difference": get_mean_absolute_percentual_difference(timeseries),
|
|
49
|
+
"mean_absolute_difference": get_absolute_sum_difference(timeseries),
|
|
50
|
+
"max_difference": get_max_difference(timeseries),
|
|
51
|
+
}
|
|
52
|
+
return metrics
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def performance_metrics_minmaximization(results: Dict[str, np.ndarray], goal: MinimizationGoalModel) -> pd.Series:
|
|
56
|
+
"""Get all relevant statistics for a min/maximization goal."""
|
|
57
|
+
state_timeseries = results[goal.state]
|
|
58
|
+
metrics = get_basic_metrics(state_timeseries)
|
|
59
|
+
return pd.Series(metrics)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_range_percentual_exceedance(
|
|
63
|
+
timeseries: np.ndarray, goal: RangeGoalModel, targets: TargetDict
|
|
64
|
+
) -> Optional[dict[str, float]]:
|
|
65
|
+
"""Calculate percentage of timesteps in which target is exceeded"""
|
|
66
|
+
if goal.goal_type not in ["range", "range_rate_of_change"]:
|
|
67
|
+
below_target = None
|
|
68
|
+
above_target = None
|
|
69
|
+
else:
|
|
70
|
+
below_target = sum(np.where(timeseries + ABS_TOL < targets["target_min"], 1, 0)) / len(timeseries)
|
|
71
|
+
above_target = sum(np.where(timeseries - ABS_TOL > targets["target_max"], 1, 0)) / len(timeseries)
|
|
72
|
+
return {"perc_below_target": below_target, "perc_above_target": above_target}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def get_range_total_exceedance(
|
|
76
|
+
timeseries: np.ndarray, goal: RangeGoalModel, targets: TargetDict
|
|
77
|
+
) -> Optional[dict[str, float]]:
|
|
78
|
+
"""Calculate sum of absolute exceedances of the target"""
|
|
79
|
+
if goal.goal_type not in ["range", "range_rate_of_change"]:
|
|
80
|
+
below_target = None
|
|
81
|
+
above_target = None
|
|
82
|
+
else:
|
|
83
|
+
below_target = sum(np.abs(np.where(timeseries < targets["target_min"], timeseries - targets["target_min"], 0)))
|
|
84
|
+
above_target = sum(np.abs(np.where(timeseries > targets["target_max"], timeseries - targets["target_max"], 0)))
|
|
85
|
+
return {"sum_below_target": below_target, "sum_above_target": above_target}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def performance_metrics_range(results: Dict[str, np.ndarray], goal: RangeGoalModel, targets: TargetDict) -> pd.Series:
|
|
89
|
+
"""Get all relevant statistics for a range goal."""
|
|
90
|
+
metrics = {}
|
|
91
|
+
state_timeseries = results[goal.state]
|
|
92
|
+
metrics = metrics | get_basic_metrics(state_timeseries)
|
|
93
|
+
metrics = metrics | get_range_percentual_exceedance(state_timeseries, goal, targets)
|
|
94
|
+
metrics = metrics | get_range_total_exceedance(state_timeseries, goal, targets)
|
|
95
|
+
return pd.Series(metrics)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def performance_metrics_rangerateofchange(
|
|
99
|
+
results: Dict[str, np.ndarray], goal: RangeGoalModel, _targets: TargetDict
|
|
100
|
+
) -> pd.Series:
|
|
101
|
+
"""Get all relevant statistics for a range-rate-of-change goal."""
|
|
102
|
+
metrics = {}
|
|
103
|
+
state_timeseries = results[goal.state]
|
|
104
|
+
metrics = metrics | get_basic_metrics(state_timeseries)
|
|
105
|
+
return pd.Series(metrics)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_performance_metrics(results, goal: BaseGoalModel, targets: TargetDict) -> Optional[pd.Series]:
|
|
109
|
+
"""Returns a series with performance metrics for each goal."""
|
|
110
|
+
if type(goal) in [MinimizationGoalModel, MaximizationGoalModel]: # pylint: disable=unidiomatic-typecheck
|
|
111
|
+
return performance_metrics_minmaximization(results, goal)
|
|
112
|
+
if type(goal) in [RangeGoalModel]:
|
|
113
|
+
return performance_metrics_range(results, goal, targets)
|
|
114
|
+
if type(goal) in [RangeRateOfChangeGoalModel]:
|
|
115
|
+
return performance_metrics_rangerateofchange(results, goal, targets)
|
|
116
|
+
logger.info("No performance metrics are implemented for goal of type: %s", str(type(goal)))
|
|
117
|
+
return None
|
|
@@ -5,17 +5,11 @@ import copy
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
import pickle
|
|
7
7
|
import time
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
from rtctools_interface.optimization.helpers.statistics_mixin import StatisticsMixin
|
|
9
11
|
|
|
10
|
-
import numpy as np
|
|
11
12
|
|
|
12
|
-
from rtctools_interface.optimization.plot_and_goal_schema import (
|
|
13
|
-
MinimizationGoalCombinedModel,
|
|
14
|
-
MaximizationGoalCombinedModel,
|
|
15
|
-
RangeGoalCombinedModel,
|
|
16
|
-
RangeRateOfChangeGoalCombinedModel,
|
|
17
|
-
)
|
|
18
|
-
from rtctools_interface.optimization.plot_table_schema import PlotTableRow
|
|
19
13
|
from rtctools_interface.optimization.plotting.plot_tools import create_plot_each_priority, create_plot_final_results
|
|
20
14
|
|
|
21
15
|
from rtctools_interface.optimization.read_plot_table import get_joined_plot_config
|
|
@@ -23,7 +17,6 @@ from rtctools_interface.optimization.type_definitions import (
|
|
|
23
17
|
PlotDataAndConfig,
|
|
24
18
|
PlotOptions,
|
|
25
19
|
PrioIndependentData,
|
|
26
|
-
TargetDict,
|
|
27
20
|
)
|
|
28
21
|
|
|
29
22
|
logger = logging.getLogger("rtctools")
|
|
@@ -75,7 +68,7 @@ def read_cache_file_from_folder(cache_folder: Path) -> Optional[PlotDataAndConfi
|
|
|
75
68
|
return loaded_data
|
|
76
69
|
|
|
77
70
|
|
|
78
|
-
class PlotGoalsMixin:
|
|
71
|
+
class PlotGoalsMixin(StatisticsMixin):
|
|
79
72
|
"""
|
|
80
73
|
Class for plotting results.
|
|
81
74
|
"""
|
|
@@ -131,98 +124,44 @@ class PlotGoalsMixin:
|
|
|
131
124
|
self.intermediate_results.append(to_store)
|
|
132
125
|
super().priority_completed(priority)
|
|
133
126
|
|
|
134
|
-
def collect_range_target_values(
|
|
135
|
-
self,
|
|
136
|
-
all_goals: List[
|
|
137
|
-
Union[
|
|
138
|
-
MinimizationGoalCombinedModel,
|
|
139
|
-
MaximizationGoalCombinedModel,
|
|
140
|
-
RangeGoalCombinedModel,
|
|
141
|
-
RangeRateOfChangeGoalCombinedModel,
|
|
142
|
-
PlotTableRow,
|
|
143
|
-
]
|
|
144
|
-
],
|
|
145
|
-
) -> Dict[str, TargetDict]:
|
|
146
|
-
"""For the goals with targets, collect the actual timeseries with these targets."""
|
|
147
|
-
t = self.times()
|
|
148
|
-
|
|
149
|
-
def get_parameter_ranges(goal):
|
|
150
|
-
try:
|
|
151
|
-
target_min = np.full_like(t, 1) * self.parameters(0)[goal.target_min]
|
|
152
|
-
target_max = np.full_like(t, 1) * self.parameters(0)[goal.target_max]
|
|
153
|
-
except TypeError:
|
|
154
|
-
target_min = np.full_like(t, 1) * self.io.get_parameter(goal.target_min)
|
|
155
|
-
target_max = np.full_like(t, 1) * self.io.get_parameter(goal.target_max)
|
|
156
|
-
return target_min, target_max
|
|
157
|
-
|
|
158
|
-
def get_value_ranges(goal):
|
|
159
|
-
target_min = np.full_like(t, 1) * float(goal.target_min)
|
|
160
|
-
target_max = np.full_like(t, 1) * float(goal.target_max)
|
|
161
|
-
return target_min, target_max
|
|
162
|
-
|
|
163
|
-
def get_timeseries_ranges(goal):
|
|
164
|
-
if isinstance(goal.target_min, str):
|
|
165
|
-
target_min = self.get_timeseries(goal.target_min).values
|
|
166
|
-
else:
|
|
167
|
-
target_min = np.full_like(t, 1) * goal.target_min
|
|
168
|
-
if isinstance(goal.target_max, str):
|
|
169
|
-
target_max = self.get_timeseries(goal.target_max).values
|
|
170
|
-
else:
|
|
171
|
-
target_max = np.full_like(t, 1) * goal.target_max
|
|
172
|
-
return target_min, target_max
|
|
173
|
-
|
|
174
|
-
target_series: Dict[str, TargetDict] = {}
|
|
175
|
-
for goal in all_goals:
|
|
176
|
-
if not goal.specified_in == "python" and goal.goal_type in ["range", "range_rate_of_change"]:
|
|
177
|
-
if goal.target_data_type == "parameter":
|
|
178
|
-
target_min, target_max = get_parameter_ranges(goal)
|
|
179
|
-
elif goal.target_data_type == "value":
|
|
180
|
-
target_min, target_max = get_value_ranges(goal)
|
|
181
|
-
elif goal.target_data_type == "timeseries":
|
|
182
|
-
target_min, target_max = get_timeseries_ranges(goal)
|
|
183
|
-
else:
|
|
184
|
-
message = "Target type {} not known.".format(goal.target_data_type)
|
|
185
|
-
logger.error(message)
|
|
186
|
-
raise ValueError(message)
|
|
187
|
-
target_series[goal.goal_id] = {"target_min": target_min, "target_max": target_max}
|
|
188
|
-
return target_series
|
|
189
|
-
|
|
190
127
|
def post(self):
|
|
191
128
|
"""Tasks after optimizing. Creates a plot for for each priority."""
|
|
192
129
|
super().post()
|
|
193
|
-
prio_independent_data: PrioIndependentData = {
|
|
194
|
-
"io_datetimes": self.io.datetimes,
|
|
195
|
-
"times": self.times(),
|
|
196
|
-
"target_series": self.collect_range_target_values(self.plot_config),
|
|
197
|
-
"all_goals": self.goals() + self.path_goals(),
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
plot_options: PlotOptions = {
|
|
201
|
-
"plot_config": self.plot_config,
|
|
202
|
-
"plot_max_rows": self.plot_max_rows,
|
|
203
|
-
"output_folder": self._output_folder,
|
|
204
|
-
"save_plot_to": self.save_plot_to,
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
current_run: PlotDataAndConfig = {
|
|
208
|
-
"intermediate_results": self.intermediate_results,
|
|
209
|
-
"plot_options": plot_options,
|
|
210
|
-
"prio_independent_data": prio_independent_data,
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
self.plot_data = {}
|
|
214
|
-
if self.plot_results_each_priority:
|
|
215
|
-
self.plot_data = self.plot_data | create_plot_each_priority(
|
|
216
|
-
current_run, plotting_library=self.plotting_library
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
if self.plot_final_results:
|
|
220
|
-
self.plot_data = self.plot_data | create_plot_final_results(
|
|
221
|
-
current_run, self._previous_run, plotting_library=self.plotting_library
|
|
222
|
-
)
|
|
223
130
|
|
|
224
|
-
|
|
225
|
-
|
|
131
|
+
if self.solver_stats["success"]:
|
|
132
|
+
prio_independent_data: PrioIndependentData = {
|
|
133
|
+
"io_datetimes": self.io.datetimes,
|
|
134
|
+
"times": self.times(),
|
|
135
|
+
"target_series": self.collect_range_target_values(self.plot_config),
|
|
136
|
+
"all_goals": self.goals() + self.path_goals(),
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
plot_options: PlotOptions = {
|
|
140
|
+
"plot_config": self.plot_config,
|
|
141
|
+
"plot_max_rows": self.plot_max_rows,
|
|
142
|
+
"output_folder": self._output_folder,
|
|
143
|
+
"save_plot_to": self.save_plot_to,
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
current_run: PlotDataAndConfig = {
|
|
147
|
+
"intermediate_results": self.intermediate_results,
|
|
148
|
+
"plot_options": plot_options,
|
|
149
|
+
"prio_independent_data": prio_independent_data,
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
self.plot_data = {}
|
|
153
|
+
if self.plot_results_each_priority:
|
|
154
|
+
self.plot_data = self.plot_data | create_plot_each_priority(
|
|
155
|
+
current_run, plotting_library=self.plotting_library
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
if self.plot_final_results:
|
|
159
|
+
self.plot_data = self.plot_data | create_plot_final_results(
|
|
160
|
+
current_run, self._previous_run, plotting_library=self.plotting_library
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Cache results, such that in a next run they can be used for comparison
|
|
164
|
+
self._store_current_results(self._cache_folder, current_run)
|
|
226
165
|
|
|
227
166
|
def _store_current_results(self, cache_folder, results_to_store):
|
|
228
167
|
write_cache_file(cache_folder, results_to_store)
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"""Module for a basic optimization problem."""
|
|
2
|
-
import logging
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
from rtctools_interface.optimization.base_goal import BaseGoal
|
|
6
|
-
from rtctools_interface.optimization.read_goals import read_goals
|
|
7
|
-
|
|
8
|
-
logger = logging.getLogger("rtctools")
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class GoalGeneratorMixin:
|
|
12
|
-
# TODO: remove pylint disable below once we have more public functions.
|
|
13
|
-
# pylint: disable=too-few-public-methods
|
|
14
|
-
"""Add path goals as specified in the goal_table.
|
|
15
|
-
|
|
16
|
-
By default, the mixin looks for the csv in the in the default input
|
|
17
|
-
folder. One can also set the path to the goal_table_file manually
|
|
18
|
-
with the `goal_table_file` class variable.
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
def __init__(self, **kwargs):
|
|
22
|
-
super().__init__(**kwargs)
|
|
23
|
-
self.goals_to_generate = kwargs.get("goals_to_generate", [])
|
|
24
|
-
self.read_from = kwargs.get("read_goals_from", "csv_table")
|
|
25
|
-
if not hasattr(self, "goal_table_file"):
|
|
26
|
-
self.goal_table_file = os.path.join(self._input_folder, "goal_table.csv")
|
|
27
|
-
|
|
28
|
-
def path_goals(self):
|
|
29
|
-
"""Return the list of path goals."""
|
|
30
|
-
goals = super().path_goals()
|
|
31
|
-
new_goals = read_goals(
|
|
32
|
-
self.goal_table_file, path_goal=True, read_from=self.read_from, goals_to_generate=self.goals_to_generate
|
|
33
|
-
)
|
|
34
|
-
if new_goals:
|
|
35
|
-
goals = goals + [BaseGoal(optimization_problem=self, **goal.__dict__) for goal in new_goals]
|
|
36
|
-
return goals
|
|
37
|
-
|
|
38
|
-
def goals(self):
|
|
39
|
-
"""Return the list of goals."""
|
|
40
|
-
goals = super().goals()
|
|
41
|
-
new_goals = read_goals(
|
|
42
|
-
self.goal_table_file, path_goal=False, read_from=self.read_from, goals_to_generate=self.goals_to_generate
|
|
43
|
-
)
|
|
44
|
-
if new_goals:
|
|
45
|
-
goals = goals + [BaseGoal(optimization_problem=self, **goal.__dict__) for goal in new_goals]
|
|
46
|
-
return goals
|
|
File without changes
|
|
File without changes
|
{rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtc_tools_interface.egg-info/requires.txt
RENAMED
|
File without changes
|
{rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtc_tools_interface.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
{rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/__init__.py
RENAMED
|
File without changes
|
{rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/optimization/base_goal.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/rtctools_interface/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/tests/optimization/test_plot_goals_mixin.py
RENAMED
|
File without changes
|
{rtc-tools-interface-0.4.4 → rtc-tools-interface-0.5.0}/tests/optimization/test_read_goals.py
RENAMED
|
File without changes
|
|
File without changes
|