graphwise 1.1.1 → 1.3.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 (147) hide show
  1. package/README.md +149 -2
  2. package/dist/expansion/frontier-balanced.d.ts +12 -0
  3. package/dist/expansion/frontier-balanced.d.ts.map +1 -0
  4. package/dist/expansion/frontier-balanced.unit.test.d.ts +2 -0
  5. package/dist/expansion/frontier-balanced.unit.test.d.ts.map +1 -0
  6. package/dist/expansion/index.d.ts +12 -13
  7. package/dist/expansion/index.d.ts.map +1 -1
  8. package/dist/expansion/random-priority.d.ts +20 -0
  9. package/dist/expansion/random-priority.d.ts.map +1 -0
  10. package/dist/expansion/random-priority.unit.test.d.ts +2 -0
  11. package/dist/expansion/random-priority.unit.test.d.ts.map +1 -0
  12. package/dist/expansion/standard-bfs.d.ts +12 -0
  13. package/dist/expansion/standard-bfs.d.ts.map +1 -0
  14. package/dist/expansion/standard-bfs.unit.test.d.ts +2 -0
  15. package/dist/expansion/standard-bfs.unit.test.d.ts.map +1 -0
  16. package/dist/extraction/index.d.ts +6 -6
  17. package/dist/extraction/index.d.ts.map +1 -1
  18. package/dist/extraction/motif.d.ts.map +1 -1
  19. package/dist/gpu/context.d.ts.map +1 -1
  20. package/dist/gpu/csr.d.ts.map +1 -1
  21. package/dist/gpu/index.cjs +410 -5
  22. package/dist/gpu/index.cjs.map +1 -0
  23. package/dist/gpu/index.d.ts +4 -5
  24. package/dist/gpu/index.d.ts.map +1 -1
  25. package/dist/gpu/index.js +400 -2
  26. package/dist/gpu/index.js.map +1 -0
  27. package/dist/graph/index.cjs +222 -2
  28. package/dist/graph/index.cjs.map +1 -0
  29. package/dist/graph/index.d.ts +3 -3
  30. package/dist/graph/index.d.ts.map +1 -1
  31. package/dist/graph/index.js +221 -1
  32. package/dist/graph/index.js.map +1 -0
  33. package/dist/index/index.cjs +966 -126
  34. package/dist/index/index.cjs.map +1 -1
  35. package/dist/index/index.js +939 -126
  36. package/dist/index/index.js.map +1 -1
  37. package/dist/{kmeans-B0HEOU6k.cjs → kmeans-87ExSUNZ.js} +27 -13
  38. package/dist/{kmeans-DgbsOznU.js.map → kmeans-87ExSUNZ.js.map} +1 -1
  39. package/dist/{kmeans-DgbsOznU.js → kmeans-BIgSyGKu.cjs} +44 -2
  40. package/dist/{kmeans-B0HEOU6k.cjs.map → kmeans-BIgSyGKu.cjs.map} +1 -1
  41. package/dist/ranking/baselines/betweenness.d.ts +13 -0
  42. package/dist/ranking/baselines/betweenness.d.ts.map +1 -0
  43. package/dist/ranking/baselines/betweenness.unit.test.d.ts +2 -0
  44. package/dist/ranking/baselines/betweenness.unit.test.d.ts.map +1 -0
  45. package/dist/ranking/baselines/communicability.d.ts +13 -0
  46. package/dist/ranking/baselines/communicability.d.ts.map +1 -0
  47. package/dist/ranking/baselines/communicability.unit.test.d.ts +2 -0
  48. package/dist/ranking/baselines/communicability.unit.test.d.ts.map +1 -0
  49. package/dist/ranking/baselines/degree-sum.d.ts +13 -0
  50. package/dist/ranking/baselines/degree-sum.d.ts.map +1 -0
  51. package/dist/ranking/baselines/degree-sum.unit.test.d.ts +2 -0
  52. package/dist/ranking/baselines/degree-sum.unit.test.d.ts.map +1 -0
  53. package/dist/ranking/baselines/index.d.ts +20 -0
  54. package/dist/ranking/baselines/index.d.ts.map +1 -0
  55. package/dist/ranking/baselines/jaccard-arithmetic.d.ts +13 -0
  56. package/dist/ranking/baselines/jaccard-arithmetic.d.ts.map +1 -0
  57. package/dist/ranking/baselines/jaccard-arithmetic.unit.test.d.ts +2 -0
  58. package/dist/ranking/baselines/jaccard-arithmetic.unit.test.d.ts.map +1 -0
  59. package/dist/ranking/baselines/katz.d.ts +13 -0
  60. package/dist/ranking/baselines/katz.d.ts.map +1 -0
  61. package/dist/ranking/baselines/katz.unit.test.d.ts +2 -0
  62. package/dist/ranking/baselines/katz.unit.test.d.ts.map +1 -0
  63. package/dist/ranking/baselines/pagerank.d.ts +13 -0
  64. package/dist/ranking/baselines/pagerank.d.ts.map +1 -0
  65. package/dist/ranking/baselines/pagerank.unit.test.d.ts +2 -0
  66. package/dist/ranking/baselines/pagerank.unit.test.d.ts.map +1 -0
  67. package/dist/ranking/baselines/random-ranking.d.ts +21 -0
  68. package/dist/ranking/baselines/random-ranking.d.ts.map +1 -0
  69. package/dist/ranking/baselines/random-ranking.unit.test.d.ts +2 -0
  70. package/dist/ranking/baselines/random-ranking.unit.test.d.ts.map +1 -0
  71. package/dist/ranking/baselines/resistance-distance.d.ts +13 -0
  72. package/dist/ranking/baselines/resistance-distance.d.ts.map +1 -0
  73. package/dist/ranking/baselines/resistance-distance.unit.test.d.ts +2 -0
  74. package/dist/ranking/baselines/resistance-distance.unit.test.d.ts.map +1 -0
  75. package/dist/ranking/baselines/widest-path.d.ts +13 -0
  76. package/dist/ranking/baselines/widest-path.d.ts.map +1 -0
  77. package/dist/ranking/baselines/widest-path.unit.test.d.ts +2 -0
  78. package/dist/ranking/baselines/widest-path.unit.test.d.ts.map +1 -0
  79. package/dist/ranking/index.d.ts +3 -6
  80. package/dist/ranking/index.d.ts.map +1 -1
  81. package/dist/ranking/mi/adamic-adar.d.ts.map +1 -1
  82. package/dist/ranking/mi/adaptive.d.ts +1 -1
  83. package/dist/ranking/mi/adaptive.d.ts.map +1 -1
  84. package/dist/ranking/mi/etch.d.ts.map +1 -1
  85. package/dist/ranking/mi/index.d.ts +9 -9
  86. package/dist/ranking/mi/index.d.ts.map +1 -1
  87. package/dist/ranking/mi/jaccard.d.ts.map +1 -1
  88. package/dist/ranking/mi/notch.d.ts.map +1 -1
  89. package/dist/ranking/mi/scale.d.ts.map +1 -1
  90. package/dist/ranking/mi/skew.d.ts.map +1 -1
  91. package/dist/ranking/mi/span.d.ts.map +1 -1
  92. package/dist/schemas/index.d.ts +2 -2
  93. package/dist/schemas/index.d.ts.map +1 -1
  94. package/dist/seeds/index.cjs +398 -3
  95. package/dist/seeds/index.cjs.map +1 -0
  96. package/dist/seeds/index.d.ts +2 -4
  97. package/dist/seeds/index.d.ts.map +1 -1
  98. package/dist/seeds/index.js +396 -1
  99. package/dist/seeds/index.js.map +1 -0
  100. package/dist/seeds/stratified.d.ts.map +1 -1
  101. package/dist/structures/index.cjs +133 -2
  102. package/dist/structures/index.cjs.map +1 -0
  103. package/dist/structures/index.d.ts +1 -2
  104. package/dist/structures/index.d.ts.map +1 -1
  105. package/dist/structures/index.js +132 -1
  106. package/dist/structures/index.js.map +1 -0
  107. package/dist/traversal/index.cjs +152 -5
  108. package/dist/traversal/index.cjs.map +1 -0
  109. package/dist/traversal/index.d.ts +2 -2
  110. package/dist/traversal/index.d.ts.map +1 -1
  111. package/dist/traversal/index.js +148 -1
  112. package/dist/traversal/index.js.map +1 -0
  113. package/dist/utils/index.cjs +254 -9
  114. package/dist/utils/index.cjs.map +1 -0
  115. package/dist/utils/index.d.ts +4 -3
  116. package/dist/utils/index.d.ts.map +1 -1
  117. package/dist/utils/index.js +242 -3
  118. package/dist/utils/index.js.map +1 -0
  119. package/dist/utils/neighbours.d.ts +54 -0
  120. package/dist/utils/neighbours.d.ts.map +1 -0
  121. package/dist/utils/neighbours.unit.test.d.ts +5 -0
  122. package/dist/utils/neighbours.unit.test.d.ts.map +1 -0
  123. package/package.json +1 -1
  124. package/dist/gpu-BJRVYBjx.cjs +0 -338
  125. package/dist/gpu-BJRVYBjx.cjs.map +0 -1
  126. package/dist/gpu-BveuXugy.js +0 -315
  127. package/dist/gpu-BveuXugy.js.map +0 -1
  128. package/dist/graph-DLWiziLB.js +0 -222
  129. package/dist/graph-DLWiziLB.js.map +0 -1
  130. package/dist/graph-az06J1YV.cjs +0 -227
  131. package/dist/graph-az06J1YV.cjs.map +0 -1
  132. package/dist/seeds-B6J9oJfU.cjs +0 -404
  133. package/dist/seeds-B6J9oJfU.cjs.map +0 -1
  134. package/dist/seeds-UNZxqm_U.js +0 -393
  135. package/dist/seeds-UNZxqm_U.js.map +0 -1
  136. package/dist/structures-BPfhfqNP.js +0 -133
  137. package/dist/structures-BPfhfqNP.js.map +0 -1
  138. package/dist/structures-CJ_S_7fs.cjs +0 -138
  139. package/dist/structures-CJ_S_7fs.cjs.map +0 -1
  140. package/dist/traversal-CQCjUwUJ.js +0 -149
  141. package/dist/traversal-CQCjUwUJ.js.map +0 -1
  142. package/dist/traversal-QeHaNUWn.cjs +0 -172
  143. package/dist/traversal-QeHaNUWn.cjs.map +0 -1
  144. package/dist/utils-Q_akvlMn.js +0 -164
  145. package/dist/utils-Q_akvlMn.js.map +0 -1
  146. package/dist/utils-spZa1ZvS.cjs +0 -205
  147. package/dist/utils-spZa1ZvS.cjs.map +0 -1
