@graphty/algorithms 2.0.6 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +9 -11
  2. package/dist/algorithms.js +499 -30
  3. package/dist/algorithms.js.map +1 -1
  4. package/dist/algorithms.standalone.js +500 -31
  5. package/dist/algorithms.standalone.js.map +1 -1
  6. package/dist/src/algorithms/centrality/betweenness.js +2 -2
  7. package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
  8. package/dist/src/algorithms/community/girvan-newman.js +1 -1
  9. package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
  10. package/dist/src/algorithms/matching/isomorphism.js +3 -3
  11. package/dist/src/algorithms/matching/isomorphism.js.map +1 -1
  12. package/dist/src/algorithms/mst/prim.js +1 -1
  13. package/dist/src/algorithms/mst/prim.js.map +1 -1
  14. package/dist/src/algorithms/shortest-path/bellman-ford.js +1 -1
  15. package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
  16. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +1 -1
  17. package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -1
  18. package/dist/src/algorithms/shortest-path/dijkstra.js +1 -1
  19. package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
  20. package/dist/src/algorithms/traversal/bfs-unified.js +2 -2
  21. package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -1
  22. package/dist/src/algorithms/traversal/dfs.js +2 -2
  23. package/dist/src/algorithms/traversal/dfs.js.map +1 -1
  24. package/dist/src/clustering/spectral.js +2 -2
  25. package/dist/src/clustering/spectral.js.map +1 -1
  26. package/dist/src/index.d.ts +4 -0
  27. package/dist/src/index.d.ts.map +1 -1
  28. package/dist/src/index.js.map +1 -1
  29. package/dist/src/indexed/accelerator.d.ts +14 -2
  30. package/dist/src/indexed/accelerator.d.ts.map +1 -1
  31. package/dist/src/indexed/accelerator.js +8 -0
  32. package/dist/src/indexed/accelerator.js.map +1 -1
  33. package/dist/src/indexed/components.d.ts +8 -0
  34. package/dist/src/indexed/components.d.ts.map +1 -1
  35. package/dist/src/indexed/components.js +8 -1
  36. package/dist/src/indexed/components.js.map +1 -1
  37. package/dist/src/indexed/hits.d.ts +39 -0
  38. package/dist/src/indexed/hits.d.ts.map +1 -0
  39. package/dist/src/indexed/hits.js +95 -0
  40. package/dist/src/indexed/hits.js.map +1 -0
  41. package/dist/src/indexed/index.d.ts +5 -1
  42. package/dist/src/indexed/index.d.ts.map +1 -1
  43. package/dist/src/indexed/index.js +5 -1
  44. package/dist/src/indexed/index.js.map +1 -1
  45. package/dist/src/indexed/k-core.d.ts +32 -0
  46. package/dist/src/indexed/k-core.d.ts.map +1 -0
  47. package/dist/src/indexed/k-core.js +118 -0
  48. package/dist/src/indexed/k-core.js.map +1 -0
  49. package/dist/src/indexed/katz.d.ts +38 -0
  50. package/dist/src/indexed/katz.d.ts.map +1 -0
  51. package/dist/src/indexed/katz.js +61 -0
  52. package/dist/src/indexed/katz.js.map +1 -0
  53. package/dist/src/indexed/louvain.d.ts +33 -0
  54. package/dist/src/indexed/louvain.d.ts.map +1 -0
  55. package/dist/src/indexed/louvain.js +301 -0
  56. package/dist/src/indexed/louvain.js.map +1 -0
  57. package/package.json +6 -6
  58. package/src/algorithms/centrality/betweenness.ts +2 -2
  59. package/src/algorithms/community/girvan-newman.ts +1 -1
  60. package/src/algorithms/matching/isomorphism.ts +3 -3
  61. package/src/algorithms/mst/prim.ts +1 -1
  62. package/src/algorithms/shortest-path/bellman-ford.ts +3 -3
  63. package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +1 -1
  64. package/src/algorithms/shortest-path/dijkstra.ts +1 -1
  65. package/src/algorithms/traversal/bfs-unified.ts +2 -2
  66. package/src/algorithms/traversal/dfs.ts +2 -2
  67. package/src/clustering/spectral.ts +2 -2
  68. package/src/index.ts +10 -0
  69. package/src/indexed/accelerator.ts +26 -2
  70. package/src/indexed/components.ts +8 -1
  71. package/src/indexed/hits.ts +126 -0
  72. package/src/indexed/index.ts +5 -7
  73. package/src/indexed/k-core.ts +138 -0
  74. package/src/indexed/katz.ts +88 -0
  75. package/src/indexed/louvain.ts +345 -0
