summaryrefslogtreecommitdiff
path: root/bin/model-config.py
diff options
context:
space:
mode:
authorDaniel Friesel <daniel.friesel@uos.de>2020-09-09 11:22:17 +0200
committerDaniel Friesel <daniel.friesel@uos.de>2020-09-09 11:22:17 +0200
commit963be43fe272e330df2f49eb55957aea1b90e579 (patch)
tree3b00f1a9406e1cbd91233f7fc1bdd77829fb4205 /bin/model-config.py
parent8b969f4945e97d811b7a5b27c99b76cf2dd2840b (diff)
add basic decisiontree model for binary kconfig files
Diffstat (limited to 'bin/model-config.py')
-rwxr-xr-xbin/model-config.py115
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])