binary-decision-diagram 3.2.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +211 -31
- package/dist/cjs/src/abstract-node.js +7 -4
- package/dist/cjs/src/abstract-node.js.map +1 -1
- package/dist/cjs/src/branches.d.ts +4 -1
- package/dist/cjs/src/branches.js +10 -9
- package/dist/cjs/src/branches.js.map +1 -1
- package/dist/cjs/src/create-bdd-from-truth-table.js +1 -2
- package/dist/cjs/src/create-bdd-from-truth-table.js.map +1 -1
- package/dist/cjs/src/ensure-correct-bdd.js +2 -3
- package/dist/cjs/src/ensure-correct-bdd.js.map +1 -1
- package/dist/cjs/src/fill-truth-table.js +1 -2
- package/dist/cjs/src/fill-truth-table.js.map +1 -1
- package/dist/cjs/src/find-similar-node.js +1 -2
- package/dist/cjs/src/find-similar-node.js.map +1 -1
- package/dist/cjs/src/index.d.ts +2 -1
- package/dist/cjs/src/index.es5.js +17 -7
- package/dist/cjs/src/index.es5.js.map +1 -1
- package/dist/cjs/src/index.js +2 -1
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/internal-node.js +6 -3
- package/dist/cjs/src/internal-node.js.map +1 -1
- package/dist/cjs/src/optimize-brute-force.js +10 -12
- package/dist/cjs/src/optimize-brute-force.js.map +1 -1
- package/dist/cjs/src/ordering/build-bdd.d.ts +13 -0
- package/dist/cjs/src/ordering/build-bdd.js +64 -0
- package/dist/cjs/src/ordering/build-bdd.js.map +1 -0
- package/dist/cjs/src/ordering/dense-truth-table.d.ts +42 -0
- package/dist/cjs/src/ordering/dense-truth-table.js +125 -0
- package/dist/cjs/src/ordering/dense-truth-table.js.map +1 -0
- package/dist/cjs/src/ordering/exact-cost-ordering.d.ts +91 -0
- package/dist/cjs/src/ordering/exact-cost-ordering.js +351 -0
- package/dist/cjs/src/ordering/exact-cost-ordering.js.map +1 -0
- package/dist/cjs/src/ordering/exact-ordering.d.ts +89 -0
- package/dist/cjs/src/ordering/exact-ordering.js +260 -0
- package/dist/cjs/src/ordering/exact-ordering.js.map +1 -0
- package/dist/cjs/src/ordering/index.d.ts +22 -0
- package/dist/cjs/src/ordering/index.js +38 -0
- package/dist/cjs/src/ordering/index.js.map +1 -0
- package/dist/cjs/src/ordering/int-pair-map.d.ts +20 -0
- package/dist/cjs/src/ordering/int-pair-map.js +85 -0
- package/dist/cjs/src/ordering/int-pair-map.js.map +1 -0
- package/dist/cjs/src/ordering/local-search.d.ts +114 -0
- package/dist/cjs/src/ordering/local-search.js +317 -0
- package/dist/cjs/src/ordering/local-search.js.map +1 -0
- package/dist/cjs/src/ordering/optimize-ordering.d.ts +153 -0
- package/dist/cjs/src/ordering/optimize-ordering.js +406 -0
- package/dist/cjs/src/ordering/optimize-ordering.js.map +1 -0
- package/dist/cjs/src/ordering/ordering-evaluator.d.ts +198 -0
- package/dist/cjs/src/ordering/ordering-evaluator.js +384 -0
- package/dist/cjs/src/ordering/ordering-evaluator.js.map +1 -0
- package/dist/cjs/src/ordering/shared-diagram.d.ts +85 -0
- package/dist/cjs/src/ordering/shared-diagram.js +295 -0
- package/dist/cjs/src/ordering/shared-diagram.js.map +1 -0
- package/dist/cjs/src/packed/index.d.ts +2 -0
- package/dist/cjs/src/{minimal-string → packed}/index.js +2 -5
- package/dist/cjs/src/packed/index.js.map +1 -0
- package/dist/cjs/src/packed/packed-bdd-base64-string.d.ts +3 -0
- package/dist/cjs/src/packed/packed-bdd-base64-string.js +46 -0
- package/dist/cjs/src/packed/packed-bdd-base64-string.js.map +1 -0
- package/dist/cjs/src/packed/packed-bdd.d.ts +13 -0
- package/dist/cjs/src/packed/packed-bdd.js +70 -0
- package/dist/cjs/src/packed/packed-bdd.js.map +1 -0
- package/dist/cjs/src/root-node.d.ts +1 -2
- package/dist/cjs/src/root-node.js +4 -9
- package/dist/cjs/src/root-node.js.map +1 -1
- package/dist/cjs/src/types.d.ts +0 -12
- package/dist/cjs/src/util.js +29 -21
- package/dist/cjs/src/util.js.map +1 -1
- package/dist/esm/src/abstract-node.js +7 -4
- package/dist/esm/src/abstract-node.js.map +1 -1
- package/dist/esm/src/branches.d.ts +4 -1
- package/dist/esm/src/branches.js +8 -7
- package/dist/esm/src/branches.js.map +1 -1
- package/dist/esm/src/create-bdd-from-truth-table.js.map +1 -1
- package/dist/esm/src/index.d.ts +2 -1
- package/dist/esm/src/index.js +2 -1
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/internal-node.js +7 -4
- package/dist/esm/src/internal-node.js.map +1 -1
- package/dist/esm/src/optimize-brute-force.js +5 -7
- package/dist/esm/src/optimize-brute-force.js.map +1 -1
- package/dist/esm/src/ordering/build-bdd.d.ts +13 -0
- package/dist/esm/src/ordering/build-bdd.js +61 -0
- package/dist/esm/src/ordering/build-bdd.js.map +1 -0
- package/dist/esm/src/ordering/dense-truth-table.d.ts +42 -0
- package/dist/esm/src/ordering/dense-truth-table.js +117 -0
- package/dist/esm/src/ordering/dense-truth-table.js.map +1 -0
- package/dist/esm/src/ordering/exact-cost-ordering.d.ts +91 -0
- package/dist/esm/src/ordering/exact-cost-ordering.js +347 -0
- package/dist/esm/src/ordering/exact-cost-ordering.js.map +1 -0
- package/dist/esm/src/ordering/exact-ordering.d.ts +89 -0
- package/dist/esm/src/ordering/exact-ordering.js +256 -0
- package/dist/esm/src/ordering/exact-ordering.js.map +1 -0
- package/dist/esm/src/ordering/index.d.ts +22 -0
- package/dist/esm/src/ordering/index.js +17 -0
- package/dist/esm/src/ordering/index.js.map +1 -0
- package/dist/esm/src/ordering/int-pair-map.d.ts +20 -0
- package/dist/esm/src/ordering/int-pair-map.js +81 -0
- package/dist/esm/src/ordering/int-pair-map.js.map +1 -0
- package/dist/esm/src/ordering/local-search.d.ts +114 -0
- package/dist/esm/src/ordering/local-search.js +308 -0
- package/dist/esm/src/ordering/local-search.js.map +1 -0
- package/dist/esm/src/ordering/optimize-ordering.d.ts +153 -0
- package/dist/esm/src/ordering/optimize-ordering.js +399 -0
- package/dist/esm/src/ordering/optimize-ordering.js.map +1 -0
- package/dist/esm/src/ordering/ordering-evaluator.d.ts +198 -0
- package/dist/esm/src/ordering/ordering-evaluator.js +377 -0
- package/dist/esm/src/ordering/ordering-evaluator.js.map +1 -0
- package/dist/esm/src/ordering/shared-diagram.d.ts +85 -0
- package/dist/esm/src/ordering/shared-diagram.js +289 -0
- package/dist/esm/src/ordering/shared-diagram.js.map +1 -0
- package/dist/esm/src/packed/index.d.ts +2 -0
- package/dist/esm/src/packed/index.js +3 -0
- package/dist/esm/src/packed/index.js.map +1 -0
- package/dist/esm/src/packed/packed-bdd-base64-string.d.ts +3 -0
- package/dist/esm/src/packed/packed-bdd-base64-string.js +42 -0
- package/dist/esm/src/packed/packed-bdd-base64-string.js.map +1 -0
- package/dist/esm/src/packed/packed-bdd.d.ts +13 -0
- package/dist/esm/src/packed/packed-bdd.js +66 -0
- package/dist/esm/src/packed/packed-bdd.js.map +1 -0
- package/dist/esm/src/root-node.d.ts +1 -2
- package/dist/esm/src/root-node.js +5 -10
- package/dist/esm/src/root-node.js.map +1 -1
- package/dist/esm/src/types.d.ts +0 -12
- package/dist/esm/src/util.js +14 -5
- package/dist/esm/src/util.js.map +1 -1
- package/docs/variable-ordering.md +306 -0
- package/package.json +15 -12
- package/src/abstract-node.ts +7 -5
- package/src/branches.ts +9 -7
- package/src/create-bdd-from-truth-table.ts +1 -1
- package/src/index.ts +2 -1
- package/src/internal-node.ts +7 -4
- package/src/optimize-brute-force.ts +5 -7
- package/src/ordering/build-bdd.ts +70 -0
- package/src/ordering/dense-truth-table.ts +161 -0
- package/src/ordering/exact-cost-ordering.ts +425 -0
- package/src/ordering/exact-ordering.ts +317 -0
- package/src/ordering/index.ts +57 -0
- package/src/ordering/int-pair-map.ts +85 -0
- package/src/ordering/local-search.ts +369 -0
- package/src/ordering/optimize-ordering.ts +570 -0
- package/src/ordering/ordering-evaluator.ts +479 -0
- package/src/ordering/shared-diagram.ts +310 -0
- package/src/packed/index.ts +2 -0
- package/src/packed/packed-bdd-base64-string.ts +47 -0
- package/src/packed/packed-bdd.ts +98 -0
- package/src/root-node.ts +8 -17
- package/src/types.ts +0 -18
- package/src/util.ts +15 -6
- package/dist/cjs/src/minimal-string/bdd-to-minimal-string.d.ts +0 -8
- package/dist/cjs/src/minimal-string/bdd-to-minimal-string.js +0 -60
- package/dist/cjs/src/minimal-string/bdd-to-minimal-string.js.map +0 -1
- package/dist/cjs/src/minimal-string/bdd-to-simple-bdd.d.ts +0 -11
- package/dist/cjs/src/minimal-string/bdd-to-simple-bdd.js +0 -24
- package/dist/cjs/src/minimal-string/bdd-to-simple-bdd.js.map +0 -1
- package/dist/cjs/src/minimal-string/index.d.ts +0 -5
- package/dist/cjs/src/minimal-string/index.js.map +0 -1
- package/dist/cjs/src/minimal-string/minimal-string-to-simple-bdd.d.ts +0 -2
- package/dist/cjs/src/minimal-string/minimal-string-to-simple-bdd.js +0 -58
- package/dist/cjs/src/minimal-string/minimal-string-to-simple-bdd.js.map +0 -1
- package/dist/cjs/src/minimal-string/resolve-with-simple-bdd.d.ts +0 -2
- package/dist/cjs/src/minimal-string/resolve-with-simple-bdd.js +0 -21
- package/dist/cjs/src/minimal-string/resolve-with-simple-bdd.js.map +0 -1
- package/dist/cjs/src/minimal-string/string-format.d.ts +0 -9
- package/dist/cjs/src/minimal-string/string-format.js +0 -61
- package/dist/cjs/src/minimal-string/string-format.js.map +0 -1
- package/dist/esm/src/minimal-string/bdd-to-minimal-string.d.ts +0 -8
- package/dist/esm/src/minimal-string/bdd-to-minimal-string.js +0 -55
- package/dist/esm/src/minimal-string/bdd-to-minimal-string.js.map +0 -1
- package/dist/esm/src/minimal-string/bdd-to-simple-bdd.d.ts +0 -11
- package/dist/esm/src/minimal-string/bdd-to-simple-bdd.js +0 -19
- package/dist/esm/src/minimal-string/bdd-to-simple-bdd.js.map +0 -1
- package/dist/esm/src/minimal-string/index.d.ts +0 -5
- package/dist/esm/src/minimal-string/index.js +0 -6
- package/dist/esm/src/minimal-string/index.js.map +0 -1
- package/dist/esm/src/minimal-string/minimal-string-to-simple-bdd.d.ts +0 -2
- package/dist/esm/src/minimal-string/minimal-string-to-simple-bdd.js +0 -54
- package/dist/esm/src/minimal-string/minimal-string-to-simple-bdd.js.map +0 -1
- package/dist/esm/src/minimal-string/resolve-with-simple-bdd.d.ts +0 -2
- package/dist/esm/src/minimal-string/resolve-with-simple-bdd.js +0 -17
- package/dist/esm/src/minimal-string/resolve-with-simple-bdd.js.map +0 -1
- package/dist/esm/src/minimal-string/string-format.d.ts +0 -9
- package/dist/esm/src/minimal-string/string-format.js +0 -54
- package/dist/esm/src/minimal-string/string-format.js.map +0 -1
- package/src/minimal-string/bdd-to-minimal-string.ts +0 -72
- package/src/minimal-string/bdd-to-simple-bdd.ts +0 -31
- package/src/minimal-string/index.ts +0 -5
- package/src/minimal-string/minimal-string-to-simple-bdd.ts +0 -67
- package/src/minimal-string/resolve-with-simple-bdd.ts +0 -25
- package/src/minimal-string/string-format.ts +0 -67
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { naturalOrdering } from './dense-truth-table.js';
|
|
2
|
+
import { OrderingEvaluator } from './ordering-evaluator.js';
|
|
3
|
+
import { SharedDiagram, StateHeap, DiagramBudgetExceededError, DEFAULT_MAX_DIAGRAM_NODES } from './shared-diagram.js';
|
|
4
|
+
/**
|
|
5
|
+
* The number of nodes on a level of a reduced BDD only depends on the SET of
|
|
6
|
+
* variables above that level, not on their order (Friedman & Supowit, 1990):
|
|
7
|
+
* it is the amount of distinct cofactors with respect to that set that still
|
|
8
|
+
* depend on the level's variable.
|
|
9
|
+
*
|
|
10
|
+
* Therefore the optimal ordering is a shortest path through the lattice of
|
|
11
|
+
* variable subsets, from the empty set to the full set, where the edge
|
|
12
|
+
* S -> S + {x} costs the amount of nodes that test x when exactly the
|
|
13
|
+
* variables of S are above it.
|
|
14
|
+
*
|
|
15
|
+
* This class finds that shortest path with an A* search. Each subset S is
|
|
16
|
+
* represented by the set of its distinct non-constant cofactors, which are
|
|
17
|
+
* nodes of one shared hash-consed diagram in the natural variable order
|
|
18
|
+
* (so equal functions always have equal ids). The admissible estimate for the
|
|
19
|
+
* remaining cost of a subset is the amount of its distinct non-constant
|
|
20
|
+
* cofactors: each of them needs its own node below.
|
|
21
|
+
*
|
|
22
|
+
* With a good upper bound (from the local search) the search typically only
|
|
23
|
+
* has to look at a tiny fraction of the 2^n subsets.
|
|
24
|
+
*/
|
|
25
|
+
export class ExactOrderingSearch {
|
|
26
|
+
table;
|
|
27
|
+
diagram;
|
|
28
|
+
n;
|
|
29
|
+
terminalCount;
|
|
30
|
+
constructor(table, options = {}) {
|
|
31
|
+
this.table = table;
|
|
32
|
+
if (table.dontCareTerminal >= 0) {
|
|
33
|
+
throw new Error('the exact search needs a truth table without don\'t-care rows, resolve them with OrderingEvaluator.complete() first');
|
|
34
|
+
}
|
|
35
|
+
this.diagram = new SharedDiagram(table, options.maxDiagramNodes === undefined ? DEFAULT_MAX_DIAGRAM_NODES : options.maxDiagramNodes);
|
|
36
|
+
this.n = table.variableCount;
|
|
37
|
+
this.terminalCount = table.terminalValues.length;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Moves the boolean functions the truth table does not depend on
|
|
41
|
+
* to the bottom. This never changes the amount of internal nodes
|
|
42
|
+
* but ensures the root node tests a relevant boolean function.
|
|
43
|
+
*/
|
|
44
|
+
normalizeOrdering(ordering) {
|
|
45
|
+
return this.diagram.normalizeOrdering(ordering);
|
|
46
|
+
}
|
|
47
|
+
run(options = {}) {
|
|
48
|
+
const log = options.log ? options.log : () => null;
|
|
49
|
+
const maxExpansions = options.maxExpansions === undefined ? 200000 : options.maxExpansions;
|
|
50
|
+
const maxCofactorEntries = options.maxCofactorEntries === undefined ? Math.pow(2, 25) : options.maxCofactorEntries;
|
|
51
|
+
const diagram = this.diagram;
|
|
52
|
+
const relevant = diagram.relevant;
|
|
53
|
+
const m = relevant.length;
|
|
54
|
+
const irrelevant = diagram.irrelevantVariables();
|
|
55
|
+
// upper bound
|
|
56
|
+
let upperBound = options.upperBound === undefined ? Infinity : options.upperBound;
|
|
57
|
+
let incumbent = null;
|
|
58
|
+
if (options.upperBoundOrdering) {
|
|
59
|
+
incumbent = this.normalizeOrdering(options.upperBoundOrdering);
|
|
60
|
+
const incumbentCount = new OrderingEvaluator(this.table).evaluate(incumbent).internalNodeCount;
|
|
61
|
+
if (incumbentCount >= upperBound) {
|
|
62
|
+
// the numeric bound is at least as good, the incumbent cannot be the answer
|
|
63
|
+
incumbent = null;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
upperBound = incumbentCount;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const giveUp = (reason, expansionCount, generatedCount) => {
|
|
70
|
+
log('exact search: ' + reason);
|
|
71
|
+
return {
|
|
72
|
+
solved: false,
|
|
73
|
+
ordering: incumbent,
|
|
74
|
+
internalNodeCount: incumbent ? upperBound : -1,
|
|
75
|
+
expansions: expansionCount,
|
|
76
|
+
generated: generatedCount
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
if (diagram.overBudget) {
|
|
80
|
+
return giveUp('diagram budget exceeded', 0, 0);
|
|
81
|
+
}
|
|
82
|
+
if (m === 0) {
|
|
83
|
+
// constant function: every ordering has 0 internal nodes
|
|
84
|
+
const constantOrdering = upperBound > 0 ? naturalOrdering(this.n) : incumbent;
|
|
85
|
+
return {
|
|
86
|
+
solved: true,
|
|
87
|
+
ordering: constantOrdering,
|
|
88
|
+
internalNodeCount: constantOrdering ? 0 : -1,
|
|
89
|
+
expansions: 0,
|
|
90
|
+
generated: 0
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const full = (1 << m) - 1;
|
|
94
|
+
const cofactors = new Map();
|
|
95
|
+
const bestCost = new Map();
|
|
96
|
+
const parentVariable = new Map();
|
|
97
|
+
const closed = new Set();
|
|
98
|
+
const heap = new StateHeap();
|
|
99
|
+
const startSet = new Int32Array(1);
|
|
100
|
+
startSet[0] = diagram.rootId;
|
|
101
|
+
cofactors.set(0, startSet);
|
|
102
|
+
bestCost.set(0, 0);
|
|
103
|
+
heap.push(this.estimate(0, startSet), 0, 0);
|
|
104
|
+
let expansions = 0;
|
|
105
|
+
let generated = 1;
|
|
106
|
+
let storedEntries = 1;
|
|
107
|
+
let solvedSet = -1;
|
|
108
|
+
let solvedCost = -1;
|
|
109
|
+
try {
|
|
110
|
+
while (heap.size > 0) {
|
|
111
|
+
const state = heap.pop();
|
|
112
|
+
const currentCost = state.cost;
|
|
113
|
+
const subset = state.subset;
|
|
114
|
+
if (currentCost !== bestCost.get(subset) || closed.has(subset)) {
|
|
115
|
+
// stale heap entry
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (state.estimate >= upperBound) {
|
|
119
|
+
// nothing left that can beat the upper bound
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
if (subset === full) {
|
|
123
|
+
solvedSet = subset;
|
|
124
|
+
solvedCost = currentCost;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
closed.add(subset);
|
|
128
|
+
expansions++;
|
|
129
|
+
if (expansions > maxExpansions) {
|
|
130
|
+
return giveUp('expansion budget exceeded', expansions, generated);
|
|
131
|
+
}
|
|
132
|
+
if (storedEntries > maxCofactorEntries) {
|
|
133
|
+
return giveUp('memory budget exceeded', expansions, generated);
|
|
134
|
+
}
|
|
135
|
+
if (expansions % 10000 === 0) {
|
|
136
|
+
log('exact search: ' + expansions + ' states expanded, ' + generated + ' generated, ' + heap.size + ' open');
|
|
137
|
+
}
|
|
138
|
+
const set = cofactors.get(subset);
|
|
139
|
+
for (let c = 0; c < m; c++) {
|
|
140
|
+
const bit = 1 << c;
|
|
141
|
+
if ((subset & bit) !== 0) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const variable = relevant[c];
|
|
145
|
+
let edgeCost = 0;
|
|
146
|
+
for (let i = 0; i < set.length; i++) {
|
|
147
|
+
if ((diagram.supportOf(set[i]) & bit) !== 0) {
|
|
148
|
+
edgeCost++;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const nextCost = currentCost + edgeCost;
|
|
152
|
+
const nextSubset = subset | bit;
|
|
153
|
+
const knownCost = bestCost.get(nextSubset);
|
|
154
|
+
if (knownCost !== undefined && knownCost <= nextCost) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
let nextSet = cofactors.get(nextSubset);
|
|
158
|
+
if (nextSet === undefined) {
|
|
159
|
+
nextSet = this.cofactorsAfter(set, variable);
|
|
160
|
+
cofactors.set(nextSubset, nextSet);
|
|
161
|
+
generated++;
|
|
162
|
+
storedEntries += nextSet.length;
|
|
163
|
+
}
|
|
164
|
+
const estimate = nextCost + this.estimate(nextSubset, nextSet);
|
|
165
|
+
if (estimate >= upperBound) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
bestCost.set(nextSubset, nextCost);
|
|
169
|
+
parentVariable.set(nextSubset, variable);
|
|
170
|
+
closed.delete(nextSubset);
|
|
171
|
+
heap.push(estimate, nextCost, nextSubset);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
if (err instanceof DiagramBudgetExceededError) {
|
|
177
|
+
return giveUp('diagram budget exceeded', expansions, generated);
|
|
178
|
+
}
|
|
179
|
+
throw err;
|
|
180
|
+
}
|
|
181
|
+
if (solvedSet === -1) {
|
|
182
|
+
// no ordering below the upper bound exists: the incumbent (if any) is optimal
|
|
183
|
+
return {
|
|
184
|
+
solved: true,
|
|
185
|
+
ordering: incumbent,
|
|
186
|
+
internalNodeCount: incumbent ? upperBound : -1,
|
|
187
|
+
expansions,
|
|
188
|
+
generated
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
// reconstruct the path
|
|
192
|
+
const reversed = [];
|
|
193
|
+
let remainingSubset = solvedSet;
|
|
194
|
+
while (remainingSubset !== 0) {
|
|
195
|
+
const variable = parentVariable.get(remainingSubset);
|
|
196
|
+
reversed.push(variable);
|
|
197
|
+
remainingSubset = remainingSubset & ~(1 << diagram.compactOf[variable]);
|
|
198
|
+
}
|
|
199
|
+
const ordering = reversed.reverse().concat(irrelevant);
|
|
200
|
+
return {
|
|
201
|
+
solved: true,
|
|
202
|
+
ordering,
|
|
203
|
+
internalNodeCount: solvedCost,
|
|
204
|
+
expansions,
|
|
205
|
+
generated
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* lower bound for the amount of nodes below the given subset
|
|
210
|
+
*/
|
|
211
|
+
estimate(subset, set) {
|
|
212
|
+
let union = 0;
|
|
213
|
+
for (let i = 0; i < set.length; i++) {
|
|
214
|
+
union |= this.diagram.supportOf(set[i]);
|
|
215
|
+
}
|
|
216
|
+
const remaining = union & ~subset;
|
|
217
|
+
let remainingCount = 0;
|
|
218
|
+
for (let x = remaining; x !== 0; x &= x - 1) {
|
|
219
|
+
remainingCount++;
|
|
220
|
+
}
|
|
221
|
+
return Math.max(set.length, remainingCount);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* the distinct non-constant cofactors after additionally fixing `variable`
|
|
225
|
+
*/
|
|
226
|
+
cofactorsAfter(set, variable) {
|
|
227
|
+
const diagram = this.diagram;
|
|
228
|
+
const bit = 1 << diagram.compactOf[variable];
|
|
229
|
+
const candidates = new Int32Array(set.length * 2);
|
|
230
|
+
let count = 0;
|
|
231
|
+
for (let i = 0; i < set.length; i++) {
|
|
232
|
+
const g = set[i];
|
|
233
|
+
if ((diagram.supportOf(g) & bit) === 0) {
|
|
234
|
+
candidates[count++] = g;
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
const lo = diagram.restrict(g, variable, 0);
|
|
238
|
+
if (lo >= this.terminalCount) {
|
|
239
|
+
candidates[count++] = lo;
|
|
240
|
+
}
|
|
241
|
+
const hi = diagram.restrict(g, variable, 1);
|
|
242
|
+
if (hi >= this.terminalCount) {
|
|
243
|
+
candidates[count++] = hi;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const sorted = candidates.subarray(0, count).sort();
|
|
247
|
+
let unique = 0;
|
|
248
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
249
|
+
if (i === 0 || sorted[i] !== sorted[i - 1]) {
|
|
250
|
+
sorted[unique++] = sorted[i];
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return sorted.slice(0, unique);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=exact-ordering.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exact-ordering.js","sourceRoot":"","sources":["../../../../src/ordering/exact-ordering.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API of the variable ordering optimizer, see docs/variable-ordering.md.
|
|
3
|
+
*
|
|
4
|
+
* - optimize-ordering.ts: optimizeOrdering(), findOrdering(), createBddWithOrdering()
|
|
5
|
+
* - ordering-evaluator.ts: counts the nodes (and the expected cost) of any ordering in O(2^n)
|
|
6
|
+
* - local-search.ts: deterministic seeds, sifting and window permutation
|
|
7
|
+
* - exact-ordering.ts, exact-cost-ordering.ts: A* searches that prove optimality
|
|
8
|
+
* - shared-diagram.ts: the shared function diagram the exact searches work on
|
|
9
|
+
* - dense-truth-table.ts, build-bdd.ts, int-pair-map.ts: data structures and helpers
|
|
10
|
+
*/
|
|
11
|
+
export { optimizeOrdering, findOrdering, createBddWithOrdering, buildCostModel, DEFAULT_MAX_EXACT_VARIABLES, DEFAULT_MAX_EXACT_NODE_COUNT } from './optimize-ordering.js';
|
|
12
|
+
export type { FindOrderingInput, FindOrderingResult, OptimizeOrderingInput, OptimizeOrderingResult, OptimizeOrderingStats } from './optimize-ordering.js';
|
|
13
|
+
export { OrderingEvaluator, OrderingCursor } from './ordering-evaluator.js';
|
|
14
|
+
export type { CostModel, OrderingEvaluation, ReducedDiagram } from './ordering-evaluator.js';
|
|
15
|
+
export { LocalOrderingSearch, DEFAULT_WINDOW_SIZE, DEFAULT_MAX_ROUNDS, MAX_WINDOW_SIZE } from './local-search.js';
|
|
16
|
+
export type { LocalSearchOptions, OrderingSearchResult, OrderingProgress, OrderingProgressCallback } from './local-search.js';
|
|
17
|
+
export { ExactOrderingSearch } from './exact-ordering.js';
|
|
18
|
+
export type { ExactOrderingOptions, ExactOrderingResult } from './exact-ordering.js';
|
|
19
|
+
export { ExactCostOrderingSearch } from './exact-cost-ordering.js';
|
|
20
|
+
export type { ExactCostOrderingOptions, ExactCostOrderingResult } from './exact-cost-ordering.js';
|
|
21
|
+
export { parseTruthTable, denseTruthTableToMap, naturalOrdering, MAX_VARIABLE_COUNT } from './dense-truth-table.js';
|
|
22
|
+
export type { DenseTruthTable } from './dense-truth-table.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API of the variable ordering optimizer, see docs/variable-ordering.md.
|
|
3
|
+
*
|
|
4
|
+
* - optimize-ordering.ts: optimizeOrdering(), findOrdering(), createBddWithOrdering()
|
|
5
|
+
* - ordering-evaluator.ts: counts the nodes (and the expected cost) of any ordering in O(2^n)
|
|
6
|
+
* - local-search.ts: deterministic seeds, sifting and window permutation
|
|
7
|
+
* - exact-ordering.ts, exact-cost-ordering.ts: A* searches that prove optimality
|
|
8
|
+
* - shared-diagram.ts: the shared function diagram the exact searches work on
|
|
9
|
+
* - dense-truth-table.ts, build-bdd.ts, int-pair-map.ts: data structures and helpers
|
|
10
|
+
*/
|
|
11
|
+
export { optimizeOrdering, findOrdering, createBddWithOrdering, buildCostModel, DEFAULT_MAX_EXACT_VARIABLES, DEFAULT_MAX_EXACT_NODE_COUNT } from './optimize-ordering.js';
|
|
12
|
+
export { OrderingEvaluator, OrderingCursor } from './ordering-evaluator.js';
|
|
13
|
+
export { LocalOrderingSearch, DEFAULT_WINDOW_SIZE, DEFAULT_MAX_ROUNDS, MAX_WINDOW_SIZE } from './local-search.js';
|
|
14
|
+
export { ExactOrderingSearch } from './exact-ordering.js';
|
|
15
|
+
export { ExactCostOrderingSearch } from './exact-cost-ordering.js';
|
|
16
|
+
export { parseTruthTable, denseTruthTableToMap, naturalOrdering, MAX_VARIABLE_COUNT } from './dense-truth-table.js';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/ordering/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EACH,gBAAgB,EAChB,YAAY,EACZ,qBAAqB,EACrB,cAAc,EACd,2BAA2B,EAC3B,4BAA4B,EAC/B,MAAM,wBAAwB,CAAC;AAQhC,OAAO,EACH,iBAAiB,EACjB,cAAc,EACjB,MAAM,yBAAyB,CAAC;AAMjC,OAAO,EACH,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EAClB,MAAM,mBAAmB,CAAC;AAO3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EACH,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EACrB,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Open addressing hash map from a pair of non-negative 32 bit integers
|
|
3
|
+
* to a non-negative 32 bit integer. Used in the hot paths of the exact search
|
|
4
|
+
* where a Map with string keys would be far too slow.
|
|
5
|
+
*/
|
|
6
|
+
export declare class IntPairMap {
|
|
7
|
+
size: number;
|
|
8
|
+
private keysA;
|
|
9
|
+
private keysB;
|
|
10
|
+
private values;
|
|
11
|
+
private mask;
|
|
12
|
+
constructor(initialCapacity?: number);
|
|
13
|
+
/**
|
|
14
|
+
* @returns the stored value or -1
|
|
15
|
+
*/
|
|
16
|
+
get(a: number, b: number): number;
|
|
17
|
+
set(a: number, b: number, value: number): void;
|
|
18
|
+
private hash;
|
|
19
|
+
private grow;
|
|
20
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Open addressing hash map from a pair of non-negative 32 bit integers
|
|
3
|
+
* to a non-negative 32 bit integer. Used in the hot paths of the exact search
|
|
4
|
+
* where a Map with string keys would be far too slow.
|
|
5
|
+
*/
|
|
6
|
+
export class IntPairMap {
|
|
7
|
+
size = 0;
|
|
8
|
+
keysA;
|
|
9
|
+
keysB;
|
|
10
|
+
values;
|
|
11
|
+
mask;
|
|
12
|
+
constructor(initialCapacity = 1024) {
|
|
13
|
+
let capacity = 16;
|
|
14
|
+
while (capacity < initialCapacity) {
|
|
15
|
+
capacity *= 2;
|
|
16
|
+
}
|
|
17
|
+
this.keysA = new Int32Array(capacity).fill(-1);
|
|
18
|
+
this.keysB = new Int32Array(capacity);
|
|
19
|
+
this.values = new Int32Array(capacity);
|
|
20
|
+
this.mask = capacity - 1;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* @returns the stored value or -1
|
|
24
|
+
*/
|
|
25
|
+
get(a, b) {
|
|
26
|
+
let h = this.hash(a, b);
|
|
27
|
+
while (true) {
|
|
28
|
+
const storedA = this.keysA[h];
|
|
29
|
+
if (storedA === -1) {
|
|
30
|
+
return -1;
|
|
31
|
+
}
|
|
32
|
+
if (storedA === a && this.keysB[h] === b) {
|
|
33
|
+
return this.values[h];
|
|
34
|
+
}
|
|
35
|
+
h = (h + 1) & this.mask;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
set(a, b, value) {
|
|
39
|
+
if ((this.size + 1) * 2 > this.keysA.length) {
|
|
40
|
+
this.grow();
|
|
41
|
+
}
|
|
42
|
+
let h = this.hash(a, b);
|
|
43
|
+
while (true) {
|
|
44
|
+
const storedA = this.keysA[h];
|
|
45
|
+
if (storedA === -1) {
|
|
46
|
+
this.keysA[h] = a;
|
|
47
|
+
this.keysB[h] = b;
|
|
48
|
+
this.values[h] = value;
|
|
49
|
+
this.size++;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (storedA === a && this.keysB[h] === b) {
|
|
53
|
+
this.values[h] = value;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
h = (h + 1) & this.mask;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
hash(a, b) {
|
|
60
|
+
let h = (Math.imul(a, 0x9E3779B1) ^ Math.imul(b + 0x7F4A7C15, 0x85EBCA77)) >>> 0;
|
|
61
|
+
h ^= h >>> 15;
|
|
62
|
+
return h & this.mask;
|
|
63
|
+
}
|
|
64
|
+
grow() {
|
|
65
|
+
const oldA = this.keysA;
|
|
66
|
+
const oldB = this.keysB;
|
|
67
|
+
const oldValues = this.values;
|
|
68
|
+
const capacity = oldA.length * 2;
|
|
69
|
+
this.keysA = new Int32Array(capacity).fill(-1);
|
|
70
|
+
this.keysB = new Int32Array(capacity);
|
|
71
|
+
this.values = new Int32Array(capacity);
|
|
72
|
+
this.mask = capacity - 1;
|
|
73
|
+
this.size = 0;
|
|
74
|
+
for (let i = 0; i < oldA.length; i++) {
|
|
75
|
+
if (oldA[i] !== -1) {
|
|
76
|
+
this.set(oldA[i], oldB[i], oldValues[i]);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=int-pair-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"int-pair-map.js","sourceRoot":"","sources":["../../../../src/ordering/int-pair-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { OrderingEvaluator, OrderingEvaluation } from './ordering-evaluator.js';
|
|
2
|
+
export interface OrderingProgress {
|
|
3
|
+
ordering: number[];
|
|
4
|
+
nodeCount: number;
|
|
5
|
+
/** 0 without cost model */
|
|
6
|
+
expectedCost: number;
|
|
7
|
+
phase: string;
|
|
8
|
+
}
|
|
9
|
+
export type OrderingProgressCallback = (progress: OrderingProgress) => void;
|
|
10
|
+
export interface LocalSearchOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Size of the windows whose variables are permuted exhaustively.
|
|
13
|
+
* 0 or 1 disables window permutation. The work grows with windowSize!,
|
|
14
|
+
* so at most MAX_WINDOW_SIZE (8) is allowed.
|
|
15
|
+
* Default: 3
|
|
16
|
+
*/
|
|
17
|
+
windowSize?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Maximum amount of sifting rounds.
|
|
20
|
+
* Default: 50
|
|
21
|
+
*/
|
|
22
|
+
maxRounds?: number;
|
|
23
|
+
onImprovement?: OrderingProgressCallback;
|
|
24
|
+
log?: (message: string) => void;
|
|
25
|
+
}
|
|
26
|
+
export interface OrderingSearchResult {
|
|
27
|
+
ordering: number[];
|
|
28
|
+
nodeCount: number;
|
|
29
|
+
expectedCost: number;
|
|
30
|
+
nodesPerLevel: number[];
|
|
31
|
+
evaluation: OrderingEvaluation;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Deterministic greedy construction:
|
|
35
|
+
* fills the levels from the top, at each level the boolean function
|
|
36
|
+
* that leads to the best BDD (with the other functions in their index order)
|
|
37
|
+
* is picked.
|
|
38
|
+
*/
|
|
39
|
+
export declare function greedyTopDownOrdering(evaluator: OrderingEvaluator): number[];
|
|
40
|
+
/**
|
|
41
|
+
* Deterministic greedy construction from the bottom:
|
|
42
|
+
* at each step the boolean function that is best as the lowest
|
|
43
|
+
* remaining level is picked.
|
|
44
|
+
*/
|
|
45
|
+
export declare function greedyBottomUpOrdering(evaluator: OrderingEvaluator): number[];
|
|
46
|
+
export declare const DEFAULT_WINDOW_SIZE = 3;
|
|
47
|
+
export declare const DEFAULT_MAX_ROUNDS = 50;
|
|
48
|
+
/**
|
|
49
|
+
* Window permutation tries all w! orderings of every window of w levels,
|
|
50
|
+
* larger windows take too long.
|
|
51
|
+
*/
|
|
52
|
+
export declare const MAX_WINDOW_SIZE = 8;
|
|
53
|
+
export declare function ensureNonNegativeInteger(value: number, name: string): void;
|
|
54
|
+
export declare function ensureWindowSize(windowSize: number): void;
|
|
55
|
+
/**
|
|
56
|
+
* Improves an ordering by sifting (moving each variable through all positions
|
|
57
|
+
* and keeping the best one) and exhaustive window permutation until no
|
|
58
|
+
* strict improvement is found anymore. "Better" is decided by
|
|
59
|
+
* OrderingEvaluator.isBetter(): fewer nodes, or with a cost model a lower
|
|
60
|
+
* expected cost. Everything is deterministic: the same input always gives
|
|
61
|
+
* the same output.
|
|
62
|
+
*/
|
|
63
|
+
export declare class LocalOrderingSearch {
|
|
64
|
+
private readonly evaluator;
|
|
65
|
+
best: OrderingEvaluation;
|
|
66
|
+
private readonly cursor;
|
|
67
|
+
private readonly n;
|
|
68
|
+
private readonly windowPermutations;
|
|
69
|
+
private readonly windowSize;
|
|
70
|
+
private readonly maxRounds;
|
|
71
|
+
private readonly onImprovement;
|
|
72
|
+
private readonly log;
|
|
73
|
+
constructor(evaluator: OrderingEvaluator, initialOrdering: ArrayLike<number>, options?: LocalSearchOptions);
|
|
74
|
+
/**
|
|
75
|
+
* ordering[level] = boolean function tested on that level
|
|
76
|
+
*/
|
|
77
|
+
get ordering(): number[];
|
|
78
|
+
result(): OrderingSearchResult;
|
|
79
|
+
/**
|
|
80
|
+
* Runs sifting rounds and window permutation rounds
|
|
81
|
+
* until a full cycle gives no improvement.
|
|
82
|
+
*/
|
|
83
|
+
run(): OrderingSearchResult;
|
|
84
|
+
/**
|
|
85
|
+
* One sifting round: each variable, largest level first,
|
|
86
|
+
* is moved to the position where the BDD is best.
|
|
87
|
+
* @returns true if the ordering improved
|
|
88
|
+
*/
|
|
89
|
+
siftRound(): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* One window permutation round: for each window of adjacent levels
|
|
92
|
+
* all permutations of its variables are tried.
|
|
93
|
+
* @returns true if the ordering improved
|
|
94
|
+
*/
|
|
95
|
+
windowRound(): boolean;
|
|
96
|
+
private progress;
|
|
97
|
+
private describe;
|
|
98
|
+
/**
|
|
99
|
+
* swaps the variables of level and level+1
|
|
100
|
+
*/
|
|
101
|
+
private swapAdjacent;
|
|
102
|
+
private swapLevels;
|
|
103
|
+
/**
|
|
104
|
+
* Arranges the window so that level (windowStart + i) holds original[permutation[i]].
|
|
105
|
+
*/
|
|
106
|
+
private setWindow;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Deterministic start orderings for the local search.
|
|
110
|
+
*/
|
|
111
|
+
export declare function seedOrderings(evaluator: OrderingEvaluator): {
|
|
112
|
+
name: string;
|
|
113
|
+
ordering: number[];
|
|
114
|
+
}[];
|