@graphty/algorithms 2.1.2 → 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
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { renumberPartition } from "@graphty/graph-format";
|
|
2
|
+
import { withGroups } from "./components.js";
|
|
3
|
+
import { exactEdgeWeights, mulberry32 } from "./label-propagation.js";
|
|
4
|
+
import { modularity } from "./modularity.js";
|
|
5
|
+
/** The randomness of refinement: 0.01 as in the paper and leidenalg. */
|
|
6
|
+
const THETA = 0.01;
|
|
7
|
+
/**
|
|
8
|
+
* Passes in a row that may fail to improve modularity by more than the threshold before the run
|
|
9
|
+
* stops. A failed pass is discarded, but the next one draws fresh visit orders and can still find a
|
|
10
|
+
* move the last one missed: on the shared random fixtures, stopping at the first failure leaves the
|
|
11
|
+
* mean modularity over 40 seeds below the legacy function's, and three restores it.
|
|
12
|
+
*/
|
|
13
|
+
const PATIENCE = 3;
|
|
14
|
+
/**
|
|
15
|
+
* Per-arc weights and weighted degrees of a level.
|
|
16
|
+
* @param s - An undirected snapshot
|
|
17
|
+
* @param edgeW - Exact weight per logical edge
|
|
18
|
+
* @returns The level
|
|
19
|
+
*/
|
|
20
|
+
function levelOf(s, edgeW) {
|
|
21
|
+
const { nodeCount: n, rowPtr, colIdx, arcToEdge } = s;
|
|
22
|
+
const arcW = new Float64Array(s.arcCount);
|
|
23
|
+
const deg = new Float64Array(n);
|
|
24
|
+
for (let u = 0; u < n; u++) {
|
|
25
|
+
for (let a = rowPtr[u], end = rowPtr[u + 1]; a < end; a++) {
|
|
26
|
+
const w = edgeW[arcToEdge[a]];
|
|
27
|
+
arcW[a] = w;
|
|
28
|
+
// An undirected self-loop is one arc; it adds to the degree twice.
|
|
29
|
+
deg[u] += colIdx[a] === u ? 2 * w : w;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return { s, edgeW, arcW, deg };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Shuffle `0..n-1` with the generator.
|
|
36
|
+
* @param n - Length
|
|
37
|
+
* @param rand - Generator
|
|
38
|
+
* @returns The permutation
|
|
39
|
+
*/
|
|
40
|
+
function shuffled(n, rand) {
|
|
41
|
+
const order = new Uint32Array(n);
|
|
42
|
+
for (let i = 0; i < n; i++) {
|
|
43
|
+
order[i] = i;
|
|
44
|
+
}
|
|
45
|
+
for (let i = n - 1; i >= 1; i--) {
|
|
46
|
+
const j = Math.floor(rand() * (i + 1));
|
|
47
|
+
const t = order[i];
|
|
48
|
+
order[i] = order[j];
|
|
49
|
+
order[j] = t;
|
|
50
|
+
}
|
|
51
|
+
return order;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Leiden's fast local moving: nodes wait in a queue started as a seeded shuffle; a visited node
|
|
55
|
+
* moves to the neighbouring community (or an empty one) with the largest modularity gain, and when
|
|
56
|
+
* it moves, its neighbours outside its new community are queued again. Ends when the queue empties.
|
|
57
|
+
* @param level - The level
|
|
58
|
+
* @param comm - Community of every node, below the node count; moved in place
|
|
59
|
+
* @param rand - Generator
|
|
60
|
+
* @param resolution - Resolution gamma
|
|
61
|
+
* @param m2 - Twice the total edge weight
|
|
62
|
+
*/
|
|
63
|
+
function moveNodesFast(level, comm, rand, resolution, m2) {
|
|
64
|
+
const { s, arcW, deg } = level;
|
|
65
|
+
const { nodeCount: n, rowPtr, colIdx } = s;
|
|
66
|
+
const tot = new Float64Array(n);
|
|
67
|
+
const size = new Uint32Array(n);
|
|
68
|
+
for (let u = 0; u < n; u++) {
|
|
69
|
+
tot[comm[u]] += deg[u];
|
|
70
|
+
size[comm[u]]++;
|
|
71
|
+
}
|
|
72
|
+
const empty = [];
|
|
73
|
+
for (let c = n - 1; c >= 0; c--) {
|
|
74
|
+
if (size[c] === 0) {
|
|
75
|
+
empty.push(c);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const acc = new Float64Array(n);
|
|
79
|
+
const stamp = new Int32Array(n).fill(-1);
|
|
80
|
+
const touched = new Uint32Array(n);
|
|
81
|
+
const capacity = n + 1;
|
|
82
|
+
const queue = new Uint32Array(capacity);
|
|
83
|
+
queue.set(shuffled(n, rand));
|
|
84
|
+
const queued = new Uint8Array(n).fill(1);
|
|
85
|
+
let head = 0;
|
|
86
|
+
let tail = n;
|
|
87
|
+
let visit = 0;
|
|
88
|
+
while (head !== tail) {
|
|
89
|
+
const u = queue[head];
|
|
90
|
+
head = head + 1 === capacity ? 0 : head + 1;
|
|
91
|
+
queued[u] = 0;
|
|
92
|
+
visit++;
|
|
93
|
+
const cu = comm[u];
|
|
94
|
+
const ku = deg[u];
|
|
95
|
+
tot[cu] -= ku;
|
|
96
|
+
size[cu]--;
|
|
97
|
+
let cnt = 0;
|
|
98
|
+
for (let a = rowPtr[u], end = rowPtr[u + 1]; a < end; a++) {
|
|
99
|
+
const v = colIdx[a];
|
|
100
|
+
if (v === u) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const c = comm[v];
|
|
104
|
+
if (stamp[c] !== visit) {
|
|
105
|
+
stamp[c] = visit;
|
|
106
|
+
acc[c] = 0;
|
|
107
|
+
touched[cnt++] = c;
|
|
108
|
+
}
|
|
109
|
+
acc[c] += arcW[a];
|
|
110
|
+
}
|
|
111
|
+
let best = cu;
|
|
112
|
+
let bestGain = (stamp[cu] === visit ? acc[cu] : 0) - (resolution * ku * tot[cu]) / m2;
|
|
113
|
+
for (let i = 0; i < cnt; i++) {
|
|
114
|
+
const c = touched[i];
|
|
115
|
+
const gain = acc[c] - (resolution * ku * tot[c]) / m2;
|
|
116
|
+
if (c !== cu && gain > bestGain) {
|
|
117
|
+
bestGain = gain;
|
|
118
|
+
best = c;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// An empty community gains 0; when u's own is empty now, staying already is that choice.
|
|
122
|
+
if (size[cu] > 0 && bestGain < 0) {
|
|
123
|
+
best = empty[empty.length - 1];
|
|
124
|
+
}
|
|
125
|
+
if (best !== cu && size[best] === 0) {
|
|
126
|
+
empty.pop();
|
|
127
|
+
}
|
|
128
|
+
tot[best] += ku;
|
|
129
|
+
size[best]++;
|
|
130
|
+
if (best === cu) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
comm[u] = best;
|
|
134
|
+
if (size[cu] === 0) {
|
|
135
|
+
empty.push(cu);
|
|
136
|
+
}
|
|
137
|
+
for (let a = rowPtr[u], end = rowPtr[u + 1]; a < end; a++) {
|
|
138
|
+
const v = colIdx[a];
|
|
139
|
+
if (queued[v] === 0 && comm[v] !== best) {
|
|
140
|
+
queued[v] = 1;
|
|
141
|
+
queue[tail] = v;
|
|
142
|
+
tail = tail + 1 === capacity ? 0 : tail + 1;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Leiden's refinement: inside every community, nodes start alone and, visited in a seeded order,
|
|
149
|
+
* a node still alone and well connected to its community merges into the well-connected
|
|
150
|
+
* sub-community of that community, drawn at random weighted by its modularity gain. Every
|
|
151
|
+
* sub-community is connected, which is the guarantee Leiden adds over Louvain.
|
|
152
|
+
*
|
|
153
|
+
* The target is drawn at random among the candidates with a non-negative gain, with probability
|
|
154
|
+
* proportional to exp(gain / theta) where the gain is in modularity units, as the paper does
|
|
155
|
+
* (theta 0.01, leidenalg's default).
|
|
156
|
+
* @param level - The level
|
|
157
|
+
* @param comm - Community of every node
|
|
158
|
+
* @param rand - Generator
|
|
159
|
+
* @param resolution - Resolution gamma
|
|
160
|
+
* @param m2 - Twice the total edge weight
|
|
161
|
+
* @returns The sub-community of every node, labelled by a member's index (not dense)
|
|
162
|
+
*/
|
|
163
|
+
function refine(level, comm, rand, resolution, m2) {
|
|
164
|
+
const { s, arcW, deg } = level;
|
|
165
|
+
const { nodeCount: n, rowPtr, colIdx } = s;
|
|
166
|
+
const commTot = new Float64Array(n);
|
|
167
|
+
for (let u = 0; u < n; u++) {
|
|
168
|
+
commTot[comm[u]] += deg[u];
|
|
169
|
+
}
|
|
170
|
+
const ref = new Uint32Array(n);
|
|
171
|
+
const refTot = new Float64Array(n);
|
|
172
|
+
const refSize = new Uint32Array(n);
|
|
173
|
+
// Weight from each sub-community to the rest of its community.
|
|
174
|
+
const ext = new Float64Array(n);
|
|
175
|
+
for (let u = 0; u < n; u++) {
|
|
176
|
+
ref[u] = u;
|
|
177
|
+
refTot[u] = deg[u];
|
|
178
|
+
refSize[u] = 1;
|
|
179
|
+
for (let a = rowPtr[u], end = rowPtr[u + 1]; a < end; a++) {
|
|
180
|
+
const v = colIdx[a];
|
|
181
|
+
if (v !== u && comm[v] === comm[u]) {
|
|
182
|
+
ext[u] += arcW[a];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const acc = new Float64Array(n);
|
|
187
|
+
const stamp = new Int32Array(n).fill(-1);
|
|
188
|
+
const touched = new Uint32Array(n);
|
|
189
|
+
const order = shuffled(n, rand);
|
|
190
|
+
for (let i = 0; i < n; i++) {
|
|
191
|
+
const v = order[i];
|
|
192
|
+
const c = comm[v];
|
|
193
|
+
const kv = deg[v];
|
|
194
|
+
if (refSize[v] !== 1 || ext[v] < (resolution * kv * (commTot[c] - kv)) / m2) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
let cnt = 0;
|
|
198
|
+
for (let a = rowPtr[v], end = rowPtr[v + 1]; a < end; a++) {
|
|
199
|
+
const x = colIdx[a];
|
|
200
|
+
if (x === v || comm[x] !== c) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const r = ref[x];
|
|
204
|
+
if (stamp[r] !== v) {
|
|
205
|
+
stamp[r] = v;
|
|
206
|
+
acc[r] = 0;
|
|
207
|
+
touched[cnt++] = r;
|
|
208
|
+
}
|
|
209
|
+
acc[r] += arcW[a];
|
|
210
|
+
}
|
|
211
|
+
// Candidates: well-connected sub-communities with a non-negative gain, drawn with probability
|
|
212
|
+
// exp(gain in modularity units / theta), shifted by the best gain so exp never overflows.
|
|
213
|
+
const gainOf = (r) => acc[r] - (resolution * kv * refTot[r]) / m2;
|
|
214
|
+
let maxGain = -Infinity;
|
|
215
|
+
let kept = 0;
|
|
216
|
+
for (let j = 0; j < cnt; j++) {
|
|
217
|
+
const r = touched[j];
|
|
218
|
+
const gain = gainOf(r);
|
|
219
|
+
if (gain >= 0 && ext[r] >= (resolution * refTot[r] * (commTot[c] - refTot[r])) / m2) {
|
|
220
|
+
touched[kept++] = r;
|
|
221
|
+
maxGain = Math.max(maxGain, gain);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (kept === 0) {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
const weight = (r) => Math.exp(((gainOf(r) - maxGain) * 2) / m2 / THETA);
|
|
228
|
+
let total = 0;
|
|
229
|
+
for (let j = 0; j < kept; j++) {
|
|
230
|
+
total += weight(touched[j]);
|
|
231
|
+
}
|
|
232
|
+
let draw = rand() * total;
|
|
233
|
+
let best = touched[kept - 1];
|
|
234
|
+
for (let j = 0; j < kept - 1; j++) {
|
|
235
|
+
draw -= weight(touched[j]);
|
|
236
|
+
if (draw < 0) {
|
|
237
|
+
best = touched[j];
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
ref[v] = best;
|
|
242
|
+
refSize[v] = 0;
|
|
243
|
+
refSize[best]++;
|
|
244
|
+
refTot[best] += kv;
|
|
245
|
+
// The edges between v and its new sub-community are now inside it.
|
|
246
|
+
ext[best] += ext[v] - 2 * acc[best];
|
|
247
|
+
}
|
|
248
|
+
return ref;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* One pass of Leiden from a starting partition of the original graph: local moving, refinement,
|
|
252
|
+
* aggregation by the refined partition with each aggregate node starting in its community, repeated
|
|
253
|
+
* until local moving leaves every community a single node of its level.
|
|
254
|
+
* @param base - Level 0, the original graph
|
|
255
|
+
* @param start - Dense community of every original node
|
|
256
|
+
* @param rand - Generator
|
|
257
|
+
* @param resolution - Resolution gamma
|
|
258
|
+
* @param m2 - Twice the total edge weight
|
|
259
|
+
* @returns The partition of the original nodes (not dense) and the levels processed
|
|
260
|
+
*/
|
|
261
|
+
function pass(base, start, rand, resolution, m2) {
|
|
262
|
+
const n0 = base.s.nodeCount;
|
|
263
|
+
// Which node of the current level holds each original node.
|
|
264
|
+
const top = new Uint32Array(n0);
|
|
265
|
+
for (let u = 0; u < n0; u++) {
|
|
266
|
+
top[u] = u;
|
|
267
|
+
}
|
|
268
|
+
let level = base;
|
|
269
|
+
let comm = start.slice();
|
|
270
|
+
let levels = 0;
|
|
271
|
+
for (;;) {
|
|
272
|
+
moveNodesFast(level, comm, rand, resolution, m2);
|
|
273
|
+
levels++;
|
|
274
|
+
const dense = renumberPartition(comm);
|
|
275
|
+
if (dense.count === level.s.nodeCount) {
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
let blocks = refine(level, dense.labels, rand, resolution, m2);
|
|
279
|
+
if (renumberPartition(blocks).count === level.s.nodeCount) {
|
|
280
|
+
// No sub-community merged: aggregate by the communities themselves, as Louvain does, so
|
|
281
|
+
// the next level is smaller.
|
|
282
|
+
blocks = dense.labels;
|
|
283
|
+
}
|
|
284
|
+
const d = level.s.contract(blocks);
|
|
285
|
+
const { nodeRemap, edgeRemap } = d;
|
|
286
|
+
const next = d.snapshot;
|
|
287
|
+
const edgeW = new Float64Array(next.edgeCount);
|
|
288
|
+
for (let e = 0; e < level.edgeW.length; e++) {
|
|
289
|
+
edgeW[edgeRemap === null ? e : edgeRemap[e]] += level.edgeW[e];
|
|
290
|
+
}
|
|
291
|
+
const nextComm = new Uint32Array(next.nodeCount);
|
|
292
|
+
for (let u = 0; u < level.s.nodeCount; u++) {
|
|
293
|
+
nextComm[nodeRemap === null ? u : nodeRemap[u]] = dense.labels[u];
|
|
294
|
+
}
|
|
295
|
+
if (nodeRemap !== null) {
|
|
296
|
+
for (let u = 0; u < n0; u++) {
|
|
297
|
+
top[u] = nodeRemap[top[u]];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
comm = renumberPartition(nextComm).labels;
|
|
301
|
+
level = levelOf(next, edgeW);
|
|
302
|
+
}
|
|
303
|
+
const out = new Uint32Array(n0);
|
|
304
|
+
for (let u = 0; u < n0; u++) {
|
|
305
|
+
out[u] = comm[top[u]];
|
|
306
|
+
}
|
|
307
|
+
return { comm: out, levels };
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Leiden community detection (Traag, Waltman and van Eck, Sci. Rep. 9:5233, 2019) over an
|
|
311
|
+
* undirected snapshot: fast local moving, refinement into well-connected sub-communities, and
|
|
312
|
+
* aggregation by `contract()` once per level. Whole passes repeat from the previous answer, keeping
|
|
313
|
+
* a pass only when it raises modularity, until three passes in a row improve it by no more than
|
|
314
|
+
* `threshold` or `maxIterations` passes have run; every pass starts by moving single original
|
|
315
|
+
* nodes, so the answer is also a local optimum of those moves.
|
|
316
|
+
*
|
|
317
|
+
* Modularity follows graph-format's `weightedDegree()` convention (a self-loop counts twice), which
|
|
318
|
+
* on a graph without self-loops equals the legacy `leiden`'s. Weights are the exact f64 ones when
|
|
319
|
+
* the snapshot keeps them. The partition is not the legacy function's move for move: the legacy
|
|
320
|
+
* `leiden` splits disconnected communities rather than refining them, and visits nodes in another
|
|
321
|
+
* order; what this guarantees is connected communities. Both are randomised heuristics, so for one
|
|
322
|
+
* seed either can come out ahead; on the shared fixtures this one's modularity is at least the
|
|
323
|
+
* legacy's at the default seed and on average over seeds.
|
|
324
|
+
* @param s - An undirected snapshot
|
|
325
|
+
* @param options - Resolution, seed, pass cap and stopping threshold
|
|
326
|
+
* @returns The partition, its modularity, and the levels processed
|
|
327
|
+
* @throws Error on a directed snapshot; RangeError for a negative, NaN or infinite weight or a
|
|
328
|
+
* fractional seed
|
|
329
|
+
* @public
|
|
330
|
+
*/
|
|
331
|
+
export function leiden(s, options = {}) {
|
|
332
|
+
if (s.directed) {
|
|
333
|
+
throw new Error("Leiden requires an undirected graph. Pass s.toUndirected().snapshot.");
|
|
334
|
+
}
|
|
335
|
+
const resolution = options.resolution ?? 1;
|
|
336
|
+
const randomSeed = options.randomSeed ?? 42;
|
|
337
|
+
const maxIterations = options.maxIterations ?? 100;
|
|
338
|
+
const threshold = options.threshold ?? 1e-7;
|
|
339
|
+
if (!Number.isInteger(randomSeed)) {
|
|
340
|
+
throw new RangeError(`randomSeed must be a finite integer, got ${randomSeed}`);
|
|
341
|
+
}
|
|
342
|
+
const n = s.nodeCount;
|
|
343
|
+
const given = exactEdgeWeights(s) ?? s.edgeList().weights;
|
|
344
|
+
const edgeW = given === null ? new Float64Array(s.edgeCount).fill(1) : Float64Array.from(given);
|
|
345
|
+
for (let e = 0; e < edgeW.length; e++) {
|
|
346
|
+
const w = edgeW[e];
|
|
347
|
+
if (!(w >= 0) || w === Infinity) {
|
|
348
|
+
throw new RangeError(`edge ${e} has weight ${w}; Leiden needs finite, non-negative weights`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
const base = levelOf(s, edgeW);
|
|
352
|
+
let m2 = 0;
|
|
353
|
+
for (let u = 0; u < n; u++) {
|
|
354
|
+
m2 += base.deg[u];
|
|
355
|
+
}
|
|
356
|
+
let labels = new Uint32Array(n);
|
|
357
|
+
for (let u = 0; u < n; u++) {
|
|
358
|
+
labels[u] = u;
|
|
359
|
+
}
|
|
360
|
+
if (m2 === 0) {
|
|
361
|
+
return { ...withGroups(labels, n), modularity: 0, iterations: 0 };
|
|
362
|
+
}
|
|
363
|
+
const quality = (partition) => modularity(s, partition, { resolution, weights: base.arcW });
|
|
364
|
+
const rand = mulberry32(randomSeed);
|
|
365
|
+
let q = quality(labels);
|
|
366
|
+
let iterations = 0;
|
|
367
|
+
let idle = 0;
|
|
368
|
+
for (let i = 0; i < maxIterations && idle < PATIENCE; i++) {
|
|
369
|
+
const { comm, levels } = pass(base, labels, rand, resolution, m2);
|
|
370
|
+
iterations += levels;
|
|
371
|
+
const candidate = renumberPartition(comm).labels;
|
|
372
|
+
const qNext = quality(candidate);
|
|
373
|
+
if (qNext > q) {
|
|
374
|
+
idle = qNext - q <= threshold ? idle + 1 : 0;
|
|
375
|
+
labels = candidate;
|
|
376
|
+
q = qNext;
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
idle++;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return { ...withGroups(labels, renumberPartition(labels).count), modularity: q, iterations };
|
|
383
|
+
}
|
|
384
|
+
//# sourceMappingURL=leiden.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leiden.js","sourceRoot":"","sources":["../../../src/indexed/leiden.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Link prediction over a snapshot: common-neighbour and Adamic-Adar scores for one pair, a list of
|
|
3
|
+
* pairs, every pair, or one node's candidates, and the ranking metrics of a held-out evaluation.
|
|
4
|
+
*
|
|
5
|
+
* Every score is a merge of two sorted rows with simple-graph semantics: a neighbour reached by
|
|
6
|
+
* parallel arcs counts once, and a self-loop makes a node its own neighbour. With
|
|
7
|
+
* `{ directed: true }` a pair (u, v) intersects out(u) with in(v) -- the nodes on a path u -> z -> v
|
|
8
|
+
* -- and otherwise the two out rows (the two rows of an undirected snapshot).
|
|
9
|
+
*
|
|
10
|
+
* A node index at or beyond `nodeCount`, `INVALID_INDEX` included, is an absent node: its pairs
|
|
11
|
+
* score 0 and it has no candidates.
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import type { F64, GraphSnapshot, U32 } from "@graphty/graph-format";
|
|
15
|
+
import { type CommonNeighborsOptions } from "./common-neighbors.js";
|
|
16
|
+
/** Options of the link prediction functions. @public */
|
|
17
|
+
export interface LinkPredictionOptions extends CommonNeighborsOptions {
|
|
18
|
+
/** Also score pairs already joined by an arc u -> v. Default false. */
|
|
19
|
+
readonly includeExisting?: boolean | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Keep only the first `topK` ranked pairs. For the whole-graph predictions a value that is not
|
|
22
|
+
* positive keeps them all; for a node's candidates the default is 10 and the value is a slice
|
|
23
|
+
* end, so 0 keeps none and -2 drops the last two.
|
|
24
|
+
*/
|
|
25
|
+
readonly topK?: number | undefined;
|
|
26
|
+
}
|
|
27
|
+
/** Options of the per-node candidate functions. @public */
|
|
28
|
+
export interface CandidateOptions extends LinkPredictionOptions {
|
|
29
|
+
/** The node indices to consider, in this order; default every node in index order. */
|
|
30
|
+
readonly candidates?: ArrayLike<number> | undefined;
|
|
31
|
+
}
|
|
32
|
+
/** Node pairs as two parallel index lists: pair k is (sources[k], targets[k]). @public */
|
|
33
|
+
export interface NodePairs {
|
|
34
|
+
readonly sources: ArrayLike<number>;
|
|
35
|
+
readonly targets: ArrayLike<number>;
|
|
36
|
+
}
|
|
37
|
+
/** Ranked pairs, highest score first, ties in enumeration order. @public */
|
|
38
|
+
export interface LinkPredictionResult extends NodePairs {
|
|
39
|
+
readonly sources: U32;
|
|
40
|
+
readonly targets: U32;
|
|
41
|
+
readonly scores: F64;
|
|
42
|
+
}
|
|
43
|
+
/** The best-F1 threshold's precision and recall, that F1, and the ranking AUC. @public */
|
|
44
|
+
export interface LinkPredictionMetrics {
|
|
45
|
+
readonly precision: number;
|
|
46
|
+
readonly recall: number;
|
|
47
|
+
readonly f1Score: number;
|
|
48
|
+
readonly auc: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Common-neighbour scores of every pair not already joined, ranked.
|
|
52
|
+
* @param s - The snapshot
|
|
53
|
+
* @param o - Options
|
|
54
|
+
* @returns The pairs with a positive score, highest first
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
57
|
+
export declare function commonNeighborsPrediction(s: GraphSnapshot, o?: LinkPredictionOptions): LinkPredictionResult;
|
|
58
|
+
/**
|
|
59
|
+
* Common-neighbour scores of the given pairs, in order.
|
|
60
|
+
* @param s - The snapshot
|
|
61
|
+
* @param pairs - The pairs
|
|
62
|
+
* @param o - Options
|
|
63
|
+
* @returns One score per pair
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
export declare function commonNeighborsForPairs(s: GraphSnapshot, pairs: NodePairs, o?: CommonNeighborsOptions): F64;
|
|
67
|
+
/**
|
|
68
|
+
* One node's best common-neighbour candidates, ranked.
|
|
69
|
+
* @param s - The snapshot
|
|
70
|
+
* @param u - The node index
|
|
71
|
+
* @param o - Options
|
|
72
|
+
* @returns (u, v) pairs with a positive score, highest first
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
export declare function getTopCandidatesForNode(s: GraphSnapshot, u: number, o?: CandidateOptions): LinkPredictionResult;
|
|
76
|
+
/**
|
|
77
|
+
* Ranking metrics of the common-neighbour score on held-out edges against non-edges.
|
|
78
|
+
* @param s - The training snapshot
|
|
79
|
+
* @param edges - The held-out edges
|
|
80
|
+
* @param nonEdges - The non-edges
|
|
81
|
+
* @param o - Options
|
|
82
|
+
* @returns The metrics
|
|
83
|
+
* @public
|
|
84
|
+
*/
|
|
85
|
+
export declare function evaluateCommonNeighbors(s: GraphSnapshot, edges: NodePairs, nonEdges: NodePairs, o?: CommonNeighborsOptions): LinkPredictionMetrics;
|
|
86
|
+
/**
|
|
87
|
+
* The Adamic-Adar index of two nodes: the sum over distinct common neighbours z of 1 / ln(degree(z)).
|
|
88
|
+
* @param s - The snapshot
|
|
89
|
+
* @param u - A node index
|
|
90
|
+
* @param v - A node index
|
|
91
|
+
* @param o - Options
|
|
92
|
+
* @returns The score
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
export declare function adamicAdarScore(s: GraphSnapshot, u: number, v: number, o?: CommonNeighborsOptions): number;
|
|
96
|
+
/**
|
|
97
|
+
* Adamic-Adar scores of every pair not already joined, ranked.
|
|
98
|
+
* @param s - The snapshot
|
|
99
|
+
* @param o - Options
|
|
100
|
+
* @returns The pairs with a positive score, highest first
|
|
101
|
+
* @public
|
|
102
|
+
*/
|
|
103
|
+
export declare function adamicAdarPrediction(s: GraphSnapshot, o?: LinkPredictionOptions): LinkPredictionResult;
|
|
104
|
+
/**
|
|
105
|
+
* Adamic-Adar scores of the given pairs, in order.
|
|
106
|
+
* @param s - The snapshot
|
|
107
|
+
* @param pairs - The pairs
|
|
108
|
+
* @param o - Options
|
|
109
|
+
* @returns One score per pair
|
|
110
|
+
* @public
|
|
111
|
+
*/
|
|
112
|
+
export declare function adamicAdarForPairs(s: GraphSnapshot, pairs: NodePairs, o?: CommonNeighborsOptions): F64;
|
|
113
|
+
/**
|
|
114
|
+
* One node's best Adamic-Adar candidates, ranked.
|
|
115
|
+
* @param s - The snapshot
|
|
116
|
+
* @param u - The node index
|
|
117
|
+
* @param o - Options
|
|
118
|
+
* @returns (u, v) pairs with a positive score, highest first
|
|
119
|
+
* @public
|
|
120
|
+
*/
|
|
121
|
+
export declare function getTopAdamicAdarCandidatesForNode(s: GraphSnapshot, u: number, o?: CandidateOptions): LinkPredictionResult;
|
|
122
|
+
/**
|
|
123
|
+
* Ranking metrics of the Adamic-Adar score on held-out edges against non-edges.
|
|
124
|
+
* @param s - The training snapshot
|
|
125
|
+
* @param edges - The held-out edges
|
|
126
|
+
* @param nonEdges - The non-edges
|
|
127
|
+
* @param o - Options
|
|
128
|
+
* @returns The metrics
|
|
129
|
+
* @public
|
|
130
|
+
*/
|
|
131
|
+
export declare function evaluateAdamicAdar(s: GraphSnapshot, edges: NodePairs, nonEdges: NodePairs, o?: CommonNeighborsOptions): LinkPredictionMetrics;
|
|
132
|
+
/**
|
|
133
|
+
* Both evaluations on the same held-out sets. The common-neighbour side always intersects the two
|
|
134
|
+
* OUT rows, whatever `directed` says, as the legacy function of this name does; the Adamic-Adar side
|
|
135
|
+
* honours `directed`.
|
|
136
|
+
* @param s - The training snapshot
|
|
137
|
+
* @param edges - The held-out edges
|
|
138
|
+
* @param nonEdges - The non-edges
|
|
139
|
+
* @param o - Options
|
|
140
|
+
* @returns The two sets of metrics
|
|
141
|
+
* @public
|
|
142
|
+
*/
|
|
143
|
+
export declare function compareAdamicAdarWithCommonNeighbors(s: GraphSnapshot, edges: NodePairs, nonEdges: NodePairs, o?: CommonNeighborsOptions): {
|
|
144
|
+
adamicAdar: LinkPredictionMetrics;
|
|
145
|
+
commonNeighbors: LinkPredictionMetrics;
|
|
146
|
+
};
|
|
147
|
+
//# sourceMappingURL=link-prediction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link-prediction.d.ts","sourceRoot":"","sources":["../../../src/indexed/link-prediction.ts"],"names":[],"mappings":"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"}
|