diff options
author | Daniel Friesel <daniel.friesel@uos.de> | 2020-09-09 11:22:17 +0200 |
---|---|---|
committer | Daniel Friesel <daniel.friesel@uos.de> | 2020-09-09 11:22:17 +0200 |
commit | 963be43fe272e330df2f49eb55957aea1b90e579 (patch) | |
tree | 3b00f1a9406e1cbd91233f7fc1bdd77829fb4205 /bin/model-config.py | |
parent | 8b969f4945e97d811b7a5b27c99b76cf2dd2840b (diff) |
add basic decisiontree model for binary kconfig files
Diffstat (limited to 'bin/model-config.py')
-rwxr-xr-x | bin/model-config.py | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/bin/model-config.py b/bin/model-config.py new file mode 100755 index 0000000..9e86d4a --- /dev/null +++ b/bin/model-config.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 + +import json +import kconfiglib +import logging +import os +import sys + +import numpy as np + +numeric_level = getattr(logging, "DEBUG", None) +if not isinstance(numeric_level, int): + print(f"Invalid log level: {loglevel}", file=sys.stderr) + sys.exit(1) +logging.basicConfig(level=numeric_level) + +kconfig_path = "/tmp/multipass/Kconfig" +configs_base = "/tmp/multipass-model" + +kconf = kconfiglib.Kconfig(kconfig_path) + +symbols = sorted( + map( + lambda sym: sym.name, + filter( + lambda sym: kconfiglib.TYPE_TO_STR[sym.type] == "bool", kconf.syms.values() + ), + ) +) +config_vector = tuple(map(lambda sym: kconf.syms[sym].tri_value == 2, symbols)) + +with open("kconfigmodel.json", "r") as f: + data = json.load(f) + +assert symbols == data["symbols"] + +model = data["model"] + +kconf.load_config(sys.argv[1]) + + +class DTreeLeaf: + def __init__(self, value, stddev): + self.value = value + self.stddev = stddev + + def __repr__(self): + return f"<DTreeLeaf({self.value}, {self.stddev})>" + + def model(self, kconf): + return self.value + + +class DTreeNode: + def __init__(self, symbol, false_child=None, true_child=None): + self.symbol = symbol + self.false_child = false_child + self.true_child = true_child + + def set_false_child(self, child_node): + self.false_child = child_node + + def set_true_child(self, child_node): + self.true_child = child_node + + def __repr__(self): + return f"<DTreeNode({self.false_child}, {self.true_child})>" + + def model(self, kconf): + if kconf.syms[self.symbol].tri_value == 2 and self.true_child: + return self.true_child.model(kconf) + elif kconf.syms[self.symbol].tri_value == 0 and self.false_child: + return self.false_child.model(kconf) + return None + + +def load_model(tree): + if tree is None: + return None + if "value" in tree: + return DTreeLeaf(tree["value"], tree["stddev"]) + return DTreeNode( + tree["symbol"], load_model(tree["false"]), load_model(tree["true"]) + ) + + +root = load_model(model) + + +def vector_diff(v1, v2): + return sum(map(lambda i: int(v1[i] != v2[i]), range(len(v1)))) + + +current_model = root.model(kconf) +print(f"Model result: {current_model}") + +for symbol in symbols: + kconf_sym = kconf.syms[symbol] + if kconf_sym.tri_value == 0 and 2 in kconf_sym.assignable: + kconf_sym.set_value(2) + new_vector = tuple(map(lambda sym: kconf.syms[sym].tri_value == 2, symbols)) + num_changes = vector_diff(config_vector, new_vector) + model_diff = root.model(kconf) - current_model + print( + f"Setting {symbol:30s} to y changes {num_changes:2d} symbols, model change: {model_diff:+5.0f}" + ) + elif kconf_sym.tri_value == 2 and 0 in kconf_sym.assignable: + kconf_sym.set_value(0) + new_vector = tuple(map(lambda sym: kconf.syms[sym].tri_value == 2, symbols)) + num_changes = vector_diff(config_vector, new_vector) + model_diff = root.model(kconf) - current_model + print( + f"Setting {symbol:30s} to n changes {num_changes:2d} symbols, model change: {model_diff:+5.0f}" + ) + kconf.load_config(sys.argv[1]) |