@graphty/algorithms 2.0.6 → 2.1.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/README.md +9 -11
- package/dist/algorithms.js +499 -30
- package/dist/algorithms.js.map +1 -1
- package/dist/algorithms.standalone.js +500 -31
- package/dist/algorithms.standalone.js.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +2 -2
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.js +1 -1
- package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
- package/dist/src/algorithms/matching/isomorphism.js +3 -3
- package/dist/src/algorithms/matching/isomorphism.js.map +1 -1
- package/dist/src/algorithms/mst/prim.js +1 -1
- package/dist/src/algorithms/mst/prim.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.js +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs-unified.js +2 -2
- package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -1
- package/dist/src/algorithms/traversal/dfs.js +2 -2
- package/dist/src/algorithms/traversal/dfs.js.map +1 -1
- package/dist/src/clustering/spectral.js +2 -2
- package/dist/src/clustering/spectral.js.map +1 -1
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexed/accelerator.d.ts +14 -2
- package/dist/src/indexed/accelerator.d.ts.map +1 -1
- package/dist/src/indexed/accelerator.js +8 -0
- package/dist/src/indexed/accelerator.js.map +1 -1
- package/dist/src/indexed/components.d.ts +8 -0
- package/dist/src/indexed/components.d.ts.map +1 -1
- package/dist/src/indexed/components.js +8 -1
- package/dist/src/indexed/components.js.map +1 -1
- package/dist/src/indexed/hits.d.ts +39 -0
- package/dist/src/indexed/hits.d.ts.map +1 -0
- package/dist/src/indexed/hits.js +95 -0
- package/dist/src/indexed/hits.js.map +1 -0
- package/dist/src/indexed/index.d.ts +5 -1
- package/dist/src/indexed/index.d.ts.map +1 -1
- package/dist/src/indexed/index.js +5 -1
- package/dist/src/indexed/index.js.map +1 -1
- package/dist/src/indexed/k-core.d.ts +32 -0
- package/dist/src/indexed/k-core.d.ts.map +1 -0
- package/dist/src/indexed/k-core.js +118 -0
- package/dist/src/indexed/k-core.js.map +1 -0
- package/dist/src/indexed/katz.d.ts +38 -0
- package/dist/src/indexed/katz.d.ts.map +1 -0
- package/dist/src/indexed/katz.js +61 -0
- package/dist/src/indexed/katz.js.map +1 -0
- package/dist/src/indexed/louvain.d.ts +33 -0
- package/dist/src/indexed/louvain.d.ts.map +1 -0
- package/dist/src/indexed/louvain.js +301 -0
- package/dist/src/indexed/louvain.js.map +1 -0
- package/package.json +5 -5
- package/src/algorithms/centrality/betweenness.ts +2 -2
- package/src/algorithms/community/girvan-newman.ts +1 -1
- package/src/algorithms/matching/isomorphism.ts +3 -3
- package/src/algorithms/mst/prim.ts +1 -1
- package/src/algorithms/shortest-path/bellman-ford.ts +3 -3
- package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +1 -1
- package/src/algorithms/shortest-path/dijkstra.ts +1 -1
- package/src/algorithms/traversal/bfs-unified.ts +2 -2
- package/src/algorithms/traversal/dfs.ts +2 -2
- package/src/clustering/spectral.ts +2 -2
- package/src/index.ts +10 -0
- package/src/indexed/accelerator.ts +26 -2
- package/src/indexed/components.ts +8 -1
- package/src/indexed/hits.ts +126 -0
- package/src/indexed/index.ts +5 -7
- package/src/indexed/k-core.ts +138 -0
- package/src/indexed/katz.ts +88 -0
- package/src/indexed/louvain.ts +345 -0
|
@@ -3281,7 +3281,7 @@ function breadthFirstSearchStandard(graph, startNode, options = {}) {
|
|
|
3281
3281
|
if (options.visitCallback) {
|
|
3282
3282
|
options.visitCallback(current.node, current.level);
|
|
3283
3283
|
}
|
|
3284
|
-
if (options.targetNode && current.node === options.targetNode) {
|
|
3284
|
+
if (options.targetNode !== void 0 && current.node === options.targetNode) {
|
|
3285
3285
|
break;
|
|
3286
3286
|
}
|
|
3287
3287
|
for (const neighbor of graph.neighbors(current.node)) {
|
|
@@ -3471,7 +3471,7 @@ function isBipartite(graph) {
|
|
|
3471
3471
|
visited.add(node.id);
|
|
3472
3472
|
while (queue.length > 0) {
|
|
3473
3473
|
const current = queue.shift();
|
|
3474
|
-
if (
|
|
3474
|
+
if (current === void 0) {
|
|
3475
3475
|
break;
|
|
3476
3476
|
}
|
|
3477
3477
|
const currentColor = color.get(current);
|
|
@@ -3525,7 +3525,7 @@ function dfsIterative(graph, startNode, visited, order, tree, options) {
|
|
|
3525
3525
|
if (options.visitCallback) {
|
|
3526
3526
|
options.visitCallback(current.node, current.depth);
|
|
3527
3527
|
}
|
|
3528
|
-
if (options.targetNode && current.node === options.targetNode) {
|
|
3528
|
+
if (options.targetNode !== void 0 && current.node === options.targetNode) {
|
|
3529
3529
|
break;
|
|
3530
3530
|
}
|
|
3531
3531
|
const neighbors = Array.from(graph.neighbors(current.node));
|
|
@@ -3546,7 +3546,7 @@ function dfsRecursive(graph, node, visited, order, tree, options, depth, parent
|
|
|
3546
3546
|
if (options.visitCallback) {
|
|
3547
3547
|
options.visitCallback(node, depth);
|
|
3548
3548
|
}
|
|
3549
|
-
if (options.targetNode && node === options.targetNode) {
|
|
3549
|
+
if (options.targetNode !== void 0 && node === options.targetNode) {
|
|
3550
3550
|
return;
|
|
3551
3551
|
}
|
|
3552
3552
|
}
|
|
@@ -3722,7 +3722,7 @@ function bellmanFord(graph, source, options = {}) {
|
|
|
3722
3722
|
distances.set(v, newDistance);
|
|
3723
3723
|
predecessors.set(v, u);
|
|
3724
3724
|
updated = true;
|
|
3725
|
-
if (options.target && v === options.target) {
|
|
3725
|
+
if (options.target !== void 0 && v === options.target) {
|
|
3726
3726
|
break;
|
|
3727
3727
|
}
|
|
3728
3728
|
}
|
|
@@ -4076,7 +4076,7 @@ class BidirectionalDijkstra {
|
|
|
4076
4076
|
return minDist;
|
|
4077
4077
|
}
|
|
4078
4078
|
reconstructPath() {
|
|
4079
|
-
if (
|
|
4079
|
+
if (this.meetingNode === null) {
|
|
4080
4080
|
return [];
|
|
4081
4081
|
}
|
|
4082
4082
|
const path = [];
|
|
@@ -4137,7 +4137,7 @@ function dijkstra$1(graph, source, options = {}) {
|
|
|
4137
4137
|
continue;
|
|
4138
4138
|
}
|
|
4139
4139
|
visited.add(currentNode);
|
|
4140
|
-
if (options.target && currentNode === options.target) {
|
|
4140
|
+
if (options.target !== void 0 && currentNode === options.target) {
|
|
4141
4141
|
break;
|
|
4142
4142
|
}
|
|
4143
4143
|
if (currentDistance === Infinity) {
|
|
@@ -4712,7 +4712,7 @@ function accumulateBetweenness(result, source, centrality, options) {
|
|
|
4712
4712
|
}
|
|
4713
4713
|
for (let i = stack.length - 1; i >= 0; i--) {
|
|
4714
4714
|
const w = stack[i];
|
|
4715
|
-
if (
|
|
4715
|
+
if (w === void 0) {
|
|
4716
4716
|
continue;
|
|
4717
4717
|
}
|
|
4718
4718
|
const wPreds = predecessors.get(w) ?? [];
|
|
@@ -4746,7 +4746,7 @@ function accumulateEdgeBetweenness(result, source, edgeCentrality, options) {
|
|
|
4746
4746
|
}
|
|
4747
4747
|
for (let i = stack.length - 1; i >= 0; i--) {
|
|
4748
4748
|
const w = stack[i];
|
|
4749
|
-
if (
|
|
4749
|
+
if (w === void 0) {
|
|
4750
4750
|
continue;
|
|
4751
4751
|
}
|
|
4752
4752
|
const wPreds = predecessors.get(w) ?? [];
|
|
@@ -5380,7 +5380,7 @@ function nodeEigenvectorCentrality(graph, nodeId, options = {}) {
|
|
|
5380
5380
|
const centrality = eigenvectorCentrality(graph, options);
|
|
5381
5381
|
return centrality[nodeId.toString()] ?? 0;
|
|
5382
5382
|
}
|
|
5383
|
-
function hits(graph, options = {}) {
|
|
5383
|
+
function hits$1(graph, options = {}) {
|
|
5384
5384
|
const { maxIterations = 100, tolerance = 1e-6, normalized = true } = options;
|
|
5385
5385
|
const hubs = {};
|
|
5386
5386
|
const authorities = {};
|
|
@@ -5497,14 +5497,14 @@ function nodeHITS(graph, nodeId, options = {}) {
|
|
|
5497
5497
|
if (!graph.hasNode(nodeId)) {
|
|
5498
5498
|
throw new Error(`Node ${String(nodeId)} not found in graph`);
|
|
5499
5499
|
}
|
|
5500
|
-
const result = hits(graph, options);
|
|
5500
|
+
const result = hits$1(graph, options);
|
|
5501
5501
|
const key = nodeId.toString();
|
|
5502
5502
|
return {
|
|
5503
5503
|
hub: result.hubs[key] ?? 0,
|
|
5504
5504
|
authority: result.authorities[key] ?? 0
|
|
5505
5505
|
};
|
|
5506
5506
|
}
|
|
5507
|
-
function katzCentrality(graph, options = {}) {
|
|
5507
|
+
function katzCentrality$1(graph, options = {}) {
|
|
5508
5508
|
const { alpha = 0.1, beta = 1, maxIterations = 100, tolerance = 1e-6, normalized = true } = options;
|
|
5509
5509
|
const centrality = {};
|
|
5510
5510
|
const nodes = Array.from(graph.nodes());
|
|
@@ -5565,7 +5565,7 @@ function nodeKatzCentrality(graph, nodeId, options = {}) {
|
|
|
5565
5565
|
if (!graph.hasNode(nodeId)) {
|
|
5566
5566
|
throw new Error(`Node ${String(nodeId)} not found in graph`);
|
|
5567
5567
|
}
|
|
5568
|
-
const centrality = katzCentrality(graph, options);
|
|
5568
|
+
const centrality = katzCentrality$1(graph, options);
|
|
5569
5569
|
return centrality[nodeId.toString()] ?? 0;
|
|
5570
5570
|
}
|
|
5571
5571
|
class SimpleDeltaPageRank {
|
|
@@ -6410,7 +6410,7 @@ function primMST(graph, startNode) {
|
|
|
6410
6410
|
};
|
|
6411
6411
|
}
|
|
6412
6412
|
const start = startNode ?? nodes[0]?.id;
|
|
6413
|
-
if (
|
|
6413
|
+
if (start === void 0) {
|
|
6414
6414
|
return {
|
|
6415
6415
|
edges: [],
|
|
6416
6416
|
totalWeight: 0
|
|
@@ -6578,7 +6578,7 @@ function findAllShortestPaths(graph, source) {
|
|
|
6578
6578
|
let queueIndex = 0;
|
|
6579
6579
|
while (queueIndex < queue.length) {
|
|
6580
6580
|
const current = queue[queueIndex++];
|
|
6581
|
-
if (
|
|
6581
|
+
if (current === void 0) {
|
|
6582
6582
|
continue;
|
|
6583
6583
|
}
|
|
6584
6584
|
if (visited.has(current)) {
|
|
@@ -7360,7 +7360,7 @@ class OptimizedLouvain {
|
|
|
7360
7360
|
for (let i = 0; i < membership.length; i++) {
|
|
7361
7361
|
membership[i] = community[membership[i]];
|
|
7362
7362
|
}
|
|
7363
|
-
level = aggregate(level, community, count);
|
|
7363
|
+
level = aggregate$1(level, community, count);
|
|
7364
7364
|
}
|
|
7365
7365
|
const groups = Array.from({ length: level.n }, () => []);
|
|
7366
7366
|
for (let i = 0; i < membership.length; i++) {
|
|
@@ -7543,7 +7543,7 @@ function buildCsr(n, counts, edges, self, degree) {
|
|
|
7543
7543
|
}
|
|
7544
7544
|
return { n, offsets, targets, weights, self, degree };
|
|
7545
7545
|
}
|
|
7546
|
-
function aggregate(level, community, count) {
|
|
7546
|
+
function aggregate$1(level, community, count) {
|
|
7547
7547
|
const self = new Float64Array(count);
|
|
7548
7548
|
const degree = new Float64Array(count);
|
|
7549
7549
|
const members = Array.from({ length: count }, () => []);
|
|
@@ -7651,7 +7651,7 @@ function calculateModularity$1(graph, communities, resolution = 1) {
|
|
|
7651
7651
|
}
|
|
7652
7652
|
return modularity;
|
|
7653
7653
|
}
|
|
7654
|
-
function louvain(graph, options = {}) {
|
|
7654
|
+
function louvain$1(graph, options = {}) {
|
|
7655
7655
|
const resolution = options.resolution ?? 1;
|
|
7656
7656
|
const maxIterations = options.maxIterations ?? 100;
|
|
7657
7657
|
const tolerance = options.tolerance ?? 1e-6;
|
|
@@ -9017,7 +9017,7 @@ function kCoreDecompositionImpl(graph) {
|
|
|
9017
9017
|
return { cores, coreness, maxCore };
|
|
9018
9018
|
}
|
|
9019
9019
|
function getKCore(graph, k) {
|
|
9020
|
-
const { coreness } = kCoreDecomposition(graph);
|
|
9020
|
+
const { coreness } = kCoreDecomposition$1(graph);
|
|
9021
9021
|
const kCore = /* @__PURE__ */ new Set();
|
|
9022
9022
|
for (const [node, core] of coreness) {
|
|
9023
9023
|
if (core >= k) {
|
|
@@ -9026,7 +9026,7 @@ function getKCore(graph, k) {
|
|
|
9026
9026
|
}
|
|
9027
9027
|
return kCore;
|
|
9028
9028
|
}
|
|
9029
|
-
function kCoreDecomposition(graph) {
|
|
9029
|
+
function kCoreDecomposition$1(graph) {
|
|
9030
9030
|
const adjacencySet = graphToAdjacencySet(graph);
|
|
9031
9031
|
return kCoreDecompositionImpl(adjacencySet);
|
|
9032
9032
|
}
|
|
@@ -9382,7 +9382,7 @@ function spectralClustering(graph, options) {
|
|
|
9382
9382
|
for (let i = 0; i < nodeIds.length; i++) {
|
|
9383
9383
|
const clusterId = kmeans.assignments[i] ?? 0;
|
|
9384
9384
|
const nodeId = nodeIds[i];
|
|
9385
|
-
if (
|
|
9385
|
+
if (nodeId === void 0) {
|
|
9386
9386
|
continue;
|
|
9387
9387
|
}
|
|
9388
9388
|
if (clusterId >= 0 && clusterId < k) {
|
|
@@ -9414,7 +9414,7 @@ function buildAdjacencyMatrix(graph, nodeIds) {
|
|
|
9414
9414
|
nodeIds.forEach((id, index2) => nodeToIndex.set(id, index2));
|
|
9415
9415
|
for (let i = 0; i < n; i++) {
|
|
9416
9416
|
const nodeId = nodeIds[i];
|
|
9417
|
-
if (
|
|
9417
|
+
if (nodeId === void 0) {
|
|
9418
9418
|
continue;
|
|
9419
9419
|
}
|
|
9420
9420
|
const neighbors = graph.neighbors(nodeId);
|
|
@@ -9954,7 +9954,7 @@ function getCandidatePairs(g1, g2, state, nodes1, nodes2) {
|
|
|
9954
9954
|
break;
|
|
9955
9955
|
}
|
|
9956
9956
|
}
|
|
9957
|
-
if (
|
|
9957
|
+
if (node1 === null) {
|
|
9958
9958
|
for (const [n] of state.in1) {
|
|
9959
9959
|
if (!state.core1.has(n)) {
|
|
9960
9960
|
node1 = n;
|
|
@@ -9962,7 +9962,7 @@ function getCandidatePairs(g1, g2, state, nodes1, nodes2) {
|
|
|
9962
9962
|
}
|
|
9963
9963
|
}
|
|
9964
9964
|
}
|
|
9965
|
-
if (
|
|
9965
|
+
if (node1 === null) {
|
|
9966
9966
|
for (const n of nodes1) {
|
|
9967
9967
|
if (!state.core1.has(n)) {
|
|
9968
9968
|
node1 = n;
|
|
@@ -9970,7 +9970,7 @@ function getCandidatePairs(g1, g2, state, nodes1, nodes2) {
|
|
|
9970
9970
|
}
|
|
9971
9971
|
}
|
|
9972
9972
|
}
|
|
9973
|
-
if (
|
|
9973
|
+
if (node1 === null) {
|
|
9974
9974
|
return pairs;
|
|
9975
9975
|
}
|
|
9976
9976
|
for (const node2 of nodes2) {
|
|
@@ -18476,7 +18476,7 @@ function checkUniqueColumn(table, column) {
|
|
|
18476
18476
|
throw err;
|
|
18477
18477
|
}
|
|
18478
18478
|
}
|
|
18479
|
-
const WIRE_PRODUCER = `@graphty/graph-format@${"
|
|
18479
|
+
const WIRE_PRODUCER = `@graphty/graph-format@${"a3bb78842b4e"}`;
|
|
18480
18480
|
const SCALAR_VIEWS = /* @__PURE__ */ new Set(["totalWeight", "symmetric"]);
|
|
18481
18481
|
const encoder = new TextEncoder();
|
|
18482
18482
|
function assertLittleEndianHost(littleEndian = IS_LITTLE_ENDIAN) {
|
|
@@ -24316,6 +24316,467 @@ function dijkstra(g, source, options = {}) {
|
|
|
24316
24316
|
pathEdges: (target) => walkPredEdges(g, predArc, source, target)
|
|
24317
24317
|
};
|
|
24318
24318
|
}
|
|
24319
|
+
function l2Normalize(v) {
|
|
24320
|
+
let sum = 0;
|
|
24321
|
+
for (let i = 0; i < v.length; i++) {
|
|
24322
|
+
sum += v[i] * v[i];
|
|
24323
|
+
}
|
|
24324
|
+
const norm = Math.sqrt(sum);
|
|
24325
|
+
if (norm > 0) {
|
|
24326
|
+
for (let i = 0; i < v.length; i++) {
|
|
24327
|
+
v[i] /= norm;
|
|
24328
|
+
}
|
|
24329
|
+
}
|
|
24330
|
+
}
|
|
24331
|
+
function maxNormalize(v) {
|
|
24332
|
+
let max = 0;
|
|
24333
|
+
for (let i = 0; i < v.length; i++) {
|
|
24334
|
+
if (v[i] > max) {
|
|
24335
|
+
max = v[i];
|
|
24336
|
+
}
|
|
24337
|
+
}
|
|
24338
|
+
if (max > 0) {
|
|
24339
|
+
for (let i = 0; i < v.length; i++) {
|
|
24340
|
+
v[i] /= max;
|
|
24341
|
+
}
|
|
24342
|
+
}
|
|
24343
|
+
}
|
|
24344
|
+
function hits(s, o = {}) {
|
|
24345
|
+
const n = s.nodeCount;
|
|
24346
|
+
const maxIter = o.maxIterations ?? 100;
|
|
24347
|
+
const tol = o.tolerance ?? 1e-6;
|
|
24348
|
+
const rev = s.reverse();
|
|
24349
|
+
const fwdW = o.weighted === true ? s.weights : null;
|
|
24350
|
+
const revW = o.weighted === true ? rev.weights : null;
|
|
24351
|
+
let hubs = new Float64Array(n).fill(n === 0 ? 0 : 1 / Math.sqrt(n));
|
|
24352
|
+
let authorities = new Float64Array(n).fill(n === 0 ? 0 : 1 / Math.sqrt(n));
|
|
24353
|
+
let nextHubs = new Float64Array(n);
|
|
24354
|
+
let nextAuthorities = new Float64Array(n);
|
|
24355
|
+
let it = 0;
|
|
24356
|
+
let converged = false;
|
|
24357
|
+
for (; it < maxIter && !converged; it++) {
|
|
24358
|
+
for (let v = 0; v < n; v++) {
|
|
24359
|
+
let auth = 0;
|
|
24360
|
+
const inEnd = rev.rowPtr[v + 1];
|
|
24361
|
+
for (let a = rev.rowPtr[v]; a < inEnd; a++) {
|
|
24362
|
+
auth += hubs[rev.colIdx[a]] * (revW === null ? 1 : revW[a]);
|
|
24363
|
+
}
|
|
24364
|
+
nextAuthorities[v] = auth;
|
|
24365
|
+
let hub = 0;
|
|
24366
|
+
const outEnd = s.rowPtr[v + 1];
|
|
24367
|
+
for (let a = s.rowPtr[v]; a < outEnd; a++) {
|
|
24368
|
+
hub += authorities[s.colIdx[a]] * (fwdW === null ? 1 : fwdW[a]);
|
|
24369
|
+
}
|
|
24370
|
+
nextHubs[v] = hub;
|
|
24371
|
+
}
|
|
24372
|
+
l2Normalize(nextAuthorities);
|
|
24373
|
+
l2Normalize(nextHubs);
|
|
24374
|
+
let maxDiff = 0;
|
|
24375
|
+
for (let v = 0; v < n; v++) {
|
|
24376
|
+
const dh = Math.abs(nextHubs[v] - hubs[v]);
|
|
24377
|
+
if (dh > maxDiff) {
|
|
24378
|
+
maxDiff = dh;
|
|
24379
|
+
}
|
|
24380
|
+
const da = Math.abs(nextAuthorities[v] - authorities[v]);
|
|
24381
|
+
if (da > maxDiff) {
|
|
24382
|
+
maxDiff = da;
|
|
24383
|
+
}
|
|
24384
|
+
}
|
|
24385
|
+
[hubs, nextHubs] = [nextHubs, hubs];
|
|
24386
|
+
[authorities, nextAuthorities] = [nextAuthorities, authorities];
|
|
24387
|
+
converged = maxDiff < tol;
|
|
24388
|
+
}
|
|
24389
|
+
if (o.normalized === false) {
|
|
24390
|
+
maxNormalize(hubs);
|
|
24391
|
+
maxNormalize(authorities);
|
|
24392
|
+
}
|
|
24393
|
+
return { hubs, authorities, iterations: it, converged };
|
|
24394
|
+
}
|
|
24395
|
+
function kCoreDecomposition(s) {
|
|
24396
|
+
if (s.directed) {
|
|
24397
|
+
throw new Error("k-core requires an undirected graph. Pass s.toUndirected().snapshot.");
|
|
24398
|
+
}
|
|
24399
|
+
const n = s.nodeCount;
|
|
24400
|
+
const { rowPtr, colIdx } = s;
|
|
24401
|
+
const degree = new Uint32Array(n);
|
|
24402
|
+
let maxDegree = 0;
|
|
24403
|
+
for (let u = 0; u < n; u++) {
|
|
24404
|
+
let d = 0;
|
|
24405
|
+
let last = -1;
|
|
24406
|
+
const end = rowPtr[u + 1];
|
|
24407
|
+
for (let a = rowPtr[u]; a < end; a++) {
|
|
24408
|
+
const v = colIdx[a];
|
|
24409
|
+
if (v !== u && v !== last) {
|
|
24410
|
+
d++;
|
|
24411
|
+
}
|
|
24412
|
+
last = v;
|
|
24413
|
+
}
|
|
24414
|
+
degree[u] = d;
|
|
24415
|
+
if (d > maxDegree) {
|
|
24416
|
+
maxDegree = d;
|
|
24417
|
+
}
|
|
24418
|
+
}
|
|
24419
|
+
const bin = new Uint32Array(maxDegree + 1);
|
|
24420
|
+
for (let u = 0; u < n; u++) {
|
|
24421
|
+
bin[degree[u]]++;
|
|
24422
|
+
}
|
|
24423
|
+
let start = 0;
|
|
24424
|
+
for (let d = 0; d <= maxDegree; d++) {
|
|
24425
|
+
const count = bin[d];
|
|
24426
|
+
bin[d] = start;
|
|
24427
|
+
start += count;
|
|
24428
|
+
}
|
|
24429
|
+
const vert = new Uint32Array(n);
|
|
24430
|
+
const pos = new Uint32Array(n);
|
|
24431
|
+
for (let u = 0; u < n; u++) {
|
|
24432
|
+
pos[u] = bin[degree[u]];
|
|
24433
|
+
vert[pos[u]] = u;
|
|
24434
|
+
bin[degree[u]]++;
|
|
24435
|
+
}
|
|
24436
|
+
for (let d = maxDegree; d > 0; d--) {
|
|
24437
|
+
bin[d] = bin[d - 1];
|
|
24438
|
+
}
|
|
24439
|
+
bin[0] = 0;
|
|
24440
|
+
let maxCore = 0;
|
|
24441
|
+
for (let i = 0; i < n; i++) {
|
|
24442
|
+
const v = vert[i];
|
|
24443
|
+
const dv = degree[v];
|
|
24444
|
+
if (dv > maxCore) {
|
|
24445
|
+
maxCore = dv;
|
|
24446
|
+
}
|
|
24447
|
+
const end = rowPtr[v + 1];
|
|
24448
|
+
let last = -1;
|
|
24449
|
+
for (let a = rowPtr[v]; a < end; a++) {
|
|
24450
|
+
const u = colIdx[a];
|
|
24451
|
+
const skip = u === v || u === last;
|
|
24452
|
+
last = u;
|
|
24453
|
+
if (skip) {
|
|
24454
|
+
continue;
|
|
24455
|
+
}
|
|
24456
|
+
const du = degree[u];
|
|
24457
|
+
if (du > dv) {
|
|
24458
|
+
const pu = pos[u];
|
|
24459
|
+
const pw = bin[du];
|
|
24460
|
+
const w = vert[pw];
|
|
24461
|
+
if (u !== w) {
|
|
24462
|
+
vert[pu] = w;
|
|
24463
|
+
vert[pw] = u;
|
|
24464
|
+
pos[u] = pw;
|
|
24465
|
+
pos[w] = pu;
|
|
24466
|
+
}
|
|
24467
|
+
bin[du]++;
|
|
24468
|
+
degree[u] = du - 1;
|
|
24469
|
+
}
|
|
24470
|
+
}
|
|
24471
|
+
}
|
|
24472
|
+
let cached = null;
|
|
24473
|
+
return {
|
|
24474
|
+
coreness: degree,
|
|
24475
|
+
maxCore,
|
|
24476
|
+
cores() {
|
|
24477
|
+
if (cached === null) {
|
|
24478
|
+
const sizes = new Uint32Array(maxCore + 1);
|
|
24479
|
+
for (let u = 0; u < n; u++) {
|
|
24480
|
+
sizes[degree[u]]++;
|
|
24481
|
+
}
|
|
24482
|
+
const out = [];
|
|
24483
|
+
for (let k = 0; k <= maxCore; k++) {
|
|
24484
|
+
out.push(new Uint32Array(sizes[k]));
|
|
24485
|
+
}
|
|
24486
|
+
const fill = new Uint32Array(maxCore + 1);
|
|
24487
|
+
for (let u = 0; u < n; u++) {
|
|
24488
|
+
const k = degree[u];
|
|
24489
|
+
out[k][fill[k]++] = u;
|
|
24490
|
+
}
|
|
24491
|
+
cached = out;
|
|
24492
|
+
}
|
|
24493
|
+
return cached;
|
|
24494
|
+
}
|
|
24495
|
+
};
|
|
24496
|
+
}
|
|
24497
|
+
function katzCentrality(s, o = {}) {
|
|
24498
|
+
const n = s.nodeCount;
|
|
24499
|
+
const alpha = o.alpha ?? 0.1;
|
|
24500
|
+
const beta = o.beta ?? 1;
|
|
24501
|
+
const maxIter = o.maxIterations ?? 100;
|
|
24502
|
+
const tol = o.tolerance ?? 1e-6;
|
|
24503
|
+
const rev = s.reverse();
|
|
24504
|
+
const weights = o.weighted === true ? rev.weights : null;
|
|
24505
|
+
let cur = new Float64Array(n).fill(beta);
|
|
24506
|
+
let next = new Float64Array(n);
|
|
24507
|
+
let it = 0;
|
|
24508
|
+
let converged = false;
|
|
24509
|
+
for (; it < maxIter && !converged; it++) {
|
|
24510
|
+
let maxDiff = 0;
|
|
24511
|
+
for (let v = 0; v < n; v++) {
|
|
24512
|
+
let sum = 0;
|
|
24513
|
+
const end = rev.rowPtr[v + 1];
|
|
24514
|
+
for (let a = rev.rowPtr[v]; a < end; a++) {
|
|
24515
|
+
sum += cur[rev.colIdx[a]] * (weights === null ? 1 : weights[a]);
|
|
24516
|
+
}
|
|
24517
|
+
next[v] = alpha * sum + beta;
|
|
24518
|
+
const diff = Math.abs(next[v] - cur[v]);
|
|
24519
|
+
if (diff > maxDiff) {
|
|
24520
|
+
maxDiff = diff;
|
|
24521
|
+
}
|
|
24522
|
+
}
|
|
24523
|
+
[cur, next] = [next, cur];
|
|
24524
|
+
converged = maxDiff < tol;
|
|
24525
|
+
}
|
|
24526
|
+
if (o.normalized !== false) {
|
|
24527
|
+
let min = Infinity;
|
|
24528
|
+
let max = -Infinity;
|
|
24529
|
+
for (let v = 0; v < n; v++) {
|
|
24530
|
+
if (cur[v] < min) {
|
|
24531
|
+
min = cur[v];
|
|
24532
|
+
}
|
|
24533
|
+
if (cur[v] > max) {
|
|
24534
|
+
max = cur[v];
|
|
24535
|
+
}
|
|
24536
|
+
}
|
|
24537
|
+
const range = max - min;
|
|
24538
|
+
if (range > 0) {
|
|
24539
|
+
for (let v = 0; v < n; v++) {
|
|
24540
|
+
cur[v] = (cur[v] - min) / range;
|
|
24541
|
+
}
|
|
24542
|
+
}
|
|
24543
|
+
}
|
|
24544
|
+
return { scores: cur, iterations: it, converged };
|
|
24545
|
+
}
|
|
24546
|
+
function buildLevel0(s) {
|
|
24547
|
+
const n = s.nodeCount;
|
|
24548
|
+
const rowPtr = new Uint32Array(n + 1);
|
|
24549
|
+
for (let u = 0; u < n; u++) {
|
|
24550
|
+
let kept = 0;
|
|
24551
|
+
const end = s.rowPtr[u + 1];
|
|
24552
|
+
for (let a = s.rowPtr[u]; a < end; a++) {
|
|
24553
|
+
if (s.colIdx[a] !== u) {
|
|
24554
|
+
kept++;
|
|
24555
|
+
}
|
|
24556
|
+
}
|
|
24557
|
+
rowPtr[u + 1] = rowPtr[u] + kept;
|
|
24558
|
+
}
|
|
24559
|
+
const arcs = rowPtr[n];
|
|
24560
|
+
const colIdx = new Uint32Array(arcs);
|
|
24561
|
+
const w = new Float64Array(arcs);
|
|
24562
|
+
const loop = new Float64Array(n);
|
|
24563
|
+
const deg = new Float64Array(n);
|
|
24564
|
+
let k = 0;
|
|
24565
|
+
for (let u = 0; u < n; u++) {
|
|
24566
|
+
let rowWeight = 0;
|
|
24567
|
+
const end = s.rowPtr[u + 1];
|
|
24568
|
+
for (let a = s.rowPtr[u]; a < end; a++) {
|
|
24569
|
+
const v = s.colIdx[a];
|
|
24570
|
+
const weight = s.weights === null ? 1 : s.weights[a];
|
|
24571
|
+
if (v === u) {
|
|
24572
|
+
loop[u] += weight;
|
|
24573
|
+
} else {
|
|
24574
|
+
colIdx[k] = v;
|
|
24575
|
+
w[k] = weight;
|
|
24576
|
+
k++;
|
|
24577
|
+
rowWeight += weight;
|
|
24578
|
+
}
|
|
24579
|
+
}
|
|
24580
|
+
deg[u] = rowWeight + 2 * loop[u];
|
|
24581
|
+
}
|
|
24582
|
+
return { n, rowPtr, colIdx, w, loop, deg };
|
|
24583
|
+
}
|
|
24584
|
+
function modularityOf(level, comm, count, resolution, m2) {
|
|
24585
|
+
const inside = new Float64Array(count);
|
|
24586
|
+
const tot = new Float64Array(count);
|
|
24587
|
+
for (let u = 0; u < level.n; u++) {
|
|
24588
|
+
const c = comm[u];
|
|
24589
|
+
tot[c] += level.deg[u];
|
|
24590
|
+
inside[c] += 2 * level.loop[u];
|
|
24591
|
+
const end = level.rowPtr[u + 1];
|
|
24592
|
+
for (let a = level.rowPtr[u]; a < end; a++) {
|
|
24593
|
+
if (comm[level.colIdx[a]] === c) {
|
|
24594
|
+
inside[c] += level.w[a];
|
|
24595
|
+
}
|
|
24596
|
+
}
|
|
24597
|
+
}
|
|
24598
|
+
let q = 0;
|
|
24599
|
+
for (let c = 0; c < count; c++) {
|
|
24600
|
+
const share = tot[c] / m2;
|
|
24601
|
+
q += inside[c] / m2 - resolution * share * share;
|
|
24602
|
+
}
|
|
24603
|
+
return q;
|
|
24604
|
+
}
|
|
24605
|
+
function localMove(level, comm, resolution, m2, maxVisitsPerNode) {
|
|
24606
|
+
const { n } = level;
|
|
24607
|
+
const tot = new Float64Array(n);
|
|
24608
|
+
for (let u = 0; u < n; u++) {
|
|
24609
|
+
comm[u] = u;
|
|
24610
|
+
tot[u] = level.deg[u];
|
|
24611
|
+
}
|
|
24612
|
+
const acc = new Float64Array(n);
|
|
24613
|
+
const stamp = new Int32Array(n).fill(-1);
|
|
24614
|
+
const touched = new Uint32Array(n);
|
|
24615
|
+
const capacity = n + 1;
|
|
24616
|
+
const queue = new Uint32Array(capacity);
|
|
24617
|
+
const queued = new Uint8Array(n);
|
|
24618
|
+
let head = 0;
|
|
24619
|
+
let tail = n;
|
|
24620
|
+
for (let u = 0; u < n; u++) {
|
|
24621
|
+
queue[u] = u;
|
|
24622
|
+
queued[u] = 1;
|
|
24623
|
+
}
|
|
24624
|
+
let mark = 0;
|
|
24625
|
+
let visits = 0;
|
|
24626
|
+
const maxVisits = maxVisitsPerNode * n;
|
|
24627
|
+
let movedAny = false;
|
|
24628
|
+
while (head !== tail && visits < maxVisits) {
|
|
24629
|
+
const u = queue[head];
|
|
24630
|
+
head = head + 1 === capacity ? 0 : head + 1;
|
|
24631
|
+
queued[u] = 0;
|
|
24632
|
+
visits++;
|
|
24633
|
+
const cu = comm[u];
|
|
24634
|
+
const ku = level.deg[u];
|
|
24635
|
+
tot[cu] -= ku;
|
|
24636
|
+
mark++;
|
|
24637
|
+
let cnt = 0;
|
|
24638
|
+
const end = level.rowPtr[u + 1];
|
|
24639
|
+
for (let a = level.rowPtr[u]; a < end; a++) {
|
|
24640
|
+
const c = comm[level.colIdx[a]];
|
|
24641
|
+
if (stamp[c] !== mark) {
|
|
24642
|
+
stamp[c] = mark;
|
|
24643
|
+
acc[c] = 0;
|
|
24644
|
+
touched[cnt++] = c;
|
|
24645
|
+
}
|
|
24646
|
+
acc[c] += level.w[a];
|
|
24647
|
+
}
|
|
24648
|
+
let best = cu;
|
|
24649
|
+
let bestGain = (stamp[cu] === mark ? acc[cu] : 0) - resolution * ku * tot[cu] / m2;
|
|
24650
|
+
for (let i = 0; i < cnt; i++) {
|
|
24651
|
+
const c = touched[i];
|
|
24652
|
+
if (c === cu) {
|
|
24653
|
+
continue;
|
|
24654
|
+
}
|
|
24655
|
+
const gain = acc[c] - resolution * ku * tot[c] / m2;
|
|
24656
|
+
if (gain > bestGain) {
|
|
24657
|
+
bestGain = gain;
|
|
24658
|
+
best = c;
|
|
24659
|
+
}
|
|
24660
|
+
}
|
|
24661
|
+
tot[best] += ku;
|
|
24662
|
+
if (best !== cu) {
|
|
24663
|
+
comm[u] = best;
|
|
24664
|
+
movedAny = true;
|
|
24665
|
+
for (let a = level.rowPtr[u]; a < end; a++) {
|
|
24666
|
+
const v = level.colIdx[a];
|
|
24667
|
+
if (queued[v] === 0 && comm[v] !== best) {
|
|
24668
|
+
queued[v] = 1;
|
|
24669
|
+
queue[tail] = v;
|
|
24670
|
+
tail = tail + 1 === capacity ? 0 : tail + 1;
|
|
24671
|
+
}
|
|
24672
|
+
}
|
|
24673
|
+
}
|
|
24674
|
+
}
|
|
24675
|
+
return movedAny;
|
|
24676
|
+
}
|
|
24677
|
+
function aggregate(level, comm, count) {
|
|
24678
|
+
const start = new Uint32Array(count + 1);
|
|
24679
|
+
for (let u = 0; u < level.n; u++) {
|
|
24680
|
+
start[comm[u] + 1]++;
|
|
24681
|
+
}
|
|
24682
|
+
for (let c = 0; c < count; c++) {
|
|
24683
|
+
start[c + 1] += start[c];
|
|
24684
|
+
}
|
|
24685
|
+
const members = new Uint32Array(level.n);
|
|
24686
|
+
const fill = start.slice(0, count);
|
|
24687
|
+
for (let u = 0; u < level.n; u++) {
|
|
24688
|
+
members[fill[comm[u]]++] = u;
|
|
24689
|
+
}
|
|
24690
|
+
const rowPtr = new Uint32Array(count + 1);
|
|
24691
|
+
const colIdx = new Uint32Array(level.colIdx.length);
|
|
24692
|
+
const w = new Float64Array(level.colIdx.length);
|
|
24693
|
+
const loop = new Float64Array(count);
|
|
24694
|
+
const deg = new Float64Array(count);
|
|
24695
|
+
const acc = new Float64Array(count);
|
|
24696
|
+
const stamp = new Int32Array(count).fill(-1);
|
|
24697
|
+
const touched = new Uint32Array(count);
|
|
24698
|
+
let k = 0;
|
|
24699
|
+
for (let c = 0; c < count; c++) {
|
|
24700
|
+
rowPtr[c] = k;
|
|
24701
|
+
let internalArcs = 0;
|
|
24702
|
+
let cnt = 0;
|
|
24703
|
+
for (let i = start[c]; i < start[c + 1]; i++) {
|
|
24704
|
+
const u = members[i];
|
|
24705
|
+
loop[c] += level.loop[u];
|
|
24706
|
+
const end = level.rowPtr[u + 1];
|
|
24707
|
+
for (let a = level.rowPtr[u]; a < end; a++) {
|
|
24708
|
+
const other = comm[level.colIdx[a]];
|
|
24709
|
+
if (other === c) {
|
|
24710
|
+
internalArcs += level.w[a];
|
|
24711
|
+
continue;
|
|
24712
|
+
}
|
|
24713
|
+
if (stamp[other] !== c) {
|
|
24714
|
+
stamp[other] = c;
|
|
24715
|
+
acc[other] = 0;
|
|
24716
|
+
touched[cnt++] = other;
|
|
24717
|
+
}
|
|
24718
|
+
acc[other] += level.w[a];
|
|
24719
|
+
}
|
|
24720
|
+
}
|
|
24721
|
+
loop[c] += internalArcs / 2;
|
|
24722
|
+
let rowWeight = 0;
|
|
24723
|
+
for (let i = 0; i < cnt; i++) {
|
|
24724
|
+
const other = touched[i];
|
|
24725
|
+
colIdx[k] = other;
|
|
24726
|
+
w[k] = acc[other];
|
|
24727
|
+
rowWeight += acc[other];
|
|
24728
|
+
k++;
|
|
24729
|
+
}
|
|
24730
|
+
deg[c] = rowWeight + 2 * loop[c];
|
|
24731
|
+
}
|
|
24732
|
+
rowPtr[count] = k;
|
|
24733
|
+
return { n: count, rowPtr, colIdx: colIdx.subarray(0, k), w: w.subarray(0, k), loop, deg };
|
|
24734
|
+
}
|
|
24735
|
+
function louvain(s, o = {}) {
|
|
24736
|
+
if (s.directed) {
|
|
24737
|
+
throw new Error("Louvain requires an undirected graph. Pass s.toUndirected().snapshot.");
|
|
24738
|
+
}
|
|
24739
|
+
const resolution = o.resolution ?? 1;
|
|
24740
|
+
const maxIterations = o.maxIterations ?? 100;
|
|
24741
|
+
const tolerance = o.tolerance ?? 1e-6;
|
|
24742
|
+
const n0 = s.nodeCount;
|
|
24743
|
+
const labels = new Uint32Array(n0);
|
|
24744
|
+
for (let u = 0; u < n0; u++) {
|
|
24745
|
+
labels[u] = u;
|
|
24746
|
+
}
|
|
24747
|
+
let level = buildLevel0(s);
|
|
24748
|
+
let m2 = 0;
|
|
24749
|
+
for (let u = 0; u < n0; u++) {
|
|
24750
|
+
m2 += level.deg[u];
|
|
24751
|
+
}
|
|
24752
|
+
if (m2 === 0) {
|
|
24753
|
+
return { ...withGroups(labels, n0), modularity: 0, iterations: 0 };
|
|
24754
|
+
}
|
|
24755
|
+
let q = modularityOf(level, labels, n0, resolution, m2);
|
|
24756
|
+
let iterations = 0;
|
|
24757
|
+
for (let iteration = 0; iteration < maxIterations; iteration++) {
|
|
24758
|
+
const comm = new Uint32Array(level.n);
|
|
24759
|
+
if (!localMove(level, comm, resolution, m2, maxIterations)) {
|
|
24760
|
+
break;
|
|
24761
|
+
}
|
|
24762
|
+
const dense = renumberPartition(comm);
|
|
24763
|
+
const { count } = dense;
|
|
24764
|
+
const packed = dense.labels;
|
|
24765
|
+
const newQ = modularityOf(level, packed, count, resolution, m2);
|
|
24766
|
+
for (let u = 0; u < n0; u++) {
|
|
24767
|
+
labels[u] = packed[labels[u]];
|
|
24768
|
+
}
|
|
24769
|
+
iterations = iteration + 1;
|
|
24770
|
+
const gain = newQ - q;
|
|
24771
|
+
q = newQ;
|
|
24772
|
+
if (gain < tolerance || count === level.n) {
|
|
24773
|
+
break;
|
|
24774
|
+
}
|
|
24775
|
+
level = aggregate(level, packed, count);
|
|
24776
|
+
}
|
|
24777
|
+
const final = renumberPartition(labels);
|
|
24778
|
+
return { ...withGroups(final.labels, final.count), modularity: q, iterations };
|
|
24779
|
+
}
|
|
24319
24780
|
function kruskalMST(s, o = {}) {
|
|
24320
24781
|
const el = s.edgeList();
|
|
24321
24782
|
const m = s.edgeCount;
|
|
@@ -24399,7 +24860,11 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
24399
24860
|
commonNeighborsScore,
|
|
24400
24861
|
connectedComponents,
|
|
24401
24862
|
dijkstra,
|
|
24863
|
+
hits,
|
|
24864
|
+
kCoreDecomposition,
|
|
24865
|
+
katzCentrality,
|
|
24402
24866
|
kruskalMST,
|
|
24867
|
+
louvain,
|
|
24403
24868
|
pageRank,
|
|
24404
24869
|
walkPredArcs,
|
|
24405
24870
|
walkPredEdges,
|
|
@@ -24445,7 +24910,11 @@ function accelerated(acc) {
|
|
|
24445
24910
|
breadthFirstSearch: (s, source, options) => acc?.breadthFirstSearch !== void 0 ? acc.breadthFirstSearch(s, source, options) : Promise.resolve(breadthFirstSearch(s, source, options)),
|
|
24446
24911
|
connectedComponents: (s) => acc?.connectedComponents !== void 0 ? acc.connectedComponents(s) : Promise.resolve(connectedComponents(s)),
|
|
24447
24912
|
weaklyConnectedComponents: (s) => acc?.weaklyConnectedComponents !== void 0 ? acc.weaklyConnectedComponents(s) : Promise.resolve(weaklyConnectedComponents(s)),
|
|
24448
|
-
minimumSpanningTree: (s, options) => acc?.minimumSpanningTree !== void 0 ? acc.minimumSpanningTree(s, options) : Promise.resolve(kruskalMST(s, options))
|
|
24913
|
+
minimumSpanningTree: (s, options) => acc?.minimumSpanningTree !== void 0 ? acc.minimumSpanningTree(s, options) : Promise.resolve(kruskalMST(s, options)),
|
|
24914
|
+
kCoreDecomposition: (s) => acc?.kCoreDecomposition !== void 0 ? acc.kCoreDecomposition(s) : Promise.resolve(kCoreDecomposition(s)),
|
|
24915
|
+
katzCentrality: (s, options) => acc?.katzCentrality !== void 0 ? acc.katzCentrality(s, options) : Promise.resolve(katzCentrality(s, options)),
|
|
24916
|
+
hits: (s, options) => acc?.hits !== void 0 ? acc.hits(s, options) : Promise.resolve(hits(s, options)),
|
|
24917
|
+
louvain: (s, options) => acc?.louvain !== void 0 ? acc.louvain(s, options) : Promise.resolve(louvain(s, options))
|
|
24449
24918
|
};
|
|
24450
24919
|
}
|
|
24451
24920
|
export {
|
|
@@ -24511,7 +24980,7 @@ export {
|
|
|
24511
24980
|
hasNegativeCycle,
|
|
24512
24981
|
heuristics,
|
|
24513
24982
|
hierarchicalClustering,
|
|
24514
|
-
hits,
|
|
24983
|
+
hits$1 as hits,
|
|
24515
24984
|
index as indexed,
|
|
24516
24985
|
isBipartite,
|
|
24517
24986
|
isCSRGraph,
|
|
@@ -24519,16 +24988,16 @@ export {
|
|
|
24519
24988
|
isGraphIsomorphic,
|
|
24520
24989
|
isStronglyConnected,
|
|
24521
24990
|
isWeaklyConnected,
|
|
24522
|
-
kCoreDecomposition,
|
|
24991
|
+
kCoreDecomposition$1 as kCoreDecomposition,
|
|
24523
24992
|
kargerMinCut,
|
|
24524
|
-
katzCentrality,
|
|
24993
|
+
katzCentrality$1 as katzCentrality,
|
|
24525
24994
|
kruskalMST$1 as kruskalMST,
|
|
24526
24995
|
labelPropagation,
|
|
24527
24996
|
labelPropagationAsync,
|
|
24528
24997
|
labelPropagationSemiSupervised,
|
|
24529
24998
|
largestConnectedComponent,
|
|
24530
24999
|
leiden,
|
|
24531
|
-
louvain,
|
|
25000
|
+
louvain$1 as louvain,
|
|
24532
25001
|
markovClustering,
|
|
24533
25002
|
maximumBipartiteMatching,
|
|
24534
25003
|
minSTCut,
|