#!/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"" 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"" 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])