binary-decision-diagram
Version:
A library to create, minimize and optimize binary decision diagrams
157 lines • 5.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RootNode = void 0;
const abstract_node_js_1 = require("./abstract-node.js");
const branches_js_1 = require("./branches.js");
const util_js_1 = require("./util.js");
const index_js_1 = require("./minimal-string/index.js");
class RootNode extends abstract_node_js_1.AbstractNode {
branches = new branches_js_1.Branches(this);
levels = [];
nodesByLevel = new Map();
constructor() {
super(0, null, 'RootNode');
this.levels.push(0);
const level0Set = new Set();
level0Set.add(this);
this.nodesByLevel.set(0, level0Set);
}
addNode(node) {
const level = node.level;
if (!this.levels.includes(level)) {
this.levels.push(level);
}
this.ensureLevelSetExists(level);
const set = this.nodesByLevel.get(level);
set?.add(node);
}
removeNode(node) {
const set = this.nodesByLevel.get(node.level);
if (!set.has(node)) {
throw new Error('removed non-existing node ' + node.id);
}
set.delete(node);
}
ensureLevelSetExists(level) {
if (!this.nodesByLevel.has(level)) {
this.nodesByLevel.set(level, new Set());
}
}
getLevels() {
return Array.from(this.levels).sort((a, b) => a - b);
}
getNodesOfLevel(level) {
this.ensureLevelSetExists(level);
const set = this.nodesByLevel.get(level);
return Array.from(set);
}
countNodes() {
let ret = 0;
this.getLevels().forEach(level => {
const nodesAmount = this.getNodesOfLevel(level).length;
ret = ret + nodesAmount;
});
return ret;
}
/**
* applies the reduction rules to the whole bdd
*/
minimize(logState = false) {
// console.log('minimize(): START ###############');
let done = false;
while (!done) {
if (logState) {
console.log('minimize() itterate once');
}
let successCount = 0;
let lastLevel = (0, util_js_1.lastOfArray)(this.getLevels());
while (lastLevel > 0) {
const nodes = this.getNodesOfLevel(lastLevel);
if (logState) {
console.log('minimize() run for level ' + lastLevel +
' with ' + nodes.length + ' nodes');
// console.dir(nodes);
}
let nodeCount = 0;
for (const node of nodes) {
nodeCount++;
// do not run that often because it is expensive
if (logState && nodeCount % 4000 === 0) {
console.log('minimize() node #' + node.id);
}
if (node.isLeafNode()) {
// console.log('have leaf node ' + node.id);
const reductionDone = node.asLeafNode().applyEliminationRule();
if (reductionDone) {
successCount++;
}
}
if (!node.deleted && node.isInternalNode()) {
const useNode = node;
const reductionDone = useNode.applyReductionRule();
let eliminationDone = false;
if (!useNode.deleted) {
// not might now be deleted from reduction-rule
eliminationDone = useNode.applyEliminationRule(nodes);
}
if (reductionDone || eliminationDone) {
successCount++;
}
}
}
lastLevel--;
}
if (successCount === 0) {
// could do no more optimisations
done = true;
}
else {
if (logState) {
console.log('minimize() itteration done with ' +
successCount + ' minimisations');
}
}
}
}
getLeafNodes() {
const lastLevel = (0, util_js_1.lastOfArray)(this.getLevels());
const leafNodes = this.getNodesOfLevel(lastLevel).reverse();
return leafNodes;
}
/**
* strips all leaf-nodes
* with the given value
*/
removeIrrelevantLeafNodes(leafNodeValue) {
let done = false;
while (!done) {
let countRemoved = 0;
const leafNodes = this.getLeafNodes();
for (const leafNode of leafNodes) {
const removed = leafNode.removeIfValueEquals(leafNodeValue);
if (removed) {
countRemoved++;
}
}
this.minimize();
if (countRemoved === 0) {
done = true;
}
}
}
resolve(fns, booleanFunctionInput) {
let currentNode = this;
while (true) {
const booleanResult = fns[currentNode.level](booleanFunctionInput);
currentNode = currentNode.branches.data[booleanResult ? '1' : '0'];
if (currentNode.type === 'LeafNode') {
return currentNode.value;
}
}
}
toSimpleBdd() {
return (0, index_js_1.bddToSimpleBdd)(this);
}
}
exports.RootNode = RootNode;
//# sourceMappingURL=root-node.js.map