@@ -1,138 +0,0 @@
1
- //#region src/structures/priority-queue.ts
2
- /**
3
- * Min-heap priority queue implementation using an array-based binary heap.
4
- * Lower priority values have higher precedence (extracted first).
5
- */
6
- var PriorityQueue = class {
7
- heap = [];
8
- /**
9
- * Returns the number of items in the queue.
10
- */
11
- size() {
12
- return this.heap.length;
13
- }
14
- /**
15
- * Returns true if the queue is empty.
16
- */
17
- isEmpty() {
18
- return this.heap.length === 0;
19
- }
20
- /**
21
- * Adds an item with the given priority to the queue.
22
- */
23
- push(item, priority) {
24
- const entry = {
25
- item,
26
- priority
27
- };
28
- this.heap.push(entry);
29
- this.heapifyUp(this.heap.length - 1);
30
- }
31
- /**
32
- * Removes and returns the highest precedence item (lowest priority value).
33
- * Returns undefined if the queue is empty.
34
- */
35
- pop() {
36
- if (this.heap.length === 0) return;
37
- const root = this.heap[0];
38
- if (root === void 0) return;
39
- const last = this.heap.pop();
40
- if (last === void 0) return root;
41
- if (this.heap.length > 0) {
42
- this.heap[0] = last;
43
- this.heapifyDown(0);
44
- }
45
- return root;
46
- }
47
- /**
48
- * Returns the highest precedence item without removing it.
49
- * Returns undefined if the queue is empty.
50
- */
51
- peek() {
52
- return this.heap[0];
53
- }
54
- /**
55
- * Rebuilds the heap from the current array state.
56
- * Useful when priorities have been modified externally (e.g., phase transitions).
57
- */
58
- rebuild() {
59
- const start = Math.floor(this.heap.length / 2) - 1;
60
- for (let i = start; i >= 0; i--) this.heapifyDown(i);
61
- }
62
- /**
63
- * Decreases the priority of an existing item in the queue.
64
- * Returns true if the item was found and updated, false otherwise.
65
- *
66
- * @param item - The item to find
67
- * @param newPriority - The new (lower) priority value
68
- * @param equals - Function to compare items for equality
69
- */
70
- decreaseKey(item, newPriority, equals) {
71
- let foundIndex = -1;
72
- for (let i = 0; i < this.heap.length; i++) {
73
- const entry = this.heap[i];
74
- if (entry !== void 0 && equals(entry.item, item)) {
75
- foundIndex = i;
76
- break;
77
- }
78
- }
79
- if (foundIndex === -1) return false;
80
- const entry = this.heap[foundIndex];
81
- if (entry === void 0) return false;
82
- if (newPriority >= entry.priority) return false;
83
- entry.priority = newPriority;
84
- this.heapifyUp(foundIndex);
85
- return true;
86
- }
87
- /**
88
- * Restores heap property by moving element up from given index.
89
- */
90
- heapifyUp(index) {
91
- let current = index;
92
- while (current > 0) {
93
- const parent = Math.floor((current - 1) / 2);
94
- const currentEntry = this.heap[current];
95
- const parentEntry = this.heap[parent];
96
- if (currentEntry === void 0 || parentEntry === void 0) return;
97
- if (currentEntry.priority >= parentEntry.priority) return;
98
- this.heap[current] = parentEntry;
99
- this.heap[parent] = currentEntry;
100
- current = parent;
101
- }
102
- }
103
- /**
104
- * Restores heap property by moving element down from given index.
105
- */
106
- heapifyDown(index) {
107
- let current = index;
108
- const length = this.heap.length;
109
- while (current < length) {
110
- const left = 2 * current + 1;
111
- const right = 2 * current + 2;
112
- let smallest = current;
113
- const currentEntry = this.heap[current];
114
- if (currentEntry === void 0) return;
115
- const leftEntry = this.heap[left];
116
- if (left < length && leftEntry !== void 0 && leftEntry.priority < currentEntry.priority) smallest = left;
117
- const rightEntry = this.heap[right];
118
- const currentSmallestEntry = this.heap[smallest];
119
- if (right < length && rightEntry !== void 0 && currentSmallestEntry !== void 0 && rightEntry.priority < currentSmallestEntry.priority) smallest = right;
120
- if (smallest === current) return;
121
- const finalSmallestEntry = this.heap[smallest];
122
- if (finalSmallestEntry !== void 0) {
123
- this.heap[current] = finalSmallestEntry;
124
- this.heap[smallest] = currentEntry;
125
- current = smallest;
126
- } else return;
127
- }
128
- }
129
- };
130
- //#endregion
131
- Object.defineProperty(exports, "PriorityQueue", {
132
- enumerable: true,
133
- get: function() {
134
- return PriorityQueue;
135
- }
136
- });
137
-
138
- //# sourceMappingURL=structures-CJ_S_7fs.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"structures-CJ_S_7fs.cjs","names":[],"sources":["../src/structures/priority-queue.ts"],"sourcesContent":["/**\n * Priority queue entry containing an item and its priority.\n */\nexport interface PriorityEntry<T> {\n\titem: T;\n\tpriority: number;\n}\n\n/**\n * Min-heap priority queue implementation using an array-based binary heap.\n * Lower priority values have higher precedence (extracted first).\n */\nexport class PriorityQueue<T> {\n\tprivate heap: PriorityEntry<T>[] = [];\n\n\t/**\n\t * Returns the number of items in the queue.\n\t */\n\tpublic size(): number {\n\t\treturn this.heap.length;\n\t}\n\n\t/**\n\t * Returns true if the queue is empty.\n\t */\n\tpublic isEmpty(): boolean {\n\t\treturn this.heap.length === 0;\n\t}\n\n\t/**\n\t * Adds an item with the given priority to the queue.\n\t */\n\tpublic push(item: T, priority: number): void {\n\t\tconst entry: PriorityEntry<T> = { item, priority };\n\t\tthis.heap.push(entry);\n\t\tthis.heapifyUp(this.heap.length - 1);\n\t}\n\n\t/**\n\t * Removes and returns the highest precedence item (lowest priority value).\n\t * Returns undefined if the queue is empty.\n\t */\n\tpublic pop(): PriorityEntry<T> | undefined {\n\t\tif (this.heap.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst root = this.heap[0];\n\t\tif (root === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst last = this.heap.pop();\n\t\tif (last === undefined) {\n\t\t\treturn root;\n\t\t}\n\n\t\tif (this.heap.length > 0) {\n\t\t\tthis.heap[0] = last;\n\t\t\tthis.heapifyDown(0);\n\t\t}\n\n\t\treturn root;\n\t}\n\n\t/**\n\t * Returns the highest precedence item without removing it.\n\t * Returns undefined if the queue is empty.\n\t */\n\tpublic peek(): PriorityEntry<T> | undefined {\n\t\treturn this.heap[0];\n\t}\n\n\t/**\n\t * Rebuilds the heap from the current array state.\n\t * Useful when priorities have been modified externally (e.g., phase transitions).\n\t */\n\tpublic rebuild(): void {\n\t\t// Floyd's algorithm: heapify down from last non-leaf to root\n\t\tconst start = Math.floor(this.heap.length / 2) - 1;\n\t\tfor (let i = start; i >= 0; i--) {\n\t\t\tthis.heapifyDown(i);\n\t\t}\n\t}\n\n\t/**\n\t * Decreases the priority of an existing item in the queue.\n\t * Returns true if the item was found and updated, false otherwise.\n\t *\n\t * @param item - The item to find\n\t * @param newPriority - The new (lower) priority value\n\t * @param equals - Function to compare items for equality\n\t */\n\tpublic decreaseKey(\n\t\titem: T,\n\t\tnewPriority: number,\n\t\tequals: (a: T, b: T) => boolean,\n\t): boolean {\n\t\tlet foundIndex = -1;\n\n\t\tfor (let i = 0; i < this.heap.length; i++) {\n\t\t\tconst entry = this.heap[i];\n\t\t\tif (entry !== undefined && equals(entry.item, item)) {\n\t\t\t\tfoundIndex = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (foundIndex === -1) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst entry = this.heap[foundIndex];\n\t\tif (entry === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Only update if new priority is lower (higher precedence)\n\t\tif (newPriority >= entry.priority) {\n\t\t\treturn false;\n\t\t}\n\n\t\tentry.priority = newPriority;\n\t\tthis.heapifyUp(foundIndex);\n\t\treturn true;\n\t}\n\n\t/**\n\t * Restores heap property by moving element up from given index.\n\t */\n\tprivate heapifyUp(index: number): void {\n\t\tlet current = index;\n\n\t\twhile (current > 0) {\n\t\t\tconst parent = Math.floor((current - 1) / 2);\n\t\t\tconst currentEntry = this.heap[current];\n\t\t\tconst parentEntry = this.heap[parent];\n\n\t\t\tif (currentEntry === undefined || parentEntry === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (currentEntry.priority >= parentEntry.priority) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Swap current and parent\n\t\t\tthis.heap[current] = parentEntry;\n\t\t\tthis.heap[parent] = currentEntry;\n\t\t\tcurrent = parent;\n\t\t}\n\t}\n\n\t/**\n\t * Restores heap property by moving element down from given index.\n\t */\n\tprivate heapifyDown(index: number): void {\n\t\tlet current = index;\n\t\tconst length = this.heap.length;\n\n\t\twhile (current < length) {\n\t\t\tconst left = 2 * current + 1;\n\t\t\tconst right = 2 * current + 2;\n\t\t\tlet smallest = current;\n\n\t\t\tconst currentEntry = this.heap[current];\n\t\t\tif (currentEntry === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Compare with left child\n\t\t\tconst leftEntry = this.heap[left];\n\t\t\tif (\n\t\t\t\tleft < length &&\n\t\t\t\tleftEntry !== undefined &&\n\t\t\t\tleftEntry.priority < currentEntry.priority\n\t\t\t) {\n\t\t\t\tsmallest = left;\n\t\t\t}\n\n\t\t\t// Compare with right child (need to re-fetch smallest after potential update)\n\t\t\tconst rightEntry = this.heap[right];\n\t\t\tconst currentSmallestEntry = this.heap[smallest];\n\t\t\tif (\n\t\t\t\tright < length &&\n\t\t\t\trightEntry !== undefined &&\n\t\t\t\tcurrentSmallestEntry !== undefined &&\n\t\t\t\trightEntry.priority < currentSmallestEntry.priority\n\t\t\t) {\n\t\t\t\tsmallest = right;\n\t\t\t}\n\n\t\t\tif (smallest === current) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Get the final smallest entry (after determining final smallest index)\n\t\t\tconst finalSmallestEntry = this.heap[smallest];\n\t\t\tif (finalSmallestEntry !== undefined) {\n\t\t\t\tthis.heap[current] = finalSmallestEntry;\n\t\t\t\tthis.heap[smallest] = currentEntry;\n\t\t\t\tcurrent = smallest;\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n}\n"],"mappings":";;;;;AAYA,IAAa,gBAAb,MAA8B;CAC7B,OAAmC,EAAE;;;;CAKrC,OAAsB;AACrB,SAAO,KAAK,KAAK;;;;;CAMlB,UAA0B;AACzB,SAAO,KAAK,KAAK,WAAW;;;;;CAM7B,KAAY,MAAS,UAAwB;EAC5C,MAAM,QAA0B;GAAE;GAAM;GAAU;AAClD,OAAK,KAAK,KAAK,MAAM;AACrB,OAAK,UAAU,KAAK,KAAK,SAAS,EAAE;;;;;;CAOrC,MAA2C;AAC1C,MAAI,KAAK,KAAK,WAAW,EACxB;EAGD,MAAM,OAAO,KAAK,KAAK;AACvB,MAAI,SAAS,KAAA,EACZ;EAGD,MAAM,OAAO,KAAK,KAAK,KAAK;AAC5B,MAAI,SAAS,KAAA,EACZ,QAAO;AAGR,MAAI,KAAK,KAAK,SAAS,GAAG;AACzB,QAAK,KAAK,KAAK;AACf,QAAK,YAAY,EAAE;;AAGpB,SAAO;;;;;;CAOR,OAA4C;AAC3C,SAAO,KAAK,KAAK;;;;;;CAOlB,UAAuB;EAEtB,MAAM,QAAQ,KAAK,MAAM,KAAK,KAAK,SAAS,EAAE,GAAG;AACjD,OAAK,IAAI,IAAI,OAAO,KAAK,GAAG,IAC3B,MAAK,YAAY,EAAE;;;;;;;;;;CAYrB,YACC,MACA,aACA,QACU;EACV,IAAI,aAAa;AAEjB,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK,QAAQ,KAAK;GAC1C,MAAM,QAAQ,KAAK,KAAK;AACxB,OAAI,UAAU,KAAA,KAAa,OAAO,MAAM,MAAM,KAAK,EAAE;AACpD,iBAAa;AACb;;;AAIF,MAAI,eAAe,GAClB,QAAO;EAGR,MAAM,QAAQ,KAAK,KAAK;AACxB,MAAI,UAAU,KAAA,EACb,QAAO;AAIR,MAAI,eAAe,MAAM,SACxB,QAAO;AAGR,QAAM,WAAW;AACjB,OAAK,UAAU,WAAW;AAC1B,SAAO;;;;;CAMR,UAAkB,OAAqB;EACtC,IAAI,UAAU;AAEd,SAAO,UAAU,GAAG;GACnB,MAAM,SAAS,KAAK,OAAO,UAAU,KAAK,EAAE;GAC5C,MAAM,eAAe,KAAK,KAAK;GAC/B,MAAM,cAAc,KAAK,KAAK;AAE9B,OAAI,iBAAiB,KAAA,KAAa,gBAAgB,KAAA,EACjD;AAGD,OAAI,aAAa,YAAY,YAAY,SACxC;AAID,QAAK,KAAK,WAAW;AACrB,QAAK,KAAK,UAAU;AACpB,aAAU;;;;;;CAOZ,YAAoB,OAAqB;EACxC,IAAI,UAAU;EACd,MAAM,SAAS,KAAK,KAAK;AAEzB,SAAO,UAAU,QAAQ;GACxB,MAAM,OAAO,IAAI,UAAU;GAC3B,MAAM,QAAQ,IAAI,UAAU;GAC5B,IAAI,WAAW;GAEf,MAAM,eAAe,KAAK,KAAK;AAC/B,OAAI,iBAAiB,KAAA,EACpB;GAID,MAAM,YAAY,KAAK,KAAK;AAC5B,OACC,OAAO,UACP,cAAc,KAAA,KACd,UAAU,WAAW,aAAa,SAElC,YAAW;GAIZ,MAAM,aAAa,KAAK,KAAK;GAC7B,MAAM,uBAAuB,KAAK,KAAK;AACvC,OACC,QAAQ,UACR,eAAe,KAAA,KACf,yBAAyB,KAAA,KACzB,WAAW,WAAW,qBAAqB,SAE3C,YAAW;AAGZ,OAAI,aAAa,QAChB;GAID,MAAM,qBAAqB,KAAK,KAAK;AACrC,OAAI,uBAAuB,KAAA,GAAW;AACrC,SAAK,KAAK,WAAW;AACrB,SAAK,KAAK,YAAY;AACtB,cAAU;SAEV"}
@@ -1,149 +0,0 @@
1
- //#region src/traversal/bfs.ts
2
- /**
3
- * Perform a breadth-first search traversal from a start node.
4
- *
5
- * This generator yields node IDs in BFS order. It uses lazy evaluation
6
- * via a generator, making it memory-efficient for large graphs.
7
- *
8
- * @param graph - The graph to traverse
9
- * @param start - The starting node ID
10
- * @yields Node IDs in BFS order
11
- *
12
- * @example
13
- * ```typescript
14
- * for (const nodeId of bfs(graph, "A")) {
15
- * console.log(nodeId);
16
- * }
17
- * ```
18
- */
19
- function* bfs(graph, start) {
20
- if (!graph.hasNode(start)) return;
21
- const visited = new Set([start]);
22
- const queue = [start];
23
- while (queue.length > 0) {
24
- const current = queue.shift();
25
- if (current === void 0) break;
26
- yield current;
27
- for (const neighbour of graph.neighbours(current)) if (!visited.has(neighbour)) {
28
- visited.add(neighbour);
29
- queue.push(neighbour);
30
- }
31
- }
32
- }
33
- /**
34
- * Perform a breadth-first search traversal with path information.
35
- *
36
- * This generator yields detailed information about each visited node,
37
- * including its depth from the start and parent in the BFS tree.
38
- * Useful for reconstructing shortest paths.
39
- *
40
- * @param graph - The graph to traverse
41
- * @param start - The starting node ID
42
- * @yields Objects containing node ID, depth, and parent
43
- *
44
- * @example
45
- * ```typescript
46
- * for (const entry of bfsWithPath(graph, "A")) {
47
- * console.log(`${entry.node} at depth ${entry.depth}`);
48
- * }
49
- * ```
50
- */
51
- function* bfsWithPath(graph, start) {
52
- if (!graph.hasNode(start)) return;
53
- const visited = new Set([start]);
54
- const queue = [{
55
- node: start,
56
- depth: 0,
57
- parent: void 0
58
- }];
59
- while (queue.length > 0) {
60
- const current = queue.shift();
61
- if (current === void 0) break;
62
- yield current;
63
- for (const neighbour of graph.neighbours(current.node)) if (!visited.has(neighbour)) {
64
- visited.add(neighbour);
65
- queue.push({
66
- node: neighbour,
67
- depth: current.depth + 1,
68
- parent: current.node
69
- });
70
- }
71
- }
72
- }
73
- //#endregion
74
- //#region src/traversal/dfs.ts
75
- /**
76
- * Perform a depth-first search traversal from a start node.
77
- *
78
- * This generator yields node IDs in DFS order (pre-order traversal).
79
- * It uses lazy evaluation via a generator, making it memory-efficient
80
- * for large graphs.
81
- *
82
- * @param graph - The graph to traverse
83
- * @param start - The starting node ID
84
- * @yields Node IDs in DFS order
85
- *
86
- * @example
87
- * ```typescript
88
- * for (const nodeId of dfs(graph, "A")) {
89
- * console.log(nodeId);
90
- * }
91
- * ```
92
- */
93
- function* dfs(graph, start) {
94
- if (!graph.hasNode(start)) return;
95
- const visited = /* @__PURE__ */ new Set();
96
- const stack = [start];
97
- while (stack.length > 0) {
98
- const current = stack.pop();
99
- if (current === void 0) break;
100
- if (visited.has(current)) continue;
101
- visited.add(current);
102
- yield current;
103
- const neighbours = [...graph.neighbours(current)].reverse();
104
- for (const neighbour of neighbours) if (!visited.has(neighbour)) stack.push(neighbour);
105
- }
106
- }
107
- /**
108
- * Perform a depth-first search traversal with path information.
109
- *
110
- * This generator yields detailed information about each visited node,
111
- * including its depth from the start and parent in the DFS tree.
112
- *
113
- * @param graph - The graph to traverse
114
- * @param start - The starting node ID
115
- * @yields Objects containing node ID, depth, and parent
116
- *
117
- * @example
118
- * ```typescript
119
- * for (const entry of dfsWithPath(graph, "A")) {
120
- * console.log(`${entry.node} at depth ${entry.depth}`);
121
- * }
122
- * ```
123
- */
124
- function* dfsWithPath(graph, start) {
125
- if (!graph.hasNode(start)) return;
126
- const visited = /* @__PURE__ */ new Set();
127
- const stack = [{
128
- node: start,
129
- depth: 0,
130
- parent: void 0
131
- }];
132
- while (stack.length > 0) {
133
- const current = stack.pop();
134
- if (current === void 0) break;
135
- if (visited.has(current.node)) continue;
136
- visited.add(current.node);
137
- yield current;
138
- const neighbours = [...graph.neighbours(current.node)].reverse();
139
- for (const neighbour of neighbours) if (!visited.has(neighbour)) stack.push({
140
- node: neighbour,
141
- depth: current.depth + 1,
142
- parent: current.node
143
- });
144
- }
145
- }
146
- //#endregion
147
- export { bfsWithPath as i, dfsWithPath as n, bfs as r, dfs as t };
148
-
149
- //# sourceMappingURL=traversal-CQCjUwUJ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"traversal-CQCjUwUJ.js","names":[],"sources":["../src/traversal/bfs.ts","../src/traversal/dfs.ts"],"sourcesContent":["/**\n * Breadth-first search traversal algorithms.\n *\n * BFS explores nodes level by level, visiting all neighbours at the current\n * depth before moving to nodes at the next depth level. This guarantees\n * shortest path discovery in unweighted graphs.\n */\n\nimport type { ReadableGraph, NodeId } from \"../graph\";\n\n/**\n * Node visit information during BFS traversal.\n */\nexport interface BfsPathEntry {\n\t/** The visited node identifier */\n\tnode: NodeId;\n\t/** Distance from the start node (0 for start node) */\n\tdepth: number;\n\t/** Parent node in the BFS tree (undefined for start node) */\n\tparent: NodeId | undefined;\n}\n\n/**\n * Perform a breadth-first search traversal from a start node.\n *\n * This generator yields node IDs in BFS order. It uses lazy evaluation\n * via a generator, making it memory-efficient for large graphs.\n *\n * @param graph - The graph to traverse\n * @param start - The starting node ID\n * @yields Node IDs in BFS order\n *\n * @example\n * ```typescript\n * for (const nodeId of bfs(graph, \"A\")) {\n * console.log(nodeId);\n * }\n * ```\n */\nexport function* bfs(graph: ReadableGraph, start: NodeId): Iterable<NodeId> {\n\tif (!graph.hasNode(start)) {\n\t\treturn;\n\t}\n\n\tconst visited = new Set<NodeId>([start]);\n\tconst queue: NodeId[] = [start];\n\n\twhile (queue.length > 0) {\n\t\tconst current = queue.shift();\n\t\tif (current === undefined) break;\n\t\tyield current;\n\n\t\tfor (const neighbour of graph.neighbours(current)) {\n\t\t\tif (!visited.has(neighbour)) {\n\t\t\t\tvisited.add(neighbour);\n\t\t\t\tqueue.push(neighbour);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Perform a breadth-first search traversal with path information.\n *\n * This generator yields detailed information about each visited node,\n * including its depth from the start and parent in the BFS tree.\n * Useful for reconstructing shortest paths.\n *\n * @param graph - The graph to traverse\n * @param start - The starting node ID\n * @yields Objects containing node ID, depth, and parent\n *\n * @example\n * ```typescript\n * for (const entry of bfsWithPath(graph, \"A\")) {\n * console.log(`${entry.node} at depth ${entry.depth}`);\n * }\n * ```\n */\nexport function* bfsWithPath(\n\tgraph: ReadableGraph,\n\tstart: NodeId,\n): Iterable<BfsPathEntry> {\n\tif (!graph.hasNode(start)) {\n\t\treturn;\n\t}\n\n\tconst visited = new Set<NodeId>([start]);\n\tconst queue: { node: NodeId; depth: number; parent: NodeId | undefined }[] = [\n\t\t{ node: start, depth: 0, parent: undefined },\n\t];\n\n\twhile (queue.length > 0) {\n\t\tconst current = queue.shift();\n\t\tif (current === undefined) break;\n\t\tyield current;\n\n\t\tfor (const neighbour of graph.neighbours(current.node)) {\n\t\t\tif (!visited.has(neighbour)) {\n\t\t\t\tvisited.add(neighbour);\n\t\t\t\tqueue.push({\n\t\t\t\t\tnode: neighbour,\n\t\t\t\t\tdepth: current.depth + 1,\n\t\t\t\t\tparent: current.node,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * Depth-first search traversal algorithms.\n *\n * DFS explores as far as possible along each branch before backtracking.\n * This makes it useful for cycle detection, topological sorting, and\n * finding connected components.\n */\n\nimport type { ReadableGraph, NodeId } from \"../graph\";\n\n/**\n * Node visit information during DFS traversal.\n */\nexport interface DfsPathEntry {\n\t/** The visited node identifier */\n\tnode: NodeId;\n\t/** Distance from the start node (0 for start node) */\n\tdepth: number;\n\t/** Parent node in the DFS tree (undefined for start node) */\n\tparent: NodeId | undefined;\n}\n\n/**\n * Perform a depth-first search traversal from a start node.\n *\n * This generator yields node IDs in DFS order (pre-order traversal).\n * It uses lazy evaluation via a generator, making it memory-efficient\n * for large graphs.\n *\n * @param graph - The graph to traverse\n * @param start - The starting node ID\n * @yields Node IDs in DFS order\n *\n * @example\n * ```typescript\n * for (const nodeId of dfs(graph, \"A\")) {\n * console.log(nodeId);\n * }\n * ```\n */\nexport function* dfs(graph: ReadableGraph, start: NodeId): Iterable<NodeId> {\n\tif (!graph.hasNode(start)) {\n\t\treturn;\n\t}\n\n\tconst visited = new Set<NodeId>();\n\tconst stack: NodeId[] = [start];\n\n\twhile (stack.length > 0) {\n\t\tconst current = stack.pop();\n\t\tif (current === undefined) break;\n\n\t\tif (visited.has(current)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvisited.add(current);\n\t\tyield current;\n\n\t\t// Add neighbours in reverse order to maintain left-to-right traversal\n\t\t// when popping from the stack\n\t\tconst neighbours = [...graph.neighbours(current)].reverse();\n\t\tfor (const neighbour of neighbours) {\n\t\t\tif (!visited.has(neighbour)) {\n\t\t\t\tstack.push(neighbour);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Perform a depth-first search traversal with path information.\n *\n * This generator yields detailed information about each visited node,\n * including its depth from the start and parent in the DFS tree.\n *\n * @param graph - The graph to traverse\n * @param start - The starting node ID\n * @yields Objects containing node ID, depth, and parent\n *\n * @example\n * ```typescript\n * for (const entry of dfsWithPath(graph, \"A\")) {\n * console.log(`${entry.node} at depth ${entry.depth}`);\n * }\n * ```\n */\nexport function* dfsWithPath(\n\tgraph: ReadableGraph,\n\tstart: NodeId,\n): Iterable<DfsPathEntry> {\n\tif (!graph.hasNode(start)) {\n\t\treturn;\n\t}\n\n\tconst visited = new Set<NodeId>();\n\tconst stack: { node: NodeId; depth: number; parent: NodeId | undefined }[] = [\n\t\t{ node: start, depth: 0, parent: undefined },\n\t];\n\n\twhile (stack.length > 0) {\n\t\tconst current = stack.pop();\n\t\tif (current === undefined) break;\n\n\t\tif (visited.has(current.node)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvisited.add(current.node);\n\t\tyield current;\n\n\t\t// Add neighbours in reverse order to maintain left-to-right traversal\n\t\t// when popping from the stack\n\t\tconst neighbours = [...graph.neighbours(current.node)].reverse();\n\t\tfor (const neighbour of neighbours) {\n\t\t\tif (!visited.has(neighbour)) {\n\t\t\t\tstack.push({\n\t\t\t\t\tnode: neighbour,\n\t\t\t\t\tdepth: current.depth + 1,\n\t\t\t\t\tparent: current.node,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAuCA,UAAiB,IAAI,OAAsB,OAAiC;AAC3E,KAAI,CAAC,MAAM,QAAQ,MAAM,CACxB;CAGD,MAAM,UAAU,IAAI,IAAY,CAAC,MAAM,CAAC;CACxC,MAAM,QAAkB,CAAC,MAAM;AAE/B,QAAO,MAAM,SAAS,GAAG;EACxB,MAAM,UAAU,MAAM,OAAO;AAC7B,MAAI,YAAY,KAAA,EAAW;AAC3B,QAAM;AAEN,OAAK,MAAM,aAAa,MAAM,WAAW,QAAQ,CAChD,KAAI,CAAC,QAAQ,IAAI,UAAU,EAAE;AAC5B,WAAQ,IAAI,UAAU;AACtB,SAAM,KAAK,UAAU;;;;;;;;;;;;;;;;;;;;;;AAwBzB,UAAiB,YAChB,OACA,OACyB;AACzB,KAAI,CAAC,MAAM,QAAQ,MAAM,CACxB;CAGD,MAAM,UAAU,IAAI,IAAY,CAAC,MAAM,CAAC;CACxC,MAAM,QAAuE,CAC5E;EAAE,MAAM;EAAO,OAAO;EAAG,QAAQ,KAAA;EAAW,CAC5C;AAED,QAAO,MAAM,SAAS,GAAG;EACxB,MAAM,UAAU,MAAM,OAAO;AAC7B,MAAI,YAAY,KAAA,EAAW;AAC3B,QAAM;AAEN,OAAK,MAAM,aAAa,MAAM,WAAW,QAAQ,KAAK,CACrD,KAAI,CAAC,QAAQ,IAAI,UAAU,EAAE;AAC5B,WAAQ,IAAI,UAAU;AACtB,SAAM,KAAK;IACV,MAAM;IACN,OAAO,QAAQ,QAAQ;IACvB,QAAQ,QAAQ;IAChB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AChEN,UAAiB,IAAI,OAAsB,OAAiC;AAC3E,KAAI,CAAC,MAAM,QAAQ,MAAM,CACxB;CAGD,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,QAAkB,CAAC,MAAM;AAE/B,QAAO,MAAM,SAAS,GAAG;EACxB,MAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,YAAY,KAAA,EAAW;AAE3B,MAAI,QAAQ,IAAI,QAAQ,CACvB;AAGD,UAAQ,IAAI,QAAQ;AACpB,QAAM;EAIN,MAAM,aAAa,CAAC,GAAG,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS;AAC3D,OAAK,MAAM,aAAa,WACvB,KAAI,CAAC,QAAQ,IAAI,UAAU,CAC1B,OAAM,KAAK,UAAU;;;;;;;;;;;;;;;;;;;;AAuBzB,UAAiB,YAChB,OACA,OACyB;AACzB,KAAI,CAAC,MAAM,QAAQ,MAAM,CACxB;CAGD,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,QAAuE,CAC5E;EAAE,MAAM;EAAO,OAAO;EAAG,QAAQ,KAAA;EAAW,CAC5C;AAED,QAAO,MAAM,SAAS,GAAG;EACxB,MAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,YAAY,KAAA,EAAW;AAE3B,MAAI,QAAQ,IAAI,QAAQ,KAAK,CAC5B;AAGD,UAAQ,IAAI,QAAQ,KAAK;AACzB,QAAM;EAIN,MAAM,aAAa,CAAC,GAAG,MAAM,WAAW,QAAQ,KAAK,CAAC,CAAC,SAAS;AAChE,OAAK,MAAM,aAAa,WACvB,KAAI,CAAC,QAAQ,IAAI,UAAU,CAC1B,OAAM,KAAK;GACV,MAAM;GACN,OAAO,QAAQ,QAAQ;GACvB,QAAQ,QAAQ;GAChB,CAAC"}
@@ -1,172 +0,0 @@
1
- //#region src/traversal/bfs.ts
2
- /**
3
- * Perform a breadth-first search traversal from a start node.
4
- *
5
- * This generator yields node IDs in BFS order. It uses lazy evaluation
6
- * via a generator, making it memory-efficient for large graphs.
7
- *
8
- * @param graph - The graph to traverse
9
- * @param start - The starting node ID
10
- * @yields Node IDs in BFS order
11
- *
12
- * @example
13
- * ```typescript
14
- * for (const nodeId of bfs(graph, "A")) {
15
- * console.log(nodeId);
16
- * }
17
- * ```
18
- */
19
- function* bfs(graph, start) {
20
- if (!graph.hasNode(start)) return;
21
- const visited = new Set([start]);
22
- const queue = [start];
23
- while (queue.length > 0) {
24
- const current = queue.shift();
25
- if (current === void 0) break;
26
- yield current;
27
- for (const neighbour of graph.neighbours(current)) if (!visited.has(neighbour)) {
28
- visited.add(neighbour);
29
- queue.push(neighbour);
30
- }
31
- }
32
- }
33
- /**
34
- * Perform a breadth-first search traversal with path information.
35
- *
36
- * This generator yields detailed information about each visited node,
37
- * including its depth from the start and parent in the BFS tree.
38
- * Useful for reconstructing shortest paths.
39
- *
40
- * @param graph - The graph to traverse
41
- * @param start - The starting node ID
42
- * @yields Objects containing node ID, depth, and parent
43
- *
44
- * @example
45
- * ```typescript
46
- * for (const entry of bfsWithPath(graph, "A")) {
47
- * console.log(`${entry.node} at depth ${entry.depth}`);
48
- * }
49
- * ```
50
- */
51
- function* bfsWithPath(graph, start) {
52
- if (!graph.hasNode(start)) return;
53
- const visited = new Set([start]);
54
- const queue = [{
55
- node: start,
56
- depth: 0,
57
- parent: void 0
58
- }];
59
- while (queue.length > 0) {
60
- const current = queue.shift();
61
- if (current === void 0) break;
62
- yield current;
63
- for (const neighbour of graph.neighbours(current.node)) if (!visited.has(neighbour)) {
64
- visited.add(neighbour);
65
- queue.push({
66
- node: neighbour,
67
- depth: current.depth + 1,
68
- parent: current.node
69
- });
70
- }
71
- }
72
- }
73
- //#endregion
74
- //#region src/traversal/dfs.ts
75
- /**
76
- * Perform a depth-first search traversal from a start node.
77
- *
78
- * This generator yields node IDs in DFS order (pre-order traversal).
79
- * It uses lazy evaluation via a generator, making it memory-efficient
80
- * for large graphs.
81
- *
82
- * @param graph - The graph to traverse
83
- * @param start - The starting node ID
84
- * @yields Node IDs in DFS order
85
- *
86
- * @example
87
- * ```typescript
88
- * for (const nodeId of dfs(graph, "A")) {
89
- * console.log(nodeId);
90
- * }
91
- * ```
92
- */
93
- function* dfs(graph, start) {
94
- if (!graph.hasNode(start)) return;
95
- const visited = /* @__PURE__ */ new Set();
96
- const stack = [start];
97
- while (stack.length > 0) {
98
- const current = stack.pop();
99
- if (current === void 0) break;
100
- if (visited.has(current)) continue;
101
- visited.add(current);
102
- yield current;
103
- const neighbours = [...graph.neighbours(current)].reverse();
104
- for (const neighbour of neighbours) if (!visited.has(neighbour)) stack.push(neighbour);
105
- }
106
- }
107
- /**
108
- * Perform a depth-first search traversal with path information.
109
- *
110
- * This generator yields detailed information about each visited node,
111
- * including its depth from the start and parent in the DFS tree.
112
- *
113
- * @param graph - The graph to traverse
114
- * @param start - The starting node ID
115
- * @yields Objects containing node ID, depth, and parent
116
- *
117
- * @example
118
- * ```typescript
119
- * for (const entry of dfsWithPath(graph, "A")) {
120
- * console.log(`${entry.node} at depth ${entry.depth}`);
121
- * }
122
- * ```
123
- */
124
- function* dfsWithPath(graph, start) {
125
- if (!graph.hasNode(start)) return;
126
- const visited = /* @__PURE__ */ new Set();
127
- const stack = [{
128
- node: start,
129
- depth: 0,
130
- parent: void 0
131
- }];
132
- while (stack.length > 0) {
133
- const current = stack.pop();
134
- if (current === void 0) break;
135
- if (visited.has(current.node)) continue;
136
- visited.add(current.node);
137
- yield current;
138
- const neighbours = [...graph.neighbours(current.node)].reverse();
139
- for (const neighbour of neighbours) if (!visited.has(neighbour)) stack.push({
140
- node: neighbour,
141
- depth: current.depth + 1,
142
- parent: current.node
143
- });
144
- }
145
- }
146
- //#endregion
147
- Object.defineProperty(exports, "bfs", {
148
- enumerable: true,
149
- get: function() {
150
- return bfs;
151
- }
152
- });
153
- Object.defineProperty(exports, "bfsWithPath", {
154
- enumerable: true,
155
- get: function() {
156
- return bfsWithPath;
157
- }
158
- });
159
- Object.defineProperty(exports, "dfs", {
160
- enumerable: true,
161
- get: function() {
162
- return dfs;
163
- }
164
- });
165
- Object.defineProperty(exports, "dfsWithPath", {
166
- enumerable: true,
167
- get: function() {
168
- return dfsWithPath;
169
- }
170
- });
171
-
172
- //# sourceMappingURL=traversal-QeHaNUWn.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"traversal-QeHaNUWn.cjs","names":[],"sources":["../src/traversal/bfs.ts","../src/traversal/dfs.ts"],"sourcesContent":["/**\n * Breadth-first search traversal algorithms.\n *\n * BFS explores nodes level by level, visiting all neighbours at the current\n * depth before moving to nodes at the next depth level. This guarantees\n * shortest path discovery in unweighted graphs.\n */\n\nimport type { ReadableGraph, NodeId } from \"../graph\";\n\n/**\n * Node visit information during BFS traversal.\n */\nexport interface BfsPathEntry {\n\t/** The visited node identifier */\n\tnode: NodeId;\n\t/** Distance from the start node (0 for start node) */\n\tdepth: number;\n\t/** Parent node in the BFS tree (undefined for start node) */\n\tparent: NodeId | undefined;\n}\n\n/**\n * Perform a breadth-first search traversal from a start node.\n *\n * This generator yields node IDs in BFS order. It uses lazy evaluation\n * via a generator, making it memory-efficient for large graphs.\n *\n * @param graph - The graph to traverse\n * @param start - The starting node ID\n * @yields Node IDs in BFS order\n *\n * @example\n * ```typescript\n * for (const nodeId of bfs(graph, \"A\")) {\n * console.log(nodeId);\n * }\n * ```\n */\nexport function* bfs(graph: ReadableGraph, start: NodeId): Iterable<NodeId> {\n\tif (!graph.hasNode(start)) {\n\t\treturn;\n\t}\n\n\tconst visited = new Set<NodeId>([start]);\n\tconst queue: NodeId[] = [start];\n\n\twhile (queue.length > 0) {\n\t\tconst current = queue.shift();\n\t\tif (current === undefined) break;\n\t\tyield current;\n\n\t\tfor (const neighbour of graph.neighbours(current)) {\n\t\t\tif (!visited.has(neighbour)) {\n\t\t\t\tvisited.add(neighbour);\n\t\t\t\tqueue.push(neighbour);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Perform a breadth-first search traversal with path information.\n *\n * This generator yields detailed information about each visited node,\n * including its depth from the start and parent in the BFS tree.\n * Useful for reconstructing shortest paths.\n *\n * @param graph - The graph to traverse\n * @param start - The starting node ID\n * @yields Objects containing node ID, depth, and parent\n *\n * @example\n * ```typescript\n * for (const entry of bfsWithPath(graph, \"A\")) {\n * console.log(`${entry.node} at depth ${entry.depth}`);\n * }\n * ```\n */\nexport function* bfsWithPath(\n\tgraph: ReadableGraph,\n\tstart: NodeId,\n): Iterable<BfsPathEntry> {\n\tif (!graph.hasNode(start)) {\n\t\treturn;\n\t}\n\n\tconst visited = new Set<NodeId>([start]);\n\tconst queue: { node: NodeId; depth: number; parent: NodeId | undefined }[] = [\n\t\t{ node: start, depth: 0, parent: undefined },\n\t];\n\n\twhile (queue.length > 0) {\n\t\tconst current = queue.shift();\n\t\tif (current === undefined) break;\n\t\tyield current;\n\n\t\tfor (const neighbour of graph.neighbours(current.node)) {\n\t\t\tif (!visited.has(neighbour)) {\n\t\t\t\tvisited.add(neighbour);\n\t\t\t\tqueue.push({\n\t\t\t\t\tnode: neighbour,\n\t\t\t\t\tdepth: current.depth + 1,\n\t\t\t\t\tparent: current.node,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * Depth-first search traversal algorithms.\n *\n * DFS explores as far as possible along each branch before backtracking.\n * This makes it useful for cycle detection, topological sorting, and\n * finding connected components.\n */\n\nimport type { ReadableGraph, NodeId } from \"../graph\";\n\n/**\n * Node visit information during DFS traversal.\n */\nexport interface DfsPathEntry {\n\t/** The visited node identifier */\n\tnode: NodeId;\n\t/** Distance from the start node (0 for start node) */\n\tdepth: number;\n\t/** Parent node in the DFS tree (undefined for start node) */\n\tparent: NodeId | undefined;\n}\n\n/**\n * Perform a depth-first search traversal from a start node.\n *\n * This generator yields node IDs in DFS order (pre-order traversal).\n * It uses lazy evaluation via a generator, making it memory-efficient\n * for large graphs.\n *\n * @param graph - The graph to traverse\n * @param start - The starting node ID\n * @yields Node IDs in DFS order\n *\n * @example\n * ```typescript\n * for (const nodeId of dfs(graph, \"A\")) {\n * console.log(nodeId);\n * }\n * ```\n */\nexport function* dfs(graph: ReadableGraph, start: NodeId): Iterable<NodeId> {\n\tif (!graph.hasNode(start)) {\n\t\treturn;\n\t}\n\n\tconst visited = new Set<NodeId>();\n\tconst stack: NodeId[] = [start];\n\n\twhile (stack.length > 0) {\n\t\tconst current = stack.pop();\n\t\tif (current === undefined) break;\n\n\t\tif (visited.has(current)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvisited.add(current);\n\t\tyield current;\n\n\t\t// Add neighbours in reverse order to maintain left-to-right traversal\n\t\t// when popping from the stack\n\t\tconst neighbours = [...graph.neighbours(current)].reverse();\n\t\tfor (const neighbour of neighbours) {\n\t\t\tif (!visited.has(neighbour)) {\n\t\t\t\tstack.push(neighbour);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Perform a depth-first search traversal with path information.\n *\n * This generator yields detailed information about each visited node,\n * including its depth from the start and parent in the DFS tree.\n *\n * @param graph - The graph to traverse\n * @param start - The starting node ID\n * @yields Objects containing node ID, depth, and parent\n *\n * @example\n * ```typescript\n * for (const entry of dfsWithPath(graph, \"A\")) {\n * console.log(`${entry.node} at depth ${entry.depth}`);\n * }\n * ```\n */\nexport function* dfsWithPath(\n\tgraph: ReadableGraph,\n\tstart: NodeId,\n): Iterable<DfsPathEntry> {\n\tif (!graph.hasNode(start)) {\n\t\treturn;\n\t}\n\n\tconst visited = new Set<NodeId>();\n\tconst stack: { node: NodeId; depth: number; parent: NodeId | undefined }[] = [\n\t\t{ node: start, depth: 0, parent: undefined },\n\t];\n\n\twhile (stack.length > 0) {\n\t\tconst current = stack.pop();\n\t\tif (current === undefined) break;\n\n\t\tif (visited.has(current.node)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvisited.add(current.node);\n\t\tyield current;\n\n\t\t// Add neighbours in reverse order to maintain left-to-right traversal\n\t\t// when popping from the stack\n\t\tconst neighbours = [...graph.neighbours(current.node)].reverse();\n\t\tfor (const neighbour of neighbours) {\n\t\t\tif (!visited.has(neighbour)) {\n\t\t\t\tstack.push({\n\t\t\t\t\tnode: neighbour,\n\t\t\t\t\tdepth: current.depth + 1,\n\t\t\t\t\tparent: current.node,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAuCA,UAAiB,IAAI,OAAsB,OAAiC;AAC3E,KAAI,CAAC,MAAM,QAAQ,MAAM,CACxB;CAGD,MAAM,UAAU,IAAI,IAAY,CAAC,MAAM,CAAC;CACxC,MAAM,QAAkB,CAAC,MAAM;AAE/B,QAAO,MAAM,SAAS,GAAG;EACxB,MAAM,UAAU,MAAM,OAAO;AAC7B,MAAI,YAAY,KAAA,EAAW;AAC3B,QAAM;AAEN,OAAK,MAAM,aAAa,MAAM,WAAW,QAAQ,CAChD,KAAI,CAAC,QAAQ,IAAI,UAAU,EAAE;AAC5B,WAAQ,IAAI,UAAU;AACtB,SAAM,KAAK,UAAU;;;;;;;;;;;;;;;;;;;;;;AAwBzB,UAAiB,YAChB,OACA,OACyB;AACzB,KAAI,CAAC,MAAM,QAAQ,MAAM,CACxB;CAGD,MAAM,UAAU,IAAI,IAAY,CAAC,MAAM,CAAC;CACxC,MAAM,QAAuE,CAC5E;EAAE,MAAM;EAAO,OAAO;EAAG,QAAQ,KAAA;EAAW,CAC5C;AAED,QAAO,MAAM,SAAS,GAAG;EACxB,MAAM,UAAU,MAAM,OAAO;AAC7B,MAAI,YAAY,KAAA,EAAW;AAC3B,QAAM;AAEN,OAAK,MAAM,aAAa,MAAM,WAAW,QAAQ,KAAK,CACrD,KAAI,CAAC,QAAQ,IAAI,UAAU,EAAE;AAC5B,WAAQ,IAAI,UAAU;AACtB,SAAM,KAAK;IACV,MAAM;IACN,OAAO,QAAQ,QAAQ;IACvB,QAAQ,QAAQ;IAChB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AChEN,UAAiB,IAAI,OAAsB,OAAiC;AAC3E,KAAI,CAAC,MAAM,QAAQ,MAAM,CACxB;CAGD,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,QAAkB,CAAC,MAAM;AAE/B,QAAO,MAAM,SAAS,GAAG;EACxB,MAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,YAAY,KAAA,EAAW;AAE3B,MAAI,QAAQ,IAAI,QAAQ,CACvB;AAGD,UAAQ,IAAI,QAAQ;AACpB,QAAM;EAIN,MAAM,aAAa,CAAC,GAAG,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS;AAC3D,OAAK,MAAM,aAAa,WACvB,KAAI,CAAC,QAAQ,IAAI,UAAU,CAC1B,OAAM,KAAK,UAAU;;;;;;;;;;;;;;;;;;;;AAuBzB,UAAiB,YAChB,OACA,OACyB;AACzB,KAAI,CAAC,MAAM,QAAQ,MAAM,CACxB;CAGD,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,QAAuE,CAC5E;EAAE,MAAM;EAAO,OAAO;EAAG,QAAQ,KAAA;EAAW,CAC5C;AAED,QAAO,MAAM,SAAS,GAAG;EACxB,MAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,YAAY,KAAA,EAAW;AAE3B,MAAI,QAAQ,IAAI,QAAQ,KAAK,CAC5B;AAGD,UAAQ,IAAI,QAAQ,KAAK;AACzB,QAAM;EAIN,MAAM,aAAa,CAAC,GAAG,MAAM,WAAW,QAAQ,KAAK,CAAC,CAAC,SAAS;AAChE,OAAK,MAAM,aAAa,WACvB,KAAI,CAAC,QAAQ,IAAI,UAAU,CAC1B,OAAM,KAAK;GACV,MAAM;GACN,OAAO,QAAQ,QAAQ;GACvB,QAAQ,QAAQ;GAChB,CAAC"}
@@ -1,164 +0,0 @@
1
- //#region src/utils/clustering-coefficient.ts
2
- /**
3
- * Compute the local clustering coefficient for a single node.
4
- *
5
- * The clustering coefficient is defined as:
6
- * CC(v) = (triangles through v) / (possible triangles)
7
- * CC(v) = 2 * |{(u,w) : u,w in N(v), (u,w) in E}| / (deg(v) * (deg(v) - 1))
8
- *
9
- * For nodes with degree < 2, the clustering coefficient is 0.
10
- *
11
- * @param graph - The graph to compute on
12
- * @param nodeId - The node to compute clustering coefficient for
13
- * @returns The clustering coefficient in [0, 1], or 0 if undefined
14
- */
15
- function localClusteringCoefficient(graph, nodeId) {
16
- const neighbours = [...graph.neighbours(nodeId, "both")];
17
- const degree = neighbours.length;
18
- if (degree < 2) return 0;
19
- let triangleCount = 0;
20
- for (let i = 0; i < neighbours.length; i++) {
21
- const u = neighbours[i];
22
- if (u === void 0) continue;
23
- for (let j = i + 1; j < neighbours.length; j++) {
24
- const w = neighbours[j];
25
- if (w === void 0) continue;
26
- if (graph.getEdge(u, w) !== void 0 || graph.getEdge(w, u) !== void 0) triangleCount++;
27
- }
28
- }
29
- const possibleTriangles = degree * (degree - 1) / 2;
30
- return triangleCount / possibleTriangles;
31
- }
32
- /**
33
- * Compute approximate local clustering coefficient using sampling.
34
- *
35
- * For nodes with many neighbours, this samples neighbour pairs rather than
36
- * checking all pairs. Useful for large graphs where exact computation is expensive.
37
- *
38
- * @param graph - The graph to compute on
39
- * @param nodeId - The node to compute clustering coefficient for
40
- * @param sampleSize - Maximum number of neighbour pairs to check (default: 100)
41
- * @returns The approximate clustering coefficient in [0, 1]
42
- */
43
- function approximateClusteringCoefficient(graph, nodeId, sampleSize = 100) {
44
- const neighbours = [...graph.neighbours(nodeId, "both")];
45
- const degree = neighbours.length;
46
- if (degree < 2) return 0;
47
- const possibleTriangles = degree * (degree - 1) / 2;
48
- if (possibleTriangles <= sampleSize) return localClusteringCoefficient(graph, nodeId);
49
- let triangleCount = 0;
50
- let sampled = 0;
51
- for (let i = 0; i < neighbours.length && sampled < sampleSize; i++) {
52
- const u = neighbours[i];
53
- if (u === void 0) continue;
54
- for (let j = i + 1; j < neighbours.length && sampled < sampleSize; j++) {
55
- const w = neighbours[j];
56
- if (w === void 0) continue;
57
- sampled++;
58
- if (graph.getEdge(u, w) !== void 0 || graph.getEdge(w, u) !== void 0) triangleCount++;
59
- }
60
- }
61
- return triangleCount / sampled * (possibleTriangles / possibleTriangles);
62
- }
63
- /**
64
- * Compute clustering coefficients for multiple nodes efficiently.
65
- *
66
- * Reuses neighbour sets to avoid repeated iteration.
67
- *
68
- * @param graph - The graph to compute on
69
- * @param nodeIds - The nodes to compute clustering coefficients for
70
- * @returns Map from nodeId to clustering coefficient
71
- */
72
- function batchClusteringCoefficients(graph, nodeIds) {
73
- const results = /* @__PURE__ */ new Map();
74
- for (const nodeId of nodeIds) results.set(nodeId, localClusteringCoefficient(graph, nodeId));
75
- return results;
76
- }
77
- //#endregion
78
- //#region src/utils/entropy.ts
79
- /**
80
- * Entropy computation utilities for graph analysis.
81
- *
82
- * Shannon entropy measures uncertainty or randomness in a distribution.
83
- * Used in EDGE and HAE algorithms for heterogeneity-aware expansion.
84
- *
85
- * @packageDocumentation
86
- */
87
- /**
88
- * Compute Shannon entropy of a probability distribution.
89
- *
90
- * Shannon entropy is defined as:
91
- * H(X) = -Σ p(x) × log₂(p(x))
92
- *
93
- * A uniform distribution has maximum entropy.
94
- * A deterministic distribution (all probability on one value) has zero entropy.
95
- *
96
- * @param probabilities - Array of probabilities (should sum to 1)
97
- * @returns Entropy in bits (log base 2), or 0 if probabilities are invalid
98
- */
99
- function shannonEntropy(probabilities) {
100
- if (probabilities.length === 0) return 0;
101
- let entropy = 0;
102
- for (const p of probabilities) if (p > 0) entropy -= p * Math.log2(p);
103
- return entropy;
104
- }
105
- /**
106
- * Compute normalised entropy (entropy divided by maximum possible entropy).
107
- *
108
- * Normalised entropy is in [0, 1], where:
109
- * - 0 means the distribution is deterministic (all mass on one value)
110
- * - 1 means the distribution is uniform (maximum uncertainty)
111
- *
112
- * This is useful for comparing entropy across distributions with different
113
- * numbers of possible values.
114
- *
115
- * @param probabilities - Array of probabilities (should sum to 1)
116
- * @returns Normalised entropy in [0, 1], or 0 if only one category
117
- */
118
- function normalisedEntropy(probabilities) {
119
- if (probabilities.length <= 1) return 0;
120
- const H = shannonEntropy(probabilities);
121
- const Hmax = Math.log2(probabilities.length);
122
- if (Hmax === 0) return 0;
123
- return H / Hmax;
124
- }
125
- /**
126
- * Compute entropy from a frequency count.
127
- *
128
- * Converts counts to probabilities and then computes entropy.
129
- * This is a convenience function when you have raw counts rather than
130
- * normalised probabilities.
131
- *
132
- * @param counts - Array of frequency counts
133
- * @returns Entropy in bits
134
- */
135
- function entropyFromCounts(counts) {
136
- if (counts.length === 0) return 0;
137
- const total = counts.reduce((sum, c) => sum + c, 0);
138
- if (total === 0) return 0;
139
- return shannonEntropy(counts.map((c) => c / total));
140
- }
141
- /**
142
- * Compute local type entropy for a node's neighbours.
143
- *
144
- * This measures the diversity of types among a node's neighbours.
145
- * High entropy = heterogeneous neighbourhood (diverse types).
146
- * Low entropy = homogeneous neighbourhood (similar types).
147
- *
148
- * @param neighbourTypes - Array of type labels for neighbours
149
- * @returns Normalised entropy in [0, 1]
150
- */
151
- function localTypeEntropy(neighbourTypes) {
152
- if (neighbourTypes.length <= 1) return 0;
153
- const typeCounts = /* @__PURE__ */ new Map();
154
- for (const t of neighbourTypes) typeCounts.set(t, (typeCounts.get(t) ?? 0) + 1);
155
- if (typeCounts.size === 1) return 0;
156
- const probabilities = [];
157
- const total = neighbourTypes.length;
158
- for (const count of typeCounts.values()) probabilities.push(count / total);
159
- return normalisedEntropy(probabilities);
160
- }
161
- //#endregion
162
- export { approximateClusteringCoefficient as a, shannonEntropy as i, localTypeEntropy as n, batchClusteringCoefficients as o, normalisedEntropy as r, localClusteringCoefficient as s, entropyFromCounts as t };
163
-
164
- //# sourceMappingURL=utils-Q_akvlMn.js.map