graphwise 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adjacency-map-BtKzcuJq.js +229 -0
- package/dist/adjacency-map-BtKzcuJq.js.map +1 -0
- package/dist/adjacency-map-JqBnMNkF.cjs +234 -0
- package/dist/adjacency-map-JqBnMNkF.cjs.map +1 -0
- package/dist/async/index.cjs +15 -242
- package/dist/async/index.js +2 -229
- package/dist/expansion/index.cjs +43 -0
- package/dist/expansion/index.js +2 -0
- package/dist/expansion-ClDhlMK8.js +1704 -0
- package/dist/expansion-ClDhlMK8.js.map +1 -0
- package/dist/expansion-DaTroIyv.cjs +1949 -0
- package/dist/expansion-DaTroIyv.cjs.map +1 -0
- package/dist/extraction/index.cjs +630 -0
- package/dist/extraction/index.cjs.map +1 -0
- package/dist/extraction/index.js +621 -0
- package/dist/extraction/index.js.map +1 -0
- package/dist/gpu/csr.d.ts +29 -30
- package/dist/gpu/csr.d.ts.map +1 -1
- package/dist/gpu/dispatch.d.ts +31 -0
- package/dist/gpu/dispatch.d.ts.map +1 -0
- package/dist/gpu/dispatch.unit.test.d.ts +5 -0
- package/dist/gpu/dispatch.unit.test.d.ts.map +1 -0
- package/dist/gpu/index.cjs +15 -410
- package/dist/gpu/index.d.ts +3 -1
- package/dist/gpu/index.d.ts.map +1 -1
- package/dist/gpu/index.js +2 -400
- package/dist/gpu/kernels/bfs/kernel.d.ts +59 -0
- package/dist/gpu/kernels/bfs/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/bfs/logic.d.ts +47 -0
- package/dist/gpu/kernels/bfs/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/bfs/logic.unit.test.d.ts +2 -0
- package/dist/gpu/kernels/bfs/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/kernels/degree-histogram/kernel.d.ts +32 -0
- package/dist/gpu/kernels/degree-histogram/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/degree-histogram/logic.d.ts +45 -0
- package/dist/gpu/kernels/degree-histogram/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/degree-histogram/logic.unit.test.d.ts +2 -0
- package/dist/gpu/kernels/degree-histogram/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/kernels/jaccard/kernel.d.ts +40 -0
- package/dist/gpu/kernels/jaccard/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/jaccard/logic.d.ts +43 -0
- package/dist/gpu/kernels/jaccard/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/jaccard/logic.unit.test.d.ts +2 -0
- package/dist/gpu/kernels/jaccard/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/kernels/pagerank/kernel.d.ts +44 -0
- package/dist/gpu/kernels/pagerank/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/pagerank/logic.d.ts +50 -0
- package/dist/gpu/kernels/pagerank/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/pagerank/logic.unit.test.d.ts +2 -0
- package/dist/gpu/kernels/pagerank/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/kernels/spmv/kernel.d.ts +43 -0
- package/dist/gpu/kernels/spmv/kernel.d.ts.map +1 -0
- package/dist/gpu/kernels/spmv/logic.d.ts +31 -0
- package/dist/gpu/kernels/spmv/logic.d.ts.map +1 -0
- package/dist/gpu/kernels/spmv/logic.unit.test.d.ts +2 -0
- package/dist/gpu/kernels/spmv/logic.unit.test.d.ts.map +1 -0
- package/dist/gpu/operations.d.ts +76 -0
- package/dist/gpu/operations.d.ts.map +1 -0
- package/dist/gpu/operations.unit.test.d.ts +5 -0
- package/dist/gpu/operations.unit.test.d.ts.map +1 -0
- package/dist/gpu/root.d.ts +53 -0
- package/dist/gpu/root.d.ts.map +1 -0
- package/dist/gpu/root.unit.test.d.ts +2 -0
- package/dist/gpu/root.unit.test.d.ts.map +1 -0
- package/dist/gpu/types.d.ts +3 -8
- package/dist/gpu/types.d.ts.map +1 -1
- package/dist/gpu-CHiCN0wa.js +16945 -0
- package/dist/gpu-CHiCN0wa.js.map +1 -0
- package/dist/gpu-Y6owRVMi.cjs +17028 -0
- package/dist/gpu-Y6owRVMi.cjs.map +1 -0
- package/dist/graph/index.cjs +2 -229
- package/dist/graph/index.js +1 -228
- package/dist/index/index.cjs +141 -4040
- package/dist/index/index.js +15 -3917
- package/dist/jaccard-3rCdilwm.js +39 -0
- package/dist/jaccard-3rCdilwm.js.map +1 -0
- package/dist/jaccard-Bys9_dGW.cjs +50 -0
- package/dist/jaccard-Bys9_dGW.cjs.map +1 -0
- package/dist/{kmeans-BIgSyGKu.cjs → kmeans-B8x9D1kt.cjs} +1 -1
- package/dist/{kmeans-BIgSyGKu.cjs.map → kmeans-B8x9D1kt.cjs.map} +1 -1
- package/dist/{kmeans-87ExSUNZ.js → kmeans-DKkL9rAN.js} +1 -1
- package/dist/{kmeans-87ExSUNZ.js.map → kmeans-DKkL9rAN.js.map} +1 -1
- package/dist/ops-djAsQQSh.cjs +277 -0
- package/dist/ops-djAsQQSh.cjs.map +1 -0
- package/dist/ops-upIi6JIi.js +212 -0
- package/dist/ops-upIi6JIi.js.map +1 -0
- package/dist/priority-queue-BIiD1L0k.cjs +148 -0
- package/dist/priority-queue-BIiD1L0k.cjs.map +1 -0
- package/dist/priority-queue-CFDd5cBg.js +143 -0
- package/dist/priority-queue-CFDd5cBg.js.map +1 -0
- package/dist/ranking/index.cjs +43 -0
- package/dist/ranking/index.js +4 -0
- package/dist/ranking/mi/index.cjs +581 -0
- package/dist/ranking/mi/index.cjs.map +1 -0
- package/dist/ranking/mi/index.js +555 -0
- package/dist/ranking/mi/index.js.map +1 -0
- package/dist/ranking-3ez5m67U.js +1016 -0
- package/dist/ranking-3ez5m67U.js.map +1 -0
- package/dist/ranking-DVvajgUZ.cjs +1093 -0
- package/dist/ranking-DVvajgUZ.cjs.map +1 -0
- package/dist/seeds/index.cjs +1 -1
- package/dist/seeds/index.js +1 -1
- package/dist/structures/index.cjs +2 -143
- package/dist/structures/index.js +1 -142
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils-BodeE2Mo.js +22 -0
- package/dist/utils-BodeE2Mo.js.map +1 -0
- package/dist/utils-CDtCcsyF.cjs +33 -0
- package/dist/utils-CDtCcsyF.cjs.map +1 -0
- package/package.json +3 -1
- package/dist/async/index.cjs.map +0 -1
- package/dist/async/index.js.map +0 -1
- package/dist/gpu/context.d.ts +0 -118
- package/dist/gpu/context.d.ts.map +0 -1
- package/dist/gpu/context.unit.test.d.ts +0 -2
- package/dist/gpu/context.unit.test.d.ts.map +0 -1
- package/dist/gpu/index.cjs.map +0 -1
- package/dist/gpu/index.js.map +0 -1
- package/dist/graph/index.cjs.map +0 -1
- package/dist/graph/index.js.map +0 -1
- package/dist/index/index.cjs.map +0 -1
- package/dist/index/index.js.map +0 -1
- package/dist/structures/index.cjs.map +0 -1
- package/dist/structures/index.js.map +0 -1
package/dist/graph/index.cjs
CHANGED
|
@@ -1,230 +1,3 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Graph implementation using adjacency map data structure.
|
|
5
|
-
*
|
|
6
|
-
* Uses Map<NodeId, N> for node storage and Map<NodeId, Map<NodeId, E>>
|
|
7
|
-
* for adjacency representation. This provides O(1) average-case lookup
|
|
8
|
-
* for nodes and edges, with memory proportional to V + E.
|
|
9
|
-
*
|
|
10
|
-
* @typeParam N - Node data type, must extend NodeData
|
|
11
|
-
* @typeParam E - Edge data type, must extend EdgeData
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* // Create a directed citation graph
|
|
16
|
-
* const graph = AdjacencyMapGraph.directed<AuthorNode, CitationEdge>()
|
|
17
|
-
* .addNode({ id: 'A1', name: 'Alice' })
|
|
18
|
-
* .addNode({ id: 'B1', name: 'Bob' })
|
|
19
|
-
* .addEdge({ source: 'A1', target: 'B1', year: 2024 });
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
var AdjacencyMapGraph = class AdjacencyMapGraph {
|
|
23
|
-
directed;
|
|
24
|
-
nodes;
|
|
25
|
-
adjacency;
|
|
26
|
-
reverseAdjacency;
|
|
27
|
-
_edgeCount;
|
|
28
|
-
constructor(directed) {
|
|
29
|
-
this.directed = directed;
|
|
30
|
-
this.nodes = /* @__PURE__ */ new Map();
|
|
31
|
-
this.adjacency = /* @__PURE__ */ new Map();
|
|
32
|
-
this.reverseAdjacency = directed ? /* @__PURE__ */ new Map() : null;
|
|
33
|
-
this._edgeCount = 0;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Create a new directed graph.
|
|
37
|
-
*
|
|
38
|
-
* In a directed graph, edges have direction from source to target.
|
|
39
|
-
* The `neighbours` method with direction 'out' returns successors,
|
|
40
|
-
* and direction 'in' returns predecessors.
|
|
41
|
-
*
|
|
42
|
-
* @typeParam N - Node data type
|
|
43
|
-
* @typeParam E - Edge data type
|
|
44
|
-
* @returns A new empty directed graph
|
|
45
|
-
*/
|
|
46
|
-
static directed() {
|
|
47
|
-
return new AdjacencyMapGraph(true);
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Create a new undirected graph.
|
|
51
|
-
*
|
|
52
|
-
* In an undirected graph, edges have no direction. Adding an edge
|
|
53
|
-
* from A to B automatically creates the connection from B to A.
|
|
54
|
-
*
|
|
55
|
-
* @typeParam N - Node data type
|
|
56
|
-
* @typeParam E - Edge data type
|
|
57
|
-
* @returns A new empty undirected graph
|
|
58
|
-
*/
|
|
59
|
-
static undirected() {
|
|
60
|
-
return new AdjacencyMapGraph(false);
|
|
61
|
-
}
|
|
62
|
-
get nodeCount() {
|
|
63
|
-
return this.nodes.size;
|
|
64
|
-
}
|
|
65
|
-
get edgeCount() {
|
|
66
|
-
return this._edgeCount;
|
|
67
|
-
}
|
|
68
|
-
hasNode(id) {
|
|
69
|
-
return this.nodes.has(id);
|
|
70
|
-
}
|
|
71
|
-
getNode(id) {
|
|
72
|
-
return this.nodes.get(id);
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Iterate over all node identifiers in the graph.
|
|
76
|
-
*
|
|
77
|
-
* @returns An iterable of all node IDs
|
|
78
|
-
*/
|
|
79
|
-
*nodeIds() {
|
|
80
|
-
yield* this.nodes.keys();
|
|
81
|
-
}
|
|
82
|
-
neighbours(id, direction = "out") {
|
|
83
|
-
if (!this.nodes.has(id)) return [];
|
|
84
|
-
if (this.directed) {
|
|
85
|
-
if (direction === "out") return this.adjacency.get(id)?.keys() ?? [];
|
|
86
|
-
if (direction === "in") return this.reverseAdjacency?.get(id)?.keys() ?? [];
|
|
87
|
-
return this.iterateBothDirections(id);
|
|
88
|
-
}
|
|
89
|
-
return this.adjacency.get(id)?.keys() ?? [];
|
|
90
|
-
}
|
|
91
|
-
*iterateBothDirections(id) {
|
|
92
|
-
const seen = /* @__PURE__ */ new Set();
|
|
93
|
-
const outNeighbours = this.adjacency.get(id);
|
|
94
|
-
if (outNeighbours !== void 0) {
|
|
95
|
-
for (const neighbour of outNeighbours.keys()) if (!seen.has(neighbour)) {
|
|
96
|
-
seen.add(neighbour);
|
|
97
|
-
yield neighbour;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
const inNeighbours = this.reverseAdjacency?.get(id);
|
|
101
|
-
if (inNeighbours !== void 0) {
|
|
102
|
-
for (const neighbour of inNeighbours.keys()) if (!seen.has(neighbour)) {
|
|
103
|
-
seen.add(neighbour);
|
|
104
|
-
yield neighbour;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
degree(id, direction = "out") {
|
|
109
|
-
if (!this.nodes.has(id)) return 0;
|
|
110
|
-
if (this.directed) {
|
|
111
|
-
if (direction === "out") return this.adjacency.get(id)?.size ?? 0;
|
|
112
|
-
if (direction === "in") return this.reverseAdjacency?.get(id)?.size ?? 0;
|
|
113
|
-
return (this.adjacency.get(id)?.size ?? 0) + (this.reverseAdjacency?.get(id)?.size ?? 0);
|
|
114
|
-
}
|
|
115
|
-
return this.adjacency.get(id)?.size ?? 0;
|
|
116
|
-
}
|
|
117
|
-
getEdge(source, target) {
|
|
118
|
-
const forward = this.adjacency.get(source)?.get(target);
|
|
119
|
-
if (forward !== void 0) return forward;
|
|
120
|
-
if (!this.directed) return this.adjacency.get(target)?.get(source);
|
|
121
|
-
}
|
|
122
|
-
*edges() {
|
|
123
|
-
const emitted = /* @__PURE__ */ new Set();
|
|
124
|
-
for (const [, neighbours] of this.adjacency) for (const [, edge] of neighbours) if (this.directed) yield edge;
|
|
125
|
-
else {
|
|
126
|
-
const key = this.edgeKey(edge.source, edge.target);
|
|
127
|
-
if (!emitted.has(key)) {
|
|
128
|
-
emitted.add(key);
|
|
129
|
-
yield edge;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
edgeKey(source, target) {
|
|
134
|
-
const [a, b] = source < target ? [source, target] : [target, source];
|
|
135
|
-
return `${a}::${b}`;
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Add a node to the graph (builder pattern).
|
|
139
|
-
*
|
|
140
|
-
* If a node with the same ID already exists, it is not replaced.
|
|
141
|
-
*
|
|
142
|
-
* @param node - The node data to add
|
|
143
|
-
* @returns this (for method chaining)
|
|
144
|
-
*/
|
|
145
|
-
addNode(node) {
|
|
146
|
-
if (!this.nodes.has(node.id)) this.nodes.set(node.id, node);
|
|
147
|
-
return this;
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Add an edge to the graph (builder pattern).
|
|
151
|
-
*
|
|
152
|
-
* @param edge - The edge data to add
|
|
153
|
-
* @returns this (for method chaining)
|
|
154
|
-
* @throws Error if either endpoint node does not exist
|
|
155
|
-
*/
|
|
156
|
-
addEdge(edge) {
|
|
157
|
-
if (!this.nodes.has(edge.source) || !this.nodes.has(edge.target)) throw new Error(`Cannot add edge: nodes ${edge.source} and/or ${edge.target} do not exist`);
|
|
158
|
-
if (!this.directed) {
|
|
159
|
-
const [cSource, cTarget] = edge.source < edge.target ? [edge.source, edge.target] : [edge.target, edge.source];
|
|
160
|
-
if (this.adjacency.get(cSource)?.get(cTarget) !== void 0) {
|
|
161
|
-
this.adjacency.get(cSource)?.set(cTarget, edge);
|
|
162
|
-
return this;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
let forwardMap = this.adjacency.get(edge.source);
|
|
166
|
-
if (forwardMap === void 0) {
|
|
167
|
-
forwardMap = /* @__PURE__ */ new Map();
|
|
168
|
-
this.adjacency.set(edge.source, forwardMap);
|
|
169
|
-
}
|
|
170
|
-
const isNewEdge = !forwardMap.has(edge.target);
|
|
171
|
-
forwardMap.set(edge.target, edge);
|
|
172
|
-
if (this.directed) {
|
|
173
|
-
let reverseMap = this.reverseAdjacency?.get(edge.target);
|
|
174
|
-
if (reverseMap === void 0) {
|
|
175
|
-
reverseMap = /* @__PURE__ */ new Map();
|
|
176
|
-
this.reverseAdjacency?.set(edge.target, reverseMap);
|
|
177
|
-
}
|
|
178
|
-
reverseMap.set(edge.source, edge);
|
|
179
|
-
} else {
|
|
180
|
-
let reverseMap = this.adjacency.get(edge.target);
|
|
181
|
-
if (reverseMap === void 0) {
|
|
182
|
-
reverseMap = /* @__PURE__ */ new Map();
|
|
183
|
-
this.adjacency.set(edge.target, reverseMap);
|
|
184
|
-
}
|
|
185
|
-
reverseMap.set(edge.source, edge);
|
|
186
|
-
}
|
|
187
|
-
if (isNewEdge) this._edgeCount++;
|
|
188
|
-
return this;
|
|
189
|
-
}
|
|
190
|
-
removeNode(id) {
|
|
191
|
-
if (!this.nodes.has(id)) return false;
|
|
192
|
-
const outNeighbours = [...this.adjacency.get(id)?.keys() ?? []];
|
|
193
|
-
for (const neighbour of outNeighbours) this.removeEdgeInternal(id, neighbour);
|
|
194
|
-
if (this.directed && this.reverseAdjacency !== null) {
|
|
195
|
-
const inNeighbours = [...this.reverseAdjacency.get(id)?.keys() ?? []];
|
|
196
|
-
for (const neighbour of inNeighbours) this.removeEdgeFromDirected(neighbour, id);
|
|
197
|
-
}
|
|
198
|
-
this.nodes.delete(id);
|
|
199
|
-
this.adjacency.delete(id);
|
|
200
|
-
this.reverseAdjacency?.delete(id);
|
|
201
|
-
return true;
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Remove an edge from a directed graph, updating both adjacency maps.
|
|
205
|
-
* This handles the case where we're removing an edge that points TO the removed node.
|
|
206
|
-
*/
|
|
207
|
-
removeEdgeFromDirected(source, target) {
|
|
208
|
-
if (this.adjacency.get(source)?.delete(target) === true) this._edgeCount--;
|
|
209
|
-
this.reverseAdjacency?.get(target)?.delete(source);
|
|
210
|
-
}
|
|
211
|
-
removeEdgeInternal(source, target) {
|
|
212
|
-
if (this.adjacency.get(source)?.delete(target) === true) this._edgeCount--;
|
|
213
|
-
if (this.directed) this.reverseAdjacency?.get(target)?.delete(source);
|
|
214
|
-
else this.adjacency.get(target)?.delete(source);
|
|
215
|
-
}
|
|
216
|
-
removeEdge(source, target) {
|
|
217
|
-
if (!this.hasEdgeInternal(source, target)) return false;
|
|
218
|
-
this.removeEdgeInternal(source, target);
|
|
219
|
-
return true;
|
|
220
|
-
}
|
|
221
|
-
hasEdgeInternal(source, target) {
|
|
222
|
-
if (this.adjacency.get(source)?.has(target) === true) return true;
|
|
223
|
-
if (!this.directed) return this.adjacency.get(target)?.has(source) === true;
|
|
224
|
-
return false;
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
//#endregion
|
|
228
|
-
exports.AdjacencyMapGraph = AdjacencyMapGraph;
|
|
229
|
-
|
|
230
|
-
//# sourceMappingURL=index.cjs.map
|
|
2
|
+
const require_adjacency_map = require("../adjacency-map-JqBnMNkF.cjs");
|
|
3
|
+
exports.AdjacencyMapGraph = require_adjacency_map.AdjacencyMapGraph;
|
package/dist/graph/index.js
CHANGED
|
@@ -1,229 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Graph implementation using adjacency map data structure.
|
|
4
|
-
*
|
|
5
|
-
* Uses Map<NodeId, N> for node storage and Map<NodeId, Map<NodeId, E>>
|
|
6
|
-
* for adjacency representation. This provides O(1) average-case lookup
|
|
7
|
-
* for nodes and edges, with memory proportional to V + E.
|
|
8
|
-
*
|
|
9
|
-
* @typeParam N - Node data type, must extend NodeData
|
|
10
|
-
* @typeParam E - Edge data type, must extend EdgeData
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```typescript
|
|
14
|
-
* // Create a directed citation graph
|
|
15
|
-
* const graph = AdjacencyMapGraph.directed<AuthorNode, CitationEdge>()
|
|
16
|
-
* .addNode({ id: 'A1', name: 'Alice' })
|
|
17
|
-
* .addNode({ id: 'B1', name: 'Bob' })
|
|
18
|
-
* .addEdge({ source: 'A1', target: 'B1', year: 2024 });
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
var AdjacencyMapGraph = class AdjacencyMapGraph {
|
|
22
|
-
directed;
|
|
23
|
-
nodes;
|
|
24
|
-
adjacency;
|
|
25
|
-
reverseAdjacency;
|
|
26
|
-
_edgeCount;
|
|
27
|
-
constructor(directed) {
|
|
28
|
-
this.directed = directed;
|
|
29
|
-
this.nodes = /* @__PURE__ */ new Map();
|
|
30
|
-
this.adjacency = /* @__PURE__ */ new Map();
|
|
31
|
-
this.reverseAdjacency = directed ? /* @__PURE__ */ new Map() : null;
|
|
32
|
-
this._edgeCount = 0;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Create a new directed graph.
|
|
36
|
-
*
|
|
37
|
-
* In a directed graph, edges have direction from source to target.
|
|
38
|
-
* The `neighbours` method with direction 'out' returns successors,
|
|
39
|
-
* and direction 'in' returns predecessors.
|
|
40
|
-
*
|
|
41
|
-
* @typeParam N - Node data type
|
|
42
|
-
* @typeParam E - Edge data type
|
|
43
|
-
* @returns A new empty directed graph
|
|
44
|
-
*/
|
|
45
|
-
static directed() {
|
|
46
|
-
return new AdjacencyMapGraph(true);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Create a new undirected graph.
|
|
50
|
-
*
|
|
51
|
-
* In an undirected graph, edges have no direction. Adding an edge
|
|
52
|
-
* from A to B automatically creates the connection from B to A.
|
|
53
|
-
*
|
|
54
|
-
* @typeParam N - Node data type
|
|
55
|
-
* @typeParam E - Edge data type
|
|
56
|
-
* @returns A new empty undirected graph
|
|
57
|
-
*/
|
|
58
|
-
static undirected() {
|
|
59
|
-
return new AdjacencyMapGraph(false);
|
|
60
|
-
}
|
|
61
|
-
get nodeCount() {
|
|
62
|
-
return this.nodes.size;
|
|
63
|
-
}
|
|
64
|
-
get edgeCount() {
|
|
65
|
-
return this._edgeCount;
|
|
66
|
-
}
|
|
67
|
-
hasNode(id) {
|
|
68
|
-
return this.nodes.has(id);
|
|
69
|
-
}
|
|
70
|
-
getNode(id) {
|
|
71
|
-
return this.nodes.get(id);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Iterate over all node identifiers in the graph.
|
|
75
|
-
*
|
|
76
|
-
* @returns An iterable of all node IDs
|
|
77
|
-
*/
|
|
78
|
-
*nodeIds() {
|
|
79
|
-
yield* this.nodes.keys();
|
|
80
|
-
}
|
|
81
|
-
neighbours(id, direction = "out") {
|
|
82
|
-
if (!this.nodes.has(id)) return [];
|
|
83
|
-
if (this.directed) {
|
|
84
|
-
if (direction === "out") return this.adjacency.get(id)?.keys() ?? [];
|
|
85
|
-
if (direction === "in") return this.reverseAdjacency?.get(id)?.keys() ?? [];
|
|
86
|
-
return this.iterateBothDirections(id);
|
|
87
|
-
}
|
|
88
|
-
return this.adjacency.get(id)?.keys() ?? [];
|
|
89
|
-
}
|
|
90
|
-
*iterateBothDirections(id) {
|
|
91
|
-
const seen = /* @__PURE__ */ new Set();
|
|
92
|
-
const outNeighbours = this.adjacency.get(id);
|
|
93
|
-
if (outNeighbours !== void 0) {
|
|
94
|
-
for (const neighbour of outNeighbours.keys()) if (!seen.has(neighbour)) {
|
|
95
|
-
seen.add(neighbour);
|
|
96
|
-
yield neighbour;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
const inNeighbours = this.reverseAdjacency?.get(id);
|
|
100
|
-
if (inNeighbours !== void 0) {
|
|
101
|
-
for (const neighbour of inNeighbours.keys()) if (!seen.has(neighbour)) {
|
|
102
|
-
seen.add(neighbour);
|
|
103
|
-
yield neighbour;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
degree(id, direction = "out") {
|
|
108
|
-
if (!this.nodes.has(id)) return 0;
|
|
109
|
-
if (this.directed) {
|
|
110
|
-
if (direction === "out") return this.adjacency.get(id)?.size ?? 0;
|
|
111
|
-
if (direction === "in") return this.reverseAdjacency?.get(id)?.size ?? 0;
|
|
112
|
-
return (this.adjacency.get(id)?.size ?? 0) + (this.reverseAdjacency?.get(id)?.size ?? 0);
|
|
113
|
-
}
|
|
114
|
-
return this.adjacency.get(id)?.size ?? 0;
|
|
115
|
-
}
|
|
116
|
-
getEdge(source, target) {
|
|
117
|
-
const forward = this.adjacency.get(source)?.get(target);
|
|
118
|
-
if (forward !== void 0) return forward;
|
|
119
|
-
if (!this.directed) return this.adjacency.get(target)?.get(source);
|
|
120
|
-
}
|
|
121
|
-
*edges() {
|
|
122
|
-
const emitted = /* @__PURE__ */ new Set();
|
|
123
|
-
for (const [, neighbours] of this.adjacency) for (const [, edge] of neighbours) if (this.directed) yield edge;
|
|
124
|
-
else {
|
|
125
|
-
const key = this.edgeKey(edge.source, edge.target);
|
|
126
|
-
if (!emitted.has(key)) {
|
|
127
|
-
emitted.add(key);
|
|
128
|
-
yield edge;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
edgeKey(source, target) {
|
|
133
|
-
const [a, b] = source < target ? [source, target] : [target, source];
|
|
134
|
-
return `${a}::${b}`;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Add a node to the graph (builder pattern).
|
|
138
|
-
*
|
|
139
|
-
* If a node with the same ID already exists, it is not replaced.
|
|
140
|
-
*
|
|
141
|
-
* @param node - The node data to add
|
|
142
|
-
* @returns this (for method chaining)
|
|
143
|
-
*/
|
|
144
|
-
addNode(node) {
|
|
145
|
-
if (!this.nodes.has(node.id)) this.nodes.set(node.id, node);
|
|
146
|
-
return this;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Add an edge to the graph (builder pattern).
|
|
150
|
-
*
|
|
151
|
-
* @param edge - The edge data to add
|
|
152
|
-
* @returns this (for method chaining)
|
|
153
|
-
* @throws Error if either endpoint node does not exist
|
|
154
|
-
*/
|
|
155
|
-
addEdge(edge) {
|
|
156
|
-
if (!this.nodes.has(edge.source) || !this.nodes.has(edge.target)) throw new Error(`Cannot add edge: nodes ${edge.source} and/or ${edge.target} do not exist`);
|
|
157
|
-
if (!this.directed) {
|
|
158
|
-
const [cSource, cTarget] = edge.source < edge.target ? [edge.source, edge.target] : [edge.target, edge.source];
|
|
159
|
-
if (this.adjacency.get(cSource)?.get(cTarget) !== void 0) {
|
|
160
|
-
this.adjacency.get(cSource)?.set(cTarget, edge);
|
|
161
|
-
return this;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
let forwardMap = this.adjacency.get(edge.source);
|
|
165
|
-
if (forwardMap === void 0) {
|
|
166
|
-
forwardMap = /* @__PURE__ */ new Map();
|
|
167
|
-
this.adjacency.set(edge.source, forwardMap);
|
|
168
|
-
}
|
|
169
|
-
const isNewEdge = !forwardMap.has(edge.target);
|
|
170
|
-
forwardMap.set(edge.target, edge);
|
|
171
|
-
if (this.directed) {
|
|
172
|
-
let reverseMap = this.reverseAdjacency?.get(edge.target);
|
|
173
|
-
if (reverseMap === void 0) {
|
|
174
|
-
reverseMap = /* @__PURE__ */ new Map();
|
|
175
|
-
this.reverseAdjacency?.set(edge.target, reverseMap);
|
|
176
|
-
}
|
|
177
|
-
reverseMap.set(edge.source, edge);
|
|
178
|
-
} else {
|
|
179
|
-
let reverseMap = this.adjacency.get(edge.target);
|
|
180
|
-
if (reverseMap === void 0) {
|
|
181
|
-
reverseMap = /* @__PURE__ */ new Map();
|
|
182
|
-
this.adjacency.set(edge.target, reverseMap);
|
|
183
|
-
}
|
|
184
|
-
reverseMap.set(edge.source, edge);
|
|
185
|
-
}
|
|
186
|
-
if (isNewEdge) this._edgeCount++;
|
|
187
|
-
return this;
|
|
188
|
-
}
|
|
189
|
-
removeNode(id) {
|
|
190
|
-
if (!this.nodes.has(id)) return false;
|
|
191
|
-
const outNeighbours = [...this.adjacency.get(id)?.keys() ?? []];
|
|
192
|
-
for (const neighbour of outNeighbours) this.removeEdgeInternal(id, neighbour);
|
|
193
|
-
if (this.directed && this.reverseAdjacency !== null) {
|
|
194
|
-
const inNeighbours = [...this.reverseAdjacency.get(id)?.keys() ?? []];
|
|
195
|
-
for (const neighbour of inNeighbours) this.removeEdgeFromDirected(neighbour, id);
|
|
196
|
-
}
|
|
197
|
-
this.nodes.delete(id);
|
|
198
|
-
this.adjacency.delete(id);
|
|
199
|
-
this.reverseAdjacency?.delete(id);
|
|
200
|
-
return true;
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Remove an edge from a directed graph, updating both adjacency maps.
|
|
204
|
-
* This handles the case where we're removing an edge that points TO the removed node.
|
|
205
|
-
*/
|
|
206
|
-
removeEdgeFromDirected(source, target) {
|
|
207
|
-
if (this.adjacency.get(source)?.delete(target) === true) this._edgeCount--;
|
|
208
|
-
this.reverseAdjacency?.get(target)?.delete(source);
|
|
209
|
-
}
|
|
210
|
-
removeEdgeInternal(source, target) {
|
|
211
|
-
if (this.adjacency.get(source)?.delete(target) === true) this._edgeCount--;
|
|
212
|
-
if (this.directed) this.reverseAdjacency?.get(target)?.delete(source);
|
|
213
|
-
else this.adjacency.get(target)?.delete(source);
|
|
214
|
-
}
|
|
215
|
-
removeEdge(source, target) {
|
|
216
|
-
if (!this.hasEdgeInternal(source, target)) return false;
|
|
217
|
-
this.removeEdgeInternal(source, target);
|
|
218
|
-
return true;
|
|
219
|
-
}
|
|
220
|
-
hasEdgeInternal(source, target) {
|
|
221
|
-
if (this.adjacency.get(source)?.has(target) === true) return true;
|
|
222
|
-
if (!this.directed) return this.adjacency.get(target)?.has(source) === true;
|
|
223
|
-
return false;
|
|
224
|
-
}
|
|
225
|
-
};
|
|
226
|
-
//#endregion
|
|
1
|
+
import { t as AdjacencyMapGraph } from "../adjacency-map-BtKzcuJq.js";
|
|
227
2
|
export { AdjacencyMapGraph };
|
|
228
|
-
|
|
229
|
-
//# sourceMappingURL=index.js.map
|