@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,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Priority Queue implementation using a binary heap
|
|
3
|
+
*
|
|
4
|
+
* Optimized for graph algorithms requiring efficient priority-based operations.
|
|
5
|
+
* Uses a min-heap by default but supports custom comparison functions.
|
|
6
|
+
*/
|
|
7
|
+
export class PriorityQueue<T> {
|
|
8
|
+
private heap: {item: T, priority: number}[];
|
|
9
|
+
private compareFn: (a: number, b: number) => number;
|
|
10
|
+
|
|
11
|
+
constructor(compareFn?: (a: number, b: number) => number) {
|
|
12
|
+
this.heap = [];
|
|
13
|
+
// Default to min-heap (smaller priority values have higher priority)
|
|
14
|
+
this.compareFn = compareFn ?? ((a, b) => a - b);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Add an item with the given priority to the queue
|
|
19
|
+
*/
|
|
20
|
+
enqueue(item: T, priority: number): void {
|
|
21
|
+
const element = {item, priority};
|
|
22
|
+
this.heap.push(element);
|
|
23
|
+
this.heapifyUp(this.heap.length - 1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Remove and return the item with the highest priority
|
|
28
|
+
*/
|
|
29
|
+
dequeue(): T | undefined {
|
|
30
|
+
if (this.heap.length === 0) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (this.heap.length === 1) {
|
|
35
|
+
return this.heap.pop()?.item;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const root = this.heap[0];
|
|
39
|
+
const lastElement = this.heap.pop();
|
|
40
|
+
|
|
41
|
+
if (!root) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (lastElement) {
|
|
46
|
+
this.heap[0] = lastElement;
|
|
47
|
+
this.heapifyDown(0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return root.item;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* View the item with the highest priority without removing it
|
|
55
|
+
*/
|
|
56
|
+
peek(): T | undefined {
|
|
57
|
+
const first = this.heap[0];
|
|
58
|
+
return first ? first.item : undefined;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Check if the queue is empty
|
|
63
|
+
*/
|
|
64
|
+
isEmpty(): boolean {
|
|
65
|
+
return this.heap.length === 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get the number of items in the queue
|
|
70
|
+
*/
|
|
71
|
+
size(): number {
|
|
72
|
+
return this.heap.length;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Update the priority of an item if it exists in the queue
|
|
77
|
+
* Returns true if the item was found and updated
|
|
78
|
+
*/
|
|
79
|
+
updatePriority(item: T, newPriority: number): boolean {
|
|
80
|
+
const index = this.heap.findIndex((element) => element.item === item);
|
|
81
|
+
|
|
82
|
+
if (index === -1) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const element = this.heap[index];
|
|
87
|
+
if (!element) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const oldPriority = element.priority;
|
|
92
|
+
element.priority = newPriority;
|
|
93
|
+
|
|
94
|
+
// Determine whether to heapify up or down based on priority change
|
|
95
|
+
if (this.compareFn(newPriority, oldPriority) < 0) {
|
|
96
|
+
this.heapifyUp(index);
|
|
97
|
+
} else if (this.compareFn(newPriority, oldPriority) > 0) {
|
|
98
|
+
this.heapifyDown(index);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Clear all items from the queue
|
|
106
|
+
*/
|
|
107
|
+
clear(): void {
|
|
108
|
+
this.heap = [];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Convert queue to array (for testing/debugging)
|
|
113
|
+
*/
|
|
114
|
+
toArray(): {item: T, priority: number}[] {
|
|
115
|
+
return [... this.heap];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Move element up the heap until heap property is satisfied
|
|
120
|
+
*/
|
|
121
|
+
private heapifyUp(index: number): void {
|
|
122
|
+
if (index === 0) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const parentIndex = Math.floor((index - 1) / 2);
|
|
127
|
+
|
|
128
|
+
const current = this.heap[index];
|
|
129
|
+
const parent = this.heap[parentIndex];
|
|
130
|
+
|
|
131
|
+
if (current && parent && this.compareFn(current.priority, parent.priority) < 0) {
|
|
132
|
+
this.swap(index, parentIndex);
|
|
133
|
+
this.heapifyUp(parentIndex);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Move element down the heap until heap property is satisfied
|
|
139
|
+
*/
|
|
140
|
+
private heapifyDown(index: number): void {
|
|
141
|
+
const leftChildIndex = (2 * index) + 1;
|
|
142
|
+
const rightChildIndex = (2 * index) + 2;
|
|
143
|
+
let targetIndex = index;
|
|
144
|
+
|
|
145
|
+
// Find the child with highest priority (lowest value for min-heap)
|
|
146
|
+
const leftChild = this.heap[leftChildIndex];
|
|
147
|
+
const target = this.heap[targetIndex];
|
|
148
|
+
|
|
149
|
+
if (leftChildIndex < this.heap.length && leftChild && target &&
|
|
150
|
+
this.compareFn(leftChild.priority, target.priority) < 0) {
|
|
151
|
+
targetIndex = leftChildIndex;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const rightChild = this.heap[rightChildIndex];
|
|
155
|
+
const newTarget = this.heap[targetIndex];
|
|
156
|
+
|
|
157
|
+
if (rightChildIndex < this.heap.length && rightChild && newTarget &&
|
|
158
|
+
this.compareFn(rightChild.priority, newTarget.priority) < 0) {
|
|
159
|
+
targetIndex = rightChildIndex;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// If we found a child with higher priority, swap and continue
|
|
163
|
+
if (targetIndex !== index) {
|
|
164
|
+
this.swap(index, targetIndex);
|
|
165
|
+
this.heapifyDown(targetIndex);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Swap two elements in the heap
|
|
171
|
+
*/
|
|
172
|
+
private swap(i: number, j: number): void {
|
|
173
|
+
const temp = this.heap[i];
|
|
174
|
+
const other = this.heap[j];
|
|
175
|
+
if (temp && other) {
|
|
176
|
+
this.heap[i] = other;
|
|
177
|
+
this.heap[j] = temp;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type {NodeId} from "../types/index.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Union-Find (Disjoint Set) data structure with path compression and union by rank
|
|
5
|
+
*
|
|
6
|
+
* Efficiently supports dynamic connectivity queries and is essential for
|
|
7
|
+
* algorithms like connected components and minimum spanning trees.
|
|
8
|
+
*/
|
|
9
|
+
export class UnionFind {
|
|
10
|
+
private parent: Map<NodeId, NodeId>;
|
|
11
|
+
private rank: Map<NodeId, number>;
|
|
12
|
+
private componentCount: number;
|
|
13
|
+
|
|
14
|
+
constructor(elements: NodeId[]) {
|
|
15
|
+
this.parent = new Map();
|
|
16
|
+
this.rank = new Map();
|
|
17
|
+
this.componentCount = elements.length;
|
|
18
|
+
|
|
19
|
+
// Initialize each element as its own parent with rank 0
|
|
20
|
+
for (const element of elements) {
|
|
21
|
+
this.parent.set(element, element);
|
|
22
|
+
this.rank.set(element, 0);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Find the root of the set containing the element with path compression
|
|
28
|
+
*/
|
|
29
|
+
find(element: NodeId): NodeId {
|
|
30
|
+
const parent = this.parent.get(element);
|
|
31
|
+
|
|
32
|
+
if (parent === undefined) {
|
|
33
|
+
throw new Error(`Element ${String(element)} not found in UnionFind`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Path compression: make every node on the path point directly to the root
|
|
37
|
+
if (parent !== element) {
|
|
38
|
+
this.parent.set(element, this.find(parent));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const result = this.parent.get(element);
|
|
42
|
+
if (result === undefined) {
|
|
43
|
+
throw new Error(`Element ${String(element)} not found in UnionFind`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Union two sets using union by rank
|
|
51
|
+
*/
|
|
52
|
+
union(elementA: NodeId, elementB: NodeId): void {
|
|
53
|
+
const rootA = this.find(elementA);
|
|
54
|
+
const rootB = this.find(elementB);
|
|
55
|
+
|
|
56
|
+
// Already in the same set
|
|
57
|
+
if (rootA === rootB) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const rankA = this.rank.get(rootA);
|
|
62
|
+
const rankB = this.rank.get(rootB);
|
|
63
|
+
if (rankA === undefined || rankB === undefined) {
|
|
64
|
+
throw new Error("Rank not found for root elements");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Union by rank: attach smaller tree under root of larger tree
|
|
68
|
+
if (rankA < rankB) {
|
|
69
|
+
this.parent.set(rootA, rootB);
|
|
70
|
+
} else if (rankA > rankB) {
|
|
71
|
+
this.parent.set(rootB, rootA);
|
|
72
|
+
} else {
|
|
73
|
+
// Same rank: make one root and increment its rank
|
|
74
|
+
this.parent.set(rootB, rootA);
|
|
75
|
+
this.rank.set(rootA, rankA + 1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this.componentCount--;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Check if two elements are in the same connected component
|
|
83
|
+
*/
|
|
84
|
+
connected(elementA: NodeId, elementB: NodeId): boolean {
|
|
85
|
+
try {
|
|
86
|
+
return this.find(elementA) === this.find(elementB);
|
|
87
|
+
} catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get the number of connected components
|
|
94
|
+
*/
|
|
95
|
+
getComponentCount(): number {
|
|
96
|
+
return this.componentCount;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get all elements that belong to the same component as the given element
|
|
101
|
+
*/
|
|
102
|
+
getComponent(element: NodeId): NodeId[] {
|
|
103
|
+
const root = this.find(element);
|
|
104
|
+
const component: NodeId[] = [];
|
|
105
|
+
|
|
106
|
+
for (const [node] of this.parent) {
|
|
107
|
+
if (this.find(node) === root) {
|
|
108
|
+
component.push(node);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return component;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Get all connected components as separate arrays
|
|
117
|
+
*/
|
|
118
|
+
getAllComponents(): NodeId[][] {
|
|
119
|
+
const componentMap = new Map<NodeId, NodeId[]>();
|
|
120
|
+
|
|
121
|
+
for (const [node] of this.parent) {
|
|
122
|
+
const root = this.find(node);
|
|
123
|
+
|
|
124
|
+
if (!componentMap.has(root)) {
|
|
125
|
+
componentMap.set(root, []);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const component = componentMap.get(root);
|
|
129
|
+
if (component) {
|
|
130
|
+
component.push(node);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return Array.from(componentMap.values());
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Get the size of the component containing the given element
|
|
139
|
+
*/
|
|
140
|
+
getComponentSize(element: NodeId): number {
|
|
141
|
+
return this.getComponent(element).length;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Add a new element to the data structure
|
|
146
|
+
*/
|
|
147
|
+
addElement(element: NodeId): void {
|
|
148
|
+
if (this.parent.has(element)) {
|
|
149
|
+
return; // Element already exists
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
this.parent.set(element, element);
|
|
153
|
+
this.rank.set(element, 0);
|
|
154
|
+
this.componentCount++;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Check if an element exists in the data structure
|
|
159
|
+
*/
|
|
160
|
+
hasElement(element: NodeId): boolean {
|
|
161
|
+
return this.parent.has(element);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get the total number of elements
|
|
166
|
+
*/
|
|
167
|
+
size(): number {
|
|
168
|
+
return this.parent.size;
|
|
169
|
+
}
|
|
170
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @graphty/algorithms - Graph algorithms library for browser environments
|
|
3
|
+
*
|
|
4
|
+
* A comprehensive TypeScript library implementing fundamental graph algorithms
|
|
5
|
+
* optimized for browser environments and visualization applications.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Core exports
|
|
9
|
+
export {Graph} from "./core/graph.js";
|
|
10
|
+
|
|
11
|
+
// Type exports
|
|
12
|
+
export type {
|
|
13
|
+
BellmanFordResult,
|
|
14
|
+
CentralityOptions,
|
|
15
|
+
CentralityResult,
|
|
16
|
+
CommunityResult,
|
|
17
|
+
ComponentResult,
|
|
18
|
+
DijkstraOptions,
|
|
19
|
+
Edge,
|
|
20
|
+
GirvanNewmanOptions,
|
|
21
|
+
GraphConfig,
|
|
22
|
+
LouvainOptions,
|
|
23
|
+
Node,
|
|
24
|
+
NodeId,
|
|
25
|
+
PageRankOptions,
|
|
26
|
+
ShortestPathResult,
|
|
27
|
+
TraversalOptions,
|
|
28
|
+
TraversalResult,
|
|
29
|
+
} from "./types/index.js";
|
|
30
|
+
|
|
31
|
+
// Algorithm exports
|
|
32
|
+
export * from "./algorithms/index.js";
|
|
33
|
+
|
|
34
|
+
// Data structure exports
|
|
35
|
+
export * from "./data-structures/index.js";
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for the Graphty Algorithms library
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Node identifier type
|
|
6
|
+
export type NodeId = string | number;
|
|
7
|
+
|
|
8
|
+
// Edge representation
|
|
9
|
+
export interface Edge {
|
|
10
|
+
source: NodeId;
|
|
11
|
+
target: NodeId;
|
|
12
|
+
weight?: number;
|
|
13
|
+
id?: string;
|
|
14
|
+
data?: Record<string, unknown> | undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Node representation
|
|
18
|
+
export interface Node {
|
|
19
|
+
id: NodeId;
|
|
20
|
+
data?: Record<string, unknown> | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Graph configuration
|
|
24
|
+
export interface GraphConfig {
|
|
25
|
+
directed: boolean;
|
|
26
|
+
allowSelfLoops: boolean;
|
|
27
|
+
allowParallelEdges: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Algorithm result interfaces
|
|
31
|
+
export interface ShortestPathResult {
|
|
32
|
+
distance: number;
|
|
33
|
+
path: NodeId[];
|
|
34
|
+
predecessor: Map<NodeId, NodeId | null>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type CentralityResult = Record<string, number>;
|
|
38
|
+
|
|
39
|
+
export interface TraversalResult {
|
|
40
|
+
visited: Set<NodeId>;
|
|
41
|
+
order: NodeId[];
|
|
42
|
+
tree?: Map<NodeId, NodeId | null>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface CommunityResult {
|
|
46
|
+
communities: NodeId[][];
|
|
47
|
+
modularity: number;
|
|
48
|
+
iterations?: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface ComponentResult {
|
|
52
|
+
components: NodeId[][];
|
|
53
|
+
componentMap: Map<NodeId, number>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Algorithm options interfaces
|
|
57
|
+
export interface TraversalOptions {
|
|
58
|
+
targetNode?: NodeId;
|
|
59
|
+
visitCallback?: (node: NodeId, level: number) => void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface DijkstraOptions {
|
|
63
|
+
target?: NodeId;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface BellmanFordResult {
|
|
67
|
+
distances: Map<NodeId, number>;
|
|
68
|
+
previous: Map<NodeId, NodeId | null>;
|
|
69
|
+
hasNegativeCycle: boolean;
|
|
70
|
+
negativeCycleNodes?: NodeId[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface CentralityOptions {
|
|
74
|
+
normalized?: boolean;
|
|
75
|
+
endpoints?: boolean;
|
|
76
|
+
mode?: "in" | "out" | "total"; // For directed graphs
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface PageRankOptions {
|
|
80
|
+
alpha?: number; // Damping factor (default: 0.85)
|
|
81
|
+
maxIterations?: number; // Maximum iterations (default: 100)
|
|
82
|
+
tolerance?: number; // Convergence tolerance (default: 1e-6)
|
|
83
|
+
personalization?: Map<NodeId, number>; // Personalized PageRank
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface LouvainOptions {
|
|
87
|
+
resolution?: number; // Resolution parameter (default: 1.0)
|
|
88
|
+
maxIterations?: number; // Maximum iterations (default: 100)
|
|
89
|
+
tolerance?: number; // Improvement tolerance (default: 1e-6)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface GirvanNewmanOptions {
|
|
93
|
+
maxCommunities?: number; // Stop when this many communities reached
|
|
94
|
+
minCommunitySize?: number; // Minimum size for valid community
|
|
95
|
+
}
|