@@ -3282,7 +3282,7 @@ function breadthFirstSearchStandard(graph, startNode, options = {}) {
3282
3282
  if (options.visitCallback) {
3283
3283
  options.visitCallback(current.node, current.level);
3284
3284
  }
3285
- if (options.targetNode && current.node === options.targetNode) {
3285
+ if (options.targetNode !== void 0 && current.node === options.targetNode) {
3286
3286
  break;
3287
3287
  }
3288
3288
  for (const neighbor of graph.neighbors(current.node)) {
@@ -3472,7 +3472,7 @@ function isBipartite(graph) {
3472
3472
  visited.add(node.id);
3473
3473
  while (queue.length > 0) {
3474
3474
  const current = queue.shift();
3475
- if (!current) {
3475
+ if (current === void 0) {
3476
3476
  break;
3477
3477
  }
3478
3478
  const currentColor = color.get(current);
@@ -3526,7 +3526,7 @@ function dfsIterative(graph, startNode, visited, order, tree, options) {
3526
3526
  if (options.visitCallback) {
3527
3527
  options.visitCallback(current.node, current.depth);
3528
3528
  }
3529
- if (options.targetNode && current.node === options.targetNode) {
3529
+ if (options.targetNode !== void 0 && current.node === options.targetNode) {
3530
3530
  break;
3531
3531
  }
3532
3532
  const neighbors = Array.from(graph.neighbors(current.node));
@@ -3547,7 +3547,7 @@ function dfsRecursive(graph, node, visited, order, tree, options, depth, parent
3547
3547
  if (options.visitCallback) {
3548
3548
  options.visitCallback(node, depth);
3549
3549
  }
3550
- if (options.targetNode && node === options.targetNode) {
3550
+ if (options.targetNode !== void 0 && node === options.targetNode) {
3551
3551
  return;
3552
3552
  }
3553
3553
  }
@@ -3723,7 +3723,7 @@ function bellmanFord(graph, source, options = {}) {
3723
3723
  distances.set(v, newDistance);
3724
3724
  predecessors.set(v, u);
3725
3725
  updated = true;
3726
- if (options.target && v === options.target) {
3726
+ if (options.target !== void 0 && v === options.target) {
3727
3727
  break;
3728
3728
  }
3729
3729
  }
@@ -4077,7 +4077,7 @@ class BidirectionalDijkstra {
4077
4077
  return minDist;
4078
4078
  }
4079
4079
  reconstructPath() {
4080
- if (!this.meetingNode) {
4080
+ if (this.meetingNode === null) {
4081
4081
  return [];
4082
4082
  }
4083
4083
  const path = [];
@@ -4138,7 +4138,7 @@ function dijkstra$1(graph, source, options = {}) {
4138
4138
  continue;
4139
4139
  }
4140
4140
  visited.add(currentNode);
4141
- if (options.target && currentNode === options.target) {
4141
+ if (options.target !== void 0 && currentNode === options.target) {
4142
4142
  break;
4143
4143
  }
4144
4144
  if (currentDistance === Infinity) {
@@ -4713,7 +4713,7 @@ function accumulateBetweenness(result, source, centrality, options) {
4713
4713
  }
4714
4714
  for (let i = stack.length - 1; i >= 0; i--) {
4715
4715
  const w = stack[i];
4716
- if (!w) {
4716
+ if (w === void 0) {
4717
4717
  continue;
4718
4718
  }
4719
4719
  const wPreds = predecessors.get(w) ?? [];
@@ -4747,7 +4747,7 @@ function accumulateEdgeBetweenness(result, source, edgeCentrality, options) {
4747
4747
  }
4748
4748
  for (let i = stack.length - 1; i >= 0; i--) {
4749
4749
  const w = stack[i];
4750
- if (!w) {
4750
+ if (w === void 0) {
4751
4751
  continue;
4752
4752
  }
4753
4753
  const wPreds = predecessors.get(w) ?? [];
@@ -5381,7 +5381,7 @@ function nodeEigenvectorCentrality(graph, nodeId, options = {}) {
5381
5381
  const centrality = eigenvectorCentrality(graph, options);
5382
5382
  return centrality[nodeId.toString()] ?? 0;
5383
5383
  }
5384
- function hits(graph, options = {}) {
5384
+ function hits$1(graph, options = {}) {
5385
5385
  const { maxIterations = 100, tolerance = 1e-6, normalized = true } = options;
5386
5386
  const hubs = {};
5387
5387
  const authorities = {};
@@ -5498,14 +5498,14 @@ function nodeHITS(graph, nodeId, options = {}) {
5498
5498
  if (!graph.hasNode(nodeId)) {
5499
5499
  throw new Error(`Node ${String(nodeId)} not found in graph`);
5500
5500
  }
5501
- const result = hits(graph, options);
5501
+ const result = hits$1(graph, options);
5502
5502
  const key = nodeId.toString();
5503
5503
  return {
5504
5504
  hub: result.hubs[key] ?? 0,
5505
5505
  authority: result.authorities[key] ?? 0
5506
5506
  };
5507
5507
  }
5508
- function katzCentrality(graph, options = {}) {
5508
+ function katzCentrality$1(graph, options = {}) {
5509
5509
  const { alpha = 0.1, beta = 1, maxIterations = 100, tolerance = 1e-6, normalized = true } = options;
5510
5510
  const centrality = {};
5511
5511
  const nodes = Array.from(graph.nodes());
@@ -5566,7 +5566,7 @@ function nodeKatzCentrality(graph, nodeId, options = {}) {
5566
5566
  if (!graph.hasNode(nodeId)) {
5567
5567
  throw new Error(`Node ${String(nodeId)} not found in graph`);
5568
5568
  }
5569
- const centrality = katzCentrality(graph, options);
5569
+ const centrality = katzCentrality$1(graph, options);
5570
5570
  return centrality[nodeId.toString()] ?? 0;
5571
5571
  }
5572
5572
  class SimpleDeltaPageRank {
@@ -6411,7 +6411,7 @@ function primMST(graph, startNode) {
6411
6411
  };
6412
6412
  }
6413
6413
  const start = startNode ?? nodes[0]?.id;
6414
- if (!start) {
6414
+ if (start === void 0) {
6415
6415
  return {
6416
6416
  edges: [],
6417
6417
  totalWeight: 0
@@ -6579,7 +6579,7 @@ function findAllShortestPaths(graph, source) {
6579
6579
  let queueIndex = 0;
6580
6580
  while (queueIndex < queue.length) {
6581
6581
  const current = queue[queueIndex++];
6582
- if (!current) {
6582
+ if (current === void 0) {
6583
6583
  continue;
6584
6584
  }
6585
6585
  if (visited.has(current)) {
@@ -7361,7 +7361,7 @@ class OptimizedLouvain {
7361
7361
  for (let i = 0; i < membership.length; i++) {
7362
7362
  membership[i] = community[membership[i]];
7363
7363
  }
7364
- level = aggregate(level, community, count);
7364
+ level = aggregate$1(level, community, count);
7365
7365
  }
7366
7366
  const groups = Array.from({ length: level.n }, () => []);
7367
7367
  for (let i = 0; i < membership.length; i++) {
@@ -7544,7 +7544,7 @@ function buildCsr(n, counts, edges, self, degree) {
7544
7544
  }
7545
7545
  return { n, offsets, targets, weights, self, degree };
7546
7546
  }
7547
- function aggregate(level, community, count) {
7547
+ function aggregate$1(level, community, count) {
7548
7548
  const self = new Float64Array(count);
7549
7549
  const degree = new Float64Array(count);
7550
7550
  const members = Array.from({ length: count }, () => []);
@@ -7652,7 +7652,7 @@ function calculateModularity$1(graph, communities, resolution = 1) {
7652
7652
  }
7653
7653
  return modularity;
7654
7654
  }
7655
- function louvain(graph, options = {}) {
7655
+ function louvain$1(graph, options = {}) {
7656
7656
  const resolution = options.resolution ?? 1;
7657
7657
  const maxIterations = options.maxIterations ?? 100;
7658
7658
  const tolerance = options.tolerance ?? 1e-6;
@@ -9018,7 +9018,7 @@ function kCoreDecompositionImpl(graph) {
9018
9018
  return { cores, coreness, maxCore };
9019
9019
  }
9020
9020
  function getKCore(graph, k) {
9021
- const { coreness } = kCoreDecomposition(graph);
9021
+ const { coreness } = kCoreDecomposition$1(graph);
9022
9022
  const kCore = /* @__PURE__ */ new Set();
9023
9023
  for (const [node, core] of coreness) {
9024
9024
  if (core >= k) {
@@ -9027,7 +9027,7 @@ function getKCore(graph, k) {
9027
9027
  }
9028
9028
  return kCore;
9029
9029
  }
9030
- function kCoreDecomposition(graph) {
9030
+ function kCoreDecomposition$1(graph) {
9031
9031
  const adjacencySet = graphToAdjacencySet(graph);
9032
9032
  return kCoreDecompositionImpl(adjacencySet);
9033
9033
  }
@@ -9383,7 +9383,7 @@ function spectralClustering(graph, options) {
9383
9383
  for (let i = 0; i < nodeIds.length; i++) {
9384
9384
  const clusterId = kmeans.assignments[i] ?? 0;
9385
9385
  const nodeId = nodeIds[i];
9386
- if (!nodeId) {
9386
+ if (nodeId === void 0) {
9387
9387
  continue;
9388
9388
  }
9389
9389
  if (clusterId >= 0 && clusterId < k) {
@@ -9415,7 +9415,7 @@ function buildAdjacencyMatrix(graph, nodeIds) {
9415
9415
  nodeIds.forEach((id, index2) => nodeToIndex.set(id, index2));
9416
9416
  for (let i = 0; i < n; i++) {
9417
9417
  const nodeId = nodeIds[i];
9418
- if (!nodeId) {
9418
+ if (nodeId === void 0) {
9419
9419
  continue;
9420
9420
  }
9421
9421
  const neighbors = graph.neighbors(nodeId);
@@ -9955,7 +9955,7 @@ function getCandidatePairs(g1, g2, state, nodes1, nodes2) {
9955
9955
  break;
9956
9956
  }
9957
9957
  }
9958
- if (!node1) {
9958
+ if (node1 === null) {
9959
9959
  for (const [n] of state.in1) {
9960
9960
  if (!state.core1.has(n)) {
9961
9961
  node1 = n;
@@ -9963,7 +9963,7 @@ function getCandidatePairs(g1, g2, state, nodes1, nodes2) {
9963
9963
  }
9964
9964
  }
9965
9965
  }
9966
- if (!node1) {
9966
+ if (node1 === null) {
9967
9967
  for (const n of nodes1) {
9968
9968
  if (!state.core1.has(n)) {
9969
9969
  node1 = n;
@@ -9971,7 +9971,7 @@ function getCandidatePairs(g1, g2, state, nodes1, nodes2) {
9971
9971
  }
9972
9972
  }
9973
9973
  }
9974
- if (!node1) {
9974
+ if (node1 === null) {
9975
9975
  return pairs;
9976
9976
  }
9977
9977
  for (const node2 of nodes2) {
@@ -11708,6 +11708,467 @@ function dijkstra(g, source, options = {}) {
11708
11708
  pathEdges: (target) => walkPredEdges(g, predArc, source, target)
11709
11709
  };
11710
11710
  }
11711
+ function l2Normalize(v) {
11712
+ let sum = 0;
11713
+ for (let i = 0; i < v.length; i++) {
11714
+ sum += v[i] * v[i];
11715
+ }
11716
+ const norm = Math.sqrt(sum);
11717
+ if (norm > 0) {
11718
+ for (let i = 0; i < v.length; i++) {
11719
+ v[i] /= norm;
11720
+ }
11721
+ }
11722
+ }
11723
+ function maxNormalize(v) {
11724
+ let max = 0;
11725
+ for (let i = 0; i < v.length; i++) {
11726
+ if (v[i] > max) {
11727
+ max = v[i];
11728
+ }
11729
+ }
11730
+ if (max > 0) {
11731
+ for (let i = 0; i < v.length; i++) {
11732
+ v[i] /= max;
11733
+ }
11734
+ }
11735
+ }
11736
+ function hits(s, o = {}) {
11737
+ const n = s.nodeCount;
11738
+ const maxIter = o.maxIterations ?? 100;
11739
+ const tol = o.tolerance ?? 1e-6;
11740
+ const rev = s.reverse();
11741
+ const fwdW = o.weighted === true ? s.weights : null;
11742
+ const revW = o.weighted === true ? rev.weights : null;
11743
+ let hubs = new Float64Array(n).fill(n === 0 ? 0 : 1 / Math.sqrt(n));
11744
+ let authorities = new Float64Array(n).fill(n === 0 ? 0 : 1 / Math.sqrt(n));
11745
+ let nextHubs = new Float64Array(n);
11746
+ let nextAuthorities = new Float64Array(n);
11747
+ let it = 0;
11748
+ let converged = false;
11749
+ for (; it < maxIter && !converged; it++) {
11750
+ for (let v = 0; v < n; v++) {
11751
+ let auth = 0;
11752
+ const inEnd = rev.rowPtr[v + 1];
11753
+ for (let a = rev.rowPtr[v]; a < inEnd; a++) {
11754
+ auth += hubs[rev.colIdx[a]] * (revW === null ? 1 : revW[a]);
11755
+ }
11756
+ nextAuthorities[v] = auth;
11757
+ let hub = 0;
11758
+ const outEnd = s.rowPtr[v + 1];
11759
+ for (let a = s.rowPtr[v]; a < outEnd; a++) {
11760
+ hub += authorities[s.colIdx[a]] * (fwdW === null ? 1 : fwdW[a]);
11761
+ }
11762
+ nextHubs[v] = hub;
11763
+ }
11764
+ l2Normalize(nextAuthorities);
11765
+ l2Normalize(nextHubs);
11766
+ let maxDiff = 0;
11767
+ for (let v = 0; v < n; v++) {
11768
+ const dh = Math.abs(nextHubs[v] - hubs[v]);
11769
+ if (dh > maxDiff) {
11770
+ maxDiff = dh;
11771
+ }
11772
+ const da = Math.abs(nextAuthorities[v] - authorities[v]);
11773
+ if (da > maxDiff) {
11774
+ maxDiff = da;
11775
+ }
11776
+ }
11777
+ [hubs, nextHubs] = [nextHubs, hubs];
11778
+ [authorities, nextAuthorities] = [nextAuthorities, authorities];
11779
+ converged = maxDiff < tol;
11780
+ }
11781
+ if (o.normalized === false) {
11782
+ maxNormalize(hubs);
11783
+ maxNormalize(authorities);
11784
+ }
11785
+ return { hubs, authorities, iterations: it, converged };
11786
+ }
11787
+ function kCoreDecomposition(s) {
11788
+ if (s.directed) {
11789
+ throw new Error("k-core requires an undirected graph. Pass s.toUndirected().snapshot.");
11790
+ }
11791
+ const n = s.nodeCount;
11792
+ const { rowPtr, colIdx } = s;
11793
+ const degree = new Uint32Array(n);
11794
+ let maxDegree = 0;
11795
+ for (let u = 0; u < n; u++) {
11796
+ let d = 0;
11797
+ let last = -1;
11798
+ const end = rowPtr[u + 1];
11799
+ for (let a = rowPtr[u]; a < end; a++) {
11800
+ const v = colIdx[a];
11801
+ if (v !== u && v !== last) {
11802
+ d++;
11803
+ }
11804
+ last = v;
11805
+ }
11806
+ degree[u] = d;
11807
+ if (d > maxDegree) {
11808
+ maxDegree = d;
11809
+ }
11810
+ }
11811
+ const bin = new Uint32Array(maxDegree + 1);
11812
+ for (let u = 0; u < n; u++) {
11813
+ bin[degree[u]]++;
11814
+ }
11815
+ let start = 0;
11816
+ for (let d = 0; d <= maxDegree; d++) {
11817
+ const count = bin[d];
11818
+ bin[d] = start;
11819
+ start += count;
11820
+ }
11821
+ const vert = new Uint32Array(n);
11822
+ const pos = new Uint32Array(n);
11823
+ for (let u = 0; u < n; u++) {
11824
+ pos[u] = bin[degree[u]];
11825
+ vert[pos[u]] = u;
11826
+ bin[degree[u]]++;
11827
+ }
11828
+ for (let d = maxDegree; d > 0; d--) {
11829
+ bin[d] = bin[d - 1];
11830
+ }
11831
+ bin[0] = 0;
11832
+ let maxCore = 0;
11833
+ for (let i = 0; i < n; i++) {
11834
+ const v = vert[i];
11835
+ const dv = degree[v];
11836
+ if (dv > maxCore) {
11837
+ maxCore = dv;
11838
+ }
11839
+ const end = rowPtr[v + 1];
11840
+ let last = -1;
11841
+ for (let a = rowPtr[v]; a < end; a++) {
11842
+ const u = colIdx[a];
11843
+ const skip = u === v || u === last;
11844
+ last = u;
11845
+ if (skip) {
11846
+ continue;
11847
+ }
11848
+ const du = degree[u];
11849
+ if (du > dv) {
11850
+ const pu = pos[u];
11851
+ const pw = bin[du];
11852
+ const w = vert[pw];
11853
+ if (u !== w) {
11854
+ vert[pu] = w;
11855
+ vert[pw] = u;
11856
+ pos[u] = pw;
11857
+ pos[w] = pu;
11858
+ }
11859
+ bin[du]++;
11860
+ degree[u] = du - 1;
11861
+ }
11862
+ }
11863
+ }
11864
+ let cached = null;
11865
+ return {
11866
+ coreness: degree,
11867
+ maxCore,
11868
+ cores() {
11869
+ if (cached === null) {
11870
+ const sizes = new Uint32Array(maxCore + 1);
11871
+ for (let u = 0; u < n; u++) {
11872
+ sizes[degree[u]]++;
11873
+ }
11874
+ const out = [];
11875
+ for (let k = 0; k <= maxCore; k++) {
11876
+ out.push(new Uint32Array(sizes[k]));
11877
+ }
11878
+ const fill = new Uint32Array(maxCore + 1);
11879
+ for (let u = 0; u < n; u++) {
11880
+ const k = degree[u];
11881
+ out[k][fill[k]++] = u;
11882
+ }
11883
+ cached = out;
11884
+ }
11885
+ return cached;
11886
+ }
11887
+ };
11888
+ }
11889
+ function katzCentrality(s, o = {}) {
11890
+ const n = s.nodeCount;
11891
+ const alpha = o.alpha ?? 0.1;
11892
+ const beta = o.beta ?? 1;
11893
+ const maxIter = o.maxIterations ?? 100;
11894
+ const tol = o.tolerance ?? 1e-6;
11895
+ const rev = s.reverse();
11896
+ const weights = o.weighted === true ? rev.weights : null;
11897
+ let cur = new Float64Array(n).fill(beta);
11898
+ let next = new Float64Array(n);
11899
+ let it = 0;
11900
+ let converged = false;
11901
+ for (; it < maxIter && !converged; it++) {
11902
+ let maxDiff = 0;
11903
+ for (let v = 0; v < n; v++) {
11904
+ let sum = 0;
11905
+ const end = rev.rowPtr[v + 1];
11906
+ for (let a = rev.rowPtr[v]; a < end; a++) {
11907
+ sum += cur[rev.colIdx[a]] * (weights === null ? 1 : weights[a]);
11908
+ }
11909
+ next[v] = alpha * sum + beta;
11910
+ const diff = Math.abs(next[v] - cur[v]);
11911
+ if (diff > maxDiff) {
11912
+ maxDiff = diff;
11913
+ }
11914
+ }
11915
+ [cur, next] = [next, cur];
11916
+ converged = maxDiff < tol;
11917
+ }
11918
+ if (o.normalized !== false) {
11919
+ let min = Infinity;
11920
+ let max = -Infinity;
11921
+ for (let v = 0; v < n; v++) {
11922
+ if (cur[v] < min) {
11923
+ min = cur[v];
11924
+ }
11925
+ if (cur[v] > max) {
11926
+ max = cur[v];
11927
+ }
11928
+ }
11929
+ const range = max - min;
11930
+ if (range > 0) {
11931
+ for (let v = 0; v < n; v++) {
11932
+ cur[v] = (cur[v] - min) / range;
11933
+ }
11934
+ }
11935
+ }
11936
+ return { scores: cur, iterations: it, converged };
11937
+ }
11938
+ function buildLevel0(s) {
11939
+ const n = s.nodeCount;
11940
+ const rowPtr = new Uint32Array(n + 1);
11941
+ for (let u = 0; u < n; u++) {
11942
+ let kept = 0;
11943
+ const end = s.rowPtr[u + 1];
11944
+ for (let a = s.rowPtr[u]; a < end; a++) {
11945
+ if (s.colIdx[a] !== u) {
11946
+ kept++;
11947
+ }
11948
+ }
11949
+ rowPtr[u + 1] = rowPtr[u] + kept;
11950
+ }
11951
+ const arcs = rowPtr[n];
11952
+ const colIdx = new Uint32Array(arcs);
11953
+ const w = new Float64Array(arcs);
11954
+ const loop = new Float64Array(n);
11955
+ const deg = new Float64Array(n);
11956
+ let k = 0;
11957
+ for (let u = 0; u < n; u++) {
11958
+ let rowWeight = 0;
11959
+ const end = s.rowPtr[u + 1];
11960
+ for (let a = s.rowPtr[u]; a < end; a++) {
11961
+ const v = s.colIdx[a];
11962
+ const weight = s.weights === null ? 1 : s.weights[a];
11963
+ if (v === u) {
11964
+ loop[u] += weight;
11965
+ } else {
11966
+ colIdx[k] = v;
11967
+ w[k] = weight;
11968
+ k++;
11969
+ rowWeight += weight;
11970
+ }
11971
+ }
11972
+ deg[u] = rowWeight + 2 * loop[u];
11973
+ }
11974
+ return { n, rowPtr, colIdx, w, loop, deg };
11975
+ }
11976
+ function modularityOf(level, comm, count, resolution, m2) {
11977
+ const inside = new Float64Array(count);
11978
+ const tot = new Float64Array(count);
11979
+ for (let u = 0; u < level.n; u++) {
11980
+ const c = comm[u];
11981
+ tot[c] += level.deg[u];
11982
+ inside[c] += 2 * level.loop[u];
11983
+ const end = level.rowPtr[u + 1];
11984
+ for (let a = level.rowPtr[u]; a < end; a++) {
11985
+ if (comm[level.colIdx[a]] === c) {
11986
+ inside[c] += level.w[a];
11987
+ }
11988
+ }
11989
+ }
11990
+ let q = 0;
11991
+ for (let c = 0; c < count; c++) {
11992
+ const share = tot[c] / m2;
11993
+ q += inside[c] / m2 - resolution * share * share;
11994
+ }
11995
+ return q;
11996
+ }
11997
+ function localMove(level, comm, resolution, m2, maxVisitsPerNode) {
11998
+ const { n } = level;
11999
+ const tot = new Float64Array(n);
12000
+ for (let u = 0; u < n; u++) {
12001
+ comm[u] = u;
12002
+ tot[u] = level.deg[u];
12003
+ }
12004
+ const acc = new Float64Array(n);
12005
+ const stamp = new Int32Array(n).fill(-1);
12006
+ const touched = new Uint32Array(n);
12007
+ const capacity = n + 1;
12008
+ const queue = new Uint32Array(capacity);
12009
+ const queued = new Uint8Array(n);
12010
+ let head = 0;
12011
+ let tail = n;
12012
+ for (let u = 0; u < n; u++) {
12013
+ queue[u] = u;
12014
+ queued[u] = 1;
12015
+ }
12016
+ let mark = 0;
12017
+ let visits = 0;
12018
+ const maxVisits = maxVisitsPerNode * n;
12019
+ let movedAny = false;
12020
+ while (head !== tail && visits < maxVisits) {
12021
+ const u = queue[head];
12022
+ head = head + 1 === capacity ? 0 : head + 1;
12023
+ queued[u] = 0;
12024
+ visits++;
12025
+ const cu = comm[u];
12026
+ const ku = level.deg[u];
12027
+ tot[cu] -= ku;
12028
+ mark++;
12029
+ let cnt = 0;
12030
+ const end = level.rowPtr[u + 1];
12031
+ for (let a = level.rowPtr[u]; a < end; a++) {
12032
+ const c = comm[level.colIdx[a]];
12033
+ if (stamp[c] !== mark) {
12034
+ stamp[c] = mark;
12035
+ acc[c] = 0;
12036
+ touched[cnt++] = c;
12037
+ }
12038
+ acc[c] += level.w[a];
12039
+ }
12040
+ let best = cu;
12041
+ let bestGain = (stamp[cu] === mark ? acc[cu] : 0) - resolution * ku * tot[cu] / m2;
12042
+ for (let i = 0; i < cnt; i++) {
12043
+ const c = touched[i];
12044
+ if (c === cu) {
12045
+ continue;
12046
+ }
12047
+ const gain = acc[c] - resolution * ku * tot[c] / m2;
12048
+ if (gain > bestGain) {
12049
+ bestGain = gain;
12050
+ best = c;
12051
+ }
12052
+ }
12053
+ tot[best] += ku;
12054
+ if (best !== cu) {
12055
+ comm[u] = best;
12056
+ movedAny = true;
12057
+ for (let a = level.rowPtr[u]; a < end; a++) {
12058
+ const v = level.colIdx[a];
12059
+ if (queued[v] === 0 && comm[v] !== best) {
12060
+ queued[v] = 1;
12061
+ queue[tail] = v;
12062
+ tail = tail + 1 === capacity ? 0 : tail + 1;
12063
+ }
12064
+ }
12065
+ }
12066
+ }
12067
+ return movedAny;
12068
+ }
12069
+ function aggregate(level, comm, count) {
12070
+ const start = new Uint32Array(count + 1);
12071
+ for (let u = 0; u < level.n; u++) {
12072
+ start[comm[u] + 1]++;
12073
+ }
12074
+ for (let c = 0; c < count; c++) {
12075
+ start[c + 1] += start[c];
12076
+ }
12077
+ const members = new Uint32Array(level.n);
12078
+ const fill = start.slice(0, count);
12079
+ for (let u = 0; u < level.n; u++) {
12080
+ members[fill[comm[u]]++] = u;
12081
+ }
12082
+ const rowPtr = new Uint32Array(count + 1);
12083
+ const colIdx = new Uint32Array(level.colIdx.length);
12084
+ const w = new Float64Array(level.colIdx.length);
12085
+ const loop = new Float64Array(count);
12086
+ const deg = new Float64Array(count);
12087
+ const acc = new Float64Array(count);
12088
+ const stamp = new Int32Array(count).fill(-1);
12089
+ const touched = new Uint32Array(count);
12090
+ let k = 0;
12091
+ for (let c = 0; c < count; c++) {
12092
+ rowPtr[c] = k;
12093
+ let internalArcs = 0;
12094
+ let cnt = 0;
12095
+ for (let i = start[c]; i < start[c + 1]; i++) {
12096
+ const u = members[i];
12097
+ loop[c] += level.loop[u];
12098
+ const end = level.rowPtr[u + 1];
12099
+ for (let a = level.rowPtr[u]; a < end; a++) {
12100
+ const other = comm[level.colIdx[a]];
12101
+ if (other === c) {
12102
+ internalArcs += level.w[a];
12103
+ continue;
12104
+ }
12105
+ if (stamp[other] !== c) {
12106
+ stamp[other] = c;
12107
+ acc[other] = 0;
12108
+ touched[cnt++] = other;
12109
+ }
12110
+ acc[other] += level.w[a];
12111
+ }
12112
+ }
12113
+ loop[c] += internalArcs / 2;
12114
+ let rowWeight = 0;
12115
+ for (let i = 0; i < cnt; i++) {
12116
+ const other = touched[i];
12117
+ colIdx[k] = other;
12118
+ w[k] = acc[other];
12119
+ rowWeight += acc[other];
12120
+ k++;
12121
+ }
12122
+ deg[c] = rowWeight + 2 * loop[c];
12123
+ }
12124
+ rowPtr[count] = k;
12125
+ return { n: count, rowPtr, colIdx: colIdx.subarray(0, k), w: w.subarray(0, k), loop, deg };
12126
+ }
12127
+ function louvain(s, o = {}) {
12128
+ if (s.directed) {
12129
+ throw new Error("Louvain requires an undirected graph. Pass s.toUndirected().snapshot.");
12130
+ }
12131
+ const resolution = o.resolution ?? 1;
12132
+ const maxIterations = o.maxIterations ?? 100;
12133
+ const tolerance = o.tolerance ?? 1e-6;
12134
+ const n0 = s.nodeCount;
12135
+ const labels = new Uint32Array(n0);
12136
+ for (let u = 0; u < n0; u++) {
12137
+ labels[u] = u;
12138
+ }
12139
+ let level = buildLevel0(s);
12140
+ let m2 = 0;
12141
+ for (let u = 0; u < n0; u++) {
12142
+ m2 += level.deg[u];
12143
+ }
12144
+ if (m2 === 0) {
12145
+ return { ...withGroups(labels, n0), modularity: 0, iterations: 0 };
12146
+ }
12147
+ let q = modularityOf(level, labels, n0, resolution, m2);
12148
+ let iterations = 0;
12149
+ for (let iteration = 0; iteration < maxIterations; iteration++) {
12150
+ const comm = new Uint32Array(level.n);
12151
+ if (!localMove(level, comm, resolution, m2, maxIterations)) {
12152
+ break;
12153
+ }
12154
+ const dense = renumberPartition(comm);
12155
+ const { count } = dense;
12156
+ const packed = dense.labels;
12157
+ const newQ = modularityOf(level, packed, count, resolution, m2);
12158
+ for (let u = 0; u < n0; u++) {
12159
+ labels[u] = packed[labels[u]];
12160
+ }
12161
+ iterations = iteration + 1;
12162
+ const gain = newQ - q;
12163
+ q = newQ;
12164
+ if (gain < tolerance || count === level.n) {
12165
+ break;
12166
+ }
12167
+ level = aggregate(level, packed, count);
12168
+ }
12169
+ const final = renumberPartition(labels);
12170
+ return { ...withGroups(final.labels, final.count), modularity: q, iterations };
12171
+ }
11711
12172
  function kruskalMST(s, o = {}) {
11712
12173
  const el = s.edgeList();
11713
12174
  const m = s.edgeCount;
@@ -11791,7 +12252,11 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
11791
12252
  commonNeighborsScore,
11792
12253
  connectedComponents,
11793
12254
  dijkstra,
12255
+ hits,
12256
+ kCoreDecomposition,
12257
+ katzCentrality,
11794
12258
  kruskalMST,
12259
+ louvain,
11795
12260
  pageRank,
11796
12261
  walkPredArcs,
11797
12262
  walkPredEdges,
@@ -11837,7 +12302,11 @@ function accelerated(acc) {
11837
12302
  breadthFirstSearch: (s, source, options) => acc?.breadthFirstSearch !== void 0 ? acc.breadthFirstSearch(s, source, options) : Promise.resolve(breadthFirstSearch(s, source, options)),
11838
12303
  connectedComponents: (s) => acc?.connectedComponents !== void 0 ? acc.connectedComponents(s) : Promise.resolve(connectedComponents(s)),
11839
12304
  weaklyConnectedComponents: (s) => acc?.weaklyConnectedComponents !== void 0 ? acc.weaklyConnectedComponents(s) : Promise.resolve(weaklyConnectedComponents(s)),
11840
- minimumSpanningTree: (s, options) => acc?.minimumSpanningTree !== void 0 ? acc.minimumSpanningTree(s, options) : Promise.resolve(kruskalMST(s, options))
12305
+ minimumSpanningTree: (s, options) => acc?.minimumSpanningTree !== void 0 ? acc.minimumSpanningTree(s, options) : Promise.resolve(kruskalMST(s, options)),
12306
+ kCoreDecomposition: (s) => acc?.kCoreDecomposition !== void 0 ? acc.kCoreDecomposition(s) : Promise.resolve(kCoreDecomposition(s)),
12307
+ katzCentrality: (s, options) => acc?.katzCentrality !== void 0 ? acc.katzCentrality(s, options) : Promise.resolve(katzCentrality(s, options)),
12308
+ hits: (s, options) => acc?.hits !== void 0 ? acc.hits(s, options) : Promise.resolve(hits(s, options)),
12309
+ louvain: (s, options) => acc?.louvain !== void 0 ? acc.louvain(s, options) : Promise.resolve(louvain(s, options))
11841
12310
  };
11842
12311
  }
11843
12312
  export {
@@ -11903,7 +12372,7 @@ export {
11903
12372
  hasNegativeCycle,
11904
12373
  heuristics,
11905
12374
  hierarchicalClustering,
11906
- hits,
12375
+ hits$1 as hits,
11907
12376
  index as indexed,
11908
12377
  isBipartite,
11909
12378
  isCSRGraph,
@@ -11911,16 +12380,16 @@ export {
11911
12380
  isGraphIsomorphic,
11912
12381
  isStronglyConnected,
11913
12382
  isWeaklyConnected,
11914
- kCoreDecomposition,
12383
+ kCoreDecomposition$1 as kCoreDecomposition,
11915
12384
  kargerMinCut,
11916
- katzCentrality,
12385
+ katzCentrality$1 as katzCentrality,
11917
12386
  kruskalMST$1 as kruskalMST,
11918
12387
  labelPropagation,
11919
12388
  labelPropagationAsync,
11920
12389
  labelPropagationSemiSupervised,
11921
12390
  largestConnectedComponent,
11922
12391
  leiden,
11923
- louvain,
12392
+ louvain$1 as louvain,
11924
12393
  markovClustering,
11925
12394
  maximumBipartiteMatching,
11926
12395
  minSTCut,