summaryrefslogtreecommitdiff
path: root/lib/model.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/model.py')
-rw-r--r--lib/model.py87
1 files changed, 23 insertions, 64 deletions
diff --git a/lib/model.py b/lib/model.py
index 4c4c226..527a19e 100644
--- a/lib/model.py
+++ b/lib/model.py
@@ -4,7 +4,7 @@ import logging
import numpy as np
import os
from .automata import PTA, ModelAttribute
-from .functions import StaticFunction
+from .functions import StaticFunction, SubstateFunction
from .parameters import ParallelParamStats
from .paramfit import ParallelParamFit
from .utils import soft_cast_int, by_name_to_by_param, regression_measures
@@ -439,6 +439,7 @@ class PTAModel(AnalyticModel):
from .pelt import PELT
self.pelt = PELT(**pelt)
+ # must run before _compute_stats so that _compute_stats produces a "substate_count" model
self.find_substates()
else:
self.pelt = None
@@ -448,6 +449,9 @@ class PTAModel(AnalyticModel):
self._compute_stats(by_name)
if self.pelt is not None:
+ # cluster_substates uses self.attr_by_name[*]["power"].param_values, which is set by _compute_stats
+ # cluster_substates relies on fitted "substate_count" models, which are generated by get_fitted.
+ self.get_fitted()
# cluster_substates alters submodel_by_name, so we cannot use its keys() iterator.
names_with_submodel = list(self.submodel_by_name.keys())
for name in names_with_submodel:
@@ -465,60 +469,6 @@ class PTAModel(AnalyticModel):
for key in elem["attributes"]:
elem[key] = np.array(elem[key])
- def get_fitted_sub(
- self, use_mean=False, safe_functions_enabled=False, state_duration=None
- ):
-
- param_model_getter, param_info_getter = self.get_fitted(
- use_mean=use_mean, safe_functions_enabled=safe_functions_enabled
- )
-
- def model_getter(name, key, **kwargs):
- if key != "power":
- return param_model_getter(name, key, **kwargs)
-
- try:
- substate_count = round(param_model_getter(name, "substate_count"))
- except KeyError:
- return param_model_getter(name, key, **kwargs)
- if substate_count == 1:
- return param_model_getter(name, key, **kwargs)
-
- cumulative_energy = 0
- total_duration = 0
- substate_model, _ = self.submodel_by_name[name].get_fitted()
- substate_sequence = self.substate_sequence_by_nc[(name, substate_count)]
- for i, sub_name in enumerate(substate_sequence):
- sub_duration = substate_model(sub_name, "duration", **kwargs)
- sub_power = substate_model(sub_name, "power", **kwargs)
-
- if i == substate_count - 1:
- if "duration" in kwargs:
- sub_duration = kwargs["duration"] - total_duration
- elif name in self.states and state_duration is not None:
- sub_duration = state_duration - total_duration
-
- cumulative_energy += sub_power * sub_duration
- total_duration += sub_duration
-
- return cumulative_energy / total_duration
-
- def info_getter(name, key, **kwargs):
- if key != "power":
- return None
-
- try:
- substate_count = round(param_model_getter(name, "substate_count"))
- except KeyError:
- return None
- if substate_count == 1:
- return None
-
- # TODO
- return True
-
- return model_getter, info_getter
-
# This heuristic is very similar to the "function is not much better than
# median" checks in get_fitted. So far, doing it here as well is mostly
# a performance and not an algorithm quality decision.
@@ -669,13 +619,10 @@ class PTAModel(AnalyticModel):
# Schwankungen, die beim separaten Fitting zu unterschiedlichen Funktionen führen würden.
p_attr = self.attr_by_name[p_name]["power"]
p_params = list(set(map(tuple, p_attr.param_values)))
- p_param_index = dict()
- for i, p_param in enumerate(p_params):
- p_param_index[p_param] = i
sub_attr_by_function = dict()
static = submodel.get_static()
lut = submodel.get_param_lut(fallback=True)
- values_to_cluster = np.zeros((len(submodel.names), len(p_param_index)))
+ values_to_cluster = np.zeros((len(submodel.names), len(p_params)))
for i, name in enumerate(submodel.names):
for j, param in enumerate(p_params):
values_to_cluster[i, j] = lut(name, "duration", param=param)
@@ -699,7 +646,7 @@ class PTAModel(AnalyticModel):
if len(cl_substates) == 1:
clusters.append(cl_substates)
continue
- values_to_cluster = np.zeros((len(cl_substates), len(p_param_index)))
+ values_to_cluster = np.zeros((len(cl_substates), len(p_params)))
for i, name in enumerate(cl_substates):
for j, param in enumerate(p_params):
values_to_cluster[i, j] = lut(name, "power", param=param)
@@ -742,10 +689,22 @@ class PTAModel(AnalyticModel):
"power": powers,
}
self.submodel_by_name[p_name] = PTAModel(by_name, self.parameters, dict())
- for k in self.substate_sequence_by_nc.keys():
- self.substate_sequence_by_nc[k] = list(
- map(lambda x: new_subname_by_old[x], self.substate_sequence_by_nc[k])
- )
+ sequence_by_count = dict()
+ for name, count in self.substate_sequence_by_nc.keys():
+ if name == p_name:
+ sequence_by_count[int(count)] = list(
+ map(
+ lambda x: new_subname_by_old[x],
+ self.substate_sequence_by_nc[(name, count)],
+ )
+ )
+
+ self.attr_by_name[p_name]["power"].model_function = SubstateFunction(
+ self.attr_by_name[p_name]["power"].get_static(),
+ sequence_by_count,
+ self.attr_by_name[p_name]["substate_count"].model_function,
+ self.submodel_by_name[p_name],
+ )
# data[0] = [first sub-state, second sub-state, ...]
# data[1] = [first sub-state, second sub-state, ...]