diff options
Diffstat (limited to 'lib/model.py')
-rw-r--r-- | lib/model.py | 112 |
1 files changed, 110 insertions, 2 deletions
diff --git a/lib/model.py b/lib/model.py index 082fe8a..68286c9 100644 --- a/lib/model.py +++ b/lib/model.py @@ -10,6 +10,7 @@ from .functions import AnalyticFunction from .parameters import ParamStats from .utils import is_numeric, soft_cast_int, param_slice_eq, remove_index_from_tuple from .utils import by_name_to_by_param, match_parameter_values +from .utils import filter_aggregate_by_param logger = logging.getLogger(__name__) arg_support_enabled = True @@ -374,7 +375,7 @@ def _num_args_from_by_name(by_name): class AnalyticModel: - u""" + """ Parameter-aware analytic energy/data size/... model. Supports both static and parameter-based model attributes, and automatic detection of parameter-dependence. @@ -661,8 +662,115 @@ class AnalyticModel: pass +def grep_aggregate_by_state_and_param(aggregate, name, param_index, param_value): + new_aggregate = dict() + new_aggregate[name] = { + "attributes": aggregate[name]["attributes"], + } + + param_index = soft_cast_int(param_index) + indices_to_copy = list( + map(lambda x: x[param_index] == param_value, aggregate[name]["param"]) + ) + + if len(indices_to_copy) == 0: + raise RuntimeError("empty result") + + new_aggregate[name]["param"] = list( + map( + lambda iv: iv[1], + filter( + lambda iv: indices_to_copy[iv[0]], enumerate(aggregate[name]["param"]), + ), + ) + ) + + for attribute in aggregate[name]["attributes"]: + new_aggregate[name][attribute] = aggregate[name][attribute][indices_to_copy] + + return new_aggregate + + +class DecisionTreeModel: + def __init__(self, by_name, parameters): + self.by_name = by_name + self.by_param = by_name_to_by_param(by_name) + self.parameters = sorted(parameters) + + # Dtree-Konzept: Für jeden Param: Split auf ==wert1 / == wert2 (-> zwei Partitionen der Daten) + # Falls Menge beeinflussender Parameter in den beiden Partitionen unterschiedlich oder + # Art der Abhängigkeit unterschiedlich: Hiernach muss der DTree unterscheiden. + # Auswahl der ersten Ebene anhand TODO (Parameter, bei dem die beiden Partitionen den niedrigsten absolute static model error haben? + # Oder bei dem es die größte Anzahl unterschiedlciher Parameter / Abhängigkeitstypen gibt? So eine Gütefunktion wäre dafür nice) + + stats = ParamStats(self.by_name, self.by_param, self.parameters, dict(), False) + pre_candidates = list() + for state in self.states(): + for i, param in enumerate(self.parameters): + if len(stats.distinct_values[state][param]) == 2: + logger.debug(f"{state} has binary param {param}") + pre_candidates.append( + (state, i, param, stats.distinct_values[state][param]) + ) + + candidates = list() + for state, param_index, param_name, param_values in pre_candidates: + by_name_sub1 = grep_aggregate_by_state_and_param( + by_name, state, param_index, param_values[0] + ) + by_param_sub1 = by_name_to_by_param(by_name_sub1) + by_name_sub2 = grep_aggregate_by_state_and_param( + by_name, state, param_index, param_values[1] + ) + by_param_sub2 = by_name_to_by_param(by_name_sub2) + stats_sub1 = ParamStats( + by_name_sub1, by_param_sub1, self.parameters, dict(), False + ) + stats_sub2 = ParamStats( + by_name_sub2, by_param_sub2, self.parameters, dict(), False + ) + for attribute in by_name[state]["attributes"]: + param1 = stats_sub1.stats[state][attribute]["depends_on_params"] + param2 = stats_sub2.stats[state][attribute]["depends_on_params"] + if param1 != param2: + logger.debug( + f"{state} {attribute} by {param_name} is dtree candidate" + ) + logger.debug( + " {} == {} -> depends on {}".format( + param_name, param_values[0], param1 + ) + ) + logger.debug( + " {} == {} -> depends on {}".format( + param_name, param_values[1], param2 + ) + ) + candidates.append( + (state, attribute, param_index, param_name, param_values) + ) + + candidates_by_state_attribute = dict() + for state, attribute, param_index, param_name, param_values in candidates: + if (state, attribute) not in candidates_by_state_attribute: + candidates_by_state_attribute[(state, attribute)] = list() + candidates_by_state_attribute[(state, attribute)].append( + (param_index, param_name, param_values) + ) + + print(candidates_by_state_attribute) + + def states(self): + """Return sorted list of state names.""" + return sorted( + list( + filter(lambda k: self.by_name[k]["isa"] == "state", self.by_name.keys()) + ) + ) + + class PTAModel: - u""" + """ Parameter-aware PTA-based energy model. Supports both static and parameter-based model attributes, and automatic detection of parameter-dependence. |