@graphty/algorithms 1.0.1

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 (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +193 -0
  3. package/dist/src/algorithms/centrality/betweenness.d.ts +34 -0
  4. package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -0
  5. package/dist/src/algorithms/centrality/betweenness.js +223 -0
  6. package/dist/src/algorithms/centrality/betweenness.js.map +1 -0
  7. package/dist/src/algorithms/centrality/closeness.d.ts +43 -0
  8. package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -0
  9. package/dist/src/algorithms/centrality/closeness.js +202 -0
  10. package/dist/src/algorithms/centrality/closeness.js.map +1 -0
  11. package/dist/src/algorithms/centrality/degree.d.ts +17 -0
  12. package/dist/src/algorithms/centrality/degree.d.ts.map +1 -0
  13. package/dist/src/algorithms/centrality/degree.js +86 -0
  14. package/dist/src/algorithms/centrality/degree.js.map +1 -0
  15. package/dist/src/algorithms/centrality/index.d.ts +11 -0
  16. package/dist/src/algorithms/centrality/index.d.ts.map +1 -0
  17. package/dist/src/algorithms/centrality/index.js +8 -0
  18. package/dist/src/algorithms/centrality/index.js.map +1 -0
  19. package/dist/src/algorithms/centrality/pagerank.d.ts +74 -0
  20. package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -0
  21. package/dist/src/algorithms/centrality/pagerank.js +191 -0
  22. package/dist/src/algorithms/centrality/pagerank.js.map +1 -0
  23. package/dist/src/algorithms/components/connected.d.ts +58 -0
  24. package/dist/src/algorithms/components/connected.d.ts.map +1 -0
  25. package/dist/src/algorithms/components/connected.js +234 -0
  26. package/dist/src/algorithms/components/connected.js.map +1 -0
  27. package/dist/src/algorithms/components/index.d.ts +5 -0
  28. package/dist/src/algorithms/components/index.d.ts.map +1 -0
  29. package/dist/src/algorithms/components/index.js +5 -0
  30. package/dist/src/algorithms/components/index.js.map +1 -0
  31. package/dist/src/algorithms/index.d.ts +8 -0
  32. package/dist/src/algorithms/index.d.ts.map +1 -0
  33. package/dist/src/algorithms/index.js +12 -0
  34. package/dist/src/algorithms/index.js.map +1 -0
  35. package/dist/src/algorithms/shortest-path/bellman-ford.d.ts +52 -0
  36. package/dist/src/algorithms/shortest-path/bellman-ford.d.ts.map +1 -0
  37. package/dist/src/algorithms/shortest-path/bellman-ford.js +131 -0
  38. package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -0
  39. package/dist/src/algorithms/shortest-path/dijkstra.d.ts +26 -0
  40. package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -0
  41. package/dist/src/algorithms/shortest-path/dijkstra.js +199 -0
  42. package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -0
  43. package/dist/src/algorithms/shortest-path/index.d.ts +7 -0
  44. package/dist/src/algorithms/shortest-path/index.d.ts.map +1 -0
  45. package/dist/src/algorithms/shortest-path/index.js +6 -0
  46. package/dist/src/algorithms/shortest-path/index.js.map +1 -0
  47. package/dist/src/algorithms/traversal/bfs.d.ts +25 -0
  48. package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -0
  49. package/dist/src/algorithms/traversal/bfs.js +189 -0
  50. package/dist/src/algorithms/traversal/bfs.js.map +1 -0
  51. package/dist/src/algorithms/traversal/dfs.d.ts +32 -0
  52. package/dist/src/algorithms/traversal/dfs.d.ts.map +1 -0
  53. package/dist/src/algorithms/traversal/dfs.js +259 -0
  54. package/dist/src/algorithms/traversal/dfs.js.map +1 -0
  55. package/dist/src/algorithms/traversal/index.d.ts +7 -0
  56. package/dist/src/algorithms/traversal/index.d.ts.map +1 -0
  57. package/dist/src/algorithms/traversal/index.js +6 -0
  58. package/dist/src/algorithms/traversal/index.js.map +1 -0
  59. package/dist/src/core/graph.d.ts +100 -0
  60. package/dist/src/core/graph.d.ts.map +1 -0
  61. package/dist/src/core/graph.js +276 -0
  62. package/dist/src/core/graph.js.map +1 -0
  63. package/dist/src/data-structures/index.d.ts +6 -0
  64. package/dist/src/data-structures/index.d.ts.map +1 -0
  65. package/dist/src/data-structures/index.js +6 -0
  66. package/dist/src/data-structures/index.js.map +1 -0
  67. package/dist/src/data-structures/priority-queue.d.ts +60 -0
  68. package/dist/src/data-structures/priority-queue.d.ts.map +1 -0
  69. package/dist/src/data-structures/priority-queue.js +152 -0
  70. package/dist/src/data-structures/priority-queue.js.map +1 -0
  71. package/dist/src/data-structures/union-find.d.ts +54 -0
  72. package/dist/src/data-structures/union-find.d.ts.map +1 -0
  73. package/dist/src/data-structures/union-find.js +145 -0
  74. package/dist/src/data-structures/union-find.js.map +1 -0
  75. package/dist/src/index.d.ts +11 -0
  76. package/dist/src/index.d.ts.map +1 -0
  77. package/dist/src/index.js +13 -0
  78. package/dist/src/index.js.map +1 -0
  79. package/dist/src/types/index.d.ts +74 -0
  80. package/dist/src/types/index.d.ts.map +1 -0
  81. package/dist/src/types/index.js +5 -0
  82. package/dist/src/types/index.js.map +1 -0
  83. package/dist/test/browser/basic.test.d.ts +2 -0
  84. package/dist/test/browser/basic.test.d.ts.map +1 -0
  85. package/dist/test/browser/basic.test.js +70 -0
  86. package/dist/test/browser/basic.test.js.map +1 -0
  87. package/dist/test/unit/bellman-ford.test.d.ts +2 -0
  88. package/dist/test/unit/bellman-ford.test.d.ts.map +1 -0
  89. package/dist/test/unit/bellman-ford.test.js +231 -0
  90. package/dist/test/unit/bellman-ford.test.js.map +1 -0
  91. package/dist/test/unit/betweenness-centrality.test.d.ts +2 -0
  92. package/dist/test/unit/betweenness-centrality.test.d.ts.map +1 -0
  93. package/dist/test/unit/betweenness-centrality.test.js +311 -0
  94. package/dist/test/unit/betweenness-centrality.test.js.map +1 -0
  95. package/dist/test/unit/bfs.test.d.ts +2 -0
  96. package/dist/test/unit/bfs.test.d.ts.map +1 -0
  97. package/dist/test/unit/bfs.test.js +277 -0
  98. package/dist/test/unit/bfs.test.js.map +1 -0
  99. package/dist/test/unit/closeness.test.d.ts +2 -0
  100. package/dist/test/unit/closeness.test.d.ts.map +1 -0
  101. package/dist/test/unit/closeness.test.js +266 -0
  102. package/dist/test/unit/closeness.test.js.map +1 -0
  103. package/dist/test/unit/connected-components.test.d.ts +2 -0
  104. package/dist/test/unit/connected-components.test.d.ts.map +1 -0
  105. package/dist/test/unit/connected-components.test.js +355 -0
  106. package/dist/test/unit/connected-components.test.js.map +1 -0
  107. package/dist/test/unit/degree-centrality.test.d.ts +2 -0
  108. package/dist/test/unit/degree-centrality.test.d.ts.map +1 -0
  109. package/dist/test/unit/degree-centrality.test.js +260 -0
  110. package/dist/test/unit/degree-centrality.test.js.map +1 -0
  111. package/dist/test/unit/dfs.test.d.ts +2 -0
  112. package/dist/test/unit/dfs.test.d.ts.map +1 -0
  113. package/dist/test/unit/dfs.test.js +350 -0
  114. package/dist/test/unit/dfs.test.js.map +1 -0
  115. package/dist/test/unit/dijkstra.test.d.ts +2 -0
  116. package/dist/test/unit/dijkstra.test.d.ts.map +1 -0
  117. package/dist/test/unit/dijkstra.test.js +311 -0
  118. package/dist/test/unit/dijkstra.test.js.map +1 -0
  119. package/dist/test/unit/graph.test.d.ts +2 -0
  120. package/dist/test/unit/graph.test.d.ts.map +1 -0
  121. package/dist/test/unit/graph.test.js +175 -0
  122. package/dist/test/unit/graph.test.js.map +1 -0
  123. package/dist/test/unit/pagerank.test.d.ts +2 -0
  124. package/dist/test/unit/pagerank.test.d.ts.map +1 -0
  125. package/dist/test/unit/pagerank.test.js +281 -0
  126. package/dist/test/unit/pagerank.test.js.map +1 -0
  127. package/dist/test/unit/priority-queue.test.d.ts +2 -0
  128. package/dist/test/unit/priority-queue.test.d.ts.map +1 -0
  129. package/dist/test/unit/priority-queue.test.js +189 -0
  130. package/dist/test/unit/priority-queue.test.js.map +1 -0
  131. package/dist/test/unit/union-find.test.d.ts +2 -0
  132. package/dist/test/unit/union-find.test.d.ts.map +1 -0
  133. package/dist/test/unit/union-find.test.js +245 -0
  134. package/dist/test/unit/union-find.test.js.map +1 -0
  135. package/package.json +100 -0
  136. package/src/algorithms/centrality/betweenness.ts +303 -0
  137. package/src/algorithms/centrality/closeness.ts +296 -0
  138. package/src/algorithms/centrality/degree.ts +105 -0
  139. package/src/algorithms/centrality/index.ts +11 -0
  140. package/src/algorithms/centrality/pagerank.ts +302 -0
  141. package/src/algorithms/components/connected.ts +298 -0
  142. package/src/algorithms/components/index.ts +17 -0
  143. package/src/algorithms/index.ts +15 -0
  144. package/src/algorithms/shortest-path/bellman-ford.ts +214 -0
  145. package/src/algorithms/shortest-path/dijkstra.ts +256 -0
  146. package/src/algorithms/shortest-path/index.ts +7 -0
  147. package/src/algorithms/traversal/bfs.ts +236 -0
  148. package/src/algorithms/traversal/dfs.ts +367 -0
  149. package/src/algorithms/traversal/index.ts +7 -0
  150. package/src/core/graph.ts +326 -0
  151. package/src/data-structures/index.ts +6 -0
  152. package/src/data-structures/priority-queue.ts +180 -0
  153. package/src/data-structures/union-find.ts +170 -0
  154. package/src/index.ts +35 -0
  155. package/src/types/index.ts +95 -0
@@ -0,0 +1,245 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { UnionFind } from "../../src/data-structures/union-find.js";
3
+ describe("UnionFind", () => {
4
+ describe("constructor", () => {
5
+ it("should initialize with separate components", () => {
6
+ const uf = new UnionFind(["a", "b", "c"]);
7
+ expect(uf.size()).toBe(3);
8
+ expect(uf.getComponentCount()).toBe(3);
9
+ expect(uf.connected("a", "b")).toBe(false);
10
+ expect(uf.connected("b", "c")).toBe(false);
11
+ expect(uf.connected("a", "c")).toBe(false);
12
+ });
13
+ it("should handle empty initialization", () => {
14
+ const uf = new UnionFind([]);
15
+ expect(uf.size()).toBe(0);
16
+ expect(uf.getComponentCount()).toBe(0);
17
+ });
18
+ it("should handle single element", () => {
19
+ const uf = new UnionFind(["only"]);
20
+ expect(uf.size()).toBe(1);
21
+ expect(uf.getComponentCount()).toBe(1);
22
+ expect(uf.connected("only", "only")).toBe(true);
23
+ });
24
+ });
25
+ describe("find", () => {
26
+ it("should return the element itself initially", () => {
27
+ const uf = new UnionFind(["a", "b", "c"]);
28
+ expect(uf.find("a")).toBe("a");
29
+ expect(uf.find("b")).toBe("b");
30
+ expect(uf.find("c")).toBe("c");
31
+ });
32
+ it("should throw error for non-existent element", () => {
33
+ const uf = new UnionFind(["a", "b"]);
34
+ expect(() => uf.find("nonexistent")).toThrow("Element nonexistent not found");
35
+ });
36
+ it("should implement path compression", () => {
37
+ const uf = new UnionFind(["a", "b", "c", "d"]);
38
+ // Create a chain: a -> b -> c -> d
39
+ uf.union("a", "b");
40
+ uf.union("b", "c");
41
+ uf.union("c", "d");
42
+ // After path compression, all should point to same root
43
+ const root = uf.find("a");
44
+ expect(uf.find("b")).toBe(root);
45
+ expect(uf.find("c")).toBe(root);
46
+ expect(uf.find("d")).toBe(root);
47
+ });
48
+ });
49
+ describe("union", () => {
50
+ it("should connect two separate elements", () => {
51
+ const uf = new UnionFind(["a", "b", "c"]);
52
+ expect(uf.connected("a", "b")).toBe(false);
53
+ uf.union("a", "b");
54
+ expect(uf.connected("a", "b")).toBe(true);
55
+ expect(uf.getComponentCount()).toBe(2);
56
+ });
57
+ it("should handle union of already connected elements", () => {
58
+ const uf = new UnionFind(["a", "b"]);
59
+ uf.union("a", "b");
60
+ const countBefore = uf.getComponentCount();
61
+ uf.union("a", "b"); // Union again
62
+ expect(uf.getComponentCount()).toBe(countBefore);
63
+ expect(uf.connected("a", "b")).toBe(true);
64
+ });
65
+ it("should connect components transitively", () => {
66
+ const uf = new UnionFind(["a", "b", "c", "d"]);
67
+ uf.union("a", "b");
68
+ uf.union("c", "d");
69
+ expect(uf.getComponentCount()).toBe(2);
70
+ uf.union("b", "c");
71
+ expect(uf.getComponentCount()).toBe(1);
72
+ expect(uf.connected("a", "d")).toBe(true);
73
+ });
74
+ it("should use union by rank for efficiency", () => {
75
+ const uf = new UnionFind(["a", "b", "c", "d", "e", "f", "g", "h"]);
76
+ // Create two trees of different heights
77
+ uf.union("a", "b");
78
+ uf.union("a", "c");
79
+ uf.union("a", "d"); // Tree 1: height 2
80
+ uf.union("e", "f"); // Tree 2: height 1
81
+ // Union should attach smaller tree to larger tree's root
82
+ uf.union("d", "e");
83
+ // All elements should be connected
84
+ expect(uf.connected("a", "f")).toBe(true);
85
+ expect(uf.getComponentCount()).toBe(3); // g, h still separate
86
+ });
87
+ });
88
+ describe("connected", () => {
89
+ it("should return true for elements in same component", () => {
90
+ const uf = new UnionFind(["a", "b", "c"]);
91
+ uf.union("a", "b");
92
+ expect(uf.connected("a", "b")).toBe(true);
93
+ expect(uf.connected("b", "a")).toBe(true);
94
+ });
95
+ it("should return false for elements in different components", () => {
96
+ const uf = new UnionFind(["a", "b", "c"]);
97
+ uf.union("a", "b");
98
+ expect(uf.connected("a", "c")).toBe(false);
99
+ expect(uf.connected("c", "a")).toBe(false);
100
+ });
101
+ it("should return false for non-existent elements", () => {
102
+ const uf = new UnionFind(["a", "b"]);
103
+ expect(uf.connected("a", "nonexistent")).toBe(false);
104
+ expect(uf.connected("nonexistent", "a")).toBe(false);
105
+ });
106
+ it("should return true for element with itself", () => {
107
+ const uf = new UnionFind(["a"]);
108
+ expect(uf.connected("a", "a")).toBe(true);
109
+ });
110
+ });
111
+ describe("getComponent", () => {
112
+ it("should return all elements in the same component", () => {
113
+ const uf = new UnionFind(["a", "b", "c", "d"]);
114
+ uf.union("a", "b");
115
+ uf.union("b", "c");
116
+ const component = uf.getComponent("a");
117
+ expect(component).toHaveLength(3);
118
+ expect(component).toContain("a");
119
+ expect(component).toContain("b");
120
+ expect(component).toContain("c");
121
+ expect(component).not.toContain("d");
122
+ });
123
+ it("should return single element for isolated component", () => {
124
+ const uf = new UnionFind(["a", "b"]);
125
+ const component = uf.getComponent("a");
126
+ expect(component).toEqual(["a"]);
127
+ });
128
+ });
129
+ describe("getAllComponents", () => {
130
+ it("should return all components as separate arrays", () => {
131
+ const uf = new UnionFind(["a", "b", "c", "d", "e"]);
132
+ uf.union("a", "b");
133
+ uf.union("c", "d");
134
+ // e remains isolated
135
+ const components = uf.getAllComponents();
136
+ expect(components).toHaveLength(3);
137
+ // Find the components by size
138
+ const sizes = components.map((comp) => comp.length).sort();
139
+ expect(sizes).toEqual([1, 2, 2]);
140
+ // Check that all elements are included
141
+ const allElements = components.flat().sort();
142
+ expect(allElements).toEqual(["a", "b", "c", "d", "e"]);
143
+ });
144
+ it("should return single component when all connected", () => {
145
+ const uf = new UnionFind(["a", "b", "c"]);
146
+ uf.union("a", "b");
147
+ uf.union("b", "c");
148
+ const components = uf.getAllComponents();
149
+ expect(components).toHaveLength(1);
150
+ expect(components[0]).toHaveLength(3);
151
+ });
152
+ });
153
+ describe("getComponentSize", () => {
154
+ it("should return correct size of component", () => {
155
+ const uf = new UnionFind(["a", "b", "c", "d"]);
156
+ uf.union("a", "b");
157
+ uf.union("b", "c");
158
+ expect(uf.getComponentSize("a")).toBe(3);
159
+ expect(uf.getComponentSize("b")).toBe(3);
160
+ expect(uf.getComponentSize("c")).toBe(3);
161
+ expect(uf.getComponentSize("d")).toBe(1);
162
+ });
163
+ });
164
+ describe("addElement", () => {
165
+ it("should add new element as separate component", () => {
166
+ const uf = new UnionFind(["a", "b"]);
167
+ expect(uf.hasElement("c")).toBe(false);
168
+ uf.addElement("c");
169
+ expect(uf.hasElement("c")).toBe(true);
170
+ expect(uf.size()).toBe(3);
171
+ expect(uf.getComponentCount()).toBe(3);
172
+ });
173
+ it("should not change anything if element already exists", () => {
174
+ const uf = new UnionFind(["a", "b"]);
175
+ const sizeBefore = uf.size();
176
+ const countBefore = uf.getComponentCount();
177
+ uf.addElement("a");
178
+ expect(uf.size()).toBe(sizeBefore);
179
+ expect(uf.getComponentCount()).toBe(countBefore);
180
+ });
181
+ });
182
+ describe("hasElement", () => {
183
+ it("should return true for existing elements", () => {
184
+ const uf = new UnionFind(["a", "b", "c"]);
185
+ expect(uf.hasElement("a")).toBe(true);
186
+ expect(uf.hasElement("b")).toBe(true);
187
+ expect(uf.hasElement("c")).toBe(true);
188
+ });
189
+ it("should return false for non-existing elements", () => {
190
+ const uf = new UnionFind(["a", "b"]);
191
+ expect(uf.hasElement("c")).toBe(false);
192
+ expect(uf.hasElement("nonexistent")).toBe(false);
193
+ });
194
+ });
195
+ describe("stress test", () => {
196
+ it("should handle large number of operations efficiently", () => {
197
+ const elements = Array.from({ length: 1000 }, (_, i) => i.toString());
198
+ const uf = new UnionFind(elements);
199
+ // Initially all separate
200
+ expect(uf.getComponentCount()).toBe(1000);
201
+ // Union adjacent elements
202
+ for (let i = 0; i < 999; i++) {
203
+ uf.union(i.toString(), (i + 1).toString());
204
+ }
205
+ // Should now have single component
206
+ expect(uf.getComponentCount()).toBe(1);
207
+ expect(uf.connected("0", "999")).toBe(true);
208
+ // Test multiple finds (should be fast due to path compression)
209
+ for (let i = 0; i < 100; i++) {
210
+ const randomElement = Math.floor(Math.random() * 1000).toString();
211
+ expect(uf.find(randomElement)).toBeDefined();
212
+ }
213
+ });
214
+ });
215
+ describe("edge cases", () => {
216
+ it("should handle numeric node IDs", () => {
217
+ const uf = new UnionFind([1, 2, 3]);
218
+ uf.union(1, 2);
219
+ expect(uf.connected(1, 2)).toBe(true);
220
+ expect(uf.connected(2, 3)).toBe(false);
221
+ });
222
+ it("should handle mixed string and number IDs", () => {
223
+ const uf = new UnionFind(["a", 1, "b", 2]);
224
+ uf.union("a", 1);
225
+ uf.union("b", 2);
226
+ expect(uf.connected("a", 1)).toBe(true);
227
+ expect(uf.connected("b", 2)).toBe(true);
228
+ expect(uf.connected("a", "b")).toBe(false);
229
+ });
230
+ it("should handle complex component merging", () => {
231
+ const uf = new UnionFind(["a", "b", "c", "d", "e", "f"]);
232
+ // Create two separate components
233
+ uf.union("a", "b");
234
+ uf.union("b", "c"); // Component 1: {a, b, c}
235
+ uf.union("d", "e");
236
+ uf.union("e", "f"); // Component 2: {d, e, f}
237
+ expect(uf.getComponentCount()).toBe(2);
238
+ // Merge the two components
239
+ uf.union("c", "d");
240
+ expect(uf.getComponentCount()).toBe(1);
241
+ expect(uf.connected("a", "f")).toBe(true);
242
+ });
243
+ });
244
+ });
245
+ //# sourceMappingURL=union-find.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"union-find.test.js","sourceRoot":"","sources":["../../../test/unit/union-find.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAC,MAAM,QAAQ,CAAC;AAE5C,OAAO,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAElE,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACvB,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YAClD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE1C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC1C,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,EAAE,CAAC,CAAC;YAE7B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACpC,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YAEnC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;QAClB,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YAClD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE1C,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/B,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/B,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACnD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAErC,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YACzC,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE/C,mCAAmC;YACnC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAEnB,wDAAwD;YACxD,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1B,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;QACnB,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC5C,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE1C,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3C,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YACzD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAErC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,MAAM,WAAW,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC;YAE3C,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,cAAc;YAElC,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACjD,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAC9C,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE/C,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEvC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YAC/C,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAEnE,wCAAwC;YACxC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,mBAAmB;YAEvC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,mBAAmB;YAEvC,yDAAyD;YACzD,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAEnB,mCAAmC;YACnC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB;QAClE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;QACvB,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YACzD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE1C,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;YAChE,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE1C,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;YACrD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAErC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrD,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YAClD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAEhC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC1B,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YACxD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE/C,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAEnB,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YACvC,MAAM,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAClC,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACjC,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACjC,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACjC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC3D,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAErC,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;YACvC,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACvD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAEpD,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,qBAAqB;YAErB,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,EAAE,CAAC;YACzC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAEnC,8BAA8B;YAC9B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3D,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAEjC,uCAAuC;YACvC,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YACzD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE1C,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAEnB,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,EAAE,CAAC;YACzC,MAAM,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YAC/C,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE/C,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAEnB,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzC,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzC,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACzC,MAAM,CAAC,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QACxB,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;YACpD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAErC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YACnB,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC5D,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAErC,MAAM,UAAU,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;YAC7B,MAAM,WAAW,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC;YAE3C,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAEnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACnC,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QACxB,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAChD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAE1C,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;YACrD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAErC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QACzB,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC5D,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,EAAC,MAAM,EAAE,IAAI,EAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACpE,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC;YAEnC,yBAAyB;YACzB,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE1C,0BAA0B;YAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC/C,CAAC;YAED,mCAAmC;YACnC,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE5C,+DAA+D;YAC/D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;gBAClE,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YACjD,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QACxB,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACtC,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAEpC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACf,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACjD,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YAE3C,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACjB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAEjB,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YAC/C,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YAEzD,iCAAiC;YACjC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,yBAAyB;YAE7C,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,yBAAyB;YAE7C,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAEvC,2BAA2B;YAC3B,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAEnB,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,100 @@
1
+ {
2
+ "name": "@graphty/algorithms",
3
+ "version": "1.0.1",
4
+ "description": "Graph algorithms library for browser environments implemented in TypeScript",
5
+ "author": "Adam Powers <apowers@ato.ms>",
6
+ "main": "dist/algorithms.js",
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/algorithms.js",
11
+ "types": "./dist/algorithms.d.ts"
12
+ }
13
+ },
14
+ "types": "dist/algorithms.d.ts",
15
+ "files": [
16
+ "dist/",
17
+ "src/",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "directories": {
22
+ "example": "examples"
23
+ },
24
+ "scripts": {
25
+ "test": "vitest",
26
+ "test:ui": "vitest --ui",
27
+ "test:run": "vitest run --project=default",
28
+ "test:coverage": "vitest run --coverage",
29
+ "test:browser": "vitest --project=browser",
30
+ "test:all": "vitest run --project=default --project=browser",
31
+ "lint": "eslint && tsc --noEmit",
32
+ "lint:fix": "eslint --fix",
33
+ "lint:pkg": "knip",
34
+ "lint:all": "npm run lint && npm run lint:pkg",
35
+ "typecheck": "tsc --noEmit",
36
+ "prepare": "husky",
37
+ "build": "tsc",
38
+ "build:watch": "tsc --watch",
39
+ "dev": "tsc --watch",
40
+ "commit": "cz",
41
+ "ready:commit": "npm run build && npm run lint && npm run test:all"
42
+ },
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/graphty-org/algorithms.git"
46
+ },
47
+ "keywords": [
48
+ "graph",
49
+ "algorithms",
50
+ "typescript",
51
+ "browser",
52
+ "graph-theory",
53
+ "network-analysis",
54
+ "centrality",
55
+ "community-detection",
56
+ "shortest-path",
57
+ "graph-traversal"
58
+ ],
59
+ "license": "MIT",
60
+ "publishConfig": {
61
+ "access": "public",
62
+ "provenance": true
63
+ },
64
+ "bugs": {
65
+ "url": "https://github.com/graphty-org/algorithms/issues"
66
+ },
67
+ "homepage": "https://github.com/graphty-org/algorithms#readme",
68
+ "engines": {
69
+ "node": ">=18.19.0"
70
+ },
71
+ "config": {
72
+ "commitizen": {
73
+ "path": "./node_modules/cz-conventional-changelog"
74
+ }
75
+ },
76
+ "devDependencies": {
77
+ "@commitlint/cli": "^19.8.1",
78
+ "@commitlint/config-conventional": "^19.8.1",
79
+ "@eslint/js": "^9.29.0",
80
+ "@semantic-release/changelog": "^6.0.3",
81
+ "@semantic-release/git": "^10.0.1",
82
+ "@stylistic/eslint-plugin": "^4.4.1",
83
+ "@types/node": "^20.19.2",
84
+ "@vitest/browser": "^3.2.4",
85
+ "@vitest/coverage-v8": "^3.2.4",
86
+ "@vitest/ui": "^3.2.4",
87
+ "cz-conventional-changelog": "^3.3.0",
88
+ "eslint": "^9.29.0",
89
+ "eslint-plugin-simple-import-sort": "^12.1.1",
90
+ "globals": "^15.12.0",
91
+ "happy-dom": "^18.0.1",
92
+ "husky": "^9.1.7",
93
+ "knip": "^5.61.3",
94
+ "playwright": "^1.53.0",
95
+ "semantic-release": "^24.2.7",
96
+ "typescript": "^5.8.3",
97
+ "typescript-eslint": "^8.34.1",
98
+ "vitest": "^3.2.4"
99
+ }
100
+ }
@@ -0,0 +1,303 @@
1
+ import type {Graph} from "../../core/graph.js";
2
+ import type {NodeId} from "../../types/index.js";
3
+
4
+ /**
5
+ * Betweenness centrality implementation using Brandes' algorithm
6
+ *
7
+ * Measures the extent to which a node lies on paths between other nodes.
8
+ * Uses the fast O(VE) algorithm by Ulrik Brandes.
9
+ */
10
+
11
+ /**
12
+ * Betweenness centrality options
13
+ */
14
+ export interface BetweennessCentralityOptions {
15
+ /**
16
+ * Whether to normalize the centrality values (default: false)
17
+ */
18
+ normalized?: boolean;
19
+ /**
20
+ * Whether to use endpoints in path counting (default: false)
21
+ */
22
+ endpoints?: boolean;
23
+ }
24
+
25
+ /**
26
+ * Calculate betweenness centrality for all nodes using Brandes' algorithm
27
+ */
28
+ export function betweennessCentrality(
29
+ graph: Graph,
30
+ options: BetweennessCentralityOptions = {},
31
+ ): Record<string, number> {
32
+ const nodes = Array.from(graph.nodes()).map((node) => node.id);
33
+ const centrality: Record<string, number> = {};
34
+
35
+ // Initialize centrality scores
36
+ for (const nodeId of nodes) {
37
+ centrality[String(nodeId)] = 0;
38
+ }
39
+
40
+ // Brandes' algorithm
41
+ for (const source of nodes) {
42
+ const stack: NodeId[] = [];
43
+ const predecessors = new Map<NodeId, NodeId[]>();
44
+ const sigma = new Map<NodeId, number>(); // Number of shortest paths
45
+ const distance = new Map<NodeId, number>();
46
+ const delta = new Map<NodeId, number>();
47
+
48
+ // Initialize
49
+ for (const nodeId of nodes) {
50
+ predecessors.set(nodeId, []);
51
+ sigma.set(nodeId, 0);
52
+ distance.set(nodeId, -1);
53
+ delta.set(nodeId, 0);
54
+ }
55
+
56
+ sigma.set(source, 1);
57
+ distance.set(source, 0);
58
+
59
+ const queue: NodeId[] = [source];
60
+
61
+ // BFS to find shortest paths
62
+ while (queue.length > 0) {
63
+ const current = queue.shift();
64
+ if (!current) {
65
+ break;
66
+ }
67
+
68
+ stack.push(current);
69
+
70
+ for (const neighbor of graph.neighbors(current)) {
71
+ const currentDistance = distance.get(current);
72
+ let neighborDistance = distance.get(neighbor);
73
+
74
+ if (currentDistance === undefined || neighborDistance === undefined) {
75
+ continue;
76
+ }
77
+
78
+ // First time we reach this neighbor
79
+ if (neighborDistance < 0) {
80
+ queue.push(neighbor);
81
+ distance.set(neighbor, currentDistance + 1);
82
+ neighborDistance = currentDistance + 1; // Update local variable
83
+ }
84
+
85
+ // Shortest path to neighbor via current
86
+ if (neighborDistance === currentDistance + 1) {
87
+ const neighborSigma = sigma.get(neighbor) ?? 0;
88
+ const currentSigma = sigma.get(current) ?? 0;
89
+ sigma.set(neighbor, neighborSigma + currentSigma);
90
+
91
+ const preds = predecessors.get(neighbor);
92
+ if (preds) {
93
+ preds.push(current);
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ // Accumulation - back-propagation of dependencies
100
+ while (stack.length > 0) {
101
+ const w = stack.pop();
102
+ if (!w) {
103
+ break;
104
+ }
105
+
106
+ const wPreds = predecessors.get(w) ?? [];
107
+ const wSigma = sigma.get(w) ?? 0;
108
+ const wDelta = delta.get(w) ?? 0;
109
+
110
+ for (const v of wPreds) {
111
+ const vSigma = sigma.get(v) ?? 0;
112
+ const vDelta = delta.get(v) ?? 0;
113
+
114
+ if (vSigma > 0 && wSigma > 0) {
115
+ const contribution = (vSigma / wSigma) * (1 + wDelta);
116
+ delta.set(v, vDelta + contribution);
117
+ }
118
+ }
119
+
120
+ if (w !== source) {
121
+ const currentCentrality = centrality[String(w)] ?? 0;
122
+ centrality[String(w)] = currentCentrality + wDelta;
123
+ }
124
+ }
125
+ }
126
+
127
+ // For undirected graphs, divide by 2 (each shortest path is counted twice)
128
+ if (!graph.isDirected) {
129
+ for (const nodeId of nodes) {
130
+ const key = String(nodeId);
131
+ const currentValue = centrality[key];
132
+ if (currentValue !== undefined) {
133
+ centrality[key] = currentValue / 2;
134
+ }
135
+ }
136
+ }
137
+
138
+ // Normalization
139
+ if (options.normalized) {
140
+ const n = nodes.length;
141
+ let normalizationFactor: number;
142
+
143
+ if (graph.isDirected) {
144
+ normalizationFactor = (n - 1) * (n - 2);
145
+ } else {
146
+ normalizationFactor = ((n - 1) * (n - 2)) / 2;
147
+ }
148
+
149
+ if (normalizationFactor > 0) {
150
+ for (const nodeId of nodes) {
151
+ const key = String(nodeId);
152
+ const currentValue = centrality[key];
153
+ if (currentValue !== undefined) {
154
+ centrality[key] = currentValue / normalizationFactor;
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ return centrality;
161
+ }
162
+
163
+ /**
164
+ * Calculate betweenness centrality for a specific node
165
+ */
166
+ export function nodeBetweennessCentrality(
167
+ graph: Graph,
168
+ targetNode: NodeId,
169
+ options: BetweennessCentralityOptions = {},
170
+ ): number {
171
+ if (!graph.hasNode(targetNode)) {
172
+ throw new Error(`Node ${String(targetNode)} not found in graph`);
173
+ }
174
+
175
+ const allCentralities = betweennessCentrality(graph, options);
176
+ return allCentralities[String(targetNode)] ?? 0;
177
+ }
178
+
179
+ /**
180
+ * Calculate edge betweenness centrality
181
+ */
182
+ export function edgeBetweennessCentrality(
183
+ graph: Graph,
184
+ options: BetweennessCentralityOptions = {},
185
+ ): Map<string, number> {
186
+ const nodes = Array.from(graph.nodes()).map((node) => node.id);
187
+ const edgeCentrality = new Map<string, number>();
188
+
189
+ // Initialize edge centrality scores
190
+ for (const edge of graph.edges()) {
191
+ const edgeKey = `${String(edge.source)}-${String(edge.target)}`;
192
+ edgeCentrality.set(edgeKey, 0);
193
+ }
194
+
195
+ // Modified Brandes' algorithm for edge betweenness
196
+ for (const source of nodes) {
197
+ const stack: NodeId[] = [];
198
+ const predecessors = new Map<NodeId, NodeId[]>();
199
+ const sigma = new Map<NodeId, number>();
200
+ const distance = new Map<NodeId, number>();
201
+ const delta = new Map<NodeId, number>();
202
+
203
+ // Initialize
204
+ for (const nodeId of nodes) {
205
+ predecessors.set(nodeId, []);
206
+ sigma.set(nodeId, 0);
207
+ distance.set(nodeId, -1);
208
+ delta.set(nodeId, 0);
209
+ }
210
+
211
+ sigma.set(source, 1);
212
+ distance.set(source, 0);
213
+
214
+ const queue: NodeId[] = [source];
215
+
216
+ // BFS to find shortest paths
217
+ while (queue.length > 0) {
218
+ const current = queue.shift();
219
+ if (!current) {
220
+ break;
221
+ }
222
+
223
+ stack.push(current);
224
+
225
+ for (const neighbor of graph.neighbors(current)) {
226
+ const currentDistance = distance.get(current);
227
+ let neighborDistance = distance.get(neighbor);
228
+
229
+ if (currentDistance === undefined || neighborDistance === undefined) {
230
+ continue;
231
+ }
232
+
233
+ if (neighborDistance < 0) {
234
+ queue.push(neighbor);
235
+ distance.set(neighbor, currentDistance + 1);
236
+ neighborDistance = currentDistance + 1; // Update local variable
237
+ }
238
+
239
+ if (neighborDistance === currentDistance + 1) {
240
+ const neighborSigma = sigma.get(neighbor) ?? 0;
241
+ const currentSigma = sigma.get(current) ?? 0;
242
+ sigma.set(neighbor, neighborSigma + currentSigma);
243
+
244
+ const preds = predecessors.get(neighbor);
245
+ if (preds) {
246
+ preds.push(current);
247
+ }
248
+ }
249
+ }
250
+ }
251
+
252
+ // Accumulation for edges
253
+ while (stack.length > 0) {
254
+ const w = stack.pop();
255
+ if (!w) {
256
+ break;
257
+ }
258
+
259
+ const wPreds = predecessors.get(w) ?? [];
260
+ const wSigma = sigma.get(w) ?? 0;
261
+ const wDelta = delta.get(w) ?? 0;
262
+
263
+ for (const v of wPreds) {
264
+ const vSigma = sigma.get(v) ?? 0;
265
+
266
+ if (vSigma > 0 && wSigma > 0) {
267
+ const edgeContribution = vSigma / wSigma * (1 + wDelta);
268
+
269
+ // Update edge centrality
270
+ const edgeKey = `${String(v)}-${String(w)}`;
271
+ const currentEdgeCentrality = edgeCentrality.get(edgeKey) ?? 0;
272
+ edgeCentrality.set(edgeKey, currentEdgeCentrality + edgeContribution);
273
+
274
+ // Update node delta
275
+ const vDelta = delta.get(v) ?? 0;
276
+ delta.set(v, vDelta + edgeContribution);
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ // For undirected graphs, divide by 2 (each shortest path is counted twice)
283
+ if (!graph.isDirected) {
284
+ for (const [edgeKey, centrality] of edgeCentrality) {
285
+ edgeCentrality.set(edgeKey, centrality / 2);
286
+ }
287
+ }
288
+
289
+ // Normalization for edges
290
+ if (options.normalized) {
291
+ const n = nodes.length;
292
+ const normalizationFactor = graph.isDirected ? (n - 1) * (n - 2) : ((n - 1) * (n - 2)) / 2;
293
+
294
+ if (normalizationFactor > 0) {
295
+ for (const [edgeKey, centrality] of edgeCentrality) {
296
+ edgeCentrality.set(edgeKey, centrality / normalizationFactor);
297
+ }
298
+ }
299
+ }
300
+
301
+ return edgeCentrality;
302
+ }
303
+