@cubingcenter/scrambler 0.6.3 → 0.8.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 (191) hide show
  1. package/README.md +17 -4
  2. package/dist/core/api.d.ts.map +1 -1
  3. package/dist/core/api.js +10 -2
  4. package/dist/puzzles/cube2/solver/browser-loader.d.ts +4 -7
  5. package/dist/puzzles/cube2/solver/browser-loader.d.ts.map +1 -1
  6. package/dist/puzzles/cube2/solver/browser-loader.js +42 -14
  7. package/dist/puzzles/cube2/solver/generated-assets.d.ts.map +1 -1
  8. package/dist/puzzles/cube2/solver/generated-assets.js +8 -3
  9. package/dist/puzzles/cube2/solver/search.d.ts.map +1 -1
  10. package/dist/puzzles/cube2/solver/search.js +3 -3
  11. package/dist/puzzles/cube2/solver/tables.d.ts +6 -0
  12. package/dist/puzzles/cube2/solver/tables.d.ts.map +1 -1
  13. package/dist/puzzles/cube2/solver/tables.js +16 -2
  14. package/dist/puzzles/cube3/index.d.ts +1 -0
  15. package/dist/puzzles/cube3/index.d.ts.map +1 -1
  16. package/dist/puzzles/cube3/moves.d.ts.map +1 -1
  17. package/dist/puzzles/cube3/moves.js +104 -18
  18. package/dist/puzzles/cube3/scrambler.d.ts +16 -1
  19. package/dist/puzzles/cube3/scrambler.d.ts.map +1 -1
  20. package/dist/puzzles/cube3/scrambler.js +1 -1
  21. package/dist/puzzles/cube3/solver/browser-loader.d.ts.map +1 -1
  22. package/dist/puzzles/cube3/solver/browser-loader.js +48 -22
  23. package/dist/puzzles/cube3/solver/generated-assets.d.ts.map +1 -1
  24. package/dist/puzzles/cube3/solver/generated-assets.js +9 -3
  25. package/dist/puzzles/cube3/solver/index.d.ts +5 -3
  26. package/dist/puzzles/cube3/solver/index.d.ts.map +1 -1
  27. package/dist/puzzles/cube3/solver/index.js +2 -1
  28. package/dist/puzzles/cube3/solver/node-loader.js +9 -2
  29. package/dist/puzzles/cube3/solver/phase1.d.ts +37 -0
  30. package/dist/puzzles/cube3/solver/phase1.d.ts.map +1 -1
  31. package/dist/puzzles/cube3/solver/phase1.js +156 -15
  32. package/dist/puzzles/cube3/solver/phase2.d.ts +75 -0
  33. package/dist/puzzles/cube3/solver/phase2.d.ts.map +1 -1
  34. package/dist/puzzles/cube3/solver/phase2.js +279 -68
  35. package/dist/puzzles/cube3/solver/search-utils.d.ts +1 -1
  36. package/dist/puzzles/cube3/solver/search-utils.d.ts.map +1 -1
  37. package/dist/puzzles/cube3/solver/symmetry.d.ts +24 -0
  38. package/dist/puzzles/cube3/solver/symmetry.d.ts.map +1 -0
  39. package/dist/puzzles/cube3/solver/symmetry.js +74 -0
  40. package/dist/puzzles/cube3/solver/tables.d.ts +6 -1
  41. package/dist/puzzles/cube3/solver/tables.d.ts.map +1 -1
  42. package/dist/puzzles/cube3/solver/tables.js +14 -12
  43. package/dist/puzzles/cube3/validation.d.ts.map +1 -1
  44. package/dist/puzzles/cube3/validation.js +15 -7
  45. package/dist/puzzles/cube4/browser-worker-pool.d.ts +82 -0
  46. package/dist/puzzles/cube4/browser-worker-pool.d.ts.map +1 -0
  47. package/dist/puzzles/cube4/browser-worker-pool.js +205 -0
  48. package/dist/puzzles/cube4/browser-worker.d.ts +2 -0
  49. package/dist/puzzles/cube4/browser-worker.d.ts.map +1 -0
  50. package/dist/puzzles/cube4/browser-worker.js +31 -0
  51. package/dist/puzzles/cube4/index.d.ts +10 -2
  52. package/dist/puzzles/cube4/index.d.ts.map +1 -1
  53. package/dist/puzzles/cube4/index.js +6 -2
  54. package/dist/puzzles/cube4/moves.d.ts +5 -0
  55. package/dist/puzzles/cube4/moves.d.ts.map +1 -1
  56. package/dist/puzzles/cube4/moves.js +212 -11
  57. package/dist/puzzles/cube4/reduction/browser-loader.d.ts +29 -1
  58. package/dist/puzzles/cube4/reduction/browser-loader.d.ts.map +1 -1
  59. package/dist/puzzles/cube4/reduction/browser-loader.js +227 -32
  60. package/dist/puzzles/cube4/reduction/center2.d.ts +44 -3
  61. package/dist/puzzles/cube4/reduction/center2.d.ts.map +1 -1
  62. package/dist/puzzles/cube4/reduction/center2.js +152 -10
  63. package/dist/puzzles/cube4/reduction/edge3.d.ts +4 -0
  64. package/dist/puzzles/cube4/reduction/edge3.d.ts.map +1 -1
  65. package/dist/puzzles/cube4/reduction/edge3.js +23 -3
  66. package/dist/puzzles/cube4/reduction/finish3.d.ts +53 -0
  67. package/dist/puzzles/cube4/reduction/finish3.d.ts.map +1 -0
  68. package/dist/puzzles/cube4/reduction/finish3.js +393 -0
  69. package/dist/puzzles/cube4/reduction/generated/c3_pair_dist.bin +1 -0
  70. package/dist/puzzles/cube4/reduction/generated/center2-manifest.json +36 -0
  71. package/dist/puzzles/cube4/reduction/generated/center2-pruning-wide.bin +1 -0
  72. package/dist/puzzles/cube4/reduction/generated/hc-distances.bin +1 -0
  73. package/dist/puzzles/cube4/reduction/generated/hc-manifest.json +44 -0
  74. package/dist/puzzles/cube4/reduction/generated/hc-move.bin +0 -0
  75. package/dist/puzzles/cube4/reduction/hc-pdb.d.ts +52 -0
  76. package/dist/puzzles/cube4/reduction/hc-pdb.d.ts.map +1 -0
  77. package/dist/puzzles/cube4/reduction/hc-pdb.js +220 -0
  78. package/dist/puzzles/cube4/reduction/node-loader.d.ts +15 -1
  79. package/dist/puzzles/cube4/reduction/node-loader.d.ts.map +1 -1
  80. package/dist/puzzles/cube4/reduction/node-loader.js +199 -25
  81. package/dist/puzzles/cube4/reduction/pair-transversal.d.ts +28 -0
  82. package/dist/puzzles/cube4/reduction/pair-transversal.d.ts.map +1 -0
  83. package/dist/puzzles/cube4/reduction/pair-transversal.js +107 -0
  84. package/dist/puzzles/cube4/reduction/pairing-coordinate.js +5 -5
  85. package/dist/puzzles/cube4/reduction/phase3-search.d.ts +116 -7
  86. package/dist/puzzles/cube4/reduction/phase3-search.d.ts.map +1 -1
  87. package/dist/puzzles/cube4/reduction/phase3-search.js +458 -32
  88. package/dist/puzzles/cube4/reduction/rotation-fix.d.ts +28 -0
  89. package/dist/puzzles/cube4/reduction/rotation-fix.d.ts.map +1 -0
  90. package/dist/puzzles/cube4/reduction/rotation-fix.js +212 -0
  91. package/dist/puzzles/cube4/reduction/solve.d.ts +172 -2
  92. package/dist/puzzles/cube4/reduction/solve.d.ts.map +1 -1
  93. package/dist/puzzles/cube4/reduction/solve.js +1201 -180
  94. package/dist/puzzles/cube4/scramble-cache.d.ts +93 -0
  95. package/dist/puzzles/cube4/scramble-cache.d.ts.map +1 -0
  96. package/dist/puzzles/cube4/scramble-cache.js +150 -0
  97. package/dist/puzzles/cube4/scrambler.d.ts +201 -6
  98. package/dist/puzzles/cube4/scrambler.d.ts.map +1 -1
  99. package/dist/puzzles/cube4/scrambler.js +414 -176
  100. package/dist/puzzles/cube4/state.d.ts.map +1 -1
  101. package/dist/puzzles/cube4/state.js +4 -1
  102. package/dist/puzzles/cube4/worker-pool.d.ts +139 -0
  103. package/dist/puzzles/cube4/worker-pool.d.ts.map +1 -0
  104. package/dist/puzzles/cube4/worker-pool.js +405 -0
  105. package/dist/puzzles/cube4/worker-protocol.d.ts +58 -0
  106. package/dist/puzzles/cube4/worker-protocol.d.ts.map +1 -0
  107. package/dist/puzzles/cube4/worker-protocol.js +58 -0
  108. package/dist/puzzles/cube4/worker.d.ts +26 -0
  109. package/dist/puzzles/cube4/worker.d.ts.map +1 -0
  110. package/dist/puzzles/cube4/worker.js +49 -0
  111. package/dist/puzzles/pyraminx/solver/browser-loader.d.ts +4 -8
  112. package/dist/puzzles/pyraminx/solver/browser-loader.d.ts.map +1 -1
  113. package/dist/puzzles/pyraminx/solver/browser-loader.js +44 -15
  114. package/dist/puzzles/pyraminx/solver/generated-assets.d.ts.map +1 -1
  115. package/dist/puzzles/pyraminx/solver/generated-assets.js +8 -3
  116. package/dist/puzzles/pyraminx/solver/search.d.ts.map +1 -1
  117. package/dist/puzzles/pyraminx/solver/search.js +3 -6
  118. package/dist/puzzles/pyraminx/solver/tables.d.ts +6 -0
  119. package/dist/puzzles/pyraminx/solver/tables.d.ts.map +1 -1
  120. package/dist/puzzles/pyraminx/solver/tables.js +17 -0
  121. package/dist/puzzles/shared/compressed-fetch.d.ts +37 -1
  122. package/dist/puzzles/shared/compressed-fetch.d.ts.map +1 -1
  123. package/dist/puzzles/shared/compressed-fetch.js +226 -31
  124. package/dist/puzzles/shared/load-once.d.ts +16 -0
  125. package/dist/puzzles/shared/load-once.d.ts.map +1 -0
  126. package/dist/puzzles/shared/load-once.js +11 -0
  127. package/dist/puzzles/skewb/solver/browser-loader.d.ts +4 -11
  128. package/dist/puzzles/skewb/solver/browser-loader.d.ts.map +1 -1
  129. package/dist/puzzles/skewb/solver/browser-loader.js +44 -16
  130. package/dist/puzzles/skewb/solver/generated-assets.d.ts.map +1 -1
  131. package/dist/puzzles/skewb/solver/generated-assets.js +8 -3
  132. package/dist/puzzles/skewb/solver/search.js +3 -3
  133. package/dist/puzzles/skewb/solver/tables.d.ts +6 -0
  134. package/dist/puzzles/skewb/solver/tables.d.ts.map +1 -1
  135. package/dist/puzzles/skewb/solver/tables.js +17 -0
  136. package/dist/puzzles/sq1/solver/browser-loader.d.ts.map +1 -1
  137. package/dist/puzzles/sq1/solver/browser-loader.js +58 -26
  138. package/dist-cjs/core/api.js +10 -2
  139. package/dist-cjs/puzzles/cube2/solver/browser-loader.js +42 -14
  140. package/dist-cjs/puzzles/cube2/solver/generated-assets.js +8 -3
  141. package/dist-cjs/puzzles/cube2/solver/search.js +2 -2
  142. package/dist-cjs/puzzles/cube2/solver/tables.js +17 -3
  143. package/dist-cjs/puzzles/cube3/moves.js +104 -18
  144. package/dist-cjs/puzzles/cube3/scrambler.js +1 -1
  145. package/dist-cjs/puzzles/cube3/solver/browser-loader.js +48 -22
  146. package/dist-cjs/puzzles/cube3/solver/generated-assets.js +9 -3
  147. package/dist-cjs/puzzles/cube3/solver/index.js +8 -1
  148. package/dist-cjs/puzzles/cube3/solver/node-loader.js +9 -2
  149. package/dist-cjs/puzzles/cube3/solver/phase1.js +157 -15
  150. package/dist-cjs/puzzles/cube3/solver/phase2.js +276 -65
  151. package/dist-cjs/puzzles/cube3/solver/symmetry.js +80 -0
  152. package/dist-cjs/puzzles/cube3/solver/tables.js +14 -12
  153. package/dist-cjs/puzzles/cube3/validation.js +15 -7
  154. package/dist-cjs/puzzles/cube4/browser-worker-pool.js +211 -0
  155. package/dist-cjs/puzzles/cube4/index.js +23 -1
  156. package/dist-cjs/puzzles/cube4/moves.js +213 -11
  157. package/dist-cjs/puzzles/cube4/reduction/browser-loader.js +227 -32
  158. package/dist-cjs/puzzles/cube4/reduction/center2.js +155 -10
  159. package/dist-cjs/puzzles/cube4/reduction/edge3.js +24 -3
  160. package/dist-cjs/puzzles/cube4/reduction/finish3.js +398 -0
  161. package/dist-cjs/puzzles/cube4/reduction/generated/c3_pair_dist.bin +1 -0
  162. package/dist-cjs/puzzles/cube4/reduction/generated/center2-manifest.json +36 -0
  163. package/dist-cjs/puzzles/cube4/reduction/generated/center2-pruning-wide.bin +1 -0
  164. package/dist-cjs/puzzles/cube4/reduction/generated/hc-distances.bin +1 -0
  165. package/dist-cjs/puzzles/cube4/reduction/generated/hc-manifest.json +44 -0
  166. package/dist-cjs/puzzles/cube4/reduction/generated/hc-move.bin +0 -0
  167. package/dist-cjs/puzzles/cube4/reduction/hc-pdb.js +232 -0
  168. package/dist-cjs/puzzles/cube4/reduction/node-loader.js +200 -25
  169. package/dist-cjs/puzzles/cube4/reduction/pair-transversal.js +112 -0
  170. package/dist-cjs/puzzles/cube4/reduction/pairing-coordinate.js +5 -5
  171. package/dist-cjs/puzzles/cube4/reduction/phase3-search.js +460 -33
  172. package/dist-cjs/puzzles/cube4/reduction/rotation-fix.js +216 -0
  173. package/dist-cjs/puzzles/cube4/reduction/solve.js +1203 -172
  174. package/dist-cjs/puzzles/cube4/scramble-cache.js +156 -0
  175. package/dist-cjs/puzzles/cube4/scrambler.js +416 -174
  176. package/dist-cjs/puzzles/cube4/state.js +4 -1
  177. package/dist-cjs/puzzles/cube4/worker-pool.js +447 -0
  178. package/dist-cjs/puzzles/cube4/worker-protocol.js +62 -0
  179. package/dist-cjs/puzzles/pyraminx/solver/browser-loader.js +44 -15
  180. package/dist-cjs/puzzles/pyraminx/solver/generated-assets.js +8 -3
  181. package/dist-cjs/puzzles/pyraminx/solver/search.js +2 -5
  182. package/dist-cjs/puzzles/pyraminx/solver/tables.js +18 -1
  183. package/dist-cjs/puzzles/shared/compressed-fetch.js +229 -31
  184. package/dist-cjs/puzzles/shared/load-once.js +14 -0
  185. package/dist-cjs/puzzles/skewb/solver/browser-loader.js +44 -16
  186. package/dist-cjs/puzzles/skewb/solver/generated-assets.js +8 -3
  187. package/dist-cjs/puzzles/skewb/solver/search.js +2 -2
  188. package/dist-cjs/puzzles/skewb/solver/tables.js +18 -1
  189. package/dist-cjs/puzzles/sq1/solver/browser-loader.js +58 -26
  190. package/docs/development.md +19 -7
  191. package/package.json +17 -7
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Phase-2 wing-transversal pruning (two-pair PDB).
3
+ *
4
+ * A phase-2 goal is only usable when the wings are "transversal": every
5
+ * pair has exactly one wing in the second-half positions
6
+ * (`PAIRING_SECOND_HALVES`). Only ~0.1-0.25% of center goals pass, so the
7
+ * phase-2 search used to enumerate millions of center goals to find the
8
+ * transversal ones. This table bounds how many phase-2 moves two given pairs
9
+ * need to become transversal, so the search can prune branches that cannot
10
+ * end transversal within the remaining depth.
11
+ *
12
+ * State: the unordered positions of the two wings of pair X and of pair Y
13
+ * (276 × 276 index; overlapping positions are unreachable). The predicate
14
+ * only depends on positions, so ONE table serves every pair-of-pairs.
15
+ * Exact BFS distances under the given phase-2 move prefix (the search set),
16
+ * hence admissible; generated at runtime (76,176 bytes, a few ms).
17
+ */
18
+ import { CENTER2_MOVES, getWingMoveMaps } from "./center2.js";
19
+ import { PAIRING_SECOND_HALVES } from "./pairing-coordinate.js";
20
+ export const PAIR_STATES = 276;
21
+ /** Unordered position pair (a != b) → 0..275, as a flat 24×24 table. */
22
+ export const PAIR_INDEX = (() => {
23
+ const index = new Uint16Array(24 * 24).fill(0xffff);
24
+ let k = 0;
25
+ for (let a = 0; a < 24; a++) {
26
+ for (let b = a + 1; b < 24; b++) {
27
+ index[a * 24 + b] = k;
28
+ index[b * 24 + a] = k;
29
+ k++;
30
+ }
31
+ }
32
+ return index;
33
+ })();
34
+ const PAIR_A = new Uint8Array(PAIR_STATES);
35
+ const PAIR_B = new Uint8Array(PAIR_STATES);
36
+ for (let a = 0; a < 24; a++) {
37
+ for (let b = a + 1; b < 24; b++) {
38
+ const k = PAIR_INDEX[a * 24 + b];
39
+ PAIR_A[k] = a;
40
+ PAIR_B[k] = b;
41
+ }
42
+ }
43
+ const IS_SECOND = new Uint8Array(24);
44
+ for (const p of PAIRING_SECOND_HALVES)
45
+ IS_SECOND[p] = 1;
46
+ /**
47
+ * Wing position maps: `posMove[m * 24 + p]` = where the wing at position p
48
+ * goes under CENTER2_MOVES[m] (inverse of the `wp` gather maps).
49
+ */
50
+ export function getWingPositionMoves() {
51
+ if (cachedPosMove)
52
+ return cachedPosMove;
53
+ const gather = getWingMoveMaps();
54
+ const posMove = new Uint8Array(CENTER2_MOVES.length * 24);
55
+ for (let m = 0; m < CENTER2_MOVES.length; m++) {
56
+ for (let i = 0; i < 24; i++)
57
+ posMove[m * 24 + gather[m * 24 + i]] = i;
58
+ }
59
+ cachedPosMove = posMove;
60
+ return posMove;
61
+ }
62
+ let cachedPosMove;
63
+ const cache = new Map();
64
+ /** Two-pair transversal distances under the first `moveCount` CENTER2_MOVES. */
65
+ export function getTransversalPairPdb(moveCount) {
66
+ const hit = cache.get(moveCount);
67
+ if (hit)
68
+ return hit;
69
+ const posMove = getWingPositionMoves();
70
+ const n = PAIR_STATES * PAIR_STATES;
71
+ const dist = new Uint8Array(n).fill(0xff);
72
+ const queue = new Int32Array(n);
73
+ let tail = 0;
74
+ for (let x = 0; x < PAIR_STATES; x++) {
75
+ if (IS_SECOND[PAIR_A[x]] === IS_SECOND[PAIR_B[x]])
76
+ continue;
77
+ for (let y = 0; y < PAIR_STATES; y++) {
78
+ if (IS_SECOND[PAIR_A[y]] === IS_SECOND[PAIR_B[y]])
79
+ continue;
80
+ const ya = PAIR_A[y];
81
+ const yb = PAIR_B[y];
82
+ if (ya === PAIR_A[x] || ya === PAIR_B[x] || yb === PAIR_A[x] || yb === PAIR_B[x])
83
+ continue;
84
+ const s = x * PAIR_STATES + y;
85
+ dist[s] = 0;
86
+ queue[tail++] = s;
87
+ }
88
+ }
89
+ for (let head = 0; head < tail; head++) {
90
+ const s = queue[head];
91
+ const x = (s / PAIR_STATES) | 0;
92
+ const y = s - x * PAIR_STATES;
93
+ const d = dist[s] + 1;
94
+ for (let m = 0; m < moveCount; m++) {
95
+ const row = m * 24;
96
+ const nx = PAIR_INDEX[posMove[row + PAIR_A[x]] * 24 + posMove[row + PAIR_B[x]]];
97
+ const ny = PAIR_INDEX[posMove[row + PAIR_A[y]] * 24 + posMove[row + PAIR_B[y]]];
98
+ const t = nx * PAIR_STATES + ny;
99
+ if (dist[t] === 0xff) {
100
+ dist[t] = d;
101
+ queue[tail++] = t;
102
+ }
103
+ }
104
+ }
105
+ cache.set(moveCount, dist);
106
+ return dist;
107
+ }
@@ -103,12 +103,12 @@ export function applyPairingMoveToArray(arr24, move) {
103
103
  * and preserved by the phase-3 move set (verified).
104
104
  */
105
105
  export function hasPairingTransversal(wp) {
106
- const seen = new Uint8Array(12);
107
- for (const s of PAIRING_SECOND_HALVES) {
108
- const pair = wp[s] >> 1;
109
- if (seen[pair] !== 0)
106
+ let mask = 0;
107
+ for (let i = 0; i < 12; i++) {
108
+ const bit = 1 << (wp[PAIRING_SECOND_HALVES[i]] >> 1);
109
+ if ((mask & bit) !== 0)
110
110
  return false;
111
- seen[pair] = 1;
111
+ mask |= bit;
112
112
  }
113
113
  return true;
114
114
  }
@@ -8,6 +8,7 @@ import type { Cube4Move } from "../types.js";
8
8
  import { type Center3Tables } from "./center3.js";
9
9
  import { type Edge3Tables } from "./edge3.js";
10
10
  import type { Phase3Start } from "./phase3.js";
11
+ import { type HcDenseTables } from "./hc-pdb.js";
11
12
  /** The 17 exploration moves (the reference's m < 17 bound). */
12
13
  export declare const SEARCH_MOVES: readonly Cube4Move[];
13
14
  export declare const ckmv3: boolean[][];
@@ -18,25 +19,133 @@ export interface Phase3Result {
18
19
  edge: Uint8Array;
19
20
  }
20
21
  /**
21
- * Fast table-driven Phase 3 IDA* solver class.
22
+ * Goal enumeration control for the phase-3 search. The classic search
23
+ * returns the FIRST goal-reaching sequence, which for some states is
24
+ * systematically unusable downstream (e.g. uniform-but-nonstandard
25
+ * centers). With a validator, the search keeps enumerating goal sequences
26
+ * — within the same node budget — until one passes or `limit` goals have
27
+ * been examined.
22
28
  */
29
+ export interface Phase3SolutionValidator {
30
+ /** Max goal states to examine per call (bounds the extra cost). */
31
+ limit: number;
32
+ /** Goals examined so far (reset per call). */
33
+ examined: number;
34
+ /**
35
+ * Inspect a goal-reaching move sequence. Return true to accept it (stops
36
+ * the whole search); false keeps searching until `limit` goals examined.
37
+ */
38
+ validate: (moves: Cube4Move[]) => boolean;
39
+ }
23
40
  export declare class FastPhase3Solver {
24
41
  private readonly tempep;
25
42
  private readonly moveLog;
26
43
  private readonly sym;
44
+ /** Transposition Table size: 2^20 = 1,048,576 entries (12 MiB per solve).
45
+ * The previous 2M table used 24 MiB per process, plus a separate 8 MiB
46
+ * generation array. The compact 1M table leaves room for concurrent
47
+ * solvers under the 150 MiB reduction-table budget. */
48
+ private static readonly TT_SIZE;
49
+ private static readonly TT_MASK;
50
+ private readonly tt;
51
+ private static readonly CALL_ID_LIMIT;
52
+ private callSeq;
53
+ private callId;
54
+ private contextCenter3;
55
+ private contextEdge3;
56
+ /** Reset this solver's cumulative node counter (legacy method name). */
57
+ resetEpochNodes(): void;
58
+ clearTranspositionTable(): void;
59
+ private setTableContext;
60
+ /** Fresh per-call id for TT-generation tagging. */
61
+ private nextCallId;
27
62
  constructor();
28
- private getPrun;
63
+ private ensureDepth;
64
+ private nodeCount;
65
+ /** Cumulative nodes across calls (reset per solve generation). */
66
+ epochNodes: number;
67
+ /**
68
+ * Proof bookkeeping for IDA* threshold propagation (reset per exact-length
69
+ * call). When a length-L search exhausts its tree WITHOUT hitting any of
70
+ * these flags, no (center, edge) solution exists at any length below
71
+ * `minExcess`, so the caller may skip straight to it:
72
+ * - `capped`: the node budget aborted the search (bounds unknown).
73
+ * - `limitHit`: goal enumeration hit its cap (tree not exhausted).
74
+ * - `sawGoal`: a goal was reached (even if the validator rejected it —
75
+ * a nearby length may still validate, so only step L+1).
76
+ * - `ttTouched`: a transposition-table hit from ANOTHER exact-length call
77
+ * skipped a subtree, and the hit was not certified goal-free across
78
+ * candidate validators.
79
+ * Bound-based axis skips need no flag: the skipped siblings are
80
+ * same-face turns, so noteExcess records their triangle-inequality bound.
81
+ */
82
+ private capped;
83
+ private limitHit;
84
+ private sawGoal;
85
+ private ttTouched;
86
+ private minExcess;
87
+ /**
88
+ * Root-length coverage of the tightest TT hit this call (depth +
89
+ * storedDepth): the pruned subtree proves no goal at or below that root
90
+ * length under the call's predicate. `Number.MAX_SAFE_INTEGER` when no hit
91
+ * pruned anything. Feeds `validatedThrough`.
92
+ */
93
+ private ttCoverage;
94
+ /**
95
+ * Recursive IDA* worker on table transitions with Transposition Table pruning.
96
+ */
97
+ search(eplast: Uint8Array, ct: number, prun: number, maxl: number, lm: number, depth: number, center3Tables: Center3Tables, edge3Distances: Uint8Array, maxNodes?: number, collect?: Phase3SolutionValidator, hc?: HcDenseTables, hcCoord?: number, c3PairDist?: Uint8Array): boolean;
98
+ /**
99
+ * Record an IDA* bound prune (inlined at the four gate sites): the child at
100
+ * `depth + 1` needs at least `childBound` more moves, so no solution exists
101
+ * through this branch below root threshold `depth + 1 + childBound`. When a
102
+ * bound-based axis skip also fires, the skipped siblings are same-face turns
103
+ * (verified: every non-empty skipAxis3 run under m < 14 is a same-base
104
+ * triple), hence at most 1 legal move apart — their bound is at least
105
+ * `childBound - 1` by the triangle inequality on the exact PDBs, so the
106
+ * recorded excess `depth + childBound` stays a true lower bound.
107
+ */
108
+ /**
109
+ * Search for a phase-3 solution with exact target length (first found).
110
+ */
111
+ solveLength(edge: Uint8Array, ct3: number, edist: number, length3: number, center3Tables: Center3Tables, edge3Distances: Uint8Array, maxNodes?: number, hc?: HcDenseTables, hcCoord?: number, c3PairDist?: Uint8Array): Cube4Move[] | null;
29
112
  /**
30
- * Recursive IDA* worker on table transitions.
113
+ * Search for a phase-3 solution with exact target length, accepting the
114
+ * first goal sequence that passes `validate` (up to `limit` examined,
115
+ * sharing `maxNodes`). With a validator that enforces the downstream
116
+ * requirements (reduction + standard orientation + 3x3 conversion), hard
117
+ * states whose first-found solutions are unusable get more draws from
118
+ * the same budget instead of an immediate miss.
31
119
  */
32
- search(eplast: Uint8Array, ct: number, prun: number, maxl: number, lm: number, depth: number, center3Tables: Center3Tables, edge3Distances: Uint8Array): Promise<boolean>;
120
+ solveLengthValid(edge: Uint8Array, ct3: number, edist: number, length3: number, center3Tables: Center3Tables, edge3Distances: Uint8Array, maxNodes: number | undefined, limit: number | undefined, validate: (moves: Cube4Move[]) => boolean, hc?: HcDenseTables, hcCoord?: number, c3PairDist?: Uint8Array): Cube4Move[] | null;
33
121
  /**
34
- * Search for a phase-3 solution with exact target length.
122
+ * Exact-length validated search that also reports what the call proved.
123
+ * `provenThrough` is the greatest length with provably no (center, edge)
124
+ * solution: set only when the tree was exhaustively explored with no goal
125
+ * reached, no node-cap abort, no TT hit, and complete excess info — the
126
+ * caller may then skip every shorter length for this candidate. Otherwise
127
+ * it is `length3 - 1` at most (only the attempted length is settled).
35
128
  */
36
- solveLength(edge: Uint8Array, ct3: number, edist: number, length3: number, center3Tables: Center3Tables, edge3Distances: Uint8Array): Promise<Cube4Move[] | null>;
129
+ solveLengthProven(edge: Uint8Array, ct3: number, edist: number, length3: number, center3Tables: Center3Tables, edge3Distances: Uint8Array, maxNodes: number | undefined, limit: number | undefined, validate: (moves: Cube4Move[]) => boolean, hc?: HcDenseTables, hcCoord?: number, c3PairDist?: Uint8Array): {
130
+ moves: Cube4Move[] | null;
131
+ provenThrough: number;
132
+ validatedThrough: number;
133
+ nodesUsed: number;
134
+ };
37
135
  }
136
+ /** Temporary instrumentation for proof-statistics (CUBE4_PROOF_STATS=1). */
137
+ export declare const proofStats: {
138
+ total: number;
139
+ capped: number;
140
+ limitHit: number;
141
+ sawGoal: number;
142
+ ttTouched: number;
143
+ clean: number;
144
+ jumpSum: number;
145
+ };
146
+ export declare function resetProofStats(): void;
38
147
  /**
39
148
  * Solve Phase 3 with iterative deepening on a single Phase3Start.
40
149
  */
41
- export declare function solvePhase3(start: Phase3Start, center3Tables: Center3Tables, edge3Tables: Edge3Tables, maxLength?: number): Promise<Phase3Result | null>;
150
+ export declare function solvePhase3(start: Phase3Start, center3Tables: Center3Tables, edge3Tables: Edge3Tables, maxLength?: number, maxNodes?: number): Promise<Phase3Result | null>;
42
151
  //# sourceMappingURL=phase3-search.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"phase3-search.d.ts","sourceRoot":"","sources":["../../../../src/puzzles/cube4/reduction/phase3-search.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAIL,KAAK,WAAW,EAEjB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,+DAA+D;AAC/D,eAAO,MAAM,YAAY,EAAE,SAAS,SAAS,EAA+B,CAAC;AAa7E,eAAO,MAAM,KAAK,EAAE,OAAO,EAAE,EAAgE,CAAC;AAO9F,eAAO,MAAM,SAAS,EAAE,MAAM,EAA2B,CAAC;AAU1D,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;;IAQhC,OAAO,CAAC,OAAO;IAKf;;OAEG;IACU,MAAM,CACjB,MAAM,EAAE,UAAU,EAClB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,UAAU,GACzB,OAAO,CAAC,OAAO,CAAC;IA8DnB;;OAEG;IACU,WAAW,CACtB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,UAAU,GACzB,OAAO,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC;CAkB/B;AAID;;GAEG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,WAAW,EACxB,SAAS,SAAK,GACb,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAmC9B"}
1
+ {"version":3,"file":"phase3-search.d.ts","sourceRoot":"","sources":["../../../../src/puzzles/cube4/reduction/phase3-search.ts"],"names":[],"mappings":"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"}