summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/utils.py62
1 files changed, 46 insertions, 16 deletions
diff --git a/lib/utils.py b/lib/utils.py
index b496a7b..e9e347e 100644
--- a/lib/utils.py
+++ b/lib/utils.py
@@ -3,6 +3,7 @@ import numpy as np
arg_support_enabled = True
def is_numeric(n):
+ """Check if n is numeric (i.e., can be converted to int)."""
if n == None:
return False
try:
@@ -25,15 +26,44 @@ def param_slice_eq(a, b, index):
example:
('foo', [1, 4]), ('foo', [2, 4]), 0 -> True
('foo', [1, 4]), ('foo', [2, 4]), 1 -> False
+
"""
if (*a[1][:index], *a[1][index+1:]) == (*b[1][:index], *b[1][index+1:]) and a[0] == b[0]:
return True
return False
-def compute_param_statistics(by_name, by_param, parameter_names, num_args, state_or_trans, key):
+def compute_param_statistics(by_name, by_param, parameter_names, arg_count, state_or_trans, attribute):
+ """
+ Compute standard deviation and correlation coefficient for various data partitions.
+
+ arguments:
+ by_name -- ground truth partitioned by state/transition name.
+ by_name[state_or_trans][attribute] must be a list or 1-D numpy array.
+ by_param -- ground truth partitioned by state/transition name and parameters.
+ by_name[(state_or_trans, *)][attribute] must be a list or 1-D numpy array.
+ parameter_names -- list of parameter names, must have the same order as the parameter
+ values in by_param (lexical sorting is recommended).
+ arg_count -- dict providing the number of functions args ("local parameters") for each function.
+ state_or_trans -- state or transition name, e.g. 'send' or 'TX'
+ attribute -- model attribute, e.g. 'power' or 'duration'
+
+ returns a dict with the following content:
+ std_static -- static parameter-unaware model error: stddev of by_name[state_or_trans][attribute]
+ std_param_lut -- static parameter-aware model error: mean stddev of by_param[(state_or_trans, *)][attribute]
+ std_by_param -- static parameter-aware model error ignoring a single parameter.
+ dictionary with one key per parameter. The value is the mean stddev
+ of measurements where all other parameters are fixed and the parameter
+ in question is variable. E.g. std_by_param['X'] is the mean stddev of
+ by_param[(state_or_trans, (X=*, Y=..., Z=...))][attribute].
+ std_by_arg -- same, but ignoring a single function argument
+ Only set if state_or_trans appears in arg_count, empty dict otherwise.
+ corr_by_param -- correlation coefficient
+ corr_by_arg -- same, but ignoring a single function argument
+ Only set if state_or_trans appears in arg_count, empty dict otherwise.
+ """
ret = {
- 'std_static' : np.std(by_name[state_or_trans][key]),
- 'std_param_lut' : np.mean([np.std(by_param[x][key]) for x in by_param.keys() if x[0] == state_or_trans]),
+ 'std_static' : np.std(by_name[state_or_trans][attribute]),
+ 'std_param_lut' : np.mean([np.std(by_param[x][attribute]) for x in by_param.keys() if x[0] == state_or_trans]),
'std_by_param' : {},
'std_by_arg' : [],
'corr_by_param' : {},
@@ -41,27 +71,27 @@ def compute_param_statistics(by_name, by_param, parameter_names, num_args, state
}
for param_idx, param in enumerate(parameter_names):
- ret['std_by_param'][param] = _mean_std_by_param(by_param, state_or_trans, key, param_idx)
- ret['corr_by_param'][param] = _corr_by_param(by_name, state_or_trans, key, param_idx)
- if arg_support_enabled and state_or_trans in num_args:
- for arg_index in range(num_args[state_or_trans]):
- ret['std_by_arg'].append(_mean_std_by_param(by_param, state_or_trans, key, len(parameter_names) + arg_index))
- ret['corr_by_arg'].append(_corr_by_param(by_name, state_or_trans, key, len(parameter_names) + arg_index))
+ ret['std_by_param'][param] = _mean_std_by_param(by_param, state_or_trans, attribute, param_idx)
+ ret['corr_by_param'][param] = _corr_by_param(by_name, state_or_trans, attribute, param_idx)
+ if arg_support_enabled and state_or_trans in arg_count:
+ for arg_index in range(arg_count[state_or_trans]):
+ ret['std_by_arg'].append(_mean_std_by_param(by_param, state_or_trans, attribute, len(parameter_names) + arg_index))
+ ret['corr_by_arg'].append(_corr_by_param(by_name, state_or_trans, attribute, len(parameter_names) + arg_index))
return ret
-def _mean_std_by_param(by_param, state_or_tran, key, param_index):
+def _mean_std_by_param(by_param, state_or_tran, attribute, param_index):
u"""
Calculate the mean standard deviation for a static model where all parameters but param_index are constant.
arguments:
by_param -- measurements sorted by key/transition name and parameter values
state_or_tran -- state or transition name (-> by_param[(state_or_tran, *)])
- key -- model attribute, e.g. 'power' or 'duration'
- (-> by_param[(state_or_tran, *)][key])
+ attribute -- model attribute, e.g. 'power' or 'duration'
+ (-> by_param[(state_or_tran, *)][attribute])
param_index -- index of variable parameter
- Returns the mean standard deviation of all measurements of 'key'
+ Returns the mean standard deviation of all measurements of 'attribute'
(e.g. power consumption or timeout) for state/transition 'state_or_tran' where
parameter 'param_index' is dynamic and all other parameters are fixed.
I.e., if parameters are a, b, c ∈ {1,2,3} and 'index' corresponds to b, then
@@ -73,18 +103,18 @@ def _mean_std_by_param(by_param, state_or_tran, key, param_index):
param_partition = []
for k, v in by_param.items():
if param_slice_eq(k, param_value, param_index):
- param_partition.extend(v[key])
+ param_partition.extend(v[attribute])
if len(param_partition):
partitions.append(param_partition)
else:
print('[W] parameter value partition for {} is empty'.format(param_value))
return np.mean([np.std(partition) for partition in partitions])
-def _corr_by_param(by_name, state_or_trans, key, param_index):
+def _corr_by_param(by_name, state_or_trans, attribute, param_index):
if _all_params_are_numeric(by_name[state_or_trans], param_index):
param_values = np.array(list((map(lambda x: x[param_index], by_name[state_or_trans]['param']))))
try:
- return np.corrcoef(by_name[state_or_trans][key], param_values)[0, 1]
+ return np.corrcoef(by_name[state_or_trans][attribute], param_values)[0, 1]
except FloatingPointError as fpe:
# Typically happens when all parameter values are identical.
# Building a correlation coefficient is pointless in this case