@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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphty/algorithms",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.2",
|
|
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",
|
|
@@ -21,44 +21,10 @@
|
|
|
21
21
|
"directories": {
|
|
22
22
|
"example": "examples"
|
|
23
23
|
},
|
|
24
|
-
"scripts": {
|
|
25
|
-
"test": "vitest",
|
|
26
|
-
"test:ui": "vitest --ui",
|
|
27
|
-
"test:run": "vitest run --project=default",
|
|
28
|
-
"test:coverage": "vitest run --coverage",
|
|
29
|
-
"test:browser": "vitest --project=browser",
|
|
30
|
-
"test:all": "vitest run --project=default --project=browser",
|
|
31
|
-
"test:performance": "tsx test/helpers/run-performance-regression.ts",
|
|
32
|
-
"test:performance:update": "tsx test/helpers/run-performance-regression.ts --update-baselines",
|
|
33
|
-
"benchmark": "tsx src/benchmark-all-algorithms.ts",
|
|
34
|
-
"benchmark:quick": "tsx src/benchmark-all-algorithms.ts --quick",
|
|
35
|
-
"benchmark:report": "tsx scripts/generate-performance-report.ts",
|
|
36
|
-
"benchmark:validation": "tsx src/optimized/benchmark-validation.ts",
|
|
37
|
-
"benchmark:comprehensive": "tsx src/optimized/benchmark-comprehensive.ts",
|
|
38
|
-
"memory:profile": "tsx test/helpers/memory-profiler.ts",
|
|
39
|
-
"lint": "eslint && tsc --noEmit",
|
|
40
|
-
"lint:fix": "eslint --fix",
|
|
41
|
-
"lint:pkg": "knip",
|
|
42
|
-
"lint:all": "npm run lint && npm run lint:pkg",
|
|
43
|
-
"typecheck": "tsc --noEmit",
|
|
44
|
-
"prepare": "husky",
|
|
45
|
-
"build": "tsc",
|
|
46
|
-
"build:bundle": "node scripts/build-bundle.js",
|
|
47
|
-
"build:all": "npm run build && npm run build:bundle",
|
|
48
|
-
"build:gh-pages": "npm run build:bundle && node scripts/build-gh-pages.js",
|
|
49
|
-
"build:watch": "tsc --watch",
|
|
50
|
-
"dev": "tsc --watch",
|
|
51
|
-
"examples": "node examples/run-all-examples.js",
|
|
52
|
-
"examples:run": "node examples/run-all-examples.js",
|
|
53
|
-
"examples:html": "npm run build:bundle && vite",
|
|
54
|
-
"serve": "npm run build:bundle && vite",
|
|
55
|
-
"commit": "cz",
|
|
56
|
-
"ready:commit": "npm run build && npm run lint && npm run test:all",
|
|
57
|
-
"watch": "tsc --watch"
|
|
58
|
-
},
|
|
59
24
|
"repository": {
|
|
60
25
|
"type": "git",
|
|
61
|
-
"url": "git+https://github.com/graphty-org/
|
|
26
|
+
"url": "git+https://github.com/graphty-org/graphty-monorepo.git",
|
|
27
|
+
"directory": "algorithms"
|
|
62
28
|
},
|
|
63
29
|
"keywords": [
|
|
64
30
|
"graph",
|
|
@@ -78,9 +44,9 @@
|
|
|
78
44
|
"provenance": true
|
|
79
45
|
},
|
|
80
46
|
"bugs": {
|
|
81
|
-
"url": "https://github.com/graphty-org/
|
|
47
|
+
"url": "https://github.com/graphty-org/graphty-monorepo/issues"
|
|
82
48
|
},
|
|
83
|
-
"homepage": "https://github.com/graphty-org/algorithms#readme",
|
|
49
|
+
"homepage": "https://github.com/graphty-org/graphty-monorepo/tree/master/algorithms#readme",
|
|
84
50
|
"engines": {
|
|
85
51
|
"node": ">=18.19.0"
|
|
86
52
|
},
|
|
@@ -90,25 +56,20 @@
|
|
|
90
56
|
}
|
|
91
57
|
},
|
|
92
58
|
"devDependencies": {
|
|
93
|
-
"@commitlint/cli": "^19.8.1",
|
|
94
|
-
"@commitlint/config-conventional": "^19.8.1",
|
|
95
59
|
"@eslint/js": "^9.29.0",
|
|
96
60
|
"@semantic-release/changelog": "^6.0.3",
|
|
97
61
|
"@semantic-release/git": "^10.0.1",
|
|
98
|
-
"@stylistic/eslint-plugin": "^4.4.1",
|
|
99
62
|
"@types/benchmark": "^2.1.5",
|
|
100
63
|
"@types/node": "^20.19.9",
|
|
101
64
|
"@vitest/browser": "^3.2.4",
|
|
102
65
|
"@vitest/coverage-v8": "^3.2.4",
|
|
103
66
|
"@vitest/ui": "^3.2.4",
|
|
104
67
|
"benchmark": "^2.1.4",
|
|
105
|
-
"cz-conventional-changelog": "^3.3.0",
|
|
106
68
|
"eslint": "^9.29.0",
|
|
107
69
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
108
70
|
"gh-pages": "^6.3.0",
|
|
109
71
|
"globals": "^15.12.0",
|
|
110
72
|
"happy-dom": "^18.0.1",
|
|
111
|
-
"husky": "^9.1.7",
|
|
112
73
|
"knip": "^5.61.3",
|
|
113
74
|
"playwright": "^1.53.0",
|
|
114
75
|
"semantic-release": "^25.0.2",
|
|
@@ -122,5 +83,48 @@
|
|
|
122
83
|
"dependencies": {
|
|
123
84
|
"pupt": "^1.3.2",
|
|
124
85
|
"typedfastbitset": "^0.6.1"
|
|
86
|
+
},
|
|
87
|
+
"scripts": {
|
|
88
|
+
"test": "vitest",
|
|
89
|
+
"test:ui": "vitest --ui",
|
|
90
|
+
"test:run": "vitest run --project=default",
|
|
91
|
+
"test:coverage": "vitest run --coverage",
|
|
92
|
+
"coverage": "npm run coverage:shards && npm run coverage:merge",
|
|
93
|
+
"coverage:merge": "./scripts/coverage-merge.sh",
|
|
94
|
+
"coverage:shards": "npm run coverage:shards:clean && npm run coverage:shards:run",
|
|
95
|
+
"coverage:shards:clean": "rm -rf .coverage-parts",
|
|
96
|
+
"coverage:shards:run": "npm run coverage:shard:default && npm run coverage:shard:browser",
|
|
97
|
+
"coverage:shard:default": "COVERAGE_DIR=.coverage-parts/default vitest run --project=default --coverage",
|
|
98
|
+
"coverage:shard:browser": "COVERAGE_DIR=.coverage-parts/browser vitest run --project=browser --coverage",
|
|
99
|
+
"coverage:fast": "vitest run --project=default --coverage",
|
|
100
|
+
"coverage:preview": "npx serve coverage -p 9051",
|
|
101
|
+
"test:browser": "vitest --project=browser",
|
|
102
|
+
"test:all": "vitest run --project=default --project=browser",
|
|
103
|
+
"test:performance": "tsx test/helpers/run-performance-regression.ts",
|
|
104
|
+
"test:performance:update": "tsx test/helpers/run-performance-regression.ts --update-baselines",
|
|
105
|
+
"benchmark": "tsx src/benchmark-all-algorithms.ts",
|
|
106
|
+
"benchmark:quick": "tsx src/benchmark-all-algorithms.ts --quick",
|
|
107
|
+
"benchmark:report": "tsx scripts/generate-performance-report.ts",
|
|
108
|
+
"benchmark:validation": "tsx src/optimized/benchmark-validation.ts",
|
|
109
|
+
"benchmark:comprehensive": "tsx src/optimized/benchmark-comprehensive.ts",
|
|
110
|
+
"memory:profile": "tsx test/helpers/memory-profiler.ts",
|
|
111
|
+
"lint": "eslint && tsc --noEmit",
|
|
112
|
+
"lint:fix": "eslint --fix",
|
|
113
|
+
"lint:pkg": "knip",
|
|
114
|
+
"lint:all": "npm run lint && npm run lint:pkg",
|
|
115
|
+
"typecheck": "tsc --noEmit",
|
|
116
|
+
"build": "tsc",
|
|
117
|
+
"build:bundle": "node scripts/build-bundle.js",
|
|
118
|
+
"build:all": "npm run build && npm run build:bundle",
|
|
119
|
+
"build:gh-pages": "npm run build:bundle && node scripts/build-gh-pages.js",
|
|
120
|
+
"build:watch": "tsc --watch",
|
|
121
|
+
"dev": "tsc --watch",
|
|
122
|
+
"examples": "node examples/run-all-examples.js",
|
|
123
|
+
"examples:run": "node examples/run-all-examples.js",
|
|
124
|
+
"examples:html": "npm run build:bundle && vite",
|
|
125
|
+
"serve": "npm run build:bundle && vite",
|
|
126
|
+
"commit": "cz",
|
|
127
|
+
"ready:commit": "npm run build && npm run lint && npm run test:all",
|
|
128
|
+
"watch": "tsc --watch"
|
|
125
129
|
}
|
|
126
|
-
}
|
|
130
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {NodeId} from "../../types/index.js";
|
|
3
|
-
import {bfsWithPathCounting} from "../traversal/bfs-variants.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { NodeId } from "../../types/index.js";
|
|
3
|
+
import { bfsWithPathCounting } from "../traversal/bfs-variants.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Betweenness centrality implementation using Brandes' algorithm
|
|
@@ -39,9 +39,13 @@ interface BrandesResult {
|
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Run single-source shortest path computation using BFS
|
|
42
|
+
* @param graph - The input graph to analyze
|
|
43
|
+
* @param source - The source node for shortest path computation
|
|
44
|
+
* @param optimized - Whether to use optimized BFS implementation
|
|
45
|
+
* @returns The BFS result containing stack, predecessors, sigma, and distances
|
|
42
46
|
*/
|
|
43
47
|
function brandesSingleSource(graph: Graph, source: NodeId, optimized?: boolean): BrandesResult {
|
|
44
|
-
const result = bfsWithPathCounting(graph, source, optimized !== undefined ? {optimized} : {});
|
|
48
|
+
const result = bfsWithPathCounting(graph, source, optimized !== undefined ? { optimized } : {});
|
|
45
49
|
|
|
46
50
|
return {
|
|
47
51
|
stack: result.stack,
|
|
@@ -53,6 +57,10 @@ function brandesSingleSource(graph: Graph, source: NodeId, optimized?: boolean):
|
|
|
53
57
|
|
|
54
58
|
/**
|
|
55
59
|
* Accumulate betweenness contributions from a single source
|
|
60
|
+
* @param result - The BFS result from brandesSingleSource
|
|
61
|
+
* @param source - The source node used in BFS
|
|
62
|
+
* @param centrality - The centrality map to update
|
|
63
|
+
* @param options - Algorithm configuration options
|
|
56
64
|
*/
|
|
57
65
|
function accumulateBetweenness(
|
|
58
66
|
result: BrandesResult,
|
|
@@ -60,7 +68,7 @@ function accumulateBetweenness(
|
|
|
60
68
|
centrality: Record<string, number>,
|
|
61
69
|
options: BetweennessCentralityOptions,
|
|
62
70
|
): void {
|
|
63
|
-
const {stack, predecessors, sigma} = result;
|
|
71
|
+
const { stack, predecessors, sigma } = result;
|
|
64
72
|
const delta = new Map<NodeId, number>();
|
|
65
73
|
|
|
66
74
|
// Initialize delta
|
|
@@ -109,6 +117,10 @@ function accumulateBetweenness(
|
|
|
109
117
|
|
|
110
118
|
/**
|
|
111
119
|
* Accumulate edge betweenness contributions from a single source
|
|
120
|
+
* @param result - The BFS result from brandesSingleSource
|
|
121
|
+
* @param source - The source node used in BFS
|
|
122
|
+
* @param edgeCentrality - The edge centrality map to update
|
|
123
|
+
* @param options - Algorithm configuration options
|
|
112
124
|
*/
|
|
113
125
|
function accumulateEdgeBetweenness(
|
|
114
126
|
result: BrandesResult,
|
|
@@ -116,7 +128,7 @@ function accumulateEdgeBetweenness(
|
|
|
116
128
|
edgeCentrality: Map<string, number>,
|
|
117
129
|
options: BetweennessCentralityOptions,
|
|
118
130
|
): void {
|
|
119
|
-
const {stack, predecessors, sigma} = result;
|
|
131
|
+
const { stack, predecessors, sigma } = result;
|
|
120
132
|
const delta = new Map<NodeId, number>();
|
|
121
133
|
|
|
122
134
|
// Initialize delta
|
|
@@ -165,16 +177,13 @@ function accumulateEdgeBetweenness(
|
|
|
165
177
|
|
|
166
178
|
/**
|
|
167
179
|
* Apply normalization to centrality values
|
|
180
|
+
* @param centrality - The centrality map to normalize in place
|
|
181
|
+
* @param nodeCount - Total number of nodes in the graph
|
|
182
|
+
* @param isDirected - Whether the graph is directed
|
|
168
183
|
*/
|
|
169
|
-
function normalizeCentrality(
|
|
170
|
-
centrality: Record<string, number>,
|
|
171
|
-
nodeCount: number,
|
|
172
|
-
isDirected: boolean,
|
|
173
|
-
): void {
|
|
184
|
+
function normalizeCentrality(centrality: Record<string, number>, nodeCount: number, isDirected: boolean): void {
|
|
174
185
|
const n = nodeCount;
|
|
175
|
-
const normalizationFactor = isDirected ?
|
|
176
|
-
(n - 1) * (n - 2) :
|
|
177
|
-
((n - 1) * (n - 2)) / 2;
|
|
186
|
+
const normalizationFactor = isDirected ? (n - 1) * (n - 2) : ((n - 1) * (n - 2)) / 2;
|
|
178
187
|
|
|
179
188
|
if (normalizationFactor > 0) {
|
|
180
189
|
for (const key in centrality) {
|
|
@@ -188,6 +197,9 @@ function normalizeCentrality(
|
|
|
188
197
|
|
|
189
198
|
/**
|
|
190
199
|
* Calculate betweenness centrality for all nodes using Brandes' algorithm
|
|
200
|
+
* @param graph - The input graph to analyze
|
|
201
|
+
* @param options - Algorithm configuration options
|
|
202
|
+
* @returns Centrality scores for each node keyed by node ID
|
|
191
203
|
*/
|
|
192
204
|
export function betweennessCentrality(
|
|
193
205
|
graph: Graph,
|
|
@@ -228,6 +240,10 @@ export function betweennessCentrality(
|
|
|
228
240
|
|
|
229
241
|
/**
|
|
230
242
|
* Calculate betweenness centrality for a specific node
|
|
243
|
+
* @param graph - The input graph to analyze
|
|
244
|
+
* @param targetNode - The node to calculate centrality for
|
|
245
|
+
* @param options - Algorithm configuration options
|
|
246
|
+
* @returns The betweenness centrality score for the target node
|
|
231
247
|
*/
|
|
232
248
|
export function nodeBetweennessCentrality(
|
|
233
249
|
graph: Graph,
|
|
@@ -244,6 +260,9 @@ export function nodeBetweennessCentrality(
|
|
|
244
260
|
|
|
245
261
|
/**
|
|
246
262
|
* Calculate edge betweenness centrality
|
|
263
|
+
* @param graph - The input graph to analyze
|
|
264
|
+
* @param options - Algorithm configuration options
|
|
265
|
+
* @returns Edge centrality scores keyed by edge string representation
|
|
247
266
|
*/
|
|
248
267
|
export function edgeBetweennessCentrality(
|
|
249
268
|
graph: Graph,
|
|
@@ -274,9 +293,7 @@ export function edgeBetweennessCentrality(
|
|
|
274
293
|
// Normalization for edges
|
|
275
294
|
if (options.normalized) {
|
|
276
295
|
const n = nodes.length;
|
|
277
|
-
const normalizationFactor = graph.isDirected ?
|
|
278
|
-
(n - 1) * (n - 2) :
|
|
279
|
-
((n - 1) * (n - 2)) / 2;
|
|
296
|
+
const normalizationFactor = graph.isDirected ? (n - 1) * (n - 2) : ((n - 1) * (n - 2)) / 2;
|
|
280
297
|
|
|
281
298
|
if (normalizationFactor > 0) {
|
|
282
299
|
for (const [edgeKey, centrality] of Array.from(edgeCentrality)) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {NodeId} from "../../types/index.js";
|
|
3
|
-
import {bfsDistancesOnly, bfsWeightedDistances} from "../traversal/bfs-variants.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { NodeId } from "../../types/index.js";
|
|
3
|
+
import { bfsDistancesOnly, bfsWeightedDistances } from "../traversal/bfs-variants.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Closeness centrality implementation
|
|
@@ -34,6 +34,11 @@ export interface ClosenessCentralityOptions {
|
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* Calculate closeness centrality from distances
|
|
37
|
+
* @param distances - Map of node IDs to their distances from source
|
|
38
|
+
* @param sourceNode - The source node for distance calculations
|
|
39
|
+
* @param totalNodes - Total number of nodes in the graph
|
|
40
|
+
* @param options - Algorithm configuration options
|
|
41
|
+
* @returns The closeness centrality score for the source node
|
|
37
42
|
*/
|
|
38
43
|
function calculateClosenessFromDistances(
|
|
39
44
|
distances: Map<NodeId, number>,
|
|
@@ -76,7 +81,7 @@ function calculateClosenessFromDistances(
|
|
|
76
81
|
|
|
77
82
|
// Wasserman and Faust normalization for disconnected graphs
|
|
78
83
|
if (options.normalized && totalNodes > 1) {
|
|
79
|
-
centrality = centrality * reachableNodes / (totalNodes - 1);
|
|
84
|
+
centrality = (centrality * reachableNodes) / (totalNodes - 1);
|
|
80
85
|
}
|
|
81
86
|
}
|
|
82
87
|
}
|
|
@@ -90,11 +95,9 @@ function calculateClosenessFromDistances(
|
|
|
90
95
|
* Closeness centrality measures how close a node is to all other nodes
|
|
91
96
|
* in the graph. It is the reciprocal of the sum of the shortest path
|
|
92
97
|
* distances to all other reachable nodes.
|
|
93
|
-
*
|
|
94
98
|
* @param graph - The input graph
|
|
95
99
|
* @param options - Algorithm options
|
|
96
100
|
* @returns Centrality scores for each node
|
|
97
|
-
*
|
|
98
101
|
* @example
|
|
99
102
|
* ```typescript
|
|
100
103
|
* const graph = new Graph();
|
|
@@ -108,10 +111,7 @@ function calculateClosenessFromDistances(
|
|
|
108
111
|
* Time Complexity: O(V * (V + E)) for unweighted graphs
|
|
109
112
|
* Space Complexity: O(V)
|
|
110
113
|
*/
|
|
111
|
-
export function closenessCentrality(
|
|
112
|
-
graph: Graph,
|
|
113
|
-
options: ClosenessCentralityOptions = {},
|
|
114
|
-
): Record<string, number> {
|
|
114
|
+
export function closenessCentrality(graph: Graph, options: ClosenessCentralityOptions = {}): Record<string, number> {
|
|
115
115
|
const nodes = Array.from(graph.nodes()).map((node) => node.id);
|
|
116
116
|
const centrality: Record<string, number> = {};
|
|
117
117
|
|
|
@@ -124,18 +124,23 @@ export function closenessCentrality(
|
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
126
|
* Calculate closeness centrality for a specific node
|
|
127
|
+
* @param graph - The input graph to analyze
|
|
128
|
+
* @param node - The node to calculate centrality for
|
|
129
|
+
* @param options - Algorithm configuration options
|
|
130
|
+
* @returns The closeness centrality score for the node
|
|
127
131
|
*/
|
|
128
|
-
export function nodeClosenessCentrality(
|
|
129
|
-
graph: Graph,
|
|
130
|
-
node: NodeId,
|
|
131
|
-
options: ClosenessCentralityOptions = {},
|
|
132
|
-
): number {
|
|
132
|
+
export function nodeClosenessCentrality(graph: Graph, node: NodeId, options: ClosenessCentralityOptions = {}): number {
|
|
133
133
|
if (!graph.hasNode(node)) {
|
|
134
134
|
throw new Error(`Node ${String(node)} not found in graph`);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
// Use optimized BFS variant for unweighted graphs
|
|
138
|
-
const distances = bfsDistancesOnly(
|
|
138
|
+
const distances = bfsDistancesOnly(
|
|
139
|
+
graph,
|
|
140
|
+
node,
|
|
141
|
+
options.cutoff,
|
|
142
|
+
options.optimized !== undefined ? { optimized: options.optimized } : {},
|
|
143
|
+
);
|
|
139
144
|
const totalNodes = graph.nodeCount;
|
|
140
145
|
|
|
141
146
|
return calculateClosenessFromDistances(distances, node, totalNodes, options);
|
|
@@ -143,6 +148,9 @@ export function nodeClosenessCentrality(
|
|
|
143
148
|
|
|
144
149
|
/**
|
|
145
150
|
* Calculate weighted closeness centrality using Dijkstra's algorithm
|
|
151
|
+
* @param graph - The input graph to analyze
|
|
152
|
+
* @param options - Algorithm configuration options
|
|
153
|
+
* @returns Centrality scores for each node keyed by node ID
|
|
146
154
|
*/
|
|
147
155
|
export function weightedClosenessCentrality(
|
|
148
156
|
graph: Graph,
|
|
@@ -160,6 +168,10 @@ export function weightedClosenessCentrality(
|
|
|
160
168
|
|
|
161
169
|
/**
|
|
162
170
|
* Calculate weighted closeness centrality for a specific node using Dijkstra
|
|
171
|
+
* @param graph - The input graph to analyze
|
|
172
|
+
* @param node - The node to calculate centrality for
|
|
173
|
+
* @param options - Algorithm configuration options
|
|
174
|
+
* @returns The weighted closeness centrality score for the node
|
|
163
175
|
*/
|
|
164
176
|
export function nodeWeightedClosenessCentrality(
|
|
165
177
|
graph: Graph,
|
|
@@ -171,7 +183,12 @@ export function nodeWeightedClosenessCentrality(
|
|
|
171
183
|
}
|
|
172
184
|
|
|
173
185
|
// Use optimized weighted BFS variant (simplified Dijkstra)
|
|
174
|
-
const distances = bfsWeightedDistances(
|
|
186
|
+
const distances = bfsWeightedDistances(
|
|
187
|
+
graph,
|
|
188
|
+
node,
|
|
189
|
+
options.cutoff,
|
|
190
|
+
options.optimized !== undefined ? { optimized: options.optimized } : {},
|
|
191
|
+
);
|
|
175
192
|
const totalNodes = graph.nodeCount;
|
|
176
193
|
|
|
177
194
|
return calculateClosenessFromDistances(distances, node, totalNodes, options);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import type {CentralityOptions, CentralityResult} from "../../types/index.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import type { CentralityOptions, CentralityResult } from "../../types/index.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Degree centrality implementation
|
|
@@ -10,13 +10,13 @@ import type {CentralityOptions, CentralityResult} from "../../types/index.js";
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Calculate degree centrality for all nodes in the graph
|
|
13
|
+
* @param graph - The input graph to analyze
|
|
14
|
+
* @param options - Algorithm configuration options
|
|
15
|
+
* @returns Centrality scores for each node keyed by node ID
|
|
13
16
|
*/
|
|
14
|
-
export function degreeCentrality(
|
|
15
|
-
graph: Graph,
|
|
16
|
-
options: CentralityOptions = {},
|
|
17
|
-
): CentralityResult {
|
|
17
|
+
export function degreeCentrality(graph: Graph, options: CentralityOptions = {}): CentralityResult {
|
|
18
18
|
const centrality: CentralityResult = {};
|
|
19
|
-
const {nodeCount} = graph;
|
|
19
|
+
const { nodeCount } = graph;
|
|
20
20
|
|
|
21
21
|
// Calculate normalization factor (same for both directed and undirected graphs)
|
|
22
22
|
const maxPossibleDegree = nodeCount - 1;
|
|
@@ -49,9 +49,7 @@ export function degreeCentrality(
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
// Apply normalization if requested
|
|
52
|
-
const normalizedDegree = options.normalized && maxPossibleDegree > 0 ?
|
|
53
|
-
degree / maxPossibleDegree :
|
|
54
|
-
degree;
|
|
52
|
+
const normalizedDegree = options.normalized && maxPossibleDegree > 0 ? degree / maxPossibleDegree : degree;
|
|
55
53
|
|
|
56
54
|
centrality[node.id.toString()] = normalizedDegree;
|
|
57
55
|
}
|
|
@@ -61,17 +59,17 @@ export function degreeCentrality(
|
|
|
61
59
|
|
|
62
60
|
/**
|
|
63
61
|
* Calculate degree centrality for a specific node
|
|
62
|
+
* @param graph - The input graph to analyze
|
|
63
|
+
* @param nodeId - The node to calculate centrality for
|
|
64
|
+
* @param options - Algorithm configuration options
|
|
65
|
+
* @returns The degree centrality score for the node
|
|
64
66
|
*/
|
|
65
|
-
export function nodeDegreeCentrality(
|
|
66
|
-
graph: Graph,
|
|
67
|
-
nodeId: string | number,
|
|
68
|
-
options: CentralityOptions = {},
|
|
69
|
-
): number {
|
|
67
|
+
export function nodeDegreeCentrality(graph: Graph, nodeId: string | number, options: CentralityOptions = {}): number {
|
|
70
68
|
if (!graph.hasNode(nodeId)) {
|
|
71
69
|
throw new Error(`Node ${String(nodeId)} not found in graph`);
|
|
72
70
|
}
|
|
73
71
|
|
|
74
|
-
const {nodeCount} = graph;
|
|
72
|
+
const { nodeCount } = graph;
|
|
75
73
|
let degree: number;
|
|
76
74
|
|
|
77
75
|
if (graph.isDirected && options.mode) {
|
|
@@ -99,7 +97,5 @@ export function nodeDegreeCentrality(
|
|
|
99
97
|
// Apply normalization if requested
|
|
100
98
|
const maxPossibleDegree = nodeCount - 1;
|
|
101
99
|
|
|
102
|
-
return options.normalized && maxPossibleDegree > 0 ?
|
|
103
|
-
degree / maxPossibleDegree :
|
|
104
|
-
degree;
|
|
100
|
+
return options.normalized && maxPossibleDegree > 0 ? degree / maxPossibleDegree : degree;
|
|
105
101
|
}
|
|
@@ -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
|
* Simplified Delta-based PageRank that matches the standard algorithm
|
|
@@ -13,6 +13,10 @@ export class SimpleDeltaPageRank {
|
|
|
13
13
|
private nodeCount: number;
|
|
14
14
|
private previousScores: Map<NodeId, number> | null = null;
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new SimpleDeltaPageRank instance for the given graph.
|
|
18
|
+
* @param graph - The directed graph to compute PageRank on
|
|
19
|
+
*/
|
|
16
20
|
constructor(graph: Graph) {
|
|
17
21
|
if (!graph.isDirected) {
|
|
18
22
|
throw new Error("PageRank requires a directed graph");
|
|
@@ -22,20 +26,26 @@ export class SimpleDeltaPageRank {
|
|
|
22
26
|
this.nodeCount = graph.nodeCount;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Computes PageRank scores for all nodes in the graph using power iteration.
|
|
31
|
+
* @param options - Configuration options for PageRank computation
|
|
32
|
+
* @param options.dampingFactor - Probability of following a link (default: 0.85)
|
|
33
|
+
* @param options.tolerance - Convergence tolerance threshold (default: 1e-6)
|
|
34
|
+
* @param options.maxIterations - Maximum number of iterations (default: 100)
|
|
35
|
+
* @param options.personalization - Personalization vector for Personalized PageRank
|
|
36
|
+
* @param options.weight - Edge attribute name for weighted PageRank
|
|
37
|
+
* @returns Map of node IDs to their PageRank scores
|
|
38
|
+
*/
|
|
39
|
+
public compute(
|
|
40
|
+
options: {
|
|
41
|
+
dampingFactor?: number;
|
|
42
|
+
tolerance?: number;
|
|
43
|
+
maxIterations?: number;
|
|
44
|
+
personalization?: Map<NodeId, number>;
|
|
45
|
+
weight?: string;
|
|
46
|
+
} = {},
|
|
47
|
+
): Map<NodeId, number> {
|
|
48
|
+
const { dampingFactor = 0.85, tolerance = 1e-6, maxIterations = 100, personalization, weight } = options;
|
|
39
49
|
|
|
40
50
|
if (this.nodeCount === 0) {
|
|
41
51
|
return new Map();
|
|
@@ -97,7 +107,7 @@ export class SimpleDeltaPageRank {
|
|
|
97
107
|
}
|
|
98
108
|
|
|
99
109
|
if (danglingSum > 0) {
|
|
100
|
-
const danglingContribution = dampingFactor * danglingSum / this.nodeCount;
|
|
110
|
+
const danglingContribution = (dampingFactor * danglingSum) / this.nodeCount;
|
|
101
111
|
for (const nodeId of scores.keys()) {
|
|
102
112
|
const current = newScores.get(nodeId) ?? 0;
|
|
103
113
|
if (personalVector) {
|
|
@@ -175,9 +185,13 @@ export class SimpleDeltaPageRank {
|
|
|
175
185
|
/**
|
|
176
186
|
* Perform incremental update after graph modification.
|
|
177
187
|
* This is where delta-based approach provides significant speedup.
|
|
178
|
-
*
|
|
179
|
-
* @param
|
|
180
|
-
* @param options
|
|
188
|
+
* @param modifiedNodes - Set of nodes that were modified (edges added/removed)
|
|
189
|
+
* @param options - Computation options
|
|
190
|
+
* @param options.dampingFactor - Probability of following a link (default: 0.85)
|
|
191
|
+
* @param options.tolerance - Convergence tolerance threshold (default: 1e-6)
|
|
192
|
+
* @param options.maxIterations - Maximum number of iterations (default: 100)
|
|
193
|
+
* @param options.personalization - Personalization vector for Personalized PageRank
|
|
194
|
+
* @param options.weight - Edge attribute name for weighted PageRank
|
|
181
195
|
* @returns Updated PageRank scores
|
|
182
196
|
*/
|
|
183
197
|
public update(
|
|
@@ -195,13 +209,7 @@ export class SimpleDeltaPageRank {
|
|
|
195
209
|
return this.compute(options);
|
|
196
210
|
}
|
|
197
211
|
|
|
198
|
-
const {
|
|
199
|
-
dampingFactor = 0.85,
|
|
200
|
-
tolerance = 1e-6,
|
|
201
|
-
maxIterations = 100,
|
|
202
|
-
personalization,
|
|
203
|
-
weight,
|
|
204
|
-
} = options;
|
|
212
|
+
const { dampingFactor = 0.85, tolerance = 1e-6, maxIterations = 100, personalization, weight } = options;
|
|
205
213
|
|
|
206
214
|
// Initialize scores from previous computation
|
|
207
215
|
const scores = new Map(this.previousScores);
|
|
@@ -275,7 +283,7 @@ export class SimpleDeltaPageRank {
|
|
|
275
283
|
}
|
|
276
284
|
|
|
277
285
|
if (danglingSum > 0) {
|
|
278
|
-
const danglingContribution = dampingFactor * danglingSum / this.nodeCount;
|
|
286
|
+
const danglingContribution = (dampingFactor * danglingSum) / this.nodeCount;
|
|
279
287
|
for (const nodeId of scores.keys()) {
|
|
280
288
|
const current = newScores.get(nodeId) ?? 0;
|
|
281
289
|
if (personalVector) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {Graph} from "../../core/graph.js";
|
|
2
|
-
import {PriorityQueue} from "../../data-structures/priority-queue.js";
|
|
3
|
-
import type {NodeId} from "../../types/index.js";
|
|
1
|
+
import type { Graph } from "../../core/graph.js";
|
|
2
|
+
import { PriorityQueue } from "../../data-structures/priority-queue.js";
|
|
3
|
+
import type { NodeId } from "../../types/index.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Delta-based PageRank implementation for faster convergence
|
|
@@ -45,6 +45,10 @@ export interface DeltaPageRankOptions {
|
|
|
45
45
|
weight?: string;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Delta-based PageRank class that tracks changes between iterations
|
|
50
|
+
* and only processes nodes with significant changes for improved performance.
|
|
51
|
+
*/
|
|
48
52
|
export class DeltaPageRank {
|
|
49
53
|
private graph: Graph;
|
|
50
54
|
private scores: Map<NodeId, number>;
|
|
@@ -55,6 +59,10 @@ export class DeltaPageRank {
|
|
|
55
59
|
private danglingNodes: Set<NodeId>;
|
|
56
60
|
private nodeCount: number;
|
|
57
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Creates a new DeltaPageRank instance for the given graph.
|
|
64
|
+
* @param graph - The directed graph to compute PageRank on
|
|
65
|
+
*/
|
|
58
66
|
constructor(graph: Graph) {
|
|
59
67
|
if (!graph.isDirected) {
|
|
60
68
|
throw new Error("DeltaPageRank requires a directed graph");
|
|
@@ -101,6 +109,11 @@ export class DeltaPageRank {
|
|
|
101
109
|
}
|
|
102
110
|
}
|
|
103
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Computes PageRank scores using delta-based iteration for faster convergence.
|
|
114
|
+
* @param options - Configuration options for PageRank computation
|
|
115
|
+
* @returns Map of node IDs to their PageRank scores
|
|
116
|
+
*/
|
|
104
117
|
public compute(options: DeltaPageRankOptions = {}): Map<NodeId, number> {
|
|
105
118
|
const {
|
|
106
119
|
dampingFactor = 0.85,
|
|
@@ -149,7 +162,7 @@ export class DeltaPageRank {
|
|
|
149
162
|
}
|
|
150
163
|
|
|
151
164
|
if (danglingSum > 0) {
|
|
152
|
-
const danglingContribution = dampingFactor * danglingSum / this.nodeCount;
|
|
165
|
+
const danglingContribution = (dampingFactor * danglingSum) / this.nodeCount;
|
|
153
166
|
for (const node of this.graph.nodes()) {
|
|
154
167
|
const nodeId = node.id;
|
|
155
168
|
const currentDelta = nextDeltas.get(nodeId) ?? 0;
|
|
@@ -197,7 +210,7 @@ export class DeltaPageRank {
|
|
|
197
210
|
const nodeId = node.id;
|
|
198
211
|
const currentDelta = nextDeltas.get(nodeId) ?? 0;
|
|
199
212
|
if (personalVector) {
|
|
200
|
-
nextDeltas.set(nodeId, currentDelta + (
|
|
213
|
+
nextDeltas.set(nodeId, currentDelta + (1 - dampingFactor) * (personalVector.get(nodeId) ?? 0));
|
|
201
214
|
} else {
|
|
202
215
|
nextDeltas.set(nodeId, currentDelta + randomJump);
|
|
203
216
|
}
|
|
@@ -231,13 +244,13 @@ export class DeltaPageRank {
|
|
|
231
244
|
}
|
|
232
245
|
|
|
233
246
|
/**
|
|
234
|
-
* Update PageRank scores after graph modification
|
|
235
|
-
* This is where delta-based approach really shines
|
|
247
|
+
* Update PageRank scores after graph modification.
|
|
248
|
+
* This is where delta-based approach really shines.
|
|
249
|
+
* @param modifiedNodes - Set of nodes that were modified (edges added/removed)
|
|
250
|
+
* @param options - Configuration options for PageRank computation
|
|
251
|
+
* @returns Updated PageRank scores
|
|
236
252
|
*/
|
|
237
|
-
public update(
|
|
238
|
-
modifiedNodes: Set<NodeId>,
|
|
239
|
-
options: DeltaPageRankOptions = {},
|
|
240
|
-
): Map<NodeId, number> {
|
|
253
|
+
public update(modifiedNodes: Set<NodeId>, options: DeltaPageRankOptions = {}): Map<NodeId, number> {
|
|
241
254
|
// Mark modified nodes and their neighbors as active
|
|
242
255
|
this.activeNodes.clear();
|
|
243
256
|
|
|
@@ -286,6 +299,10 @@ export class PriorityDeltaPageRank {
|
|
|
286
299
|
private danglingNodes: Set<NodeId>;
|
|
287
300
|
private nodeCount: number;
|
|
288
301
|
|
|
302
|
+
/**
|
|
303
|
+
* Creates a new PriorityDeltaPageRank instance for the given graph.
|
|
304
|
+
* @param graph - The directed graph to compute PageRank on
|
|
305
|
+
*/
|
|
289
306
|
constructor(graph: Graph) {
|
|
290
307
|
if (!graph.isDirected) {
|
|
291
308
|
throw new Error("PriorityDeltaPageRank requires a directed graph");
|
|
@@ -332,6 +349,12 @@ export class PriorityDeltaPageRank {
|
|
|
332
349
|
}
|
|
333
350
|
}
|
|
334
351
|
|
|
352
|
+
/**
|
|
353
|
+
* Computes PageRank scores using priority queue-based delta iteration.
|
|
354
|
+
* Processes nodes in order of their delta magnitude for optimal convergence.
|
|
355
|
+
* @param options - Configuration options for PageRank computation
|
|
356
|
+
* @returns Map of node IDs to their PageRank scores
|
|
357
|
+
*/
|
|
335
358
|
public computeWithPriority(options: DeltaPageRankOptions = {}): Map<NodeId, number> {
|
|
336
359
|
const {
|
|
337
360
|
dampingFactor = 0.85,
|