binary-decision-diagram 4.0.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 +1 -0
- package/dist/cjs/src/branches.js +2 -1
- package/dist/cjs/src/branches.js.map +1 -1
- package/dist/cjs/src/create-bdd-from-truth-table.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 +5 -7
- 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 +1 -5
- 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 +14 -5
- 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 +1 -0
- package/dist/esm/src/branches.js +1 -0
- 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 +1 -5
- 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 +11 -9
- package/src/abstract-node.ts +7 -5
- package/src/branches.ts +2 -0
- 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 +2 -8
- 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 -59
- 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 -23
- 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 -57
- 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 -18
- 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 -15
- 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 -23
- package/src/minimal-string/string-format.ts +0 -67
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { ensureValidOrdering, naturalOrdering } from './dense-truth-table.js';
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic greedy construction:
|
|
4
|
+
* fills the levels from the top, at each level the boolean function
|
|
5
|
+
* that leads to the best BDD (with the other functions in their index order)
|
|
6
|
+
* is picked.
|
|
7
|
+
*/
|
|
8
|
+
export function greedyTopDownOrdering(evaluator) {
|
|
9
|
+
const n = evaluator.variableCount;
|
|
10
|
+
const prefix = [];
|
|
11
|
+
let remaining = naturalOrdering(n);
|
|
12
|
+
while (remaining.length > 1) {
|
|
13
|
+
let bestVar = -1;
|
|
14
|
+
let best = null;
|
|
15
|
+
for (const candidate of remaining) {
|
|
16
|
+
const ordering = prefix.concat([candidate], remaining.filter(v => v !== candidate));
|
|
17
|
+
const evaluation = evaluator.evaluate(ordering);
|
|
18
|
+
if (!best || evaluator.isBetter(evaluation, best)) {
|
|
19
|
+
best = evaluation;
|
|
20
|
+
bestVar = candidate;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
prefix.push(bestVar);
|
|
24
|
+
remaining = remaining.filter(v => v !== bestVar);
|
|
25
|
+
}
|
|
26
|
+
return prefix.concat(remaining);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Deterministic greedy construction from the bottom:
|
|
30
|
+
* at each step the boolean function that is best as the lowest
|
|
31
|
+
* remaining level is picked.
|
|
32
|
+
*/
|
|
33
|
+
export function greedyBottomUpOrdering(evaluator) {
|
|
34
|
+
const n = evaluator.variableCount;
|
|
35
|
+
let suffix = [];
|
|
36
|
+
let remaining = naturalOrdering(n);
|
|
37
|
+
while (remaining.length > 1) {
|
|
38
|
+
let bestVar = -1;
|
|
39
|
+
let best = null;
|
|
40
|
+
for (const candidate of remaining) {
|
|
41
|
+
const ordering = remaining.filter(v => v !== candidate).concat([candidate], suffix);
|
|
42
|
+
const evaluation = evaluator.evaluate(ordering);
|
|
43
|
+
if (!best || evaluator.isBetter(evaluation, best)) {
|
|
44
|
+
best = evaluation;
|
|
45
|
+
bestVar = candidate;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
suffix = [bestVar].concat(suffix);
|
|
49
|
+
remaining = remaining.filter(v => v !== bestVar);
|
|
50
|
+
}
|
|
51
|
+
return remaining.concat(suffix);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Lexicographically ordered permutations of 0..size-1
|
|
55
|
+
*/
|
|
56
|
+
function allPermutations(size) {
|
|
57
|
+
const ret = [];
|
|
58
|
+
const recurse = (prefix, rest) => {
|
|
59
|
+
if (rest.length === 0) {
|
|
60
|
+
ret.push(prefix);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
for (let i = 0; i < rest.length; i++) {
|
|
64
|
+
recurse(prefix.concat([rest[i]]), rest.slice(0, i).concat(rest.slice(i + 1)));
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
recurse([], naturalOrdering(size));
|
|
68
|
+
return ret;
|
|
69
|
+
}
|
|
70
|
+
export const DEFAULT_WINDOW_SIZE = 3;
|
|
71
|
+
export const DEFAULT_MAX_ROUNDS = 50;
|
|
72
|
+
/**
|
|
73
|
+
* Window permutation tries all w! orderings of every window of w levels,
|
|
74
|
+
* larger windows take too long.
|
|
75
|
+
*/
|
|
76
|
+
export const MAX_WINDOW_SIZE = 8;
|
|
77
|
+
export function ensureNonNegativeInteger(value, name) {
|
|
78
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
79
|
+
throw new Error(name + ' must be a non-negative integer');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export function ensureWindowSize(windowSize) {
|
|
83
|
+
ensureNonNegativeInteger(windowSize, 'windowSize');
|
|
84
|
+
if (windowSize > MAX_WINDOW_SIZE) {
|
|
85
|
+
throw new Error('windowSize must be at most ' + MAX_WINDOW_SIZE + ', window permutation tries windowSize! orderings per window');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Improves an ordering by sifting (moving each variable through all positions
|
|
90
|
+
* and keeping the best one) and exhaustive window permutation until no
|
|
91
|
+
* strict improvement is found anymore. "Better" is decided by
|
|
92
|
+
* OrderingEvaluator.isBetter(): fewer nodes, or with a cost model a lower
|
|
93
|
+
* expected cost. Everything is deterministic: the same input always gives
|
|
94
|
+
* the same output.
|
|
95
|
+
*/
|
|
96
|
+
export class LocalOrderingSearch {
|
|
97
|
+
evaluator;
|
|
98
|
+
best;
|
|
99
|
+
cursor;
|
|
100
|
+
n;
|
|
101
|
+
windowPermutations;
|
|
102
|
+
windowSize;
|
|
103
|
+
maxRounds;
|
|
104
|
+
onImprovement;
|
|
105
|
+
log;
|
|
106
|
+
constructor(evaluator, initialOrdering, options = {}) {
|
|
107
|
+
this.evaluator = evaluator;
|
|
108
|
+
this.n = evaluator.variableCount;
|
|
109
|
+
ensureValidOrdering(initialOrdering, this.n);
|
|
110
|
+
const windowSize = options.windowSize === undefined ? DEFAULT_WINDOW_SIZE : options.windowSize;
|
|
111
|
+
ensureWindowSize(windowSize);
|
|
112
|
+
const maxRounds = options.maxRounds === undefined ? DEFAULT_MAX_ROUNDS : options.maxRounds;
|
|
113
|
+
ensureNonNegativeInteger(maxRounds, 'maxRounds');
|
|
114
|
+
this.cursor = evaluator.cursor(initialOrdering);
|
|
115
|
+
this.best = this.cursor.evaluation;
|
|
116
|
+
this.windowSize = Math.min(windowSize, this.n);
|
|
117
|
+
// the identity permutation is the current state, no need to evaluate it again
|
|
118
|
+
this.windowPermutations = this.windowSize >= 2 ?
|
|
119
|
+
allPermutations(this.windowSize).filter(permutation => permutation.some((v, i) => v !== i)) :
|
|
120
|
+
[];
|
|
121
|
+
this.maxRounds = maxRounds;
|
|
122
|
+
this.onImprovement = options.onImprovement ? options.onImprovement : () => null;
|
|
123
|
+
this.log = options.log ? options.log : () => null;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* ordering[level] = boolean function tested on that level
|
|
127
|
+
*/
|
|
128
|
+
get ordering() {
|
|
129
|
+
return this.cursor.ordering;
|
|
130
|
+
}
|
|
131
|
+
result() {
|
|
132
|
+
return {
|
|
133
|
+
ordering: this.ordering.slice(),
|
|
134
|
+
nodeCount: this.best.nodeCount,
|
|
135
|
+
expectedCost: this.best.expectedCost,
|
|
136
|
+
nodesPerLevel: this.best.nodesPerLevel.slice(),
|
|
137
|
+
evaluation: this.best
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Runs sifting rounds and window permutation rounds
|
|
142
|
+
* until a full cycle gives no improvement.
|
|
143
|
+
*/
|
|
144
|
+
run() {
|
|
145
|
+
let round = 0;
|
|
146
|
+
while (round < this.maxRounds) {
|
|
147
|
+
round++;
|
|
148
|
+
const before = this.best;
|
|
149
|
+
this.siftRound();
|
|
150
|
+
if (this.windowSize >= 2) {
|
|
151
|
+
this.windowRound();
|
|
152
|
+
}
|
|
153
|
+
this.log('local search round ' + round + ': ' + this.describe(before) + ' -> ' + this.describe(this.best));
|
|
154
|
+
if (!this.evaluator.isBetter(this.best, before)) {
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return this.result();
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* One sifting round: each variable, largest level first,
|
|
162
|
+
* is moved to the position where the BDD is best.
|
|
163
|
+
* @returns true if the ordering improved
|
|
164
|
+
*/
|
|
165
|
+
siftRound() {
|
|
166
|
+
const startEvaluation = this.best;
|
|
167
|
+
const n = this.n;
|
|
168
|
+
const positionOf = (v) => this.ordering.indexOf(v);
|
|
169
|
+
const variables = this.ordering.slice().sort((a, b) => {
|
|
170
|
+
const diff = this.best.nodesPerLevel[positionOf(b)] - this.best.nodesPerLevel[positionOf(a)];
|
|
171
|
+
return diff !== 0 ? diff : a - b;
|
|
172
|
+
});
|
|
173
|
+
for (const variable of variables) {
|
|
174
|
+
const start = positionOf(variable);
|
|
175
|
+
let bestEvaluation = this.best;
|
|
176
|
+
let bestPosition = start;
|
|
177
|
+
let position = start;
|
|
178
|
+
const moveTo = (target) => {
|
|
179
|
+
while (position < target) {
|
|
180
|
+
this.swapAdjacent(position);
|
|
181
|
+
position++;
|
|
182
|
+
}
|
|
183
|
+
while (position > target) {
|
|
184
|
+
this.swapAdjacent(position - 1);
|
|
185
|
+
position--;
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
const sweep = (target) => {
|
|
189
|
+
while (position !== target) {
|
|
190
|
+
const step = position < target ? 1 : -1;
|
|
191
|
+
this.swapAdjacent(step === 1 ? position : position - 1);
|
|
192
|
+
position += step;
|
|
193
|
+
const evaluation = this.cursor.evaluation;
|
|
194
|
+
if (this.evaluator.isBetter(evaluation, bestEvaluation)) {
|
|
195
|
+
bestEvaluation = evaluation;
|
|
196
|
+
bestPosition = position;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
// go to the closer end first, then to the other end
|
|
201
|
+
if (start < n - 1 - start) {
|
|
202
|
+
sweep(0);
|
|
203
|
+
sweep(n - 1);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
sweep(n - 1);
|
|
207
|
+
sweep(0);
|
|
208
|
+
}
|
|
209
|
+
moveTo(bestPosition);
|
|
210
|
+
if (this.evaluator.isBetter(bestEvaluation, this.best)) {
|
|
211
|
+
this.best = bestEvaluation;
|
|
212
|
+
this.log('sifting: ' + this.describe(bestEvaluation));
|
|
213
|
+
this.onImprovement(this.progress('sifting'));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return this.evaluator.isBetter(this.best, startEvaluation);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* One window permutation round: for each window of adjacent levels
|
|
220
|
+
* all permutations of its variables are tried.
|
|
221
|
+
* @returns true if the ordering improved
|
|
222
|
+
*/
|
|
223
|
+
windowRound() {
|
|
224
|
+
const startEvaluation = this.best;
|
|
225
|
+
const w = this.windowSize;
|
|
226
|
+
if (w < 2) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
for (let windowStart = 0; windowStart + w <= this.n; windowStart++) {
|
|
230
|
+
const original = this.ordering.slice(windowStart, windowStart + w);
|
|
231
|
+
let bestEvaluation = this.best;
|
|
232
|
+
let bestPermutation = null;
|
|
233
|
+
for (const permutation of this.windowPermutations) {
|
|
234
|
+
this.setWindow(windowStart, original, permutation);
|
|
235
|
+
const evaluation = this.cursor.evaluation;
|
|
236
|
+
if (this.evaluator.isBetter(evaluation, bestEvaluation)) {
|
|
237
|
+
bestEvaluation = evaluation;
|
|
238
|
+
bestPermutation = permutation;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (bestPermutation) {
|
|
242
|
+
this.setWindow(windowStart, original, bestPermutation);
|
|
243
|
+
this.best = bestEvaluation;
|
|
244
|
+
this.log('window permutation: ' + this.describe(bestEvaluation));
|
|
245
|
+
this.onImprovement(this.progress('window'));
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
this.setWindow(windowStart, original, naturalOrdering(w));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return this.evaluator.isBetter(this.best, startEvaluation);
|
|
252
|
+
}
|
|
253
|
+
progress(phase) {
|
|
254
|
+
return {
|
|
255
|
+
ordering: this.ordering.slice(),
|
|
256
|
+
nodeCount: this.best.nodeCount,
|
|
257
|
+
expectedCost: this.best.expectedCost,
|
|
258
|
+
phase
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
describe(evaluation) {
|
|
262
|
+
return evaluation.nodeCount + ' nodes' +
|
|
263
|
+
(this.evaluator.costModel ? ', expected cost ' + evaluation.expectedCost : '');
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* swaps the variables of level and level+1
|
|
267
|
+
*/
|
|
268
|
+
swapAdjacent(level) {
|
|
269
|
+
this.swapLevels(level, level + 1);
|
|
270
|
+
}
|
|
271
|
+
swapLevels(levelA, levelB) {
|
|
272
|
+
this.cursor.swap(levelA, levelB);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Arranges the window so that level (windowStart + i) holds original[permutation[i]].
|
|
276
|
+
*/
|
|
277
|
+
setWindow(windowStart, original, permutation) {
|
|
278
|
+
for (let i = 0; i < permutation.length; i++) {
|
|
279
|
+
const wanted = original[permutation[i]];
|
|
280
|
+
const currentLevel = this.ordering.indexOf(wanted);
|
|
281
|
+
this.swapLevels(windowStart + i, currentLevel);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Deterministic start orderings for the local search.
|
|
287
|
+
*/
|
|
288
|
+
export function seedOrderings(evaluator) {
|
|
289
|
+
const n = evaluator.variableCount;
|
|
290
|
+
const natural = naturalOrdering(n);
|
|
291
|
+
const seeds = [
|
|
292
|
+
{ name: 'natural', ordering: natural },
|
|
293
|
+
{ name: 'reversed', ordering: natural.slice().reverse() },
|
|
294
|
+
{ name: 'greedy-top-down', ordering: greedyTopDownOrdering(evaluator) },
|
|
295
|
+
{ name: 'greedy-bottom-up', ordering: greedyBottomUpOrdering(evaluator) }
|
|
296
|
+
];
|
|
297
|
+
// remove duplicates, keep the first occurrence
|
|
298
|
+
const seen = new Set();
|
|
299
|
+
return seeds.filter(seed => {
|
|
300
|
+
const key = seed.ordering.join(',');
|
|
301
|
+
if (seen.has(key)) {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
seen.add(key);
|
|
305
|
+
return true;
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
//# sourceMappingURL=local-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-search.js","sourceRoot":"","sources":["../../../../src/ordering/local-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import type { TruthTable } from '../types.js';
|
|
2
|
+
import { RootNode } from '../root-node.js';
|
|
3
|
+
import { DenseTruthTable } from './dense-truth-table.js';
|
|
4
|
+
import { CostModel } from './ordering-evaluator.js';
|
|
5
|
+
import { OrderingProgressCallback } from './local-search.js';
|
|
6
|
+
export declare const DEFAULT_MAX_EXACT_VARIABLES = 20;
|
|
7
|
+
export declare const DEFAULT_MAX_EXACT_NODE_COUNT = 5000;
|
|
8
|
+
export interface FindOrderingInput {
|
|
9
|
+
truthTable: TruthTable;
|
|
10
|
+
/**
|
|
11
|
+
* Value of the rows that can never occur at runtime.
|
|
12
|
+
* These rows are resolved exactly like removeIrrelevantLeafNodes() does it:
|
|
13
|
+
* a branch that only leads to don't-care rows is replaced by its sibling.
|
|
14
|
+
* Which ordering profits most from that is part of the search, but the
|
|
15
|
+
* rule itself is a heuristic, not the smallest possible completion.
|
|
16
|
+
*/
|
|
17
|
+
dontCareValue?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Cost of calling each boolean function: functionCosts[i] belongs to the
|
|
20
|
+
* boolean function with index i (the i-th character of the truth table keys).
|
|
21
|
+
* When given, the optimizer minimizes the expected cost of one resolve() call,
|
|
22
|
+
* that is the sum of the costs of the boolean functions that are called on the
|
|
23
|
+
* way from the root to the leaf, averaged over the rows, instead of the amount
|
|
24
|
+
* of nodes. Among orderings with the same expected cost, fewer nodes are
|
|
25
|
+
* preferred (best effort, not part of the optimality proof).
|
|
26
|
+
*/
|
|
27
|
+
functionCosts?: number[];
|
|
28
|
+
/**
|
|
29
|
+
* How often each row occurs at runtime relative to the other rows,
|
|
30
|
+
* used together with functionCosts. Default: every row that is not a
|
|
31
|
+
* don't-care row occurs equally often. Don't-care rows never occur.
|
|
32
|
+
*/
|
|
33
|
+
rowWeight?: (key: string, value: number) => number;
|
|
34
|
+
/**
|
|
35
|
+
* Additional start orderings for the local search, for example the
|
|
36
|
+
* best ordering of a previous run. ordering[level] is the index
|
|
37
|
+
* of the boolean function tested at that level.
|
|
38
|
+
*/
|
|
39
|
+
initialOrderings?: number[][];
|
|
40
|
+
/**
|
|
41
|
+
* - 'auto' (default): run the exact search when the truth table has at
|
|
42
|
+
* most maxExactVariables boolean functions and the BDD found by the local
|
|
43
|
+
* search has at most maxExactNodeCount internal nodes (unstructured
|
|
44
|
+
* functions have big BDDs, and on them the exact search is slow and
|
|
45
|
+
* cannot gain much)
|
|
46
|
+
* - true: always run the exact search (within the budgets below)
|
|
47
|
+
* - false: never
|
|
48
|
+
*/
|
|
49
|
+
exact?: boolean | 'auto';
|
|
50
|
+
/** Default: 20 */
|
|
51
|
+
maxExactVariables?: number;
|
|
52
|
+
/** Default: 5000 */
|
|
53
|
+
maxExactNodeCount?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Budget of the exact search per candidate completion of the truth table.
|
|
56
|
+
* A candidate whose search exceeds it cannot be proven optimal.
|
|
57
|
+
* Default: 200000
|
|
58
|
+
*/
|
|
59
|
+
maxExactExpansions?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Memory budget of the exact search: the maximum amount of nodes of its
|
|
62
|
+
* internal diagram (roughly 100 bytes each).
|
|
63
|
+
* Default: 4000000
|
|
64
|
+
*/
|
|
65
|
+
maxExactDiagramNodes?: number;
|
|
66
|
+
/**
|
|
67
|
+
* Size of the windows the local search permutes exhaustively,
|
|
68
|
+
* at most 8 (the work grows with windowSize!).
|
|
69
|
+
* Default: 3
|
|
70
|
+
*/
|
|
71
|
+
windowSize?: number;
|
|
72
|
+
/**
|
|
73
|
+
* Maximum amount of sifting + window permutation rounds per start ordering.
|
|
74
|
+
* Default: 50
|
|
75
|
+
*/
|
|
76
|
+
maxRounds?: number;
|
|
77
|
+
log?: boolean;
|
|
78
|
+
/** called whenever a better ordering was found */
|
|
79
|
+
onImprovement?: OrderingProgressCallback;
|
|
80
|
+
}
|
|
81
|
+
export interface FindOrderingResult {
|
|
82
|
+
/** ordering[level] = index of the boolean function tested at that level */
|
|
83
|
+
ordering: number[];
|
|
84
|
+
/** amount of nodes of the BDD, as RootNode.countNodes() returns it */
|
|
85
|
+
nodeCount: number;
|
|
86
|
+
/**
|
|
87
|
+
* Expected cost of one resolve() call with the returned ordering,
|
|
88
|
+
* only set when functionCosts were given.
|
|
89
|
+
*/
|
|
90
|
+
expectedCost?: number;
|
|
91
|
+
/**
|
|
92
|
+
* true when the exact search has proven that no other ordering gives a
|
|
93
|
+
* BDD with fewer nodes (or, with functionCosts, a lower expected cost)
|
|
94
|
+
* for the truth table in `truthTable`. With don't-care rows that is one
|
|
95
|
+
* completion of the input: another ordering can occasionally reach a smaller
|
|
96
|
+
* BDD by resolving the don't-care rows differently.
|
|
97
|
+
*/
|
|
98
|
+
optimal: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* The truth table the BDD represents: the input table with the don't-care
|
|
101
|
+
* rows resolved, with the same keys as the input (iterated in row order).
|
|
102
|
+
* createBddWithOrdering(result.truthTable, result.ordering) rebuilds the BDD.
|
|
103
|
+
* When don't-care rows exist, this completion can differ from the one that
|
|
104
|
+
* createBddWithOrdering(input, result.ordering, dontCareValue) would pick.
|
|
105
|
+
*/
|
|
106
|
+
truthTable: TruthTable;
|
|
107
|
+
stats: OptimizeOrderingStats;
|
|
108
|
+
}
|
|
109
|
+
export interface OptimizeOrderingStats {
|
|
110
|
+
/** amount of orderings that were evaluated */
|
|
111
|
+
evaluations: number;
|
|
112
|
+
/** amount of states the exact search expanded */
|
|
113
|
+
exactExpansions: number;
|
|
114
|
+
/** the amount of nodes found by the local search alone */
|
|
115
|
+
localSearchNodeCount: number;
|
|
116
|
+
durationMs: number;
|
|
117
|
+
}
|
|
118
|
+
export interface OptimizeOrderingInput extends FindOrderingInput {
|
|
119
|
+
/**
|
|
120
|
+
* Hook that runs on the created BDD before it is minimized,
|
|
121
|
+
* for compatibility with optimizeBruteForce().
|
|
122
|
+
* The optimizer cannot account for what the hook does, so prefer dontCareValue
|
|
123
|
+
* over removeIrrelevantLeafNodes() in the hook. When the hook changes the BDD,
|
|
124
|
+
* `optimal` is false, and `truthTable` and `expectedCost` describe the BDD
|
|
125
|
+
* before the hook.
|
|
126
|
+
*/
|
|
127
|
+
afterBddCreation?: (bdd: RootNode) => void;
|
|
128
|
+
}
|
|
129
|
+
export interface OptimizeOrderingResult extends FindOrderingResult {
|
|
130
|
+
bdd: RootNode;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Validates functionCosts and rowWeight and turns them into a cost model.
|
|
134
|
+
*/
|
|
135
|
+
export declare function buildCostModel(table: DenseTruthTable, functionCosts?: number[], rowWeight?: (key: string, value: number) => number): CostModel | null;
|
|
136
|
+
/**
|
|
137
|
+
* Deterministically finds a variable ordering with a small BDD
|
|
138
|
+
* (or, with functionCosts, with a cheap resolve() call).
|
|
139
|
+
* See docs/variable-ordering.md for how it works.
|
|
140
|
+
* Does not create BDD nodes, use optimizeOrdering() for that.
|
|
141
|
+
*/
|
|
142
|
+
export declare function findOrdering(input: FindOrderingInput): FindOrderingResult;
|
|
143
|
+
/**
|
|
144
|
+
* Deterministic replacement for optimizeBruteForce():
|
|
145
|
+
* finds a good variable ordering and returns the minimized BDD for it.
|
|
146
|
+
* All work is synchronous, the promise exists for compatibility with optimizeBruteForce().
|
|
147
|
+
*/
|
|
148
|
+
export declare function optimizeOrdering(input: OptimizeOrderingInput): Promise<OptimizeOrderingResult>;
|
|
149
|
+
/**
|
|
150
|
+
* Creates the minimized BDD of a truth table for a given ordering
|
|
151
|
+
* without going through the unreduced decision tree.
|
|
152
|
+
*/
|
|
153
|
+
export declare function createBddWithOrdering(truthTable: TruthTable, ordering: ArrayLike<number>, dontCareValue?: number): RootNode;
|