@graphty/algorithms 2.1.1 → 2.2.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 +139 -50
- package/dist/algorithms.js +15260 -10390
- package/dist/algorithms.js.map +1 -1
- package/dist/algorithms.standalone.js +26675 -21542
- package/dist/algorithms.standalone.js.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.d.ts +18 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +40 -1
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/algorithms/centrality/closeness.d.ts +20 -0
- package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/closeness.js +93 -8
- package/dist/src/algorithms/centrality/closeness.js.map +1 -1
- package/dist/src/algorithms/centrality/degree.d.ts +9 -0
- package/dist/src/algorithms/centrality/degree.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/degree.js +18 -0
- package/dist/src/algorithms/centrality/degree.js.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.d.ts +10 -0
- package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.js +29 -0
- package/dist/src/algorithms/centrality/eigenvector.js.map +1 -1
- package/dist/src/algorithms/centrality/hits.d.ts +9 -0
- package/dist/src/algorithms/centrality/hits.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/hits.js +23 -0
- package/dist/src/algorithms/centrality/hits.js.map +1 -1
- package/dist/src/algorithms/centrality/katz.d.ts +9 -0
- package/dist/src/algorithms/centrality/katz.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/katz.js +31 -0
- package/dist/src/algorithms/centrality/katz.js.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.d.ts +13 -13
- package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.js +47 -10
- package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
- package/dist/src/algorithms/community/girvan-newman-legacy.d.ts +27 -0
- package/dist/src/algorithms/community/girvan-newman-legacy.d.ts.map +1 -0
- package/dist/src/algorithms/community/girvan-newman-legacy.js +335 -0
- package/dist/src/algorithms/community/girvan-newman-legacy.js.map +1 -0
- package/dist/src/algorithms/community/girvan-newman.d.ts +5 -3
- package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.js +34 -308
- package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
- package/dist/src/algorithms/community/label-propagation.d.ts +9 -6
- package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -1
- package/dist/src/algorithms/community/label-propagation.js +24 -110
- package/dist/src/algorithms/community/label-propagation.js.map +1 -1
- package/dist/src/algorithms/components/connected.d.ts.map +1 -1
- package/dist/src/algorithms/components/connected.js +28 -77
- package/dist/src/algorithms/components/connected.js.map +1 -1
- package/dist/src/algorithms/mst/kruskal.d.ts.map +1 -1
- package/dist/src/algorithms/mst/kruskal.js +59 -3
- package/dist/src/algorithms/mst/kruskal.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.js +46 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js +27 -0
- package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts +15 -5
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/floyd-warshall.js +97 -107
- package/dist/src/algorithms/shortest-path/floyd-warshall.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs-unified.d.ts +2 -12
- package/dist/src/algorithms/traversal/bfs-unified.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs-unified.js +47 -308
- package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs-variants.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs-variants.js +5 -25
- package/dist/src/algorithms/traversal/bfs-variants.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs.d.ts +0 -3
- package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs.js +0 -4
- package/dist/src/algorithms/traversal/bfs.js.map +1 -1
- package/dist/src/algorithms/traversal/dfs.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/dfs.js +33 -154
- package/dist/src/algorithms/traversal/dfs.js.map +1 -1
- package/dist/src/clustering/hierarchical-legacy.d.ts +56 -0
- package/dist/src/clustering/hierarchical-legacy.d.ts.map +1 -0
- package/dist/src/clustering/hierarchical-legacy.js +441 -0
- package/dist/src/clustering/hierarchical-legacy.js.map +1 -0
- package/dist/src/clustering/hierarchical.d.ts +7 -39
- package/dist/src/clustering/hierarchical.d.ts.map +1 -1
- package/dist/src/clustering/hierarchical.js +56 -417
- package/dist/src/clustering/hierarchical.js.map +1 -1
- package/dist/src/clustering/k-core-legacy.d.ts +30 -0
- package/dist/src/clustering/k-core-legacy.d.ts.map +1 -0
- package/dist/src/clustering/k-core-legacy.js +191 -0
- package/dist/src/clustering/k-core-legacy.js.map +1 -0
- package/dist/src/clustering/k-core.d.ts +8 -7
- package/dist/src/clustering/k-core.d.ts.map +1 -1
- package/dist/src/clustering/k-core.js +33 -174
- package/dist/src/clustering/k-core.js.map +1 -1
- package/dist/src/clustering/mcl-legacy.d.ts +42 -0
- package/dist/src/clustering/mcl-legacy.d.ts.map +1 -0
- package/dist/src/clustering/mcl-legacy.js +386 -0
- package/dist/src/clustering/mcl-legacy.js.map +1 -0
- package/dist/src/clustering/mcl.d.ts +9 -32
- package/dist/src/clustering/mcl.d.ts.map +1 -1
- package/dist/src/clustering/mcl.js +48 -374
- package/dist/src/clustering/mcl.js.map +1 -1
- package/dist/src/index.d.ts +29 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/indexed/accelerator.d.ts +141 -11
- package/dist/src/indexed/accelerator.d.ts.map +1 -1
- package/dist/src/indexed/accelerator.js +319 -5
- package/dist/src/indexed/accelerator.js.map +1 -1
- package/dist/src/indexed/all-pairs.d.ts +59 -0
- package/dist/src/indexed/all-pairs.d.ts.map +1 -0
- package/dist/src/indexed/all-pairs.js +274 -0
- package/dist/src/indexed/all-pairs.js.map +1 -0
- package/dist/src/indexed/bellman-ford.d.ts +25 -0
- package/dist/src/indexed/bellman-ford.d.ts.map +1 -0
- package/dist/src/indexed/bellman-ford.js +59 -0
- package/dist/src/indexed/bellman-ford.js.map +1 -0
- package/dist/src/indexed/betweenness.d.ts +85 -0
- package/dist/src/indexed/betweenness.d.ts.map +1 -0
- package/dist/src/indexed/betweenness.js +188 -0
- package/dist/src/indexed/betweenness.js.map +1 -0
- package/dist/src/indexed/bfs.d.ts +69 -2
- package/dist/src/indexed/bfs.d.ts.map +1 -1
- package/dist/src/indexed/bfs.js +148 -1
- package/dist/src/indexed/bfs.js.map +1 -1
- package/dist/src/indexed/bipartite.d.ts +37 -0
- package/dist/src/indexed/bipartite.d.ts.map +1 -0
- package/dist/src/indexed/bipartite.js +54 -0
- package/dist/src/indexed/bipartite.js.map +1 -0
- package/dist/src/indexed/closeness.d.ts +49 -0
- package/dist/src/indexed/closeness.d.ts.map +1 -0
- package/dist/src/indexed/closeness.js +127 -0
- package/dist/src/indexed/closeness.js.map +1 -0
- package/dist/src/indexed/common-neighbors.d.ts +14 -1
- package/dist/src/indexed/common-neighbors.d.ts.map +1 -1
- package/dist/src/indexed/common-neighbors.js +24 -14
- package/dist/src/indexed/common-neighbors.js.map +1 -1
- package/dist/src/indexed/degree.d.ts +19 -0
- package/dist/src/indexed/degree.d.ts.map +1 -0
- package/dist/src/indexed/degree.js +45 -0
- package/dist/src/indexed/degree.js.map +1 -0
- package/dist/src/indexed/delta-pagerank.d.ts +145 -0
- package/dist/src/indexed/delta-pagerank.d.ts.map +1 -0
- package/dist/src/indexed/delta-pagerank.js +428 -0
- package/dist/src/indexed/delta-pagerank.js.map +1 -0
- package/dist/src/indexed/dfs.d.ts +55 -0
- package/dist/src/indexed/dfs.d.ts.map +1 -0
- package/dist/src/indexed/dfs.js +146 -0
- package/dist/src/indexed/dfs.js.map +1 -0
- package/dist/src/indexed/eigenvector.d.ts +48 -0
- package/dist/src/indexed/eigenvector.d.ts.map +1 -0
- package/dist/src/indexed/eigenvector.js +162 -0
- package/dist/src/indexed/eigenvector.js.map +1 -0
- package/dist/src/indexed/facade.d.ts +109 -0
- package/dist/src/indexed/facade.d.ts.map +1 -0
- package/dist/src/indexed/facade.js +204 -0
- package/dist/src/indexed/facade.js.map +1 -0
- package/dist/src/indexed/flow.d.ts +120 -0
- package/dist/src/indexed/flow.d.ts.map +1 -0
- package/dist/src/indexed/flow.js +377 -0
- package/dist/src/indexed/flow.js.map +1 -0
- package/dist/src/indexed/girvan-newman.d.ts +42 -0
- package/dist/src/indexed/girvan-newman.d.ts.map +1 -0
- package/dist/src/indexed/girvan-newman.js +90 -0
- package/dist/src/indexed/girvan-newman.js.map +1 -0
- package/dist/src/indexed/grsbm.d.ts +85 -0
- package/dist/src/indexed/grsbm.d.ts.map +1 -0
- package/dist/src/indexed/grsbm.js +287 -0
- package/dist/src/indexed/grsbm.js.map +1 -0
- package/dist/src/indexed/hierarchical.d.ts +69 -0
- package/dist/src/indexed/hierarchical.d.ts.map +1 -0
- package/dist/src/indexed/hierarchical.js +245 -0
- package/dist/src/indexed/hierarchical.js.map +1 -0
- package/dist/src/indexed/index.d.ts +29 -3
- package/dist/src/indexed/index.d.ts.map +1 -1
- package/dist/src/indexed/index.js +29 -3
- package/dist/src/indexed/index.js.map +1 -1
- package/dist/src/indexed/isomorphism.d.ts +42 -0
- package/dist/src/indexed/isomorphism.d.ts.map +1 -0
- package/dist/src/indexed/isomorphism.js +269 -0
- package/dist/src/indexed/isomorphism.js.map +1 -0
- package/dist/src/indexed/label-propagation.d.ts +134 -0
- package/dist/src/indexed/label-propagation.d.ts.map +1 -0
- package/dist/src/indexed/label-propagation.js +486 -0
- package/dist/src/indexed/label-propagation.js.map +1 -0
- package/dist/src/indexed/leiden.d.ts +52 -0
- package/dist/src/indexed/leiden.d.ts.map +1 -0
- package/dist/src/indexed/leiden.js +384 -0
- package/dist/src/indexed/leiden.js.map +1 -0
- package/dist/src/indexed/link-prediction.d.ts +147 -0
- package/dist/src/indexed/link-prediction.d.ts.map +1 -0
- package/dist/src/indexed/link-prediction.js +317 -0
- package/dist/src/indexed/link-prediction.js.map +1 -0
- package/dist/src/indexed/markov.d.ts +54 -0
- package/dist/src/indexed/markov.d.ts.map +1 -0
- package/dist/src/indexed/markov.js +284 -0
- package/dist/src/indexed/markov.js.map +1 -0
- package/dist/src/indexed/matching.d.ts +53 -0
- package/dist/src/indexed/matching.d.ts.map +1 -0
- package/dist/src/indexed/matching.js +139 -0
- package/dist/src/indexed/matching.js.map +1 -0
- package/dist/src/indexed/min-cut.d.ts +48 -0
- package/dist/src/indexed/min-cut.d.ts.map +1 -0
- package/dist/src/indexed/min-cut.js +175 -0
- package/dist/src/indexed/min-cut.js.map +1 -0
- package/dist/src/indexed/modularity.d.ts +34 -0
- package/dist/src/indexed/modularity.d.ts.map +1 -0
- package/dist/src/indexed/modularity.js +74 -0
- package/dist/src/indexed/modularity.js.map +1 -0
- package/dist/src/indexed/mst.d.ts +29 -1
- package/dist/src/indexed/mst.d.ts.map +1 -1
- package/dist/src/indexed/mst.js +62 -0
- package/dist/src/indexed/mst.js.map +1 -1
- package/dist/src/indexed/pagerank.d.ts +29 -6
- package/dist/src/indexed/pagerank.d.ts.map +1 -1
- package/dist/src/indexed/pagerank.js +107 -11
- package/dist/src/indexed/pagerank.js.map +1 -1
- package/dist/src/indexed/point-to-point.d.ts +53 -0
- package/dist/src/indexed/point-to-point.d.ts.map +1 -0
- package/dist/src/indexed/point-to-point.js +173 -0
- package/dist/src/indexed/point-to-point.js.map +1 -0
- package/dist/src/indexed/scc.d.ts +53 -0
- package/dist/src/indexed/scc.d.ts.map +1 -0
- package/dist/src/indexed/scc.js +110 -0
- package/dist/src/indexed/scc.js.map +1 -0
- package/dist/src/indexed/spectral.d.ts +61 -0
- package/dist/src/indexed/spectral.d.ts.map +1 -0
- package/dist/src/indexed/spectral.js +476 -0
- package/dist/src/indexed/spectral.js.map +1 -0
- package/dist/src/indexed/structures/bit-set.d.ts +45 -0
- package/dist/src/indexed/structures/bit-set.d.ts.map +1 -0
- package/dist/src/indexed/structures/bit-set.js +57 -0
- package/dist/src/indexed/structures/bit-set.js.map +1 -0
- package/dist/src/indexed/structures/max-heap.d.ts +52 -0
- package/dist/src/indexed/structures/max-heap.d.ts.map +1 -0
- package/dist/src/indexed/structures/max-heap.js +66 -0
- package/dist/src/indexed/structures/max-heap.js.map +1 -0
- package/dist/src/indexed/structures/min-heap.d.ts +30 -1
- package/dist/src/indexed/structures/min-heap.d.ts.map +1 -1
- package/dist/src/indexed/structures/min-heap.js +46 -6
- package/dist/src/indexed/structures/min-heap.js.map +1 -1
- package/dist/src/indexed/structures/ring-queue.d.ts +41 -0
- package/dist/src/indexed/structures/ring-queue.d.ts.map +1 -0
- package/dist/src/indexed/structures/ring-queue.js +64 -0
- package/dist/src/indexed/structures/ring-queue.js.map +1 -0
- package/dist/src/indexed/sync.d.ts +50 -0
- package/dist/src/indexed/sync.d.ts.map +1 -0
- package/dist/src/indexed/sync.js +175 -0
- package/dist/src/indexed/sync.js.map +1 -0
- package/dist/src/indexed/terahac.d.ts +58 -0
- package/dist/src/indexed/terahac.d.ts.map +1 -0
- package/dist/src/indexed/terahac.js +244 -0
- package/dist/src/indexed/terahac.js.map +1 -0
- package/dist/src/indexed/to-snapshot.d.ts +45 -2
- package/dist/src/indexed/to-snapshot.d.ts.map +1 -1
- package/dist/src/indexed/to-snapshot.js +140 -6
- package/dist/src/indexed/to-snapshot.js.map +1 -1
- package/dist/src/link-prediction/common-neighbors-legacy.d.ts +71 -0
- package/dist/src/link-prediction/common-neighbors-legacy.d.ts.map +1 -0
- package/dist/src/link-prediction/common-neighbors-legacy.js +172 -0
- package/dist/src/link-prediction/common-neighbors-legacy.js.map +1 -0
- package/dist/src/link-prediction/common-neighbors.d.ts +11 -19
- package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -1
- package/dist/src/link-prediction/common-neighbors.js +56 -123
- package/dist/src/link-prediction/common-neighbors.js.map +1 -1
- package/dist/src/optimized/direction-optimized-bfs.d.ts +6 -0
- package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -1
- package/dist/src/optimized/direction-optimized-bfs.js +6 -0
- package/dist/src/optimized/direction-optimized-bfs.js.map +1 -1
- package/dist/src/research/grsbm-legacy.d.ts +82 -0
- package/dist/src/research/grsbm-legacy.d.ts.map +1 -0
- package/dist/src/research/grsbm-legacy.js +416 -0
- package/dist/src/research/grsbm-legacy.js.map +1 -0
- package/dist/src/research/grsbm.d.ts +9 -66
- package/dist/src/research/grsbm.d.ts.map +1 -1
- package/dist/src/research/grsbm.js +67 -391
- package/dist/src/research/grsbm.js.map +1 -1
- package/dist/src/research/sync-legacy.d.ts +48 -0
- package/dist/src/research/sync-legacy.d.ts.map +1 -0
- package/dist/src/research/sync-legacy.js +337 -0
- package/dist/src/research/sync-legacy.js.map +1 -0
- package/dist/src/research/sync.d.ts +10 -32
- package/dist/src/research/sync.d.ts.map +1 -1
- package/dist/src/research/sync.js +28 -316
- package/dist/src/research/sync.js.map +1 -1
- package/package.json +4 -3
- package/src/algorithms/centrality/betweenness.ts +51 -1
- package/src/algorithms/centrality/closeness.ts +112 -12
- package/src/algorithms/centrality/degree.ts +19 -0
- package/src/algorithms/centrality/eigenvector.ts +34 -0
- package/src/algorithms/centrality/hits.ts +24 -0
- package/src/algorithms/centrality/katz.ts +32 -0
- package/src/algorithms/centrality/pagerank.ts +53 -13
- package/src/algorithms/community/girvan-newman-legacy.ts +414 -0
- package/src/algorithms/community/girvan-newman.ts +36 -386
- package/src/algorithms/community/label-propagation.ts +24 -133
- package/src/algorithms/components/connected.ts +28 -95
- package/src/algorithms/mst/kruskal.ts +65 -4
- package/src/algorithms/shortest-path/bellman-ford.ts +49 -0
- package/src/algorithms/shortest-path/dijkstra.ts +29 -0
- package/src/algorithms/shortest-path/floyd-warshall.ts +106 -136
- package/src/algorithms/traversal/bfs-unified.ts +52 -366
- package/src/algorithms/traversal/bfs-variants.ts +5 -28
- package/src/algorithms/traversal/bfs.ts +0 -4
- package/src/algorithms/traversal/dfs.ts +39 -182
- package/src/clustering/hierarchical-legacy.ts +551 -0
- package/src/clustering/hierarchical.ts +64 -520
- package/src/clustering/k-core-legacy.ts +229 -0
- package/src/clustering/k-core.ts +38 -209
- package/src/clustering/mcl-legacy.ts +498 -0
- package/src/clustering/mcl.ts +46 -479
- package/src/index.ts +90 -3
- package/src/indexed/accelerator.ts +502 -16
- package/src/indexed/all-pairs.ts +342 -0
- package/src/indexed/bellman-ford.ts +72 -0
- package/src/indexed/betweenness.ts +258 -0
- package/src/indexed/bfs.ts +189 -3
- package/src/indexed/bipartite.ts +77 -0
- package/src/indexed/closeness.ts +160 -0
- package/src/indexed/common-neighbors.ts +31 -14
- package/src/indexed/degree.ts +55 -0
- package/src/indexed/delta-pagerank.ts +513 -0
- package/src/indexed/dfs.ts +189 -0
- package/src/indexed/eigenvector.ts +202 -0
- package/src/indexed/facade.ts +229 -0
- package/src/indexed/flow.ts +500 -0
- package/src/indexed/girvan-newman.ts +120 -0
- package/src/indexed/grsbm.ts +390 -0
- package/src/indexed/hierarchical.ts +295 -0
- package/src/indexed/index.ts +94 -3
- package/src/indexed/isomorphism.ts +305 -0
- package/src/indexed/label-propagation.ts +582 -0
- package/src/indexed/leiden.ts +436 -0
- package/src/indexed/link-prediction.ts +399 -0
- package/src/indexed/markov.ts +324 -0
- package/src/indexed/matching.ts +192 -0
- package/src/indexed/min-cut.ts +201 -0
- package/src/indexed/modularity.ts +81 -0
- package/src/indexed/mst.ts +79 -1
- package/src/indexed/pagerank.ts +128 -15
- package/src/indexed/point-to-point.ts +220 -0
- package/src/indexed/scc.ts +132 -0
- package/src/indexed/spectral.ts +550 -0
- package/src/indexed/structures/bit-set.ts +65 -0
- package/src/indexed/structures/max-heap.ts +74 -0
- package/src/indexed/structures/min-heap.ts +51 -6
- package/src/indexed/structures/ring-queue.ts +70 -0
- package/src/indexed/sync.ts +229 -0
- package/src/indexed/terahac.ts +290 -0
- package/src/indexed/to-snapshot.ts +156 -6
- package/src/link-prediction/common-neighbors-legacy.ts +252 -0
- package/src/link-prediction/common-neighbors.ts +65 -168
- package/src/optimized/direction-optimized-bfs.ts +6 -1
- package/src/research/grsbm-legacy.ts +586 -0
- package/src/research/grsbm.ts +76 -555
- package/src/research/sync-legacy.ts +456 -0
- package/src/research/sync.ts +30 -431
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* SynC (Synergistic Deep Graph Clustering) over a legacy `Graph`. `syncClustering` delegates to
|
|
3
|
+
* `indexed.syncClustering` over an unweighted snapshot of the graph (SynC never reads a weight);
|
|
4
|
+
* clusters, embeddings, loss, iterations and convergence equal the pre-migration implementation in
|
|
5
|
+
* `sync-legacy.ts`, the floats to rounding. A run that diverges (a large learning rate) amplifies
|
|
6
|
+
* that rounding, so its embeddings and loss can differ from the old code's in the leading digits. A
|
|
7
|
+
* cluster count that is not an integer keeps the old code, which mostly fails on one ("Invalid array
|
|
8
|
+
* length"). Unlike the old code the port never replaces `Math.random`.
|
|
9
|
+
*/
|
|
10
|
+
import { syncClustering as indexedSyncClustering } from "../indexed/sync.js";
|
|
11
|
+
import { toTopologySnapshot } from "../indexed/to-snapshot.js";
|
|
12
|
+
import { syncClustering as legacySyncClustering } from "./sync-legacy.js";
|
|
2
13
|
/**
|
|
3
14
|
* Synergistic Deep Graph Clustering (SynC) Algorithm
|
|
4
15
|
*
|
|
@@ -12,326 +23,27 @@ import { euclideanDistance, SeededRandom } from "../utils/math-utilities.js";
|
|
|
12
23
|
* @returns Clustering result with assignments and embeddings
|
|
13
24
|
*/
|
|
14
25
|
export function syncClustering(graph, config) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const originalRandom = Math.random;
|
|
18
|
-
const rng = SeededRandom.createGenerator(seed);
|
|
19
|
-
Math.random = rng;
|
|
20
|
-
const nodes = Array.from(graph.nodes());
|
|
21
|
-
const nodeCount = nodes.length;
|
|
22
|
-
if (nodeCount === 0) {
|
|
23
|
-
return {
|
|
24
|
-
clusters: new Map(),
|
|
25
|
-
loss: 0,
|
|
26
|
-
iterations: 0,
|
|
27
|
-
embeddings: new Map(),
|
|
28
|
-
converged: true,
|
|
29
|
-
};
|
|
26
|
+
if (!Number.isInteger(config.numClusters)) {
|
|
27
|
+
return legacySyncClustering(graph, config);
|
|
30
28
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const embeddingDim = Math.min(64, nodeCount);
|
|
29
|
+
const s = toTopologySnapshot(graph);
|
|
30
|
+
const n = s.nodeCount;
|
|
31
|
+
const r = indexedSyncClustering(s, config);
|
|
32
|
+
const clusters = new Map();
|
|
36
33
|
const embeddings = new Map();
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
embeddings.set(
|
|
41
|
-
}
|
|
42
|
-
// Initialize cluster centers
|
|
43
|
-
const clusterCenters = initializeClusterCenters(embeddings, numClusters);
|
|
44
|
-
let previousLoss = Infinity;
|
|
45
|
-
let iterations = 0;
|
|
46
|
-
let converged = false;
|
|
47
|
-
for (iterations = 0; iterations < maxIterations; iterations++) {
|
|
48
|
-
// E-step: Assign nodes to clusters
|
|
49
|
-
const clusters = new Map();
|
|
50
|
-
for (const node of nodes) {
|
|
51
|
-
const nodeEmbedding = embeddings.get(node.id);
|
|
52
|
-
if (!nodeEmbedding) {
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
let bestCluster = 0;
|
|
56
|
-
let minDistance = Infinity;
|
|
57
|
-
for (let k = 0; k < numClusters; k++) {
|
|
58
|
-
const center = clusterCenters[k];
|
|
59
|
-
if (!center) {
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
const distance = euclideanDistance(nodeEmbedding, center);
|
|
63
|
-
if (distance < minDistance) {
|
|
64
|
-
minDistance = distance;
|
|
65
|
-
bestCluster = k;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
clusters.set(node.id, bestCluster);
|
|
69
|
-
}
|
|
70
|
-
// M-step: Update embeddings and cluster centers
|
|
71
|
-
updateEmbeddings(graph, embeddings, clusters, learningRate, lambda);
|
|
72
|
-
updateClusterCenters(embeddings, clusters, clusterCenters, numClusters);
|
|
73
|
-
// Calculate current loss
|
|
74
|
-
const currentLoss = calculateLoss(graph, embeddings, clusters, clusterCenters, lambda);
|
|
75
|
-
// Check for convergence
|
|
76
|
-
if (Math.abs(previousLoss - currentLoss) < tolerance) {
|
|
77
|
-
converged = true;
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
previousLoss = currentLoss;
|
|
34
|
+
for (let i = 0; i < n; i++) {
|
|
35
|
+
const id = s.ids.idOf(i);
|
|
36
|
+
clusters.set(id, r.labels[i]);
|
|
37
|
+
embeddings.set(id, Array.from(r.embeddings.subarray(i * r.dimensions, (i + 1) * r.dimensions)));
|
|
81
38
|
}
|
|
82
|
-
// Final cluster assignment
|
|
83
|
-
const finalClusters = new Map();
|
|
84
|
-
for (const node of nodes) {
|
|
85
|
-
const nodeEmbedding = embeddings.get(node.id);
|
|
86
|
-
if (!nodeEmbedding) {
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
let bestCluster = 0;
|
|
90
|
-
let minDistance = Infinity;
|
|
91
|
-
for (let k = 0; k < numClusters; k++) {
|
|
92
|
-
const center = clusterCenters[k];
|
|
93
|
-
if (!center) {
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
const distance = euclideanDistance(nodeEmbedding, center);
|
|
97
|
-
if (distance < minDistance) {
|
|
98
|
-
minDistance = distance;
|
|
99
|
-
bestCluster = k;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
finalClusters.set(node.id, bestCluster);
|
|
103
|
-
}
|
|
104
|
-
// Restore original random function
|
|
105
|
-
Math.random = originalRandom;
|
|
106
39
|
return {
|
|
107
|
-
clusters
|
|
108
|
-
loss
|
|
109
|
-
|
|
40
|
+
clusters,
|
|
41
|
+
// The old code reported the loss of the round before the converging one.
|
|
42
|
+
loss: r.converged && r.iterations > 1 ? r.previousLoss : r.loss,
|
|
43
|
+
// ...and one round more than it ran when it stopped at the cap.
|
|
44
|
+
iterations: r.iterations + (r.converged ? 0 : 1),
|
|
110
45
|
embeddings,
|
|
111
|
-
converged,
|
|
46
|
+
converged: r.converged,
|
|
112
47
|
};
|
|
113
48
|
}
|
|
114
|
-
/**
|
|
115
|
-
* Initialize node embedding based on graph structure and features
|
|
116
|
-
* @param graph - The input graph
|
|
117
|
-
* @param nodeId - The node ID to initialize embedding for
|
|
118
|
-
* @param dim - The embedding dimension
|
|
119
|
-
* @returns The initialized embedding vector
|
|
120
|
-
*/
|
|
121
|
-
function initializeNodeEmbedding(graph, nodeId, dim) {
|
|
122
|
-
const embedding = new Array(dim).fill(0);
|
|
123
|
-
// Use node degree as a base feature
|
|
124
|
-
const degree = graph.degree(nodeId);
|
|
125
|
-
const normalizedDegree = degree / Math.max(1, graph.nodeCount - 1);
|
|
126
|
-
// Initialize with small random values influenced by graph structure
|
|
127
|
-
for (let i = 0; i < dim; i++) {
|
|
128
|
-
embedding[i] = (Math.random() - 0.5) * 0.1 + normalizedDegree * 0.1;
|
|
129
|
-
}
|
|
130
|
-
return embedding;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Initialize cluster centers using k-means++ style initialization
|
|
134
|
-
* @param embeddings - Map of node IDs to embedding vectors
|
|
135
|
-
* @param numClusters - Number of cluster centers to initialize
|
|
136
|
-
* @returns Array of initialized cluster center vectors
|
|
137
|
-
*/
|
|
138
|
-
function initializeClusterCenters(embeddings, numClusters) {
|
|
139
|
-
const embeddingArray = Array.from(embeddings.values());
|
|
140
|
-
const centers = [];
|
|
141
|
-
// Choose first center randomly
|
|
142
|
-
const firstCenter = embeddingArray[Math.floor(Math.random() * embeddingArray.length)];
|
|
143
|
-
if (firstCenter) {
|
|
144
|
-
centers.push([...firstCenter]);
|
|
145
|
-
}
|
|
146
|
-
// Choose remaining centers using k-means++ initialization
|
|
147
|
-
for (let k = 1; k < numClusters; k++) {
|
|
148
|
-
const distances = [];
|
|
149
|
-
let totalDistance = 0;
|
|
150
|
-
for (const embedding of embeddingArray) {
|
|
151
|
-
let minDistance = Infinity;
|
|
152
|
-
for (const center of centers) {
|
|
153
|
-
const distance = euclideanDistance(embedding, center);
|
|
154
|
-
minDistance = Math.min(minDistance, distance);
|
|
155
|
-
}
|
|
156
|
-
distances.push(minDistance * minDistance);
|
|
157
|
-
totalDistance += minDistance * minDistance;
|
|
158
|
-
}
|
|
159
|
-
// Choose next center with probability proportional to squared distance
|
|
160
|
-
let randomValue = Math.random() * totalDistance;
|
|
161
|
-
for (let i = 0; i < embeddingArray.length; i++) {
|
|
162
|
-
const distanceValue = distances[i];
|
|
163
|
-
if (distanceValue !== undefined) {
|
|
164
|
-
randomValue -= distanceValue;
|
|
165
|
-
}
|
|
166
|
-
if (randomValue <= 0) {
|
|
167
|
-
const newCenter = embeddingArray[i];
|
|
168
|
-
if (newCenter) {
|
|
169
|
-
centers.push([...newCenter]);
|
|
170
|
-
}
|
|
171
|
-
break;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return centers;
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Update node embeddings using gradient descent
|
|
179
|
-
* @param graph - The input graph
|
|
180
|
-
* @param embeddings - Map of node IDs to embedding vectors
|
|
181
|
-
* @param _clusters - Map of node IDs to cluster assignments (reserved for future use)
|
|
182
|
-
* @param learningRate - Learning rate for gradient descent
|
|
183
|
-
* @param lambda - Regularization parameter
|
|
184
|
-
*/
|
|
185
|
-
function updateEmbeddings(graph, embeddings, _clusters, learningRate, lambda) {
|
|
186
|
-
const gradients = new Map();
|
|
187
|
-
// Initialize gradients
|
|
188
|
-
for (const [nodeId, embedding] of embeddings) {
|
|
189
|
-
gradients.set(nodeId, new Array(embedding.length).fill(0));
|
|
190
|
-
}
|
|
191
|
-
// Calculate gradients based on graph structure (simplified)
|
|
192
|
-
for (const node of graph.nodes()) {
|
|
193
|
-
const nodeId = node.id;
|
|
194
|
-
const nodeEmbedding = embeddings.get(nodeId);
|
|
195
|
-
if (!nodeEmbedding) {
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
const gradient = gradients.get(nodeId);
|
|
199
|
-
if (!gradient) {
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
// Neighbor reconstruction loss gradient
|
|
203
|
-
for (const neighborId of graph.neighbors(nodeId)) {
|
|
204
|
-
const neighborEmbedding = embeddings.get(neighborId);
|
|
205
|
-
if (!neighborEmbedding) {
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
const diff = nodeEmbedding.map((val, i) => val - (neighborEmbedding[i] ?? 0));
|
|
209
|
-
for (let i = 0; i < gradient.length; i++) {
|
|
210
|
-
const gradVal = gradient[i];
|
|
211
|
-
const diffVal = diff[i];
|
|
212
|
-
if (gradVal !== undefined && diffVal !== undefined) {
|
|
213
|
-
gradient[i] = gradVal + lambda * diffVal;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
// Regularization gradient
|
|
218
|
-
for (let i = 0; i < gradient.length; i++) {
|
|
219
|
-
const gradVal = gradient[i];
|
|
220
|
-
const nodeVal = nodeEmbedding[i];
|
|
221
|
-
if (gradVal !== undefined && nodeVal !== undefined) {
|
|
222
|
-
gradient[i] = gradVal + lambda * nodeVal;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
// Update embeddings
|
|
227
|
-
for (const [nodeId, embedding] of embeddings) {
|
|
228
|
-
const gradient = gradients.get(nodeId);
|
|
229
|
-
if (!gradient) {
|
|
230
|
-
continue;
|
|
231
|
-
}
|
|
232
|
-
for (let i = 0; i < embedding.length; i++) {
|
|
233
|
-
const embVal = embedding[i];
|
|
234
|
-
const gradVal = gradient[i];
|
|
235
|
-
if (embVal !== undefined && gradVal !== undefined) {
|
|
236
|
-
embedding[i] = embVal - learningRate * gradVal;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* Update cluster centers based on current assignments
|
|
243
|
-
* @param embeddings - Map of node IDs to embedding vectors
|
|
244
|
-
* @param clusters - Map of node IDs to cluster assignments
|
|
245
|
-
* @param clusterCenters - Array of cluster center vectors to update
|
|
246
|
-
* @param numClusters - Number of clusters
|
|
247
|
-
*/
|
|
248
|
-
function updateClusterCenters(embeddings, clusters, clusterCenters, numClusters) {
|
|
249
|
-
const dimensions = clusterCenters[0]?.length ?? 0;
|
|
250
|
-
const clusterSums = Array.from({ length: numClusters }, () => new Array(dimensions).fill(0));
|
|
251
|
-
const clusterCounts = new Array(numClusters).fill(0);
|
|
252
|
-
// Sum embeddings for each cluster
|
|
253
|
-
for (const [nodeId, clusterIdx] of clusters) {
|
|
254
|
-
const embedding = embeddings.get(nodeId);
|
|
255
|
-
if (!embedding) {
|
|
256
|
-
continue;
|
|
257
|
-
}
|
|
258
|
-
for (let i = 0; i < embedding.length; i++) {
|
|
259
|
-
const clusterSum = clusterSums[clusterIdx];
|
|
260
|
-
if (!clusterSum) {
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
const sumVal = clusterSum[i];
|
|
264
|
-
const embVal = embedding[i];
|
|
265
|
-
if (sumVal !== undefined && embVal !== undefined) {
|
|
266
|
-
clusterSum[i] = sumVal + embVal;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
if (clusterCounts[clusterIdx] !== undefined) {
|
|
270
|
-
clusterCounts[clusterIdx]++;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
// Update cluster centers (average of assigned embeddings)
|
|
274
|
-
for (let k = 0; k < numClusters; k++) {
|
|
275
|
-
const count = clusterCounts[k];
|
|
276
|
-
const center = clusterCenters[k];
|
|
277
|
-
const sum = clusterSums[k];
|
|
278
|
-
if (count !== undefined && count > 0 && center && sum) {
|
|
279
|
-
for (let i = 0; i < center.length; i++) {
|
|
280
|
-
const sumVal = sum[i];
|
|
281
|
-
if (sumVal !== undefined) {
|
|
282
|
-
center[i] = sumVal / count;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Calculate the total loss function
|
|
290
|
-
* @param graph - The input graph
|
|
291
|
-
* @param embeddings - Map of node IDs to embedding vectors
|
|
292
|
-
* @param clusters - Map of node IDs to cluster assignments
|
|
293
|
-
* @param clusterCenters - Array of cluster center vectors
|
|
294
|
-
* @param lambda - Regularization parameter
|
|
295
|
-
* @returns The total loss value
|
|
296
|
-
*/
|
|
297
|
-
function calculateLoss(graph, embeddings, clusters, clusterCenters, lambda) {
|
|
298
|
-
let clusteringLoss = 0;
|
|
299
|
-
let reconstructionLoss = 0;
|
|
300
|
-
let regularizationLoss = 0;
|
|
301
|
-
// Clustering loss (distance to cluster centers)
|
|
302
|
-
for (const [nodeId, clusterIdx] of clusters) {
|
|
303
|
-
const embedding = embeddings.get(nodeId);
|
|
304
|
-
if (!embedding) {
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
const center = clusterCenters[clusterIdx];
|
|
308
|
-
if (!center) {
|
|
309
|
-
continue;
|
|
310
|
-
}
|
|
311
|
-
clusteringLoss += euclideanDistance(embedding, center) ** 2;
|
|
312
|
-
}
|
|
313
|
-
// Graph reconstruction loss
|
|
314
|
-
for (const node of graph.nodes()) {
|
|
315
|
-
const nodeId = node.id;
|
|
316
|
-
const nodeEmbedding = embeddings.get(nodeId);
|
|
317
|
-
if (!nodeEmbedding) {
|
|
318
|
-
continue;
|
|
319
|
-
}
|
|
320
|
-
for (const neighborId of graph.neighbors(nodeId)) {
|
|
321
|
-
const neighborEmbedding = embeddings.get(neighborId);
|
|
322
|
-
if (!neighborEmbedding) {
|
|
323
|
-
continue;
|
|
324
|
-
}
|
|
325
|
-
const distance = euclideanDistance(nodeEmbedding, neighborEmbedding);
|
|
326
|
-
reconstructionLoss += distance ** 2;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
// Regularization loss
|
|
330
|
-
for (const embedding of embeddings.values()) {
|
|
331
|
-
for (const value of embedding) {
|
|
332
|
-
regularizationLoss += value ** 2;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
return clusteringLoss + lambda * reconstructionLoss + lambda * regularizationLoss;
|
|
336
|
-
}
|
|
337
49
|
//# sourceMappingURL=sync.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../src/research/sync.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../src/research/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,cAAc,IAAI,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,OAAO,EAAE,cAAc,IAAI,oBAAoB,EAAoC,MAAM,kBAAkB,CAAC;AAI5G;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,KAAY,EAAE,MAAkB;IAC3D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QACxC,OAAO,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,CAAC,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC;IACtB,MAAM,CAAC,GAAG,qBAAqB,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAE3C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACpG,CAAC;IACD,OAAO;QACH,QAAQ;QACR,yEAAyE;QACzE,IAAI,EAAE,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;QAC/D,gEAAgE;QAChE,UAAU,EAAE,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAChD,UAAU;QACV,SAAS,EAAE,CAAC,CAAC,SAAS;KACzB,CAAC;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphty/algorithms",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Graph algorithms library for browser environments implemented in TypeScript",
|
|
5
5
|
"author": "Adam Powers <apowers@ato.ms>",
|
|
6
6
|
"main": "dist/algorithms.js",
|
|
@@ -89,11 +89,12 @@
|
|
|
89
89
|
"typescript-eslint": "^8.34.1",
|
|
90
90
|
"vite": "^7.0.5",
|
|
91
91
|
"vitepress": "^1.6.3",
|
|
92
|
-
"vitest": "4.1.11"
|
|
92
|
+
"vitest": "4.1.11",
|
|
93
|
+
"@graphty/graph-samples": "^0.1.8"
|
|
93
94
|
},
|
|
94
95
|
"dependencies": {
|
|
95
96
|
"typedfastbitset": "^0.6.1",
|
|
96
|
-
"@graphty/graph-format": "^1.
|
|
97
|
+
"@graphty/graph-format": "^1.2.0"
|
|
97
98
|
},
|
|
98
99
|
"peerDependencies": {
|
|
99
100
|
"@graphty/graph-format": "^1.0.0"
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import {
|
|
3
|
+
betweennessCentrality as indexedBetweenness,
|
|
4
|
+
edgeBetweennessCentrality as indexedEdgeBetweenness,
|
|
5
|
+
} from "../../indexed/betweenness.js";
|
|
6
|
+
import { edgeScoresToPairMap, scoresToRecord } from "../../indexed/facade.js";
|
|
7
|
+
import { needsLegacyCode, toSnapshot } from "../../indexed/to-snapshot.js";
|
|
2
8
|
import type { NodeId } from "../../types/index.js";
|
|
3
9
|
import { bfsWithPathCounting } from "../traversal/bfs-variants.js";
|
|
4
10
|
|
|
@@ -44,7 +50,8 @@ function rejectIndexOptions(options: BetweennessCentralityOptions, fn: string):
|
|
|
44
50
|
if (options.sources !== undefined || options.k !== undefined) {
|
|
45
51
|
throw new Error(
|
|
46
52
|
`${fn}: 'sources' and 'k' are node INDICES and are meaningful only against a GraphSnapshot; ` +
|
|
47
|
-
"call
|
|
53
|
+
"for sampled betweenness call indexed.betweennessCentrality(snapshot, options), or " +
|
|
54
|
+
"accelerated(accelerator).betweennessCentrality(snapshot, options) to use an AlgorithmAccelerator",
|
|
48
55
|
);
|
|
49
56
|
}
|
|
50
57
|
}
|
|
@@ -226,6 +233,27 @@ function normalizeCentrality(centrality: Record<string, number>, nodeCount: numb
|
|
|
226
233
|
export function betweennessCentrality(
|
|
227
234
|
graph: Graph,
|
|
228
235
|
options: BetweennessCentralityOptions = {},
|
|
236
|
+
): Record<string, number> {
|
|
237
|
+
rejectIndexOptions(options, "betweennessCentrality");
|
|
238
|
+
if (needsLegacyCode(graph)) {
|
|
239
|
+
return legacyBetweennessCentrality(graph, options);
|
|
240
|
+
}
|
|
241
|
+
const s = toSnapshot(graph);
|
|
242
|
+
// `endpoints` is not passed on: the legacy accumulation accepts it and ignores it.
|
|
243
|
+
return scoresToRecord(s.ids, indexedBetweenness(s, { normalized: options.normalized }).scores);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* The implementation {@link betweennessCentrality} delegates away from, kept as its
|
|
248
|
+
* differential-test oracle. Deleted at the removal release.
|
|
249
|
+
* @param graph - The input graph to analyze
|
|
250
|
+
* @param options - Algorithm configuration options
|
|
251
|
+
* @returns Centrality scores for each node keyed by node ID
|
|
252
|
+
* @internal
|
|
253
|
+
*/
|
|
254
|
+
export function legacyBetweennessCentrality(
|
|
255
|
+
graph: Graph,
|
|
256
|
+
options: BetweennessCentralityOptions = {},
|
|
229
257
|
): Record<string, number> {
|
|
230
258
|
rejectIndexOptions(options, "betweennessCentrality");
|
|
231
259
|
const nodes = Array.from(graph.nodes()).map((node) => node.id);
|
|
@@ -291,6 +319,28 @@ export function nodeBetweennessCentrality(
|
|
|
291
319
|
export function edgeBetweennessCentrality(
|
|
292
320
|
graph: Graph,
|
|
293
321
|
options: BetweennessCentralityOptions = {},
|
|
322
|
+
): Map<string, number> {
|
|
323
|
+
rejectIndexOptions(options, "edgeBetweennessCentrality");
|
|
324
|
+
// On an undirected graph the legacy Map adds each reversed "v-u" key in the order its searches
|
|
325
|
+
// first cross the edge that way, an order the port's per-edge scores do not carry.
|
|
326
|
+
if (!graph.isDirected || needsLegacyCode(graph)) {
|
|
327
|
+
return legacyEdgeBetweennessCentrality(graph, options);
|
|
328
|
+
}
|
|
329
|
+
const s = toSnapshot(graph);
|
|
330
|
+
return edgeScoresToPairMap(s, indexedEdgeBetweenness(s, { normalized: options.normalized }).scores);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* The implementation {@link edgeBetweennessCentrality} delegates away from, kept as its
|
|
335
|
+
* differential-test oracle and for an undirected graph. Deleted at the removal release.
|
|
336
|
+
* @param graph - The input graph to analyze
|
|
337
|
+
* @param options - Algorithm configuration options
|
|
338
|
+
* @returns Edge centrality scores keyed by edge string representation
|
|
339
|
+
* @internal
|
|
340
|
+
*/
|
|
341
|
+
export function legacyEdgeBetweennessCentrality(
|
|
342
|
+
graph: Graph,
|
|
343
|
+
options: BetweennessCentralityOptions = {},
|
|
294
344
|
): Map<string, number> {
|
|
295
345
|
rejectIndexOptions(options, "edgeBetweennessCentrality");
|
|
296
346
|
const nodes = Array.from(graph.nodes()).map((node) => node.id);
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
+
import type { GraphSnapshot } from "@graphty/graph-format";
|
|
2
|
+
|
|
1
3
|
import type { Graph } from "../../core/graph.js";
|
|
4
|
+
import {
|
|
5
|
+
closenessCentrality as indexedCloseness,
|
|
6
|
+
type ClosenessOptions,
|
|
7
|
+
nodeClosenessCentrality as indexedNodeCloseness,
|
|
8
|
+
} from "../../indexed/closeness.js";
|
|
9
|
+
import { exactArcWeights, scoresToRecord } from "../../indexed/facade.js";
|
|
10
|
+
import { needsLegacyCode, toSnapshot } from "../../indexed/to-snapshot.js";
|
|
2
11
|
import type { NodeId } from "../../types/index.js";
|
|
3
12
|
import { bfsDistancesOnly, bfsWeightedDistances } from "../traversal/bfs-variants.js";
|
|
4
13
|
|
|
@@ -112,16 +121,56 @@ function calculateClosenessFromDistances(
|
|
|
112
121
|
* Space Complexity: O(V)
|
|
113
122
|
*/
|
|
114
123
|
export function closenessCentrality(graph: Graph, options: ClosenessCentralityOptions = {}): Record<string, number> {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
for (const sourceNode of nodes) {
|
|
119
|
-
centrality[String(sourceNode)] = nodeClosenessCentrality(graph, sourceNode, options);
|
|
124
|
+
if (needsLegacyCode(graph)) {
|
|
125
|
+
return perNodeRecord(graph, (id) => legacyNodeClosenessCentrality(graph, id, options));
|
|
120
126
|
}
|
|
127
|
+
const s = toSnapshot(graph);
|
|
128
|
+
return scoresToRecord(s.ids, indexedCloseness(s, portOptions(options)).scores);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The port's options for a legacy call; `optimized` picked a legacy search engine and has no
|
|
133
|
+
* counterpart.
|
|
134
|
+
* @param options - The legacy options
|
|
135
|
+
* @param s - Given only for a weighted call, which then reads this snapshot's exact f64 weights
|
|
136
|
+
* @returns The port's options
|
|
137
|
+
*/
|
|
138
|
+
function portOptions(options: ClosenessCentralityOptions, s?: GraphSnapshot): ClosenessOptions {
|
|
139
|
+
return {
|
|
140
|
+
normalized: options.normalized,
|
|
141
|
+
harmonic: options.harmonic,
|
|
142
|
+
cutoff: options.cutoff,
|
|
143
|
+
weighted: s !== undefined,
|
|
144
|
+
weights: s === undefined ? undefined : exactArcWeights(s),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
121
147
|
|
|
148
|
+
/**
|
|
149
|
+
* The legacy whole-graph loop: one per-node score per node, keyed by `String(id)` in node order.
|
|
150
|
+
* @param graph - The input graph
|
|
151
|
+
* @param score - The per-node score
|
|
152
|
+
* @returns The keyed scores
|
|
153
|
+
*/
|
|
154
|
+
function perNodeRecord(graph: Graph, score: (id: NodeId) => number): Record<string, number> {
|
|
155
|
+
const centrality: Record<string, number> = {};
|
|
156
|
+
for (const node of graph.nodes()) {
|
|
157
|
+
centrality[String(node.id)] = score(node.id);
|
|
158
|
+
}
|
|
122
159
|
return centrality;
|
|
123
160
|
}
|
|
124
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Whether a weighted search must stay on the legacy code: with a negative weight the distance a
|
|
164
|
+
* node keeps depends on the order equal keys leave the priority queue, which the port does not
|
|
165
|
+
* reproduce.
|
|
166
|
+
* @param s - The snapshot
|
|
167
|
+
* @returns True when some weight is negative
|
|
168
|
+
*/
|
|
169
|
+
function hasNegativeWeight(s: GraphSnapshot): boolean {
|
|
170
|
+
const weights = exactArcWeights(s) ?? s.weights;
|
|
171
|
+
return weights?.some((w) => w < 0) ?? false;
|
|
172
|
+
}
|
|
173
|
+
|
|
125
174
|
/**
|
|
126
175
|
* Calculate closeness centrality for a specific node
|
|
127
176
|
* @param graph - The input graph to analyze
|
|
@@ -133,6 +182,30 @@ export function nodeClosenessCentrality(graph: Graph, node: NodeId, options: Clo
|
|
|
133
182
|
if (!graph.hasNode(node)) {
|
|
134
183
|
throw new Error(`Node ${String(node)} not found in graph`);
|
|
135
184
|
}
|
|
185
|
+
if (needsLegacyCode(graph)) {
|
|
186
|
+
return legacyNodeClosenessCentrality(graph, node, options);
|
|
187
|
+
}
|
|
188
|
+
const s = toSnapshot(graph);
|
|
189
|
+
return indexedNodeCloseness(s, s.ids.indexOf(node), portOptions(options));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* The implementation {@link nodeClosenessCentrality} delegates away from, kept as its
|
|
194
|
+
* differential-test oracle. Deleted at the removal release.
|
|
195
|
+
* @param graph - The input graph to analyze
|
|
196
|
+
* @param node - The node to calculate centrality for
|
|
197
|
+
* @param options - Algorithm configuration options
|
|
198
|
+
* @returns The closeness centrality score for the node
|
|
199
|
+
* @internal
|
|
200
|
+
*/
|
|
201
|
+
export function legacyNodeClosenessCentrality(
|
|
202
|
+
graph: Graph,
|
|
203
|
+
node: NodeId,
|
|
204
|
+
options: ClosenessCentralityOptions = {},
|
|
205
|
+
): number {
|
|
206
|
+
if (!graph.hasNode(node)) {
|
|
207
|
+
throw new Error(`Node ${String(node)} not found in graph`);
|
|
208
|
+
}
|
|
136
209
|
|
|
137
210
|
// Use optimized BFS variant for unweighted graphs
|
|
138
211
|
const distances = bfsDistancesOnly(
|
|
@@ -156,14 +229,14 @@ export function weightedClosenessCentrality(
|
|
|
156
229
|
graph: Graph,
|
|
157
230
|
options: ClosenessCentralityOptions = {},
|
|
158
231
|
): Record<string, number> {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
for (const sourceNode of nodes) {
|
|
163
|
-
centrality[String(sourceNode)] = nodeWeightedClosenessCentrality(graph, sourceNode, options);
|
|
232
|
+
if (needsLegacyCode(graph)) {
|
|
233
|
+
return perNodeRecord(graph, (id) => legacyNodeWeightedClosenessCentrality(graph, id, options));
|
|
164
234
|
}
|
|
165
|
-
|
|
166
|
-
|
|
235
|
+
const s = toSnapshot(graph);
|
|
236
|
+
if (hasNegativeWeight(s)) {
|
|
237
|
+
return perNodeRecord(graph, (id) => legacyNodeWeightedClosenessCentrality(graph, id, options));
|
|
238
|
+
}
|
|
239
|
+
return scoresToRecord(s.ids, indexedCloseness(s, portOptions(options, s)).scores);
|
|
167
240
|
}
|
|
168
241
|
|
|
169
242
|
/**
|
|
@@ -181,6 +254,33 @@ export function nodeWeightedClosenessCentrality(
|
|
|
181
254
|
if (!graph.hasNode(node)) {
|
|
182
255
|
throw new Error(`Node ${String(node)} not found in graph`);
|
|
183
256
|
}
|
|
257
|
+
if (needsLegacyCode(graph)) {
|
|
258
|
+
return legacyNodeWeightedClosenessCentrality(graph, node, options);
|
|
259
|
+
}
|
|
260
|
+
const s = toSnapshot(graph);
|
|
261
|
+
if (hasNegativeWeight(s)) {
|
|
262
|
+
return legacyNodeWeightedClosenessCentrality(graph, node, options);
|
|
263
|
+
}
|
|
264
|
+
return indexedNodeCloseness(s, s.ids.indexOf(node), portOptions(options, s));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* The implementation {@link nodeWeightedClosenessCentrality} delegates away from, kept as its
|
|
269
|
+
* differential-test oracle and for a graph with a negative weight. Deleted at the removal release.
|
|
270
|
+
* @param graph - The input graph to analyze
|
|
271
|
+
* @param node - The node to calculate centrality for
|
|
272
|
+
* @param options - Algorithm configuration options
|
|
273
|
+
* @returns The weighted closeness centrality score for the node
|
|
274
|
+
* @internal
|
|
275
|
+
*/
|
|
276
|
+
export function legacyNodeWeightedClosenessCentrality(
|
|
277
|
+
graph: Graph,
|
|
278
|
+
node: NodeId,
|
|
279
|
+
options: ClosenessCentralityOptions = {},
|
|
280
|
+
): number {
|
|
281
|
+
if (!graph.hasNode(node)) {
|
|
282
|
+
throw new Error(`Node ${String(node)} not found in graph`);
|
|
283
|
+
}
|
|
184
284
|
|
|
185
285
|
// Use optimized weighted BFS variant (simplified Dijkstra)
|
|
186
286
|
const distances = bfsWeightedDistances(
|