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.
Files changed (185) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +211 -31
  3. package/dist/cjs/src/abstract-node.js +7 -4
  4. package/dist/cjs/src/abstract-node.js.map +1 -1
  5. package/dist/cjs/src/branches.d.ts +1 -0
  6. package/dist/cjs/src/branches.js +2 -1
  7. package/dist/cjs/src/branches.js.map +1 -1
  8. package/dist/cjs/src/create-bdd-from-truth-table.js.map +1 -1
  9. package/dist/cjs/src/index.d.ts +2 -1
  10. package/dist/cjs/src/index.es5.js +17 -7
  11. package/dist/cjs/src/index.es5.js.map +1 -1
  12. package/dist/cjs/src/index.js +2 -1
  13. package/dist/cjs/src/index.js.map +1 -1
  14. package/dist/cjs/src/internal-node.js +6 -3
  15. package/dist/cjs/src/internal-node.js.map +1 -1
  16. package/dist/cjs/src/optimize-brute-force.js +5 -7
  17. package/dist/cjs/src/optimize-brute-force.js.map +1 -1
  18. package/dist/cjs/src/ordering/build-bdd.d.ts +13 -0
  19. package/dist/cjs/src/ordering/build-bdd.js +64 -0
  20. package/dist/cjs/src/ordering/build-bdd.js.map +1 -0
  21. package/dist/cjs/src/ordering/dense-truth-table.d.ts +42 -0
  22. package/dist/cjs/src/ordering/dense-truth-table.js +125 -0
  23. package/dist/cjs/src/ordering/dense-truth-table.js.map +1 -0
  24. package/dist/cjs/src/ordering/exact-cost-ordering.d.ts +91 -0
  25. package/dist/cjs/src/ordering/exact-cost-ordering.js +351 -0
  26. package/dist/cjs/src/ordering/exact-cost-ordering.js.map +1 -0
  27. package/dist/cjs/src/ordering/exact-ordering.d.ts +89 -0
  28. package/dist/cjs/src/ordering/exact-ordering.js +260 -0
  29. package/dist/cjs/src/ordering/exact-ordering.js.map +1 -0
  30. package/dist/cjs/src/ordering/index.d.ts +22 -0
  31. package/dist/cjs/src/ordering/index.js +38 -0
  32. package/dist/cjs/src/ordering/index.js.map +1 -0
  33. package/dist/cjs/src/ordering/int-pair-map.d.ts +20 -0
  34. package/dist/cjs/src/ordering/int-pair-map.js +85 -0
  35. package/dist/cjs/src/ordering/int-pair-map.js.map +1 -0
  36. package/dist/cjs/src/ordering/local-search.d.ts +114 -0
  37. package/dist/cjs/src/ordering/local-search.js +317 -0
  38. package/dist/cjs/src/ordering/local-search.js.map +1 -0
  39. package/dist/cjs/src/ordering/optimize-ordering.d.ts +153 -0
  40. package/dist/cjs/src/ordering/optimize-ordering.js +406 -0
  41. package/dist/cjs/src/ordering/optimize-ordering.js.map +1 -0
  42. package/dist/cjs/src/ordering/ordering-evaluator.d.ts +198 -0
  43. package/dist/cjs/src/ordering/ordering-evaluator.js +384 -0
  44. package/dist/cjs/src/ordering/ordering-evaluator.js.map +1 -0
  45. package/dist/cjs/src/ordering/shared-diagram.d.ts +85 -0
  46. package/dist/cjs/src/ordering/shared-diagram.js +295 -0
  47. package/dist/cjs/src/ordering/shared-diagram.js.map +1 -0
  48. package/dist/cjs/src/packed/index.d.ts +2 -0
  49. package/dist/cjs/src/{minimal-string → packed}/index.js +2 -5
  50. package/dist/cjs/src/packed/index.js.map +1 -0
  51. package/dist/cjs/src/packed/packed-bdd-base64-string.d.ts +3 -0
  52. package/dist/cjs/src/packed/packed-bdd-base64-string.js +46 -0
  53. package/dist/cjs/src/packed/packed-bdd-base64-string.js.map +1 -0
  54. package/dist/cjs/src/packed/packed-bdd.d.ts +13 -0
  55. package/dist/cjs/src/packed/packed-bdd.js +70 -0
  56. package/dist/cjs/src/packed/packed-bdd.js.map +1 -0
  57. package/dist/cjs/src/root-node.d.ts +1 -2
  58. package/dist/cjs/src/root-node.js +1 -5
  59. package/dist/cjs/src/root-node.js.map +1 -1
  60. package/dist/cjs/src/types.d.ts +0 -12
  61. package/dist/cjs/src/util.js +14 -5
  62. package/dist/cjs/src/util.js.map +1 -1
  63. package/dist/esm/src/abstract-node.js +7 -4
  64. package/dist/esm/src/abstract-node.js.map +1 -1
  65. package/dist/esm/src/branches.d.ts +1 -0
  66. package/dist/esm/src/branches.js +1 -0
  67. package/dist/esm/src/branches.js.map +1 -1
  68. package/dist/esm/src/create-bdd-from-truth-table.js.map +1 -1
  69. package/dist/esm/src/index.d.ts +2 -1
  70. package/dist/esm/src/index.js +2 -1
  71. package/dist/esm/src/index.js.map +1 -1
  72. package/dist/esm/src/internal-node.js +7 -4
  73. package/dist/esm/src/internal-node.js.map +1 -1
  74. package/dist/esm/src/optimize-brute-force.js +5 -7
  75. package/dist/esm/src/optimize-brute-force.js.map +1 -1
  76. package/dist/esm/src/ordering/build-bdd.d.ts +13 -0
  77. package/dist/esm/src/ordering/build-bdd.js +61 -0
  78. package/dist/esm/src/ordering/build-bdd.js.map +1 -0
  79. package/dist/esm/src/ordering/dense-truth-table.d.ts +42 -0
  80. package/dist/esm/src/ordering/dense-truth-table.js +117 -0
  81. package/dist/esm/src/ordering/dense-truth-table.js.map +1 -0
  82. package/dist/esm/src/ordering/exact-cost-ordering.d.ts +91 -0
  83. package/dist/esm/src/ordering/exact-cost-ordering.js +347 -0
  84. package/dist/esm/src/ordering/exact-cost-ordering.js.map +1 -0
  85. package/dist/esm/src/ordering/exact-ordering.d.ts +89 -0
  86. package/dist/esm/src/ordering/exact-ordering.js +256 -0
  87. package/dist/esm/src/ordering/exact-ordering.js.map +1 -0
  88. package/dist/esm/src/ordering/index.d.ts +22 -0
  89. package/dist/esm/src/ordering/index.js +17 -0
  90. package/dist/esm/src/ordering/index.js.map +1 -0
  91. package/dist/esm/src/ordering/int-pair-map.d.ts +20 -0
  92. package/dist/esm/src/ordering/int-pair-map.js +81 -0
  93. package/dist/esm/src/ordering/int-pair-map.js.map +1 -0
  94. package/dist/esm/src/ordering/local-search.d.ts +114 -0
  95. package/dist/esm/src/ordering/local-search.js +308 -0
  96. package/dist/esm/src/ordering/local-search.js.map +1 -0
  97. package/dist/esm/src/ordering/optimize-ordering.d.ts +153 -0
  98. package/dist/esm/src/ordering/optimize-ordering.js +399 -0
  99. package/dist/esm/src/ordering/optimize-ordering.js.map +1 -0
  100. package/dist/esm/src/ordering/ordering-evaluator.d.ts +198 -0
  101. package/dist/esm/src/ordering/ordering-evaluator.js +377 -0
  102. package/dist/esm/src/ordering/ordering-evaluator.js.map +1 -0
  103. package/dist/esm/src/ordering/shared-diagram.d.ts +85 -0
  104. package/dist/esm/src/ordering/shared-diagram.js +289 -0
  105. package/dist/esm/src/ordering/shared-diagram.js.map +1 -0
  106. package/dist/esm/src/packed/index.d.ts +2 -0
  107. package/dist/esm/src/packed/index.js +3 -0
  108. package/dist/esm/src/packed/index.js.map +1 -0
  109. package/dist/esm/src/packed/packed-bdd-base64-string.d.ts +3 -0
  110. package/dist/esm/src/packed/packed-bdd-base64-string.js +42 -0
  111. package/dist/esm/src/packed/packed-bdd-base64-string.js.map +1 -0
  112. package/dist/esm/src/packed/packed-bdd.d.ts +13 -0
  113. package/dist/esm/src/packed/packed-bdd.js +66 -0
  114. package/dist/esm/src/packed/packed-bdd.js.map +1 -0
  115. package/dist/esm/src/root-node.d.ts +1 -2
  116. package/dist/esm/src/root-node.js +1 -5
  117. package/dist/esm/src/root-node.js.map +1 -1
  118. package/dist/esm/src/types.d.ts +0 -12
  119. package/dist/esm/src/util.js +14 -5
  120. package/dist/esm/src/util.js.map +1 -1
  121. package/docs/variable-ordering.md +306 -0
  122. package/package.json +11 -9
  123. package/src/abstract-node.ts +7 -5
  124. package/src/branches.ts +2 -0
  125. package/src/create-bdd-from-truth-table.ts +1 -1
  126. package/src/index.ts +2 -1
  127. package/src/internal-node.ts +7 -4
  128. package/src/optimize-brute-force.ts +5 -7
  129. package/src/ordering/build-bdd.ts +70 -0
  130. package/src/ordering/dense-truth-table.ts +161 -0
  131. package/src/ordering/exact-cost-ordering.ts +425 -0
  132. package/src/ordering/exact-ordering.ts +317 -0
  133. package/src/ordering/index.ts +57 -0
  134. package/src/ordering/int-pair-map.ts +85 -0
  135. package/src/ordering/local-search.ts +369 -0
  136. package/src/ordering/optimize-ordering.ts +570 -0
  137. package/src/ordering/ordering-evaluator.ts +479 -0
  138. package/src/ordering/shared-diagram.ts +310 -0
  139. package/src/packed/index.ts +2 -0
  140. package/src/packed/packed-bdd-base64-string.ts +47 -0
  141. package/src/packed/packed-bdd.ts +98 -0
  142. package/src/root-node.ts +2 -8
  143. package/src/types.ts +0 -18
  144. package/src/util.ts +15 -6
  145. package/dist/cjs/src/minimal-string/bdd-to-minimal-string.d.ts +0 -8
  146. package/dist/cjs/src/minimal-string/bdd-to-minimal-string.js +0 -59
  147. package/dist/cjs/src/minimal-string/bdd-to-minimal-string.js.map +0 -1
  148. package/dist/cjs/src/minimal-string/bdd-to-simple-bdd.d.ts +0 -11
  149. package/dist/cjs/src/minimal-string/bdd-to-simple-bdd.js +0 -23
  150. package/dist/cjs/src/minimal-string/bdd-to-simple-bdd.js.map +0 -1
  151. package/dist/cjs/src/minimal-string/index.d.ts +0 -5
  152. package/dist/cjs/src/minimal-string/index.js.map +0 -1
  153. package/dist/cjs/src/minimal-string/minimal-string-to-simple-bdd.d.ts +0 -2
  154. package/dist/cjs/src/minimal-string/minimal-string-to-simple-bdd.js +0 -57
  155. package/dist/cjs/src/minimal-string/minimal-string-to-simple-bdd.js.map +0 -1
  156. package/dist/cjs/src/minimal-string/resolve-with-simple-bdd.d.ts +0 -2
  157. package/dist/cjs/src/minimal-string/resolve-with-simple-bdd.js +0 -18
  158. package/dist/cjs/src/minimal-string/resolve-with-simple-bdd.js.map +0 -1
  159. package/dist/cjs/src/minimal-string/string-format.d.ts +0 -9
  160. package/dist/cjs/src/minimal-string/string-format.js +0 -61
  161. package/dist/cjs/src/minimal-string/string-format.js.map +0 -1
  162. package/dist/esm/src/minimal-string/bdd-to-minimal-string.d.ts +0 -8
  163. package/dist/esm/src/minimal-string/bdd-to-minimal-string.js +0 -55
  164. package/dist/esm/src/minimal-string/bdd-to-minimal-string.js.map +0 -1
  165. package/dist/esm/src/minimal-string/bdd-to-simple-bdd.d.ts +0 -11
  166. package/dist/esm/src/minimal-string/bdd-to-simple-bdd.js +0 -19
  167. package/dist/esm/src/minimal-string/bdd-to-simple-bdd.js.map +0 -1
  168. package/dist/esm/src/minimal-string/index.d.ts +0 -5
  169. package/dist/esm/src/minimal-string/index.js +0 -6
  170. package/dist/esm/src/minimal-string/index.js.map +0 -1
  171. package/dist/esm/src/minimal-string/minimal-string-to-simple-bdd.d.ts +0 -2
  172. package/dist/esm/src/minimal-string/minimal-string-to-simple-bdd.js +0 -54
  173. package/dist/esm/src/minimal-string/minimal-string-to-simple-bdd.js.map +0 -1
  174. package/dist/esm/src/minimal-string/resolve-with-simple-bdd.d.ts +0 -2
  175. package/dist/esm/src/minimal-string/resolve-with-simple-bdd.js +0 -15
  176. package/dist/esm/src/minimal-string/resolve-with-simple-bdd.js.map +0 -1
  177. package/dist/esm/src/minimal-string/string-format.d.ts +0 -9
  178. package/dist/esm/src/minimal-string/string-format.js +0 -54
  179. package/dist/esm/src/minimal-string/string-format.js.map +0 -1
  180. package/src/minimal-string/bdd-to-minimal-string.ts +0 -72
  181. package/src/minimal-string/bdd-to-simple-bdd.ts +0 -31
  182. package/src/minimal-string/index.ts +0 -5
  183. package/src/minimal-string/minimal-string-to-simple-bdd.ts +0 -67
  184. package/src/minimal-string/resolve-with-simple-bdd.ts +0 -23
  185. package/src/minimal-string/string-format.ts +0 -67
