@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.
- package/LICENSE +21 -0
- package/README.md +193 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts +34 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/betweenness.js +223 -0
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -0
- package/dist/src/algorithms/centrality/closeness.d.ts +43 -0
- package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/closeness.js +202 -0
- package/dist/src/algorithms/centrality/closeness.js.map +1 -0
- package/dist/src/algorithms/centrality/degree.d.ts +17 -0
- package/dist/src/algorithms/centrality/degree.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/degree.js +86 -0
- package/dist/src/algorithms/centrality/degree.js.map +1 -0
- package/dist/src/algorithms/centrality/index.d.ts +11 -0
- package/dist/src/algorithms/centrality/index.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/index.js +8 -0
- package/dist/src/algorithms/centrality/index.js.map +1 -0
- package/dist/src/algorithms/centrality/pagerank.d.ts +74 -0
- package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -0
- package/dist/src/algorithms/centrality/pagerank.js +191 -0
- package/dist/src/algorithms/centrality/pagerank.js.map +1 -0
- package/dist/src/algorithms/components/connected.d.ts +58 -0
- package/dist/src/algorithms/components/connected.d.ts.map +1 -0
- package/dist/src/algorithms/components/connected.js +234 -0
- package/dist/src/algorithms/components/connected.js.map +1 -0
- package/dist/src/algorithms/components/index.d.ts +5 -0
- package/dist/src/algorithms/components/index.d.ts.map +1 -0
- package/dist/src/algorithms/components/index.js +5 -0
- package/dist/src/algorithms/components/index.js.map +1 -0
- package/dist/src/algorithms/index.d.ts +8 -0
- package/dist/src/algorithms/index.d.ts.map +1 -0
- package/dist/src/algorithms/index.js +12 -0
- package/dist/src/algorithms/index.js.map +1 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.d.ts +52 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.d.ts.map +1 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.js +131 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -0
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts +26 -0
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -0
- package/dist/src/algorithms/shortest-path/dijkstra.js +199 -0
- package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -0
- package/dist/src/algorithms/shortest-path/index.d.ts +7 -0
- package/dist/src/algorithms/shortest-path/index.d.ts.map +1 -0
- package/dist/src/algorithms/shortest-path/index.js +6 -0
- package/dist/src/algorithms/shortest-path/index.js.map +1 -0
- package/dist/src/algorithms/traversal/bfs.d.ts +25 -0
- package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -0
- package/dist/src/algorithms/traversal/bfs.js +189 -0
- package/dist/src/algorithms/traversal/bfs.js.map +1 -0
- package/dist/src/algorithms/traversal/dfs.d.ts +32 -0
- package/dist/src/algorithms/traversal/dfs.d.ts.map +1 -0
- package/dist/src/algorithms/traversal/dfs.js +259 -0
- package/dist/src/algorithms/traversal/dfs.js.map +1 -0
- package/dist/src/algorithms/traversal/index.d.ts +7 -0
- package/dist/src/algorithms/traversal/index.d.ts.map +1 -0
- package/dist/src/algorithms/traversal/index.js +6 -0
- package/dist/src/algorithms/traversal/index.js.map +1 -0
- package/dist/src/core/graph.d.ts +100 -0
- package/dist/src/core/graph.d.ts.map +1 -0
- package/dist/src/core/graph.js +276 -0
- package/dist/src/core/graph.js.map +1 -0
- package/dist/src/data-structures/index.d.ts +6 -0
- package/dist/src/data-structures/index.d.ts.map +1 -0
- package/dist/src/data-structures/index.js +6 -0
- package/dist/src/data-structures/index.js.map +1 -0
- package/dist/src/data-structures/priority-queue.d.ts +60 -0
- package/dist/src/data-structures/priority-queue.d.ts.map +1 -0
- package/dist/src/data-structures/priority-queue.js +152 -0
- package/dist/src/data-structures/priority-queue.js.map +1 -0
- package/dist/src/data-structures/union-find.d.ts +54 -0
- package/dist/src/data-structures/union-find.d.ts.map +1 -0
- package/dist/src/data-structures/union-find.js +145 -0
- package/dist/src/data-structures/union-find.js.map +1 -0
- package/dist/src/index.d.ts +11 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +13 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/types/index.d.ts +74 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +5 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/test/browser/basic.test.d.ts +2 -0
- package/dist/test/browser/basic.test.d.ts.map +1 -0
- package/dist/test/browser/basic.test.js +70 -0
- package/dist/test/browser/basic.test.js.map +1 -0
- package/dist/test/unit/bellman-ford.test.d.ts +2 -0
- package/dist/test/unit/bellman-ford.test.d.ts.map +1 -0
- package/dist/test/unit/bellman-ford.test.js +231 -0
- package/dist/test/unit/bellman-ford.test.js.map +1 -0
- package/dist/test/unit/betweenness-centrality.test.d.ts +2 -0
- package/dist/test/unit/betweenness-centrality.test.d.ts.map +1 -0
- package/dist/test/unit/betweenness-centrality.test.js +311 -0
- package/dist/test/unit/betweenness-centrality.test.js.map +1 -0
- package/dist/test/unit/bfs.test.d.ts +2 -0
- package/dist/test/unit/bfs.test.d.ts.map +1 -0
- package/dist/test/unit/bfs.test.js +277 -0
- package/dist/test/unit/bfs.test.js.map +1 -0
- package/dist/test/unit/closeness.test.d.ts +2 -0
- package/dist/test/unit/closeness.test.d.ts.map +1 -0
- package/dist/test/unit/closeness.test.js +266 -0
- package/dist/test/unit/closeness.test.js.map +1 -0
- package/dist/test/unit/connected-components.test.d.ts +2 -0
- package/dist/test/unit/connected-components.test.d.ts.map +1 -0
- package/dist/test/unit/connected-components.test.js +355 -0
- package/dist/test/unit/connected-components.test.js.map +1 -0
- package/dist/test/unit/degree-centrality.test.d.ts +2 -0
- package/dist/test/unit/degree-centrality.test.d.ts.map +1 -0
- package/dist/test/unit/degree-centrality.test.js +260 -0
- package/dist/test/unit/degree-centrality.test.js.map +1 -0
- package/dist/test/unit/dfs.test.d.ts +2 -0
- package/dist/test/unit/dfs.test.d.ts.map +1 -0
- package/dist/test/unit/dfs.test.js +350 -0
- package/dist/test/unit/dfs.test.js.map +1 -0
- package/dist/test/unit/dijkstra.test.d.ts +2 -0
- package/dist/test/unit/dijkstra.test.d.ts.map +1 -0
- package/dist/test/unit/dijkstra.test.js +311 -0
- package/dist/test/unit/dijkstra.test.js.map +1 -0
- package/dist/test/unit/graph.test.d.ts +2 -0
- package/dist/test/unit/graph.test.d.ts.map +1 -0
- package/dist/test/unit/graph.test.js +175 -0
- package/dist/test/unit/graph.test.js.map +1 -0
- package/dist/test/unit/pagerank.test.d.ts +2 -0
- package/dist/test/unit/pagerank.test.d.ts.map +1 -0
- package/dist/test/unit/pagerank.test.js +281 -0
- package/dist/test/unit/pagerank.test.js.map +1 -0
- package/dist/test/unit/priority-queue.test.d.ts +2 -0
- package/dist/test/unit/priority-queue.test.d.ts.map +1 -0
- package/dist/test/unit/priority-queue.test.js +189 -0
- package/dist/test/unit/priority-queue.test.js.map +1 -0
- package/dist/test/unit/union-find.test.d.ts +2 -0
- package/dist/test/unit/union-find.test.d.ts.map +1 -0
- package/dist/test/unit/union-find.test.js +245 -0
- package/dist/test/unit/union-find.test.js.map +1 -0
- package/package.json +100 -0
- package/src/algorithms/centrality/betweenness.ts +303 -0
- package/src/algorithms/centrality/closeness.ts +296 -0
- package/src/algorithms/centrality/degree.ts +105 -0
- package/src/algorithms/centrality/index.ts +11 -0
- package/src/algorithms/centrality/pagerank.ts +302 -0
- package/src/algorithms/components/connected.ts +298 -0
- package/src/algorithms/components/index.ts +17 -0
- package/src/algorithms/index.ts +15 -0
- package/src/algorithms/shortest-path/bellman-ford.ts +214 -0
- package/src/algorithms/shortest-path/dijkstra.ts +256 -0
- package/src/algorithms/shortest-path/index.ts +7 -0
- package/src/algorithms/traversal/bfs.ts +236 -0
- package/src/algorithms/traversal/dfs.ts +367 -0
- package/src/algorithms/traversal/index.ts +7 -0
- package/src/core/graph.ts +326 -0
- package/src/data-structures/index.ts +6 -0
- package/src/data-structures/priority-queue.ts +180 -0
- package/src/data-structures/union-find.ts +170 -0
- package/src/index.ts +35 -0
- package/src/types/index.ts +95 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { Graph } from "../../core/graph.js";
|
|
2
|
+
/**
|
|
3
|
+
* Perform depth-first search starting from a given node
|
|
4
|
+
*/
|
|
5
|
+
export function depthFirstSearch(graph, startNode, options = {}) {
|
|
6
|
+
if (!graph.hasNode(startNode)) {
|
|
7
|
+
throw new Error(`Start node ${String(startNode)} not found in graph`);
|
|
8
|
+
}
|
|
9
|
+
const visited = new Set();
|
|
10
|
+
const order = [];
|
|
11
|
+
const tree = new Map();
|
|
12
|
+
if (options.recursive) {
|
|
13
|
+
dfsRecursive(graph, startNode, visited, order, tree, options, 0);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
dfsIterative(graph, startNode, visited, order, tree, options);
|
|
17
|
+
}
|
|
18
|
+
return { visited, order, tree };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Iterative DFS implementation (safer for browsers)
|
|
22
|
+
*/
|
|
23
|
+
function dfsIterative(graph, startNode, visited, order, tree, options) {
|
|
24
|
+
if (options.preOrder === false) {
|
|
25
|
+
// For post-order, use a simpler recursive approach to ensure correctness
|
|
26
|
+
dfsRecursive(graph, startNode, visited, order, tree, options, 0, null);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const stack = [];
|
|
30
|
+
stack.push({ node: startNode, parent: null, depth: 0 });
|
|
31
|
+
while (stack.length > 0) {
|
|
32
|
+
const current = stack.pop();
|
|
33
|
+
if (!current) {
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
if (!visited.has(current.node)) {
|
|
37
|
+
visited.add(current.node);
|
|
38
|
+
tree.set(current.node, current.parent);
|
|
39
|
+
// Pre-order processing
|
|
40
|
+
order.push(current.node);
|
|
41
|
+
// Call visitor callback if provided
|
|
42
|
+
if (options.visitCallback) {
|
|
43
|
+
options.visitCallback(current.node, current.depth);
|
|
44
|
+
}
|
|
45
|
+
// Early termination if target found
|
|
46
|
+
if (options.targetNode && current.node === options.targetNode) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
// Add neighbors to stack in reverse order to maintain left-to-right traversal
|
|
50
|
+
const neighbors = Array.from(graph.neighbors(current.node));
|
|
51
|
+
for (let i = neighbors.length - 1; i >= 0; i--) {
|
|
52
|
+
const neighbor = neighbors[i];
|
|
53
|
+
if (neighbor !== undefined && !visited.has(neighbor)) {
|
|
54
|
+
stack.push({ node: neighbor, parent: current.node, depth: current.depth + 1 });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Recursive DFS implementation
|
|
62
|
+
*/
|
|
63
|
+
function dfsRecursive(graph, node, visited, order, tree, options, depth, parent = null) {
|
|
64
|
+
visited.add(node);
|
|
65
|
+
tree.set(node, parent);
|
|
66
|
+
// Pre-order processing
|
|
67
|
+
if (options.preOrder !== false) {
|
|
68
|
+
order.push(node);
|
|
69
|
+
if (options.visitCallback) {
|
|
70
|
+
options.visitCallback(node, depth);
|
|
71
|
+
}
|
|
72
|
+
// Early termination if target found
|
|
73
|
+
if (options.targetNode && node === options.targetNode) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Recursively visit neighbors
|
|
78
|
+
for (const neighbor of graph.neighbors(node)) {
|
|
79
|
+
if (!visited.has(neighbor)) {
|
|
80
|
+
dfsRecursive(graph, neighbor, visited, order, tree, options, depth + 1, node);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Post-order processing
|
|
84
|
+
if (options.preOrder === false) {
|
|
85
|
+
order.push(node);
|
|
86
|
+
if (options.visitCallback) {
|
|
87
|
+
options.visitCallback(node, depth);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Detect cycles in a graph using DFS
|
|
93
|
+
*/
|
|
94
|
+
export function hasCycleDFS(graph) {
|
|
95
|
+
const visited = new Set();
|
|
96
|
+
// Check each unvisited node for cycles
|
|
97
|
+
for (const node of graph.nodes()) {
|
|
98
|
+
if (!visited.has(node.id)) {
|
|
99
|
+
if (graph.isDirected) {
|
|
100
|
+
const recursionStack = new Set();
|
|
101
|
+
if (hasCycleUtilDirected(graph, node.id, visited, recursionStack)) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
if (hasCycleUtilUndirected(graph, node.id, visited, null)) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Utility function for cycle detection in directed graphs
|
|
116
|
+
*/
|
|
117
|
+
function hasCycleUtilDirected(graph, node, visited, recursionStack) {
|
|
118
|
+
visited.add(node);
|
|
119
|
+
recursionStack.add(node);
|
|
120
|
+
// Check all neighbors
|
|
121
|
+
for (const neighbor of graph.neighbors(node)) {
|
|
122
|
+
if (!visited.has(neighbor)) {
|
|
123
|
+
if (hasCycleUtilDirected(graph, neighbor, visited, recursionStack)) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else if (recursionStack.has(neighbor)) {
|
|
128
|
+
// Back edge found - cycle detected
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
recursionStack.delete(node);
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Utility function for cycle detection in undirected graphs
|
|
137
|
+
*/
|
|
138
|
+
function hasCycleUtilUndirected(graph, node, visited, parent) {
|
|
139
|
+
visited.add(node);
|
|
140
|
+
// Check all neighbors
|
|
141
|
+
for (const neighbor of graph.neighbors(node)) {
|
|
142
|
+
if (!visited.has(neighbor)) {
|
|
143
|
+
if (hasCycleUtilUndirected(graph, neighbor, visited, node)) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else if (neighbor !== parent) {
|
|
148
|
+
// Found a visited node that's not the parent - cycle detected
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Topological sorting using DFS (for directed acyclic graphs)
|
|
156
|
+
*/
|
|
157
|
+
export function topologicalSort(graph) {
|
|
158
|
+
if (!graph.isDirected) {
|
|
159
|
+
throw new Error("Topological sort requires a directed graph");
|
|
160
|
+
}
|
|
161
|
+
// First check if graph has cycles
|
|
162
|
+
if (hasCycleDFS(graph)) {
|
|
163
|
+
return null; // Cannot topologically sort a graph with cycles
|
|
164
|
+
}
|
|
165
|
+
const visited = new Set();
|
|
166
|
+
const stack = [];
|
|
167
|
+
// Perform DFS from each unvisited node
|
|
168
|
+
for (const node of graph.nodes()) {
|
|
169
|
+
if (!visited.has(node.id)) {
|
|
170
|
+
topologicalSortUtil(graph, node.id, visited, stack);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Return nodes in reverse order of finishing times
|
|
174
|
+
return stack.reverse();
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Utility function for topological sorting
|
|
178
|
+
*/
|
|
179
|
+
function topologicalSortUtil(graph, node, visited, stack) {
|
|
180
|
+
visited.add(node);
|
|
181
|
+
// Visit all neighbors first
|
|
182
|
+
for (const neighbor of graph.neighbors(node)) {
|
|
183
|
+
if (!visited.has(neighbor)) {
|
|
184
|
+
topologicalSortUtil(graph, neighbor, visited, stack);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Add current node to stack after visiting all neighbors
|
|
188
|
+
stack.push(node);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Find strongly connected components using DFS (for directed graphs)
|
|
192
|
+
*/
|
|
193
|
+
export function findStronglyConnectedComponents(graph) {
|
|
194
|
+
if (!graph.isDirected) {
|
|
195
|
+
throw new Error("Strongly connected components require a directed graph");
|
|
196
|
+
}
|
|
197
|
+
const visited = new Set();
|
|
198
|
+
const finishOrder = [];
|
|
199
|
+
// Step 1: Get nodes in order of finishing times
|
|
200
|
+
for (const node of graph.nodes()) {
|
|
201
|
+
if (!visited.has(node.id)) {
|
|
202
|
+
dfsFinishOrder(graph, node.id, visited, finishOrder);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Step 2: Create transpose graph (reverse all edges)
|
|
206
|
+
const transposeGraph = createTransposeGraph(graph);
|
|
207
|
+
// Step 3: DFS on transpose graph in reverse finish order
|
|
208
|
+
const visited2 = new Set();
|
|
209
|
+
const components = [];
|
|
210
|
+
for (let i = finishOrder.length - 1; i >= 0; i--) {
|
|
211
|
+
const node = finishOrder[i];
|
|
212
|
+
if (node !== undefined && !visited2.has(node)) {
|
|
213
|
+
const component = [];
|
|
214
|
+
dfsCollectComponent(transposeGraph, node, visited2, component);
|
|
215
|
+
components.push(component);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return components;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* DFS to record finish order
|
|
222
|
+
*/
|
|
223
|
+
function dfsFinishOrder(graph, node, visited, finishOrder) {
|
|
224
|
+
visited.add(node);
|
|
225
|
+
for (const neighbor of graph.neighbors(node)) {
|
|
226
|
+
if (!visited.has(neighbor)) {
|
|
227
|
+
dfsFinishOrder(graph, neighbor, visited, finishOrder);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
finishOrder.push(node);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* DFS to collect nodes in a component
|
|
234
|
+
*/
|
|
235
|
+
function dfsCollectComponent(graph, node, visited, component) {
|
|
236
|
+
visited.add(node);
|
|
237
|
+
component.push(node);
|
|
238
|
+
for (const neighbor of graph.neighbors(node)) {
|
|
239
|
+
if (!visited.has(neighbor)) {
|
|
240
|
+
dfsCollectComponent(graph, neighbor, visited, component);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Create transpose (reverse) of a directed graph
|
|
246
|
+
*/
|
|
247
|
+
function createTransposeGraph(graph) {
|
|
248
|
+
const transpose = new Graph({ directed: true });
|
|
249
|
+
// Add all nodes
|
|
250
|
+
for (const node of graph.nodes()) {
|
|
251
|
+
transpose.addNode(node.id, node.data);
|
|
252
|
+
}
|
|
253
|
+
// Add reverse edges
|
|
254
|
+
for (const edge of graph.edges()) {
|
|
255
|
+
transpose.addEdge(edge.target, edge.source, edge.weight, edge.data);
|
|
256
|
+
}
|
|
257
|
+
return transpose;
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=dfs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dfs.js","sourceRoot":"","sources":["../../../../src/algorithms/traversal/dfs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,qBAAqB,CAAC;AAkB1C;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC5B,KAAY,EACZ,SAAiB,EACjB,UAAsB,EAAE;IAExB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,cAAc,MAAM,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAyB,CAAC;IAE9C,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACpB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACrE,CAAC;SAAM,CAAC;QACJ,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,EAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CACjB,KAAY,EACZ,SAAiB,EACjB,OAAoB,EACpB,KAAe,EACf,IAAgC,EAChC,OAAmB;IAEnB,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;QAC7B,yEAAyE;QACzE,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QACvE,OAAO;IACX,CAAC;IAED,MAAM,KAAK,GAA2D,EAAE,CAAC;IACzE,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAC,CAAC,CAAC;IAEtD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,MAAM;QACV,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAEvC,uBAAuB;YACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAEzB,oCAAoC;YACpC,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;gBACxB,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YACvD,CAAC;YAED,oCAAoC;YACpC,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC;gBAC5D,MAAM;YACV,CAAC;YAED,8EAA8E;YAC9E,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5D,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;gBAC9B,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACnD,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,EAAC,CAAC,CAAC;gBACjF,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CACjB,KAAY,EACZ,IAAY,EACZ,OAAoB,EACpB,KAAe,EACf,IAAgC,EAChC,OAAmB,EACnB,KAAa,EACb,SAAwB,IAAI;IAE5B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAEvB,uBAAuB;IACvB,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEjB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YACxB,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;QAED,oCAAoC;QACpC,IAAI,OAAO,CAAC,UAAU,IAAI,IAAI,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC;YACpD,OAAO;QACX,CAAC;IACL,CAAC;IAED,8BAA8B;IAC9B,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QAClF,CAAC;IACL,CAAC;IAED,wBAAwB;IACxB,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEjB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;YACxB,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;IACL,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAY;IACpC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,uCAAuC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACxB,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACnB,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;gBACzC,IAAI,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC;oBAChE,OAAO,IAAI,CAAC;gBAChB,CAAC;YACL,CAAC;iBAAM,CAAC;gBACJ,IAAI,sBAAsB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;oBACxD,OAAO,IAAI,CAAC;gBAChB,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CACzB,KAAY,EACZ,IAAY,EACZ,OAAoB,EACpB,cAA2B;IAE3B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEzB,sBAAsB;IACtB,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,IAAI,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC;gBACjE,OAAO,IAAI,CAAC;YAChB,CAAC;QACL,CAAC;aAAM,IAAI,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtC,mCAAmC;YACnC,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAC3B,KAAY,EACZ,IAAY,EACZ,OAAoB,EACpB,MAAqB;IAErB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAElB,sBAAsB;IACtB,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,IAAI,sBAAsB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;gBACzD,OAAO,IAAI,CAAC;YAChB,CAAC;QACL,CAAC;aAAM,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC7B,8DAA8D;YAC9D,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAY;IACxC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAClE,CAAC;IAED,kCAAkC;IAClC,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC,CAAC,gDAAgD;IACjE,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,uCAAuC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACxB,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QACxD,CAAC;IACL,CAAC;IAED,mDAAmD;IACnD,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CACxB,KAAY,EACZ,IAAY,EACZ,OAAoB,EACpB,KAAe;IAEf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAElB,4BAA4B;IAC5B,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;QACzD,CAAC;IACL,CAAC;IAED,yDAAyD;IACzD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,+BAA+B,CAAC,KAAY;IACxD,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,gDAAgD;IAChD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACxB,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QACzD,CAAC;IACL,CAAC;IAED,qDAAqD;IACrD,MAAM,cAAc,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAEnD,yDAAyD;IACzD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,MAAM,UAAU,GAAe,EAAE,CAAC;IAElC,KAAK,IAAI,CAAC,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5C,MAAM,SAAS,GAAa,EAAE,CAAC;YAC/B,mBAAmB,CAAC,cAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;YAC/D,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;IACL,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CACnB,KAAY,EACZ,IAAY,EACZ,OAAoB,EACpB,WAAqB;IAErB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAElB,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QAC1D,CAAC;IACL,CAAC;IAED,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CACxB,KAAY,EACZ,IAAY,EACZ,OAAoB,EACpB,SAAmB;IAEnB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAErB,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QAC7D,CAAC;IACL,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,KAAY;IACtC,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC,EAAC,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAC;IAE9C,gBAAgB;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAC/B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;IAED,oBAAoB;IACpB,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAC/B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACxE,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph traversal algorithms
|
|
3
|
+
*/
|
|
4
|
+
export { breadthFirstSearch, isBipartite, shortestPathBFS, singleSourceShortestPathBFS } from "./bfs.js";
|
|
5
|
+
export type { DFSOptions } from "./dfs.js";
|
|
6
|
+
export { depthFirstSearch, findStronglyConnectedComponents, hasCycleDFS, topologicalSort } from "./dfs.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/algorithms/traversal/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAC,kBAAkB,EAAE,WAAW,EAAE,eAAe,EAAE,2BAA2B,EAAC,MAAM,UAAU,CAAC;AACvG,YAAY,EAAC,UAAU,EAAC,MAAM,UAAU,CAAC;AACzC,OAAO,EAAC,gBAAgB,EAAE,+BAA+B,EAAE,WAAW,EAAE,eAAe,EAAC,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph traversal algorithms
|
|
3
|
+
*/
|
|
4
|
+
export { breadthFirstSearch, isBipartite, shortestPathBFS, singleSourceShortestPathBFS } from "./bfs.js";
|
|
5
|
+
export { depthFirstSearch, findStronglyConnectedComponents, hasCycleDFS, topologicalSort } from "./dfs.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/algorithms/traversal/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAC,kBAAkB,EAAE,WAAW,EAAE,eAAe,EAAE,2BAA2B,EAAC,MAAM,UAAU,CAAC;AAEvG,OAAO,EAAC,gBAAgB,EAAE,+BAA+B,EAAE,WAAW,EAAE,eAAe,EAAC,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { Edge, GraphConfig, Node, NodeId } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Core Graph data structure for the Graphty Algorithms library
|
|
4
|
+
*
|
|
5
|
+
* Provides efficient graph representation with support for both directed and undirected graphs.
|
|
6
|
+
* Uses adjacency lists for optimal performance with sparse graphs.
|
|
7
|
+
*/
|
|
8
|
+
export declare class Graph {
|
|
9
|
+
private nodeMap;
|
|
10
|
+
private adjacencyList;
|
|
11
|
+
private incomingEdges;
|
|
12
|
+
private config;
|
|
13
|
+
private edgeCount;
|
|
14
|
+
constructor(config?: Partial<GraphConfig>);
|
|
15
|
+
/**
|
|
16
|
+
* Add a node to the graph
|
|
17
|
+
*/
|
|
18
|
+
addNode(id: NodeId, data?: Record<string, unknown>): void;
|
|
19
|
+
/**
|
|
20
|
+
* Remove a node from the graph
|
|
21
|
+
*/
|
|
22
|
+
removeNode(id: NodeId): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Add an edge to the graph
|
|
25
|
+
*/
|
|
26
|
+
addEdge(source: NodeId, target: NodeId, weight?: number, data?: Record<string, unknown>): void;
|
|
27
|
+
/**
|
|
28
|
+
* Remove an edge from the graph
|
|
29
|
+
*/
|
|
30
|
+
removeEdge(source: NodeId, target: NodeId): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Check if a node exists in the graph
|
|
33
|
+
*/
|
|
34
|
+
hasNode(id: NodeId): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Check if an edge exists in the graph
|
|
37
|
+
*/
|
|
38
|
+
hasEdge(source: NodeId, target: NodeId): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Get a node by ID
|
|
41
|
+
*/
|
|
42
|
+
getNode(id: NodeId): Node | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Get an edge by source and target
|
|
45
|
+
*/
|
|
46
|
+
getEdge(source: NodeId, target: NodeId): Edge | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Get the number of nodes in the graph
|
|
49
|
+
*/
|
|
50
|
+
get nodeCount(): number;
|
|
51
|
+
/**
|
|
52
|
+
* Get the number of edges in the graph
|
|
53
|
+
*/
|
|
54
|
+
get totalEdgeCount(): number;
|
|
55
|
+
/**
|
|
56
|
+
* Check if the graph is directed
|
|
57
|
+
*/
|
|
58
|
+
get isDirected(): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Get all nodes in the graph
|
|
61
|
+
*/
|
|
62
|
+
nodes(): IterableIterator<Node>;
|
|
63
|
+
/**
|
|
64
|
+
* Get all edges in the graph
|
|
65
|
+
*/
|
|
66
|
+
edges(): IterableIterator<Edge>;
|
|
67
|
+
/**
|
|
68
|
+
* Get neighbors of a node (outgoing edges)
|
|
69
|
+
*/
|
|
70
|
+
neighbors(nodeId: NodeId): IterableIterator<NodeId>;
|
|
71
|
+
/**
|
|
72
|
+
* Get incoming neighbors of a node (directed graphs only)
|
|
73
|
+
*/
|
|
74
|
+
inNeighbors(nodeId: NodeId): IterableIterator<NodeId>;
|
|
75
|
+
/**
|
|
76
|
+
* Get outgoing neighbors of a node
|
|
77
|
+
*/
|
|
78
|
+
outNeighbors(nodeId: NodeId): IterableIterator<NodeId>;
|
|
79
|
+
/**
|
|
80
|
+
* Get the degree of a node
|
|
81
|
+
*/
|
|
82
|
+
degree(nodeId: NodeId): number;
|
|
83
|
+
/**
|
|
84
|
+
* Get the in-degree of a node
|
|
85
|
+
*/
|
|
86
|
+
inDegree(nodeId: NodeId): number;
|
|
87
|
+
/**
|
|
88
|
+
* Get the out-degree of a node
|
|
89
|
+
*/
|
|
90
|
+
outDegree(nodeId: NodeId): number;
|
|
91
|
+
/**
|
|
92
|
+
* Create a copy of the graph
|
|
93
|
+
*/
|
|
94
|
+
clone(): Graph;
|
|
95
|
+
/**
|
|
96
|
+
* Get graph configuration
|
|
97
|
+
*/
|
|
98
|
+
getConfig(): GraphConfig;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/core/graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAC,MAAM,mBAAmB,CAAC;AAEvE;;;;;GAKG;AACH,qBAAa,KAAK;IACd,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,aAAa,CAAiC;IACtD,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM;IAa7C;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAWzD;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAwC/B;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IA8CzF;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAyBnD;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI5B;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAKhD;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAIrC;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAKzD;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;OAEG;IACH,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;OAEG;IACH,KAAK,IAAI,gBAAgB,CAAC,IAAI,CAAC;IAI/B;;OAEG;IACF,KAAK,IAAI,gBAAgB,CAAC,IAAI,CAAC;IAahC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAKnD;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IASrD;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAItD;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAS9B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAShC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAKjC;;OAEG;IACH,KAAK,IAAI,KAAK;IAqBd;;OAEG;IACH,SAAS,IAAI,WAAW;CAG3B"}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Graph data structure for the Graphty Algorithms library
|
|
3
|
+
*
|
|
4
|
+
* Provides efficient graph representation with support for both directed and undirected graphs.
|
|
5
|
+
* Uses adjacency lists for optimal performance with sparse graphs.
|
|
6
|
+
*/
|
|
7
|
+
export class Graph {
|
|
8
|
+
nodeMap;
|
|
9
|
+
adjacencyList;
|
|
10
|
+
incomingEdges; // For directed graphs
|
|
11
|
+
config;
|
|
12
|
+
edgeCount;
|
|
13
|
+
constructor(config = {}) {
|
|
14
|
+
this.config = {
|
|
15
|
+
directed: false,
|
|
16
|
+
allowSelfLoops: true,
|
|
17
|
+
allowParallelEdges: false,
|
|
18
|
+
...config,
|
|
19
|
+
};
|
|
20
|
+
this.nodeMap = new Map();
|
|
21
|
+
this.adjacencyList = new Map();
|
|
22
|
+
this.incomingEdges = new Map();
|
|
23
|
+
this.edgeCount = 0;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Add a node to the graph
|
|
27
|
+
*/
|
|
28
|
+
addNode(id, data) {
|
|
29
|
+
if (!this.nodeMap.has(id)) {
|
|
30
|
+
this.nodeMap.set(id, { id, data });
|
|
31
|
+
this.adjacencyList.set(id, new Map());
|
|
32
|
+
if (this.config.directed) {
|
|
33
|
+
this.incomingEdges.set(id, new Map());
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Remove a node from the graph
|
|
39
|
+
*/
|
|
40
|
+
removeNode(id) {
|
|
41
|
+
if (!this.nodeMap.has(id)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
// Remove all edges connected to this node
|
|
45
|
+
const outgoingEdges = this.adjacencyList.get(id);
|
|
46
|
+
if (outgoingEdges) {
|
|
47
|
+
for (const targetId of outgoingEdges.keys()) {
|
|
48
|
+
this.removeEdge(id, targetId);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (this.config.directed) {
|
|
52
|
+
const incomingEdges = this.incomingEdges.get(id);
|
|
53
|
+
if (incomingEdges) {
|
|
54
|
+
for (const sourceId of incomingEdges.keys()) {
|
|
55
|
+
this.removeEdge(sourceId, id);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// For undirected graphs, also remove edges where this node is the target
|
|
61
|
+
for (const [nodeId, edges] of this.adjacencyList) {
|
|
62
|
+
if (edges.has(id)) {
|
|
63
|
+
this.removeEdge(nodeId, id);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Remove the node itself
|
|
68
|
+
this.nodeMap.delete(id);
|
|
69
|
+
this.adjacencyList.delete(id);
|
|
70
|
+
if (this.config.directed) {
|
|
71
|
+
this.incomingEdges.delete(id);
|
|
72
|
+
}
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Add an edge to the graph
|
|
77
|
+
*/
|
|
78
|
+
addEdge(source, target, weight = 1, data) {
|
|
79
|
+
// Ensure both nodes exist
|
|
80
|
+
this.addNode(source);
|
|
81
|
+
this.addNode(target);
|
|
82
|
+
// Check self-loops
|
|
83
|
+
if (!this.config.allowSelfLoops && source === target) {
|
|
84
|
+
throw new Error("Self-loops are not allowed in this graph");
|
|
85
|
+
}
|
|
86
|
+
// Check parallel edges
|
|
87
|
+
if (!this.config.allowParallelEdges && this.hasEdge(source, target)) {
|
|
88
|
+
throw new Error("Parallel edges are not allowed in this graph");
|
|
89
|
+
}
|
|
90
|
+
const edge = { source, target, weight, data };
|
|
91
|
+
// Add to adjacency list
|
|
92
|
+
const sourceAdjacency = this.adjacencyList.get(source);
|
|
93
|
+
if (sourceAdjacency) {
|
|
94
|
+
sourceAdjacency.set(target, edge);
|
|
95
|
+
}
|
|
96
|
+
if (this.config.directed) {
|
|
97
|
+
// For directed graphs, add to incoming edges list
|
|
98
|
+
const targetIncoming = this.incomingEdges.get(target);
|
|
99
|
+
if (targetIncoming) {
|
|
100
|
+
targetIncoming.set(source, edge);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// For undirected graphs, add the reverse edge
|
|
105
|
+
if (source !== target) {
|
|
106
|
+
const reverseEdge = { source: target, target: source, weight, data };
|
|
107
|
+
const targetAdjacency = this.adjacencyList.get(target);
|
|
108
|
+
if (targetAdjacency) {
|
|
109
|
+
targetAdjacency.set(source, reverseEdge);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
this.edgeCount++;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Remove an edge from the graph
|
|
117
|
+
*/
|
|
118
|
+
removeEdge(source, target) {
|
|
119
|
+
const sourceEdges = this.adjacencyList.get(source);
|
|
120
|
+
if (!sourceEdges?.has(target)) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
sourceEdges.delete(target);
|
|
124
|
+
if (this.config.directed) {
|
|
125
|
+
const targetIncoming = this.incomingEdges.get(target);
|
|
126
|
+
if (targetIncoming) {
|
|
127
|
+
targetIncoming.delete(source);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// For undirected graphs, remove the reverse edge
|
|
132
|
+
const targetEdges = this.adjacencyList.get(target);
|
|
133
|
+
if (targetEdges) {
|
|
134
|
+
targetEdges.delete(source);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
this.edgeCount--;
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Check if a node exists in the graph
|
|
142
|
+
*/
|
|
143
|
+
hasNode(id) {
|
|
144
|
+
return this.nodeMap.has(id);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Check if an edge exists in the graph
|
|
148
|
+
*/
|
|
149
|
+
hasEdge(source, target) {
|
|
150
|
+
const sourceEdges = this.adjacencyList.get(source);
|
|
151
|
+
return sourceEdges ? sourceEdges.has(target) : false;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get a node by ID
|
|
155
|
+
*/
|
|
156
|
+
getNode(id) {
|
|
157
|
+
return this.nodeMap.get(id);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get an edge by source and target
|
|
161
|
+
*/
|
|
162
|
+
getEdge(source, target) {
|
|
163
|
+
const sourceEdges = this.adjacencyList.get(source);
|
|
164
|
+
return sourceEdges ? sourceEdges.get(target) : undefined;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get the number of nodes in the graph
|
|
168
|
+
*/
|
|
169
|
+
get nodeCount() {
|
|
170
|
+
return this.nodeMap.size;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get the number of edges in the graph
|
|
174
|
+
*/
|
|
175
|
+
get totalEdgeCount() {
|
|
176
|
+
return this.edgeCount;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Check if the graph is directed
|
|
180
|
+
*/
|
|
181
|
+
get isDirected() {
|
|
182
|
+
return this.config.directed;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Get all nodes in the graph
|
|
186
|
+
*/
|
|
187
|
+
nodes() {
|
|
188
|
+
return this.nodeMap.values();
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get all edges in the graph
|
|
192
|
+
*/
|
|
193
|
+
*edges() {
|
|
194
|
+
for (const [source, edges] of this.adjacencyList) {
|
|
195
|
+
for (const edge of edges.values()) {
|
|
196
|
+
// For undirected graphs, only yield each edge once
|
|
197
|
+
if (!this.config.directed && source > edge.target) {
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
yield edge;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get neighbors of a node (outgoing edges)
|
|
206
|
+
*/
|
|
207
|
+
neighbors(nodeId) {
|
|
208
|
+
const edges = this.adjacencyList.get(nodeId);
|
|
209
|
+
return edges ? edges.keys() : new Map().keys();
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Get incoming neighbors of a node (directed graphs only)
|
|
213
|
+
*/
|
|
214
|
+
inNeighbors(nodeId) {
|
|
215
|
+
if (!this.config.directed) {
|
|
216
|
+
return this.neighbors(nodeId);
|
|
217
|
+
}
|
|
218
|
+
const edges = this.incomingEdges.get(nodeId);
|
|
219
|
+
return edges ? edges.keys() : new Map().keys();
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get outgoing neighbors of a node
|
|
223
|
+
*/
|
|
224
|
+
outNeighbors(nodeId) {
|
|
225
|
+
return this.neighbors(nodeId);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Get the degree of a node
|
|
229
|
+
*/
|
|
230
|
+
degree(nodeId) {
|
|
231
|
+
if (this.config.directed) {
|
|
232
|
+
return this.inDegree(nodeId) + this.outDegree(nodeId);
|
|
233
|
+
}
|
|
234
|
+
const edges = this.adjacencyList.get(nodeId);
|
|
235
|
+
return edges ? edges.size : 0;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Get the in-degree of a node
|
|
239
|
+
*/
|
|
240
|
+
inDegree(nodeId) {
|
|
241
|
+
if (!this.config.directed) {
|
|
242
|
+
return this.degree(nodeId);
|
|
243
|
+
}
|
|
244
|
+
const edges = this.incomingEdges.get(nodeId);
|
|
245
|
+
return edges ? edges.size : 0;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Get the out-degree of a node
|
|
249
|
+
*/
|
|
250
|
+
outDegree(nodeId) {
|
|
251
|
+
const edges = this.adjacencyList.get(nodeId);
|
|
252
|
+
return edges ? edges.size : 0;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Create a copy of the graph
|
|
256
|
+
*/
|
|
257
|
+
clone() {
|
|
258
|
+
const cloned = new Graph(this.config);
|
|
259
|
+
// Copy nodes
|
|
260
|
+
for (const node of this.nodeMap.values()) {
|
|
261
|
+
cloned.addNode(node.id, node.data ? { ...node.data } : undefined);
|
|
262
|
+
}
|
|
263
|
+
// Copy edges
|
|
264
|
+
for (const edge of this.edges()) {
|
|
265
|
+
cloned.addEdge(edge.source, edge.target, edge.weight, edge.data ? { ...edge.data } : undefined);
|
|
266
|
+
}
|
|
267
|
+
return cloned;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Get graph configuration
|
|
271
|
+
*/
|
|
272
|
+
getConfig() {
|
|
273
|
+
return { ...this.config };
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=graph.js.map
|