@graphty/algorithms 1.3.1 → 1.4.2
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 +358 -413
- package/dist/algorithms.js +564 -261
- package/dist/algorithms.js.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.d.ts +10 -0
- package/dist/src/algorithms/centrality/betweenness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/betweenness.js +27 -6
- package/dist/src/algorithms/centrality/betweenness.js.map +1 -1
- package/dist/src/algorithms/centrality/closeness.d.ts +11 -2
- package/dist/src/algorithms/centrality/closeness.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/closeness.js +17 -3
- package/dist/src/algorithms/centrality/closeness.js.map +1 -1
- package/dist/src/algorithms/centrality/degree.d.ts +7 -0
- package/dist/src/algorithms/centrality/degree.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/degree.js +9 -6
- package/dist/src/algorithms/centrality/degree.js.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts +21 -3
- package/dist/src/algorithms/centrality/delta-pagerank-simple.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js +25 -7
- package/dist/src/algorithms/centrality/delta-pagerank-simple.js.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts +28 -2
- package/dist/src/algorithms/centrality/delta-pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/delta-pagerank.js +30 -4
- package/dist/src/algorithms/centrality/delta-pagerank.js.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.d.ts +10 -3
- package/dist/src/algorithms/centrality/eigenvector.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/eigenvector.js +11 -4
- package/dist/src/algorithms/centrality/eigenvector.js.map +1 -1
- package/dist/src/algorithms/centrality/hits.d.ts +10 -3
- package/dist/src/algorithms/centrality/hits.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/hits.js +11 -4
- package/dist/src/algorithms/centrality/hits.js.map +1 -1
- package/dist/src/algorithms/centrality/index.d.ts +1 -1
- package/dist/src/algorithms/centrality/index.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/index.js +1 -1
- package/dist/src/algorithms/centrality/index.js.map +1 -1
- package/dist/src/algorithms/centrality/katz.d.ts +10 -3
- package/dist/src/algorithms/centrality/katz.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/katz.js +13 -8
- package/dist/src/algorithms/centrality/katz.js.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.d.ts +14 -0
- package/dist/src/algorithms/centrality/pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/centrality/pagerank.js +16 -1
- package/dist/src/algorithms/centrality/pagerank.js.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.d.ts +2 -3
- package/dist/src/algorithms/community/girvan-newman.d.ts.map +1 -1
- package/dist/src/algorithms/community/girvan-newman.js +21 -4
- package/dist/src/algorithms/community/girvan-newman.js.map +1 -1
- package/dist/src/algorithms/community/index.d.ts.map +1 -1
- package/dist/src/algorithms/community/index.js.map +1 -1
- package/dist/src/algorithms/community/label-propagation.d.ts +0 -3
- package/dist/src/algorithms/community/label-propagation.d.ts.map +1 -1
- package/dist/src/algorithms/community/label-propagation.js +13 -6
- package/dist/src/algorithms/community/label-propagation.js.map +1 -1
- package/dist/src/algorithms/community/leiden.d.ts +0 -1
- package/dist/src/algorithms/community/leiden.d.ts.map +1 -1
- package/dist/src/algorithms/community/leiden.js +37 -6
- package/dist/src/algorithms/community/leiden.js.map +1 -1
- package/dist/src/algorithms/community/louvain-optimized.d.ts +37 -0
- package/dist/src/algorithms/community/louvain-optimized.d.ts.map +1 -1
- package/dist/src/algorithms/community/louvain-optimized.js +42 -7
- package/dist/src/algorithms/community/louvain-optimized.js.map +1 -1
- package/dist/src/algorithms/community/louvain.d.ts +2 -3
- package/dist/src/algorithms/community/louvain.d.ts.map +1 -1
- package/dist/src/algorithms/community/louvain.js +19 -6
- package/dist/src/algorithms/community/louvain.js.map +1 -1
- package/dist/src/algorithms/community/modularity-utils.d.ts +0 -4
- package/dist/src/algorithms/community/modularity-utils.d.ts.map +1 -1
- package/dist/src/algorithms/community/modularity-utils.js +1 -5
- package/dist/src/algorithms/community/modularity-utils.js.map +1 -1
- package/dist/src/algorithms/components/connected.d.ts +23 -0
- package/dist/src/algorithms/components/connected.d.ts.map +1 -1
- package/dist/src/algorithms/components/connected.js +29 -3
- package/dist/src/algorithms/components/connected.js.map +1 -1
- package/dist/src/algorithms/matching/bipartite.d.ts +10 -0
- package/dist/src/algorithms/matching/bipartite.d.ts.map +1 -1
- package/dist/src/algorithms/matching/bipartite.js +10 -0
- package/dist/src/algorithms/matching/bipartite.js.map +1 -1
- package/dist/src/algorithms/matching/index.d.ts.map +1 -1
- package/dist/src/algorithms/matching/index.js.map +1 -1
- package/dist/src/algorithms/matching/isomorphism.d.ts +8 -0
- package/dist/src/algorithms/matching/isomorphism.d.ts.map +1 -1
- package/dist/src/algorithms/matching/isomorphism.js +36 -2
- package/dist/src/algorithms/matching/isomorphism.js.map +1 -1
- package/dist/src/algorithms/mst/index.d.ts.map +1 -1
- package/dist/src/algorithms/mst/index.js.map +1 -1
- package/dist/src/algorithms/mst/kruskal.d.ts +14 -0
- package/dist/src/algorithms/mst/kruskal.d.ts.map +1 -1
- package/dist/src/algorithms/mst/kruskal.js +17 -3
- package/dist/src/algorithms/mst/kruskal.js.map +1 -1
- package/dist/src/algorithms/mst/prim.d.ts +9 -0
- package/dist/src/algorithms/mst/prim.d.ts.map +1 -1
- package/dist/src/algorithms/mst/prim.js +9 -0
- package/dist/src/algorithms/mst/prim.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.d.ts +10 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/bellman-ford.js +10 -0
- package/dist/src/algorithms/shortest-path/bellman-ford.js.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts +11 -4
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js +18 -16
- package/dist/src/algorithms/shortest-path/bidirectional-dijkstra.js.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts +15 -0
- package/dist/src/algorithms/shortest-path/dijkstra.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/dijkstra.js +15 -0
- package/dist/src/algorithms/shortest-path/dijkstra.js.map +1 -1
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts +17 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/floyd-warshall.js +17 -0
- package/dist/src/algorithms/shortest-path/floyd-warshall.js.map +1 -1
- package/dist/src/algorithms/shortest-path/index.d.ts.map +1 -1
- package/dist/src/algorithms/shortest-path/index.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs-unified.d.ts +13 -0
- package/dist/src/algorithms/traversal/bfs-unified.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs-unified.js +37 -0
- package/dist/src/algorithms/traversal/bfs-unified.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs-variants.d.ts +23 -0
- package/dist/src/algorithms/traversal/bfs-variants.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs-variants.js +34 -0
- package/dist/src/algorithms/traversal/bfs-variants.js.map +1 -1
- package/dist/src/algorithms/traversal/bfs.d.ts +1 -1
- package/dist/src/algorithms/traversal/bfs.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/bfs.js +1 -1
- package/dist/src/algorithms/traversal/bfs.js.map +1 -1
- package/dist/src/algorithms/traversal/dfs.d.ts +10 -0
- package/dist/src/algorithms/traversal/dfs.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/dfs.js +48 -0
- package/dist/src/algorithms/traversal/dfs.js.map +1 -1
- package/dist/src/algorithms/traversal/index.d.ts.map +1 -1
- package/dist/src/algorithms/traversal/index.js.map +1 -1
- package/dist/src/benchmark-all-algorithms.d.ts +2 -0
- package/dist/src/benchmark-all-algorithms.d.ts.map +1 -1
- package/dist/src/benchmark-all-algorithms.js +32 -3
- package/dist/src/benchmark-all-algorithms.js.map +1 -1
- package/dist/src/clustering/hierarchical.d.ts +8 -1
- package/dist/src/clustering/hierarchical.d.ts.map +1 -1
- package/dist/src/clustering/hierarchical.js +22 -6
- package/dist/src/clustering/hierarchical.js.map +1 -1
- package/dist/src/clustering/index.d.ts.map +1 -1
- package/dist/src/clustering/index.js.map +1 -1
- package/dist/src/clustering/k-core.d.ts +2 -5
- package/dist/src/clustering/k-core.d.ts.map +1 -1
- package/dist/src/clustering/k-core.js +14 -12
- package/dist/src/clustering/k-core.js.map +1 -1
- package/dist/src/clustering/mcl.d.ts +6 -0
- package/dist/src/clustering/mcl.d.ts.map +1 -1
- package/dist/src/clustering/mcl.js +34 -3
- package/dist/src/clustering/mcl.js.map +1 -1
- package/dist/src/clustering/spectral.d.ts +4 -1
- package/dist/src/clustering/spectral.d.ts.map +1 -1
- package/dist/src/clustering/spectral.js +61 -28
- package/dist/src/clustering/spectral.js.map +1 -1
- package/dist/src/core/graph.d.ts +45 -0
- package/dist/src/core/graph.d.ts.map +1 -1
- package/dist/src/core/graph.js +45 -1
- package/dist/src/core/graph.js.map +1 -1
- package/dist/src/data-structures/index.d.ts.map +1 -1
- package/dist/src/data-structures/index.js.map +1 -1
- package/dist/src/data-structures/priority-queue.d.ts +18 -1
- package/dist/src/data-structures/priority-queue.d.ts.map +1 -1
- package/dist/src/data-structures/priority-queue.js +26 -5
- package/dist/src/data-structures/priority-queue.js.map +1 -1
- package/dist/src/data-structures/union-find.d.ts +21 -0
- package/dist/src/data-structures/union-find.d.ts.map +1 -1
- package/dist/src/data-structures/union-find.js +21 -0
- package/dist/src/data-structures/union-find.js.map +1 -1
- package/dist/src/flow/ford-fulkerson.d.ts +4 -2
- package/dist/src/flow/ford-fulkerson.d.ts.map +1 -1
- package/dist/src/flow/ford-fulkerson.js +31 -2
- package/dist/src/flow/ford-fulkerson.js.map +1 -1
- package/dist/src/flow/min-cut.d.ts +0 -3
- package/dist/src/flow/min-cut.d.ts.map +1 -1
- package/dist/src/flow/min-cut.js +17 -4
- package/dist/src/flow/min-cut.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- 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/link-prediction/adamic-adar.d.ts +26 -0
- package/dist/src/link-prediction/adamic-adar.d.ts.map +1 -1
- package/dist/src/link-prediction/adamic-adar.js +36 -10
- package/dist/src/link-prediction/adamic-adar.js.map +1 -1
- package/dist/src/link-prediction/common-neighbors.d.ts +21 -0
- package/dist/src/link-prediction/common-neighbors.d.ts.map +1 -1
- package/dist/src/link-prediction/common-neighbors.js +27 -6
- package/dist/src/link-prediction/common-neighbors.js.map +1 -1
- package/dist/src/link-prediction/index.d.ts.map +1 -1
- package/dist/src/optimized/bit-packed.d.ts +103 -53
- package/dist/src/optimized/bit-packed.d.ts.map +1 -1
- package/dist/src/optimized/bit-packed.js +104 -54
- package/dist/src/optimized/bit-packed.js.map +1 -1
- package/dist/src/optimized/csr-graph.d.ts +87 -24
- package/dist/src/optimized/csr-graph.d.ts.map +1 -1
- package/dist/src/optimized/csr-graph.js +87 -24
- package/dist/src/optimized/csr-graph.js.map +1 -1
- package/dist/src/optimized/direction-optimized-bfs.d.ts +37 -16
- package/dist/src/optimized/direction-optimized-bfs.d.ts.map +1 -1
- package/dist/src/optimized/direction-optimized-bfs.js +39 -20
- package/dist/src/optimized/direction-optimized-bfs.js.map +1 -1
- package/dist/src/optimized/graph-adapter.d.ts +58 -9
- package/dist/src/optimized/graph-adapter.d.ts.map +1 -1
- package/dist/src/optimized/graph-adapter.js +58 -10
- package/dist/src/optimized/graph-adapter.js.map +1 -1
- package/dist/src/optimized/index.d.ts +1 -1
- package/dist/src/optimized/index.d.ts.map +1 -1
- package/dist/src/optimized/index.js +3 -1
- package/dist/src/optimized/index.js.map +1 -1
- package/dist/src/pathfinding/astar.d.ts +25 -9
- package/dist/src/pathfinding/astar.d.ts.map +1 -1
- package/dist/src/pathfinding/astar.js +25 -10
- package/dist/src/pathfinding/astar.js.map +1 -1
- package/dist/src/pathfinding/utils.d.ts +15 -6
- package/dist/src/pathfinding/utils.d.ts.map +1 -1
- package/dist/src/pathfinding/utils.js +19 -7
- package/dist/src/pathfinding/utils.js.map +1 -1
- package/dist/src/research/grsbm.d.ts +0 -1
- package/dist/src/research/grsbm.d.ts.map +1 -1
- package/dist/src/research/grsbm.js +22 -9
- package/dist/src/research/grsbm.js.map +1 -1
- package/dist/src/research/index.d.ts.map +1 -1
- package/dist/src/research/index.js.map +1 -1
- package/dist/src/research/sync.d.ts +0 -1
- package/dist/src/research/sync.d.ts.map +1 -1
- package/dist/src/research/sync.js +28 -7
- package/dist/src/research/sync.js.map +1 -1
- package/dist/src/research/terahac.d.ts +0 -1
- package/dist/src/research/terahac.d.ts.map +1 -1
- package/dist/src/research/terahac.js +32 -4
- package/dist/src/research/terahac.js.map +1 -1
- package/dist/src/utils/graph-converters.d.ts +31 -0
- package/dist/src/utils/graph-converters.d.ts.map +1 -1
- package/dist/src/utils/graph-converters.js +31 -0
- package/dist/src/utils/graph-converters.js.map +1 -1
- package/dist/src/utils/graph-utilities.d.ts.map +1 -1
- package/dist/src/utils/graph-utilities.js.map +1 -1
- package/dist/src/utils/math-utilities.d.ts +11 -0
- package/dist/src/utils/math-utilities.d.ts.map +1 -1
- package/dist/src/utils/math-utilities.js +14 -5
- package/dist/src/utils/math-utilities.js.map +1 -1
- package/dist/src/utils/optimization-helpers.d.ts +9 -0
- package/dist/src/utils/optimization-helpers.d.ts.map +1 -1
- package/dist/src/utils/optimization-helpers.js +12 -0
- package/dist/src/utils/optimization-helpers.js.map +1 -1
- package/dist/src/utils/priorityQueue.d.ts +24 -0
- package/dist/src/utils/priorityQueue.d.ts.map +1 -1
- package/dist/src/utils/priorityQueue.js +34 -4
- package/dist/src/utils/priorityQueue.js.map +1 -1
- package/package.json +49 -45
- package/src/algorithms/centrality/betweenness.ts +34 -17
- package/src/algorithms/centrality/closeness.ts +34 -17
- package/src/algorithms/centrality/degree.ts +15 -19
- package/src/algorithms/centrality/delta-pagerank-simple.ts +36 -28
- package/src/algorithms/centrality/delta-pagerank.ts +34 -11
- package/src/algorithms/centrality/eigenvector.ts +14 -15
- package/src/algorithms/centrality/hits.ts +17 -17
- package/src/algorithms/centrality/index.ts +20 -15
- package/src/algorithms/centrality/katz.ts +17 -25
- package/src/algorithms/centrality/pagerank.ts +26 -17
- package/src/algorithms/community/girvan-newman.ts +39 -28
- package/src/algorithms/community/index.ts +6 -7
- package/src/algorithms/community/label-propagation.ts +20 -28
- package/src/algorithms/community/leiden.ts +61 -37
- package/src/algorithms/community/louvain-optimized.ts +49 -20
- package/src/algorithms/community/louvain.ts +35 -25
- package/src/algorithms/community/modularity-utils.ts +5 -17
- package/src/algorithms/components/connected.ts +40 -17
- package/src/algorithms/matching/bipartite.ts +17 -10
- package/src/algorithms/matching/index.ts +4 -4
- package/src/algorithms/matching/isomorphism.ts +53 -23
- package/src/algorithms/mst/index.ts +3 -4
- package/src/algorithms/mst/kruskal.ts +21 -6
- package/src/algorithms/mst/prim.ts +13 -4
- package/src/algorithms/shortest-path/bellman-ford.ts +16 -15
- package/src/algorithms/shortest-path/bidirectional-dijkstra.ts +28 -28
- package/src/algorithms/shortest-path/dijkstra.ts +23 -17
- package/src/algorithms/shortest-path/floyd-warshall.ts +21 -4
- package/src/algorithms/shortest-path/index.ts +5 -5
- package/src/algorithms/traversal/bfs-unified.ts +64 -60
- package/src/algorithms/traversal/bfs-variants.ts +61 -37
- package/src/algorithms/traversal/bfs.ts +1 -7
- package/src/algorithms/traversal/dfs.ts +61 -42
- package/src/algorithms/traversal/index.ts +3 -3
- package/src/benchmark-all-algorithms.ts +57 -25
- package/src/clustering/hierarchical.ts +40 -34
- package/src/clustering/index.ts +8 -8
- package/src/clustering/k-core.ts +26 -42
- package/src/clustering/mcl.ts +53 -23
- package/src/clustering/spectral.ts +91 -57
- package/src/core/graph.ts +54 -14
- package/src/data-structures/index.ts +2 -2
- package/src/data-structures/priority-queue.ts +36 -11
- package/src/data-structures/union-find.ts +22 -1
- package/src/flow/ford-fulkerson.ts +62 -35
- package/src/flow/min-cut.ts +43 -45
- package/src/index.ts +3 -2
- package/src/link-prediction/adamic-adar.ts +65 -51
- package/src/link-prediction/common-neighbors.ts +45 -36
- package/src/link-prediction/index.ts +1 -1
- package/src/optimized/bit-packed.ts +106 -56
- package/src/optimized/csr-graph.ts +93 -30
- package/src/optimized/direction-optimized-bfs.ts +44 -25
- package/src/optimized/graph-adapter.ts +64 -16
- package/src/optimized/index.ts +7 -9
- package/src/pathfinding/astar.ts +40 -25
- package/src/pathfinding/utils.ts +20 -13
- package/src/research/grsbm.ts +30 -24
- package/src/research/index.ts +4 -4
- package/src/research/sync.ts +39 -23
- package/src/research/terahac.ts +54 -20
- package/src/utils/graph-converters.ts +42 -14
- package/src/utils/graph-utilities.ts +11 -37
- package/src/utils/math-utilities.ts +17 -8
- package/src/utils/optimization-helpers.ts +27 -21
- package/src/utils/priorityQueue.ts +40 -6
package/src/clustering/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export type {ClusterNode, HierarchicalClusteringResult, LinkageMethod} from "./hierarchical.js";
|
|
2
|
-
export {hierarchicalClustering} from "./hierarchical.js";
|
|
3
|
-
export type {KCoreResult} from "./k-core.js";
|
|
4
|
-
export {getKCore, kCoreDecomposition} from "./k-core.js";
|
|
5
|
-
export type {MCLOptions, MCLResult} from "./mcl.js";
|
|
6
|
-
export {calculateMCLModularity, markovClustering} from "./mcl.js";
|
|
7
|
-
export type {SpectralClusteringOptions, SpectralClusteringResult} from "./spectral.js";
|
|
8
|
-
export {spectralClustering} from "./spectral.js";
|
|
1
|
+
export type { ClusterNode, HierarchicalClusteringResult, LinkageMethod } from "./hierarchical.js";
|
|
2
|
+
export { hierarchicalClustering } from "./hierarchical.js";
|
|
3
|
+
export type { KCoreResult } from "./k-core.js";
|
|
4
|
+
export { getKCore, kCoreDecomposition } from "./k-core.js";
|
|
5
|
+
export type { MCLOptions, MCLResult } from "./mcl.js";
|
|
6
|
+
export { calculateMCLModularity, markovClustering } from "./mcl.js";
|
|
7
|
+
export type { SpectralClusteringOptions, SpectralClusteringResult } from "./spectral.js";
|
|
8
|
+
export { spectralClustering } from "./spectral.js";
|
package/src/clustering/k-core.ts
CHANGED
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
* understanding graph structure.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import type {Graph} from "../core/graph.js";
|
|
9
|
+
import type { Graph } from "../core/graph.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Convert Graph to adjacency set representation
|
|
13
|
+
* @param graph - The input graph to convert
|
|
14
|
+
* @returns Map of node IDs to sets of neighbor node IDs
|
|
13
15
|
*/
|
|
14
16
|
function graphToAdjacencySet(graph: Graph): Map<string, Set<string>> {
|
|
15
17
|
const adjacency = new Map<string, Set<string>>();
|
|
@@ -49,12 +51,12 @@ export interface KCoreResult<T> {
|
|
|
49
51
|
|
|
50
52
|
/**
|
|
51
53
|
* Internal implementation of K-Core decomposition algorithm
|
|
54
|
+
* @param graph - Adjacency map representation of the graph
|
|
55
|
+
* @returns K-core decomposition result with cores, coreness values, and maximum core number
|
|
52
56
|
*/
|
|
53
|
-
function kCoreDecompositionImpl<T>(
|
|
54
|
-
graph: Map<T, Set<T>>,
|
|
55
|
-
): KCoreResult<T> {
|
|
57
|
+
function kCoreDecompositionImpl<T>(graph: Map<T, Set<T>>): KCoreResult<T> {
|
|
56
58
|
if (graph.size === 0) {
|
|
57
|
-
return {cores: new Map(), coreness: new Map(), maxCore: 0};
|
|
59
|
+
return { cores: new Map(), coreness: new Map(), maxCore: 0 };
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
const n = graph.size;
|
|
@@ -208,22 +210,18 @@ function kCoreDecompositionImpl<T>(
|
|
|
208
210
|
maxCore = Math.max(maxCore, core);
|
|
209
211
|
}
|
|
210
212
|
|
|
211
|
-
return {cores, coreness, maxCore};
|
|
213
|
+
return { cores, coreness, maxCore };
|
|
212
214
|
}
|
|
213
215
|
|
|
214
216
|
/**
|
|
215
217
|
* Extract the k-core subgraph
|
|
216
218
|
* Returns nodes that belong to k-core or higher
|
|
217
|
-
*
|
|
218
219
|
* @param graph - Undirected graph
|
|
219
220
|
* @param k - Core number
|
|
220
221
|
* @returns Set of nodes in k-core or higher
|
|
221
222
|
*/
|
|
222
|
-
export function getKCore(
|
|
223
|
-
graph
|
|
224
|
-
k: number,
|
|
225
|
-
): Set<string> {
|
|
226
|
-
const {coreness} = kCoreDecomposition(graph);
|
|
223
|
+
export function getKCore(graph: Graph, k: number): Set<string> {
|
|
224
|
+
const { coreness } = kCoreDecomposition(graph);
|
|
227
225
|
const kCore = new Set<string>();
|
|
228
226
|
|
|
229
227
|
for (const [node, core] of coreness) {
|
|
@@ -238,15 +236,11 @@ export function getKCore(
|
|
|
238
236
|
/**
|
|
239
237
|
* Get the induced subgraph for k-core
|
|
240
238
|
* Returns the actual subgraph containing only k-core nodes
|
|
241
|
-
*
|
|
242
239
|
* @param graph - Original graph
|
|
243
240
|
* @param k - Core number
|
|
244
241
|
* @returns K-core subgraph
|
|
245
242
|
*/
|
|
246
|
-
export function getKCoreSubgraph(
|
|
247
|
-
graph: Graph,
|
|
248
|
-
k: number,
|
|
249
|
-
): Map<string, Set<string>> {
|
|
243
|
+
export function getKCoreSubgraph(graph: Graph, k: number): Map<string, Set<string>> {
|
|
250
244
|
const kCoreNodes = getKCore(graph, k);
|
|
251
245
|
const adjacencySet = graphToAdjacencySet(graph);
|
|
252
246
|
const subgraph = new Map<string, Set<string>>();
|
|
@@ -270,13 +264,10 @@ export function getKCoreSubgraph(
|
|
|
270
264
|
/**
|
|
271
265
|
* Degeneracy ordering of the graph
|
|
272
266
|
* Orders nodes by their coreness values
|
|
273
|
-
*
|
|
274
267
|
* @param graph - Undirected graph
|
|
275
268
|
* @returns Array of nodes ordered by degeneracy
|
|
276
269
|
*/
|
|
277
|
-
export function degeneracyOrdering(
|
|
278
|
-
graph: Graph,
|
|
279
|
-
): string[] {
|
|
270
|
+
export function degeneracyOrdering(graph: Graph): string[] {
|
|
280
271
|
const adjacencySet = graphToAdjacencySet(graph);
|
|
281
272
|
const degree = new Map<string, number>();
|
|
282
273
|
const remaining = new Map<string, Set<string>>();
|
|
@@ -290,7 +281,7 @@ export function degeneracyOrdering(
|
|
|
290
281
|
|
|
291
282
|
// Build ordering
|
|
292
283
|
while (ordering.length < adjacencySet.size) {
|
|
293
|
-
|
|
284
|
+
// Find minimum degree node
|
|
294
285
|
let minDegree = Infinity;
|
|
295
286
|
let minNode: string | undefined;
|
|
296
287
|
|
|
@@ -327,15 +318,11 @@ export function degeneracyOrdering(
|
|
|
327
318
|
/**
|
|
328
319
|
* Find k-truss subgraph (triangular k-cores)
|
|
329
320
|
* Each edge must be part of at least k-2 triangles
|
|
330
|
-
*
|
|
331
321
|
* @param graph - Undirected graph
|
|
332
322
|
* @param k - Truss number (k >= 2)
|
|
333
323
|
* @returns Edges in k-truss
|
|
334
324
|
*/
|
|
335
|
-
export function kTruss(
|
|
336
|
-
graph: Graph,
|
|
337
|
-
k: number,
|
|
338
|
-
): Set<string> {
|
|
325
|
+
export function kTruss(graph: Graph, k: number): Set<string> {
|
|
339
326
|
if (k < 2) {
|
|
340
327
|
throw new Error("k must be at least 2 for k-truss");
|
|
341
328
|
}
|
|
@@ -349,8 +336,9 @@ export function kTruss(
|
|
|
349
336
|
// Initialize edges
|
|
350
337
|
for (const [u, neighbors] of adjacencySet) {
|
|
351
338
|
for (const v of neighbors) {
|
|
352
|
-
if (u < v) {
|
|
353
|
-
|
|
339
|
+
if (u < v) {
|
|
340
|
+
// Avoid duplicates
|
|
341
|
+
const edge = `${u},${v}`;
|
|
354
342
|
edges.add(edge);
|
|
355
343
|
edgeTriangles.set(edge, 0);
|
|
356
344
|
}
|
|
@@ -367,9 +355,9 @@ export function kTruss(
|
|
|
367
355
|
for (const w of uNeighbors) {
|
|
368
356
|
if (v < w && vNeighbors.has(w)) {
|
|
369
357
|
// Triangle found: u-v-w
|
|
370
|
-
const edge1 = `${
|
|
371
|
-
const edge2 = `${
|
|
372
|
-
const edge3 = `${
|
|
358
|
+
const edge1 = `${u},${v}`;
|
|
359
|
+
const edge2 = `${u},${w}`;
|
|
360
|
+
const edge3 = `${v},${w}`;
|
|
373
361
|
|
|
374
362
|
const edge1Count = edgeTriangles.get(edge1);
|
|
375
363
|
const edge2Count = edgeTriangles.get(edge2);
|
|
@@ -428,8 +416,8 @@ export function kTruss(
|
|
|
428
416
|
if (uNeighbors && vNeighbors) {
|
|
429
417
|
for (const w of uNeighbors) {
|
|
430
418
|
if (vNeighbors.has(w)) {
|
|
431
|
-
const edge1 = u < w ? `${
|
|
432
|
-
const edge2 = v < w ? `${
|
|
419
|
+
const edge1 = u < w ? `${u},${w}` : `${w},${u}`;
|
|
420
|
+
const edge2 = v < w ? `${v},${w}` : `${w},${v}`;
|
|
433
421
|
|
|
434
422
|
if (kTrussEdges.has(edge1)) {
|
|
435
423
|
const edge1Count = edgeTriangles.get(edge1);
|
|
@@ -455,10 +443,10 @@ export function kTruss(
|
|
|
455
443
|
|
|
456
444
|
/**
|
|
457
445
|
* Convert directed graph to undirected for k-core analysis
|
|
446
|
+
* @param directedGraph - Directed graph represented as adjacency map with edge weights
|
|
447
|
+
* @returns Undirected graph represented as adjacency map with neighbor sets
|
|
458
448
|
*/
|
|
459
|
-
export function toUndirected<T>(
|
|
460
|
-
directedGraph: Map<T, Map<T, number>>,
|
|
461
|
-
): Map<T, Set<T>> {
|
|
449
|
+
export function toUndirected<T>(directedGraph: Map<T, Map<T, number>>): Map<T, Set<T>> {
|
|
462
450
|
const undirected = new Map<T, Set<T>>();
|
|
463
451
|
|
|
464
452
|
// Initialize all nodes
|
|
@@ -491,18 +479,14 @@ export function toUndirected<T>(
|
|
|
491
479
|
/**
|
|
492
480
|
* K-Core decomposition algorithm
|
|
493
481
|
* Finds all k-cores in the graph and assigns coreness values to nodes
|
|
494
|
-
*
|
|
495
482
|
* @param graph - Undirected graph - accepts Graph class or Map<T, Set<T>>
|
|
496
483
|
* @returns K-core decomposition results
|
|
497
484
|
*
|
|
498
485
|
* Time Complexity: O(V + E)
|
|
499
486
|
* Space Complexity: O(V)
|
|
500
487
|
*/
|
|
501
|
-
export function kCoreDecomposition(
|
|
502
|
-
graph: Graph,
|
|
503
|
-
): KCoreResult<string> {
|
|
488
|
+
export function kCoreDecomposition(graph: Graph): KCoreResult<string> {
|
|
504
489
|
// Convert Graph to adjacency set representation
|
|
505
490
|
const adjacencySet = graphToAdjacencySet(graph);
|
|
506
491
|
return kCoreDecompositionImpl(adjacencySet);
|
|
507
492
|
}
|
|
508
|
-
|
package/src/clustering/mcl.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {Graph} from "../core/graph.js";
|
|
2
|
-
import type {NodeId} from "../types/index.js";
|
|
1
|
+
import type { Graph } from "../core/graph.js";
|
|
2
|
+
import type { NodeId } from "../types/index.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Markov Clustering (MCL) algorithm implementation
|
|
@@ -31,11 +31,11 @@ export interface MCLResult {
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Perform Markov Clustering on a graph
|
|
34
|
+
* @param graph - The input graph to cluster
|
|
35
|
+
* @param options - MCL algorithm options (expansion, inflation, iterations, etc.)
|
|
36
|
+
* @returns MCL clustering result with communities, attractors, and convergence info
|
|
34
37
|
*/
|
|
35
|
-
export function markovClustering(
|
|
36
|
-
graph: Graph,
|
|
37
|
-
options: MCLOptions = {},
|
|
38
|
-
): MCLResult {
|
|
38
|
+
export function markovClustering(graph: Graph, options: MCLOptions = {}): MCLResult {
|
|
39
39
|
const {
|
|
40
40
|
expansion = 2,
|
|
41
41
|
inflation = 2,
|
|
@@ -65,7 +65,7 @@ export function markovClustering(
|
|
|
65
65
|
let iteration = 0;
|
|
66
66
|
|
|
67
67
|
for (iteration = 0; iteration < maxIterations; iteration++) {
|
|
68
|
-
const oldMatrix = matrix.map((row) => [...
|
|
68
|
+
const oldMatrix = matrix.map((row) => [...row]);
|
|
69
69
|
|
|
70
70
|
// Expansion step (matrix multiplication)
|
|
71
71
|
matrix = matrixPower(matrix, expansion);
|
|
@@ -84,7 +84,7 @@ export function markovClustering(
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
// Extract clusters from final matrix
|
|
87
|
-
const {communities, attractors} = extractClusters(matrix, nodeIds);
|
|
87
|
+
const { communities, attractors } = extractClusters(matrix, nodeIds);
|
|
88
88
|
|
|
89
89
|
return {
|
|
90
90
|
communities,
|
|
@@ -96,10 +96,14 @@ export function markovClustering(
|
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
98
|
* Build initial transition matrix from graph
|
|
99
|
+
* @param graph - The input graph
|
|
100
|
+
* @param nodeIds - Array of node IDs in the graph
|
|
101
|
+
* @param selfLoops - Whether to add self-loops to the matrix
|
|
102
|
+
* @returns Column-normalized transition matrix
|
|
99
103
|
*/
|
|
100
104
|
function buildTransitionMatrix(graph: Graph, nodeIds: NodeId[], selfLoops: boolean): number[][] {
|
|
101
105
|
const n = nodeIds.length;
|
|
102
|
-
const matrix = Array.from({length: n}, (): number[] => Array(n).fill(0) as number[]);
|
|
106
|
+
const matrix = Array.from({ length: n }, (): number[] => Array(n).fill(0) as number[]);
|
|
103
107
|
const nodeToIndex = new Map<NodeId, number>();
|
|
104
108
|
|
|
105
109
|
nodeIds.forEach((id, index) => nodeToIndex.set(id, index));
|
|
@@ -168,6 +172,9 @@ function buildTransitionMatrix(graph: Graph, nodeIds: NodeId[], selfLoops: boole
|
|
|
168
172
|
|
|
169
173
|
/**
|
|
170
174
|
* Raise matrix to a power (for expansion step)
|
|
175
|
+
* @param matrix - Input square matrix
|
|
176
|
+
* @param power - Power to raise the matrix to
|
|
177
|
+
* @returns Matrix raised to the specified power
|
|
171
178
|
*/
|
|
172
179
|
function matrixPower(matrix: number[][], power: number): number[][] {
|
|
173
180
|
if (power === 1) {
|
|
@@ -187,13 +194,16 @@ function matrixPower(matrix: number[][], power: number): number[][] {
|
|
|
187
194
|
|
|
188
195
|
/**
|
|
189
196
|
* Multiply two matrices
|
|
197
|
+
* @param a - First matrix
|
|
198
|
+
* @param b - Second matrix
|
|
199
|
+
* @returns Product matrix a * b
|
|
190
200
|
*/
|
|
191
201
|
function matrixMultiply(a: number[][], b: number[][]): number[][] {
|
|
192
202
|
const n = a.length;
|
|
193
203
|
const m = b[0]?.length ?? 0;
|
|
194
204
|
const p = b.length;
|
|
195
205
|
|
|
196
|
-
const result: number[][] = Array.from({length: n}, () => Array(m).fill(0) as number[]);
|
|
206
|
+
const result: number[][] = Array.from({ length: n }, () => Array(m).fill(0) as number[]);
|
|
197
207
|
|
|
198
208
|
for (let i = 0; i < n; i++) {
|
|
199
209
|
for (let j = 0; j < m; j++) {
|
|
@@ -207,7 +217,7 @@ function matrixMultiply(a: number[][], b: number[][]): number[][] {
|
|
|
207
217
|
|
|
208
218
|
const prevVal = resultRow[j];
|
|
209
219
|
if (prevVal !== undefined) {
|
|
210
|
-
resultRow[j] = prevVal +
|
|
220
|
+
resultRow[j] = prevVal + aVal * bVal;
|
|
211
221
|
}
|
|
212
222
|
}
|
|
213
223
|
}
|
|
@@ -218,10 +228,13 @@ function matrixMultiply(a: number[][], b: number[][]): number[][] {
|
|
|
218
228
|
|
|
219
229
|
/**
|
|
220
230
|
* Inflation step: element-wise powering and column normalization
|
|
231
|
+
* @param matrix - Input matrix to inflate
|
|
232
|
+
* @param inflation - Inflation parameter for element-wise powering
|
|
233
|
+
* @returns Inflated and column-normalized matrix
|
|
221
234
|
*/
|
|
222
235
|
function inflate(matrix: number[][], inflation: number): number[][] {
|
|
223
236
|
const n = matrix.length;
|
|
224
|
-
const result: number[][] = Array.from({length: n}, () => Array(n).fill(0) as number[]);
|
|
237
|
+
const result: number[][] = Array.from({ length: n }, () => Array(n).fill(0) as number[]);
|
|
225
238
|
|
|
226
239
|
// Element-wise powering
|
|
227
240
|
for (let i = 0; i < n; i++) {
|
|
@@ -266,10 +279,13 @@ function inflate(matrix: number[][], inflation: number): number[][] {
|
|
|
266
279
|
|
|
267
280
|
/**
|
|
268
281
|
* Pruning step: remove small values
|
|
282
|
+
* @param matrix - Input matrix to prune
|
|
283
|
+
* @param threshold - Values below this threshold are set to zero
|
|
284
|
+
* @returns Pruned and re-normalized matrix
|
|
269
285
|
*/
|
|
270
286
|
function prune(matrix: number[][], threshold: number): number[][] {
|
|
271
287
|
const n = matrix.length;
|
|
272
|
-
const result: number[][] = Array.from({length: n}, () => Array(n).fill(0) as number[]);
|
|
288
|
+
const result: number[][] = Array.from({ length: n }, () => Array(n).fill(0) as number[]);
|
|
273
289
|
|
|
274
290
|
for (let i = 0; i < n; i++) {
|
|
275
291
|
for (let j = 0; j < n; j++) {
|
|
@@ -323,6 +339,10 @@ function prune(matrix: number[][], threshold: number): number[][] {
|
|
|
323
339
|
|
|
324
340
|
/**
|
|
325
341
|
* Check if the algorithm has converged
|
|
342
|
+
* @param oldMatrix - Matrix from previous iteration
|
|
343
|
+
* @param newMatrix - Matrix from current iteration
|
|
344
|
+
* @param tolerance - Convergence tolerance threshold
|
|
345
|
+
* @returns True if the maximum difference between matrices is below tolerance
|
|
326
346
|
*/
|
|
327
347
|
function hasConverged(oldMatrix: number[][], newMatrix: number[][], tolerance: number): boolean {
|
|
328
348
|
const n = oldMatrix.length;
|
|
@@ -348,8 +368,14 @@ function hasConverged(oldMatrix: number[][], newMatrix: number[][], tolerance: n
|
|
|
348
368
|
|
|
349
369
|
/**
|
|
350
370
|
* Extract clusters from the final matrix
|
|
371
|
+
* @param matrix - Final converged MCL matrix
|
|
372
|
+
* @param nodeIds - Array of node IDs corresponding to matrix indices
|
|
373
|
+
* @returns Object containing communities and attractor nodes
|
|
351
374
|
*/
|
|
352
|
-
function extractClusters(
|
|
375
|
+
function extractClusters(
|
|
376
|
+
matrix: number[][],
|
|
377
|
+
nodeIds: NodeId[],
|
|
378
|
+
): {
|
|
353
379
|
communities: NodeId[][];
|
|
354
380
|
attractors: Set<NodeId>;
|
|
355
381
|
} {
|
|
@@ -391,10 +417,14 @@ function extractClusters(matrix: number[][], nodeIds: NodeId[]): {
|
|
|
391
417
|
}
|
|
392
418
|
|
|
393
419
|
if (clusterNodes.length > 0) {
|
|
394
|
-
communities.push(
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
420
|
+
communities.push(
|
|
421
|
+
clusterNodes
|
|
422
|
+
.map((idx) => {
|
|
423
|
+
const nodeId = nodeIds[idx];
|
|
424
|
+
return nodeId;
|
|
425
|
+
})
|
|
426
|
+
.filter((node): node is NodeId => node !== undefined),
|
|
427
|
+
);
|
|
398
428
|
clusterIndex++;
|
|
399
429
|
}
|
|
400
430
|
}
|
|
@@ -411,16 +441,16 @@ function extractClusters(matrix: number[][], nodeIds: NodeId[]): {
|
|
|
411
441
|
}
|
|
412
442
|
}
|
|
413
443
|
|
|
414
|
-
return {communities, attractors};
|
|
444
|
+
return { communities, attractors };
|
|
415
445
|
}
|
|
416
446
|
|
|
417
447
|
/**
|
|
418
448
|
* Calculate modularity of MCL clustering result
|
|
449
|
+
* @param graph - The original graph that was clustered
|
|
450
|
+
* @param communities - Array of communities (each community is an array of node IDs)
|
|
451
|
+
* @returns Modularity score between -0.5 and 1.0
|
|
419
452
|
*/
|
|
420
|
-
export function calculateMCLModularity(
|
|
421
|
-
graph: Graph,
|
|
422
|
-
communities: NodeId[][],
|
|
423
|
-
): number {
|
|
453
|
+
export function calculateMCLModularity(graph: Graph, communities: NodeId[][]): number {
|
|
424
454
|
const m = graph.totalEdgeCount;
|
|
425
455
|
if (m === 0) {
|
|
426
456
|
return 0;
|