@@ -0,0 +1,399 @@
1
+ import { parseTruthTable, denseTruthTableToMap, ensureValidOrdering } from './dense-truth-table.js';
2
+ import { OrderingEvaluator } from './ordering-evaluator.js';
3
+ import { LocalOrderingSearch, seedOrderings, DEFAULT_WINDOW_SIZE, ensureWindowSize, ensureNonNegativeInteger } from './local-search.js';
4
+ import { ExactOrderingSearch } from './exact-ordering.js';
5
+ import { ExactCostOrderingSearch } from './exact-cost-ordering.js';
6
+ import { buildBddFromDiagram } from './build-bdd.js';
7
+ export const DEFAULT_MAX_EXACT_VARIABLES = 20;
8
+ export const DEFAULT_MAX_EXACT_NODE_COUNT = 5000;
9
+ /**
10
+ * Validates functionCosts and rowWeight and turns them into a cost model.
11
+ */
12
+ export function buildCostModel(table, functionCosts, rowWeight) {
13
+ if (!functionCosts) {
14
+ if (rowWeight) {
15
+ throw new Error('rowWeight can only be used together with functionCosts');
16
+ }
17
+ return null;
18
+ }
19
+ const n = table.variableCount;
20
+ if (functionCosts.length !== n) {
21
+ throw new Error('functionCosts must have one entry per boolean function (' + n + ')');
22
+ }
23
+ const costs = new Float64Array(n);
24
+ for (let v = 0; v < n; v++) {
25
+ const cost = functionCosts[v];
26
+ if (typeof cost !== 'number' || !isFinite(cost) || cost < 0) {
27
+ throw new Error('functionCosts[' + v + '] must be a non-negative number');
28
+ }
29
+ costs[v] = cost;
30
+ }
31
+ const weights = new Float64Array(table.rowCount);
32
+ let totalWeight = 0;
33
+ for (let row = 0; row < table.rowCount; row++) {
34
+ const id = table.terminalIds[row];
35
+ if (id === table.dontCareTerminal) {
36
+ continue;
37
+ }
38
+ let weight = 1;
39
+ if (rowWeight) {
40
+ const key = row.toString(2).padStart(n, '0');
41
+ weight = rowWeight(key, table.terminalValues[id]);
42
+ if (typeof weight !== 'number' || !isFinite(weight) || weight < 0) {
43
+ throw new Error('rowWeight must return a non-negative number, got ' + weight + ' for ' + key);
44
+ }
45
+ }
46
+ weights[row] = weight;
47
+ totalWeight += weight;
48
+ }
49
+ if (totalWeight <= 0) {
50
+ throw new Error('all row weights are zero');
51
+ }
52
+ let maxCost = 0;
53
+ costs.forEach(cost => maxCost = Math.max(maxCost, cost));
54
+ if (!isFinite(totalWeight) || !isFinite(maxCost * totalWeight)) {
55
+ throw new Error('the function costs or row weights are too large, scale them down');
56
+ }
57
+ return {
58
+ functionCosts: costs,
59
+ rowWeights: weights,
60
+ totalWeight
61
+ };
62
+ }
63
+ /**
64
+ * Deterministically finds a variable ordering with a small BDD
65
+ * (or, with functionCosts, with a cheap resolve() call).
66
+ * See docs/variable-ordering.md for how it works.
67
+ * Does not create BDD nodes, use optimizeOrdering() for that.
68
+ */
69
+ export function findOrdering(input) {
70
+ return findOrderingWithTable(input).result;
71
+ }
72
+ /**
73
+ * Checks the options before any expensive work starts.
74
+ */
75
+ function ensureValidOptions(input) {
76
+ if (input.windowSize !== undefined) {
77
+ ensureWindowSize(input.windowSize);
78
+ }
79
+ if (input.maxRounds !== undefined) {
80
+ ensureNonNegativeInteger(input.maxRounds, 'maxRounds');
81
+ }
82
+ const budgets = ['maxExactVariables', 'maxExactNodeCount', 'maxExactExpansions', 'maxExactDiagramNodes'];
83
+ budgets.forEach(name => {
84
+ const value = input[name];
85
+ if (value !== undefined) {
86
+ ensureNonNegativeInteger(value, name);
87
+ }
88
+ });
89
+ if (input.exact !== undefined && input.exact !== true && input.exact !== false && input.exact !== 'auto') {
90
+ throw new Error('exact must be true, false or \'auto\'');
91
+ }
92
+ }
93
+ function findOrderingWithTable(input) {
94
+ const startTime = Date.now();
95
+ ensureValidOptions(input);
96
+ const log = input.log ? (message) => console.log('findOrdering(): ' + message) : () => null;
97
+ const onImprovement = input.onImprovement ? input.onImprovement : () => null;
98
+ const base = parseTruthTable(input.truthTable, input.dontCareValue);
99
+ const n = base.variableCount;
100
+ const costModel = buildCostModel(base, input.functionCosts, input.rowWeight);
101
+ const baseEvaluator = new OrderingEvaluator(base, costModel);
102
+ const windowSize = input.windowSize === undefined ? DEFAULT_WINDOW_SIZE : input.windowSize;
103
+ let evaluations = 0;
104
+ const describe = (evaluation) => evaluation.nodeCount + ' nodes' +
105
+ (costModel ? ', expected cost ' + evaluation.expectedCost : '');
106
+ /**
107
+ * phase 1: deterministic seeds, each improved by sifting and window permutation
108
+ */
109
+ const userSeeds = (input.initialOrderings ? input.initialOrderings : []).map((ordering, index) => {
110
+ ensureValidOrdering(ordering, n);
111
+ return { name: 'initial-' + index, ordering: Array.from(ordering) };
112
+ });
113
+ const seenSeeds = new Set();
114
+ const seeds = userSeeds.concat(seedOrderings(baseEvaluator)).filter(seed => {
115
+ const key = seed.ordering.join(',');
116
+ if (seenSeeds.has(key)) {
117
+ return false;
118
+ }
119
+ seenSeeds.add(key);
120
+ return true;
121
+ });
122
+ let localBest = null;
123
+ const seedResults = [];
124
+ // the last evaluation passed to onImprovement
125
+ const reported = { evaluation: null };
126
+ for (const seed of seeds) {
127
+ const search = new LocalOrderingSearch(baseEvaluator, seed.ordering, {
128
+ windowSize,
129
+ maxRounds: input.maxRounds,
130
+ log: message => log('[' + seed.name + '] ' + message),
131
+ onImprovement: progress => {
132
+ if (!localBest || baseEvaluator.isBetter(search.best, localBest.evaluation)) {
133
+ reported.evaluation = search.best;
134
+ onImprovement(progress);
135
+ }
136
+ }
137
+ });
138
+ const result = search.run();
139
+ log('seed ' + seed.name + ': ' + describe(result.evaluation));
140
+ seedResults.push({ ordering: result.ordering, evaluation: result.evaluation });
141
+ if (!localBest || baseEvaluator.isBetter(result.evaluation, localBest.evaluation)) {
142
+ localBest = { ordering: result.ordering, evaluation: result.evaluation };
143
+ if (!reported.evaluation || baseEvaluator.isBetter(result.evaluation, reported.evaluation)) {
144
+ // the seed itself was better than everything before, the search did not report it
145
+ reported.evaluation = result.evaluation;
146
+ onImprovement({
147
+ ordering: result.ordering.slice(),
148
+ nodeCount: result.evaluation.nodeCount,
149
+ expectedCost: result.evaluation.expectedCost,
150
+ phase: 'seed'
151
+ });
152
+ }
153
+ }
154
+ }
155
+ if (!localBest) {
156
+ throw new Error('no ordering found, this should not happen');
157
+ }
158
+ let best = localBest;
159
+ const localSearchNodeCount = best.evaluation.nodeCount;
160
+ /**
161
+ * phase 2: exact search
162
+ *
163
+ * The exact search needs a fully specified function, so it runs on the
164
+ * truth table with the don't-care rows resolved. Different orderings resolve
165
+ * them differently, so every completion the local search came across is a
166
+ * candidate. Whenever a new best ordering is found, its own completion
167
+ * becomes a candidate too.
168
+ */
169
+ let completed = baseEvaluator.complete(best.ordering);
170
+ let optimal = false;
171
+ let exactExpansions = 0;
172
+ const exactMode = input.exact === undefined ? 'auto' : input.exact;
173
+ const maxExactVariables = input.maxExactVariables === undefined ? DEFAULT_MAX_EXACT_VARIABLES : input.maxExactVariables;
174
+ const maxExactNodeCount = input.maxExactNodeCount === undefined ? DEFAULT_MAX_EXACT_NODE_COUNT : input.maxExactNodeCount;
175
+ const runExact = exactMode === true || (exactMode === 'auto' &&
176
+ n <= maxExactVariables &&
177
+ best.evaluation.internalNodeCount <= maxExactNodeCount);
178
+ if (exactMode === 'auto' && !runExact) {
179
+ log('exact search skipped: ' + n + ' boolean functions, ' + best.evaluation.internalNodeCount + ' internal nodes');
180
+ }
181
+ if (runExact) {
182
+ const candidates = [];
183
+ const seenCompletions = new Set();
184
+ const addCandidate = (ordering, front) => {
185
+ const table = baseEvaluator.complete(ordering);
186
+ const key = completionKey(table);
187
+ if (seenCompletions.has(key)) {
188
+ return;
189
+ }
190
+ seenCompletions.add(key);
191
+ const candidate = { ordering, table };
192
+ if (front) {
193
+ candidates.unshift(candidate);
194
+ }
195
+ else {
196
+ candidates.push(candidate);
197
+ }
198
+ };
199
+ addCandidate(best.ordering, false);
200
+ if (base.dontCareTerminal >= 0) {
201
+ seedResults.forEach(result => addCandidate(result.ordering, false));
202
+ }
203
+ /**
204
+ * completions for which the exact search finished: on them, no ordering
205
+ * beats the best evaluation known at that time (which is never worse than
206
+ * the final one)
207
+ */
208
+ const solvedCompletions = new Set();
209
+ while (candidates.length > 0) {
210
+ const candidate = candidates.shift();
211
+ const candidateKey = completionKey(candidate.table);
212
+ let exactOrdering;
213
+ let solved;
214
+ let expansions;
215
+ const searchOptions = { maxDiagramNodes: input.maxExactDiagramNodes };
216
+ if (costModel) {
217
+ const exactResult = new ExactCostOrderingSearch(candidate.table, costModel, searchOptions).run({
218
+ maxExpansions: input.maxExactExpansions,
219
+ upperBoundOrdering: candidate.ordering,
220
+ // only orderings that beat the best known one are interesting
221
+ upperBound: best.evaluation.expectedCost,
222
+ log
223
+ });
224
+ exactOrdering = exactResult.ordering;
225
+ solved = exactResult.solved;
226
+ expansions = exactResult.expansions;
227
+ }
228
+ else {
229
+ const exactResult = new ExactOrderingSearch(candidate.table, searchOptions).run({
230
+ maxExpansions: input.maxExactExpansions,
231
+ upperBoundOrdering: candidate.ordering,
232
+ upperBound: best.evaluation.nodeCount - candidate.table.leafCount,
233
+ log
234
+ });
235
+ exactOrdering = exactResult.ordering;
236
+ solved = exactResult.solved;
237
+ expansions = exactResult.expansions;
238
+ }
239
+ exactExpansions += expansions;
240
+ if (!solved) {
241
+ log('exact search gave up on one completion of the truth table');
242
+ continue;
243
+ }
244
+ solvedCompletions.add(candidateKey);
245
+ if (!exactOrdering) {
246
+ continue;
247
+ }
248
+ const candidateEvaluator = new OrderingEvaluator(candidate.table, costModel);
249
+ let exactEvaluation = candidateEvaluator.evaluate(exactOrdering);
250
+ if (costModel) {
251
+ /**
252
+ * The exact cost search only minimizes the expected cost. Among the
253
+ * orderings with the same cost, fewer nodes are better, which the
254
+ * local search on the same completion takes care of.
255
+ */
256
+ const polished = new LocalOrderingSearch(candidateEvaluator, exactOrdering, {
257
+ windowSize,
258
+ maxRounds: input.maxRounds
259
+ }).run();
260
+ exactOrdering = polished.ordering;
261
+ exactEvaluation = polished.evaluation;
262
+ }
263
+ evaluations += candidateEvaluator.evaluations;
264
+ log('exact search: ' + describe(exactEvaluation) + ' after ' + expansions + ' expansions');
265
+ if (baseEvaluator.isBetter(exactEvaluation, best.evaluation)) {
266
+ best = { ordering: exactOrdering, evaluation: exactEvaluation };
267
+ completed = candidate.table;
268
+ onImprovement({
269
+ ordering: best.ordering.slice(),
270
+ nodeCount: exactEvaluation.nodeCount,
271
+ expectedCost: exactEvaluation.expectedCost,
272
+ phase: 'exact'
273
+ });
274
+ if (base.dontCareTerminal >= 0) {
275
+ // the don't-care rows might resolve even better with the new ordering
276
+ addCandidate(best.ordering, true);
277
+ }
278
+ }
279
+ }
280
+ /**
281
+ * When the completion the ordering picks itself is just as good,
282
+ * prefer it: then createBddWithOrdering(input, ordering, dontCareValue)
283
+ * rebuilds the same BDD.
284
+ */
285
+ if (base.dontCareTerminal >= 0) {
286
+ const own = baseEvaluator.complete(best.ordering);
287
+ if (completionKey(own) !== completionKey(completed)) {
288
+ const ownEvaluation = baseEvaluator.evaluate(best.ordering);
289
+ if (baseEvaluator.compare(ownEvaluation, best.evaluation) === 0) {
290
+ best = { ordering: best.ordering, evaluation: ownEvaluation };
291
+ completed = own;
292
+ }
293
+ }
294
+ }
295
+ optimal = solvedCompletions.has(completionKey(completed));
296
+ }
297
+ evaluations += baseEvaluator.evaluations;
298
+ return {
299
+ result: {
300
+ ordering: best.ordering,
301
+ nodeCount: best.evaluation.nodeCount,
302
+ expectedCost: costModel ? best.evaluation.expectedCost : undefined,
303
+ optimal,
304
+ truthTable: denseTruthTableToMap(completed),
305
+ stats: {
306
+ evaluations,
307
+ exactExpansions,
308
+ localSearchNodeCount,
309
+ durationMs: Date.now() - startTime
310
+ }
311
+ },
312
+ table: completed
313
+ };
314
+ }
315
+ /**
316
+ * identifies the content of a (completed) table
317
+ */
318
+ function completionKey(table) {
319
+ let h1 = 0x811C9DC5;
320
+ let h2 = 0x01000193;
321
+ const ids = table.terminalIds;
322
+ for (let i = 0; i < ids.length; i++) {
323
+ h1 = Math.imul(h1 ^ ids[i], 0x01000193);
324
+ h2 = Math.imul(h2 + ids[i], 0x9E3779B1) ^ (h2 >>> 13);
325
+ }
326
+ return (h1 >>> 0).toString(16) + ':' + (h2 >>> 0).toString(16) + ':' + ids.length;
327
+ }
328
+ /**
329
+ * Deterministic replacement for optimizeBruteForce():
330
+ * finds a good variable ordering and returns the minimized BDD for it.
331
+ * All work is synchronous, the promise exists for compatibility with optimizeBruteForce().
332
+ */
333
+ export async function optimizeOrdering(input) {
334
+ const { result: found, table } = findOrderingWithTable(input);
335
+ const bdd = buildBddForOrdering(table, found.ordering);
336
+ let optimal = found.optimal;
337
+ if (input.afterBddCreation) {
338
+ const before = fingerprint(bdd);
339
+ input.afterBddCreation(bdd);
340
+ bdd.minimize();
341
+ if (fingerprint(bdd) !== before) {
342
+ // the hook changed the BDD, the proof does not hold for it anymore
343
+ optimal = false;
344
+ }
345
+ }
346
+ return {
347
+ bdd,
348
+ ordering: found.ordering,
349
+ nodeCount: bdd.countNodes(),
350
+ expectedCost: found.expectedCost,
351
+ optimal,
352
+ truthTable: found.truthTable,
353
+ stats: found.stats
354
+ };
355
+ }
356
+ /**
357
+ * Describes the structure and the leaf values of a BDD,
358
+ * equal BDDs give equal strings.
359
+ */
360
+ function fingerprint(bdd) {
361
+ const ids = new Map();
362
+ const parts = [];
363
+ const visit = (node) => {
364
+ const known = ids.get(node);
365
+ if (known !== undefined) {
366
+ return known;
367
+ }
368
+ let part;
369
+ if (node.isLeafNode()) {
370
+ part = 'v' + String(node.asLeafNode().value);
371
+ }
372
+ else {
373
+ const branches = node.branches;
374
+ part = node.level + ':' + visit(branches.getBranch('0')) + ',' + visit(branches.getBranch('1'));
375
+ }
376
+ const id = parts.length;
377
+ parts.push(part);
378
+ ids.set(node, id);
379
+ return id;
380
+ };
381
+ visit(bdd);
382
+ return parts.join(';');
383
+ }
384
+ /**
385
+ * Creates the minimized BDD of a truth table for a given ordering
386
+ * without going through the unreduced decision tree.
387
+ */
388
+ export function createBddWithOrdering(truthTable, ordering, dontCareValue) {
389
+ const base = parseTruthTable(truthTable, dontCareValue);
390
+ const evaluator = new OrderingEvaluator(base);
391
+ const completed = evaluator.complete(ordering);
392
+ return buildBddForOrdering(completed, ordering);
393
+ }
394
+ function buildBddForOrdering(table, ordering) {
395
+ const evaluator = new OrderingEvaluator(table);
396
+ const diagram = evaluator.buildDiagram(ordering);
397
+ return buildBddFromDiagram(diagram, table);
398
+ }
399
+ //# sourceMappingURL=optimize-ordering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimize-ordering.js","sourceRoot":"","sources":["../../../../src/ordering/optimize-ordering.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,198 @@
1
+ import type { DenseTruthTable } from './dense-truth-table.js';
2
+ /**
3
+ * Describes what a resolve() call costs.
4
+ */
5
+ export interface CostModel {
6
+ /** functionCosts[v] = cost of calling boolean function v */
7
+ functionCosts: Float64Array;
8
+ /**
9
+ * rowWeights[row] = how often the row occurs at runtime, relative to the other rows.
10
+ * Must be 0 for don't-care rows, they never occur.
11
+ */
12
+ rowWeights: Float64Array;
13
+ /** sum of rowWeights */
14
+ totalWeight: number;
15
+ }
16
+ /**
17
+ * Result of evaluating a variable ordering.
18
+ */
19
+ export interface OrderingEvaluation {
20
+ /**
21
+ * nodesPerLevel[k] is the amount of nodes of the reduced BDD
22
+ * that test the boolean function ordering[k].
23
+ */
24
+ nodesPerLevel: number[];
25
+ /** sum of nodesPerLevel */
26
+ internalNodeCount: number;
27
+ /**
28
+ * Amount of nodes as RootNode.countNodes() would return it:
29
+ * the root node, plus all nodes below the top level, plus the leaf nodes.
30
+ */
31
+ nodeCount: number;
32
+ /**
33
+ * Expected cost of one resolve() call: the costs of the boolean functions
34
+ * that are called on the way from the root to the leaf, averaged over the
35
+ * rows with their weights. 0 when the evaluator has no cost model.
36
+ */
37
+ expectedCost: number;
38
+ }
39
+ /**
40
+ * A reduced ordered (multi terminal) decision diagram
41
+ * in a flat array representation. Ids below terminalCount are terminals
42
+ * (and equal the terminal id of the dense truth table), ids from terminalCount
43
+ * on are internal nodes: node i is stored at index (i - terminalCount).
44
+ */
45
+ export interface ReducedDiagram {
46
+ variableCount: number;
47
+ terminalCount: number;
48
+ /** id of the root, can be a terminal when the function is constant */
49
+ root: number;
50
+ /** level (index into the ordering) of each internal node */
51
+ nodeLevel: Int32Array;
52
+ /** id of the 0-branch of each internal node */
53
+ nodeLo: Int32Array;
54
+ /** id of the 1-branch of each internal node */
55
+ nodeHi: Int32Array;
56
+ /** ordering[level] = boolean function tested on that level */
57
+ ordering: number[];
58
+ nodesPerLevel: number[];
59
+ }
60
+ interface DiagramRecord {
61
+ nodeLevel: Int32Array;
62
+ nodeLo: Int32Array;
63
+ nodeHi: Int32Array;
64
+ }
65
+ /**
66
+ * relative tolerance for comparing expected costs
67
+ */
68
+ export declare const COST_EPSILON = 1e-9;
69
+ /**
70
+ * Two costs closer than this are treated as equal. The tolerance is relative
71
+ * to the larger of the value and the cost of one call of the most expensive
72
+ * boolean function (`unit`), so it does not depend on the unit the
73
+ * functionCosts are given in (milliseconds, seconds, ...).
74
+ */
75
+ export declare function costTolerance(value: number, unit: number): number;
76
+ /**
77
+ * The cost of one call of the most expensive boolean function,
78
+ * the unit of costTolerance() for expected costs.
79
+ */
80
+ export declare function costUnit(costModel: CostModel): number;
81
+ /**
82
+ * An ordering together with the intermediate results of its evaluation.
83
+ *
84
+ * levelIds[L] holds the ids of the 2^L blocks of level L (levelIds[n] are the
85
+ * rows of the truth table). Because blocks are indexed by the natural
86
+ * assignment to the functions above their level, swapping the functions of two
87
+ * levels keeps all levels below the lower one valid, only the levels from the
88
+ * lower one up to the root are recomputed.
89
+ */
90
+ export declare class OrderingCursor {
91
+ private readonly evaluator;
92
+ private readonly record;
93
+ readonly ordering: number[];
94
+ evaluation: OrderingEvaluation;
95
+ /** id of the root block, a terminal when the function is constant */
96
+ root: number;
97
+ private readonly n;
98
+ private readonly levelIds;
99
+ private readonly levelWeights;
100
+ private readonly created;
101
+ private readonly payingWeights;
102
+ constructor(evaluator: OrderingEvaluator, ordering: ArrayLike<number>, record?: DiagramRecord | null);
103
+ /**
104
+ * Starts over with another ordering.
105
+ */
106
+ reset(ordering: ArrayLike<number>): void;
107
+ /**
108
+ * Swaps the boolean functions of two levels and updates the evaluation.
109
+ */
110
+ swap(levelA: number, levelB: number): void;
111
+ /**
112
+ * recomputes the levels top .. 0 (the levels below stay as they are)
113
+ */
114
+ private recomputeFrom;
115
+ }
116
+ /**
117
+ * Evaluates variable orderings of a truth table without ever creating
118
+ * BDD node objects.
119
+ *
120
+ * The reduced BDD is built bottom-up: the rows of the truth table are the
121
+ * leaves, every level above merges the two children of each block into a node
122
+ * through a hash table (hash-consing). Equal children collapse to a single edge
123
+ * (reduction rule) and equal (child0, child1) pairs share one node (elimination
124
+ * rule), so the amount of nodes created per level is exactly the amount of
125
+ * nodes the reduced BDD has on that level. Everything runs in O(2^n) integer
126
+ * operations.
127
+ *
128
+ * A block on level L is the set of rows that agree on the boolean functions
129
+ * above level L. Blocks are indexed by the assignment to those functions in
130
+ * their natural (index) order, not in the order of the levels. That way the
131
+ * blocks of a level only depend on the SET of functions above it: when two
132
+ * levels swap their functions, nothing below them changes and OrderingCursor
133
+ * only recomputes the levels above.
134
+ *
135
+ * Don't-care rows are handled like RootNode.removeIrrelevantLeafNodes() does it:
136
+ * a node whose one branch is entirely don't-care is replaced by its other branch.
137
+ *
138
+ * With a cost model, the same pass also sums up the weight of the rows that
139
+ * pass through a node on each level, which gives the expected cost of a
140
+ * resolve() call: a row pays for the boolean function of a level exactly when
141
+ * its block on that level has a node. The root node always calls its boolean
142
+ * function, even when the function is irrelevant.
143
+ */
144
+ export declare class OrderingEvaluator {
145
+ readonly table: DenseTruthTable;
146
+ readonly costModel: CostModel | null;
147
+ readonly variableCount: number;
148
+ readonly rowCount: number;
149
+ readonly terminalCount: number;
150
+ readonly dontCare: number;
151
+ /** amount of evaluations run so far */
152
+ evaluations: number;
153
+ private readonly hashLo;
154
+ private readonly hashHi;
155
+ private readonly hashId;
156
+ private scratch;
157
+ private costUnit;
158
+ constructor(table: DenseTruthTable, costModel?: CostModel | null);
159
+ /**
160
+ * Evaluates an ordering.
161
+ */
162
+ evaluate(ordering: ArrayLike<number>): OrderingEvaluation;
163
+ /**
164
+ * A cursor keeps the intermediate results of an ordering so that
165
+ * swapping two levels only recomputes the levels above them.
166
+ */
167
+ cursor(ordering: ArrayLike<number>): OrderingCursor;
168
+ /**
169
+ * @returns true when evaluation a is strictly better than b:
170
+ * fewer nodes, or with a cost model a lower expected cost
171
+ * (ties in the expected cost are broken by the amount of nodes)
172
+ */
173
+ isBetter(a: OrderingEvaluation, b: OrderingEvaluation): boolean;
174
+ /**
175
+ * negative when a is better than b, positive when b is better, 0 when equal
176
+ */
177
+ compare(a: OrderingEvaluation, b: OrderingEvaluation): number;
178
+ /**
179
+ * Builds the reduced diagram of an ordering.
180
+ */
181
+ buildDiagram(ordering: ArrayLike<number>): ReducedDiagram;
182
+ /**
183
+ * Resolves the don't-care rows the same way the BDD of the given ordering
184
+ * resolves them (a don't-care branch takes the value of its sibling branch)
185
+ * and returns a table without don't-care rows.
186
+ * When the table has no don't-care rows, the same table is returned.
187
+ */
188
+ complete(ordering: ArrayLike<number>): DenseTruthTable;
189
+ /**
190
+ * Computes the blocks of one level out of the blocks of the level below.
191
+ * @internal
192
+ */
193
+ computeLevel(ordering: number[], level: number, deeperIds: Int32Array, deeperWeights: Float64Array | null, ids: Int32Array, weights: Float64Array | null, firstId: number, record: DiagramRecord | null): {
194
+ created: number;
195
+ payingWeight: number;
196
+ };
197
+ }
198
+ export {};