@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,220 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AdjacencyView,
|
|
3
|
+
type F64,
|
|
4
|
+
type GraphSnapshot,
|
|
5
|
+
INVALID_INDEX,
|
|
6
|
+
type NumericVector,
|
|
7
|
+
type U32,
|
|
8
|
+
} from "@graphty/graph-format";
|
|
9
|
+
|
|
10
|
+
import { walkPredArcs, walkPredEdges } from "./dijkstra.js";
|
|
11
|
+
import { IndexedMinHeap } from "./structures/min-heap.js";
|
|
12
|
+
|
|
13
|
+
/** Options of the point-to-point searches. @public */
|
|
14
|
+
export interface PathOptions {
|
|
15
|
+
/** Per-arc weight override, arcCount long -- the facade passes `expandEdges(s, shadow.data)`. */
|
|
16
|
+
readonly weights?: NumericVector | undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** One shortest path between two nodes. @public */
|
|
20
|
+
export interface PathResult {
|
|
21
|
+
/** Sum of the path's weights, added from the source; Infinity when the target is unreachable. */
|
|
22
|
+
readonly distance: number;
|
|
23
|
+
/** Node indices from the source to the target inclusive; empty when unreachable. */
|
|
24
|
+
readonly path: U32;
|
|
25
|
+
/** Logical edge indices along the path, one fewer than `path`: the exact parallel edge taken. */
|
|
26
|
+
readonly edges: U32;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** A* result: the path plus the search state the legacy `astarWithDetails` reports. @public */
|
|
30
|
+
export interface AstarResult extends PathResult {
|
|
31
|
+
/** Best known cost from the source per node; Infinity for a node the search never reached. */
|
|
32
|
+
readonly gScore: F64;
|
|
33
|
+
/** `gScore` plus the heuristic, per node; Infinity for a node the search never reached. */
|
|
34
|
+
readonly fScore: F64;
|
|
35
|
+
/** Nodes expanded, in expansion order; the target is not expanded, so it is not listed. */
|
|
36
|
+
readonly visited: U32;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const NO_PATH: PathResult = { distance: Infinity, path: new Uint32Array(0), edges: new Uint32Array(0) };
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Bidirectional Dijkstra between two nodes: one search forward from the source, one backward from
|
|
43
|
+
* the target over `reverse()`, each step taken by the side whose next key is smaller, stopping once
|
|
44
|
+
* the two next keys sum to at least the best path found. That is the point-to-point query legacy
|
|
45
|
+
* `dijkstraPath` answers. The path is recorded as ARCS, so a parallel edge on it is the exact edge.
|
|
46
|
+
* @param s - The snapshot to search
|
|
47
|
+
* @param source - The node index to start from
|
|
48
|
+
* @param target - The node index to reach
|
|
49
|
+
* @param options - Per-arc weight override
|
|
50
|
+
* @returns The distance, the node path and the logical edges on it
|
|
51
|
+
* @throws Error when any weight is negative
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
export function bidirectionalDijkstra(
|
|
55
|
+
s: GraphSnapshot,
|
|
56
|
+
source: number,
|
|
57
|
+
target: number,
|
|
58
|
+
options: PathOptions = {},
|
|
59
|
+
): PathResult {
|
|
60
|
+
if (source === target) {
|
|
61
|
+
return { distance: 0, path: Uint32Array.of(source), edges: new Uint32Array(0) };
|
|
62
|
+
}
|
|
63
|
+
const n = s.nodeCount;
|
|
64
|
+
const weights: NumericVector | null = options.weights ?? s.weights;
|
|
65
|
+
// Checked up front, not per relaxed arc: the search stops early, so a per-arc check would miss
|
|
66
|
+
// a negative edge beyond the meeting point that legacy (which runs both searches out) refuses.
|
|
67
|
+
if (weights?.some((w) => w < 0) === true) {
|
|
68
|
+
throw new Error("Bidirectional Dijkstra does not support negative edge weights");
|
|
69
|
+
}
|
|
70
|
+
const rev = s.reverse();
|
|
71
|
+
const weightOf = (arc: number): number => (weights === null ? 1 : weights[arc]);
|
|
72
|
+
const distF = new Float64Array(n).fill(Infinity);
|
|
73
|
+
const distB = new Float64Array(n).fill(Infinity);
|
|
74
|
+
// Forward: the arc into each node. Backward: the reverse-view arc that reached each node from
|
|
75
|
+
// its successor toward the target -- on an undirected snapshot that arc points the other way,
|
|
76
|
+
// so the successor node is kept too rather than read off the arc.
|
|
77
|
+
const predArc = new Uint32Array(n).fill(INVALID_INDEX);
|
|
78
|
+
const succRevArc = new Uint32Array(n).fill(INVALID_INDEX);
|
|
79
|
+
const succNode = new Uint32Array(n).fill(INVALID_INDEX);
|
|
80
|
+
const heapF = new IndexedMinHeap(n);
|
|
81
|
+
const heapB = new IndexedMinHeap(n);
|
|
82
|
+
distF[source] = 0;
|
|
83
|
+
distB[target] = 0;
|
|
84
|
+
heapF.push(source, 0);
|
|
85
|
+
heapB.push(target, 0);
|
|
86
|
+
let best = Infinity;
|
|
87
|
+
// The step joining the two searches: meetFrom -> meetTo over logical edge meetEdge.
|
|
88
|
+
let meetFrom = INVALID_INDEX;
|
|
89
|
+
let meetTo = INVALID_INDEX;
|
|
90
|
+
let meetEdge = INVALID_INDEX;
|
|
91
|
+
let meetWeight = 0;
|
|
92
|
+
|
|
93
|
+
while (heapF.peekKey() + heapB.peekKey() < best) {
|
|
94
|
+
if (heapF.peekKey() <= heapB.peekKey()) {
|
|
95
|
+
const u = heapF.pop();
|
|
96
|
+
for (let a = s.rowPtr[u]; a < s.rowPtr[u + 1]; a++) {
|
|
97
|
+
const v = s.colIdx[a];
|
|
98
|
+
const w = weightOf(a);
|
|
99
|
+
const dv = distF[u] + w;
|
|
100
|
+
if (dv < distF[v]) {
|
|
101
|
+
distF[v] = dv;
|
|
102
|
+
predArc[v] = a;
|
|
103
|
+
heapF.pushOrDecrease(v, dv);
|
|
104
|
+
}
|
|
105
|
+
if (dv + distB[v] < best) {
|
|
106
|
+
best = dv + distB[v];
|
|
107
|
+
[meetFrom, meetTo, meetEdge, meetWeight] = [u, v, s.arcToEdge[a], w];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
const v = heapB.pop();
|
|
112
|
+
for (let k = rev.rowPtr[v]; k < rev.rowPtr[v + 1]; k++) {
|
|
113
|
+
const u = rev.colIdx[k];
|
|
114
|
+
const w = weightOf(rev.fwdArc[k]);
|
|
115
|
+
const du = distB[v] + w;
|
|
116
|
+
if (du < distB[u]) {
|
|
117
|
+
distB[u] = du;
|
|
118
|
+
succRevArc[u] = k;
|
|
119
|
+
succNode[u] = v;
|
|
120
|
+
heapB.pushOrDecrease(u, du);
|
|
121
|
+
}
|
|
122
|
+
if (distF[u] + du < best) {
|
|
123
|
+
best = distF[u] + du;
|
|
124
|
+
[meetFrom, meetTo, meetEdge, meetWeight] = [u, v, rev.arcToEdge[k], w];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (meetFrom === INVALID_INDEX) {
|
|
130
|
+
return NO_PATH;
|
|
131
|
+
}
|
|
132
|
+
const nodes: number[] = [];
|
|
133
|
+
const edges: number[] = [];
|
|
134
|
+
const steps: number[] = []; // the weight of each edge, source end first
|
|
135
|
+
for (let node = meetFrom; node !== source; node = s.arcSource(predArc[node])) {
|
|
136
|
+
nodes.push(node);
|
|
137
|
+
edges.push(s.arcToEdge[predArc[node]]);
|
|
138
|
+
steps.push(weightOf(predArc[node]));
|
|
139
|
+
}
|
|
140
|
+
nodes.push(source);
|
|
141
|
+
nodes.reverse();
|
|
142
|
+
edges.reverse();
|
|
143
|
+
steps.reverse();
|
|
144
|
+
edges.push(meetEdge);
|
|
145
|
+
steps.push(meetWeight);
|
|
146
|
+
nodes.push(meetTo);
|
|
147
|
+
for (let node = meetTo; node !== target; node = succNode[node]) {
|
|
148
|
+
edges.push(rev.arcToEdge[succRevArc[node]]);
|
|
149
|
+
steps.push(weightOf(rev.fwdArc[succRevArc[node]]));
|
|
150
|
+
nodes.push(succNode[node]);
|
|
151
|
+
}
|
|
152
|
+
let distance = 0;
|
|
153
|
+
for (const w of steps) {
|
|
154
|
+
distance += w;
|
|
155
|
+
}
|
|
156
|
+
return { distance, path: Uint32Array.from(nodes), edges: Uint32Array.from(edges) };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* A* between two nodes: Dijkstra keyed by cost so far plus `heuristic(node, target)`, stopping when
|
|
161
|
+
* the target is taken from the queue. An expanded node is never reopened, as in legacy `astar`, so
|
|
162
|
+
* the path is shortest when the heuristic is consistent. The predecessor is the relaxing ARC, so a
|
|
163
|
+
* parallel edge on the path is the exact edge.
|
|
164
|
+
* @param g - The adjacency to search
|
|
165
|
+
* @param source - The node index to start from
|
|
166
|
+
* @param target - The node index to reach
|
|
167
|
+
* @param heuristic - Estimated remaining cost from a node index to the target index
|
|
168
|
+
* @param options - Per-arc weight override
|
|
169
|
+
* @returns The path, plus the per-node scores and the expansion order
|
|
170
|
+
* @public
|
|
171
|
+
*/
|
|
172
|
+
export function astar(
|
|
173
|
+
g: AdjacencyView,
|
|
174
|
+
source: number,
|
|
175
|
+
target: number,
|
|
176
|
+
heuristic: (node: number, target: number) => number,
|
|
177
|
+
options: PathOptions = {},
|
|
178
|
+
): AstarResult {
|
|
179
|
+
const n = g.nodeCount;
|
|
180
|
+
if (!(target >= 0 && target < n)) {
|
|
181
|
+
throw new RangeError(`Target index ${String(target)} is outside the graph's ${String(n)} nodes`);
|
|
182
|
+
}
|
|
183
|
+
const weights: NumericVector | null = options.weights ?? g.weights;
|
|
184
|
+
const gScore = new Float64Array(n).fill(Infinity);
|
|
185
|
+
const fScore = new Float64Array(n).fill(Infinity);
|
|
186
|
+
const predArc = new Uint32Array(n).fill(INVALID_INDEX);
|
|
187
|
+
const closed = new Uint8Array(n);
|
|
188
|
+
const visited: number[] = [];
|
|
189
|
+
const heap = new IndexedMinHeap(n);
|
|
190
|
+
gScore[source] = 0;
|
|
191
|
+
fScore[source] = heuristic(source, target);
|
|
192
|
+
heap.push(source, fScore[source]);
|
|
193
|
+
while (!heap.isEmpty()) {
|
|
194
|
+
const u = heap.pop();
|
|
195
|
+
if (u === target) {
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
closed[u] = 1;
|
|
199
|
+
visited.push(u);
|
|
200
|
+
for (let a = g.rowPtr[u]; a < g.rowPtr[u + 1]; a++) {
|
|
201
|
+
const v = g.colIdx[a];
|
|
202
|
+
if (closed[v] === 1) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const tentative = gScore[u] + (weights === null ? 1 : weights[a]);
|
|
206
|
+
if (tentative < gScore[v]) {
|
|
207
|
+
gScore[v] = tentative;
|
|
208
|
+
fScore[v] = tentative + heuristic(v, target);
|
|
209
|
+
predArc[v] = a;
|
|
210
|
+
heap.pushOrDecrease(v, fScore[v]);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const state = { gScore, fScore, visited: Uint32Array.from(visited) };
|
|
215
|
+
if (gScore[target] === Infinity) {
|
|
216
|
+
return { ...NO_PATH, ...state };
|
|
217
|
+
}
|
|
218
|
+
const path = walkPredArcs(g, predArc, source, target);
|
|
219
|
+
return { distance: gScore[target], path, edges: walkPredEdges(g, predArc, source, target), ...state };
|
|
220
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AdjacencyView,
|
|
3
|
+
type DerivedGraph,
|
|
4
|
+
type GraphSnapshot,
|
|
5
|
+
INVALID_INDEX,
|
|
6
|
+
type U32,
|
|
7
|
+
} from "@graphty/graph-format";
|
|
8
|
+
|
|
9
|
+
import { type ArcOrderOption, checkArcOrder } from "./bfs.js";
|
|
10
|
+
import { type LabelResult, withGroups } from "./components.js";
|
|
11
|
+
|
|
12
|
+
/** Result of {@link condensation}. @public */
|
|
13
|
+
export interface CondensationResult {
|
|
14
|
+
/** The strongly connected components, labelled in Tarjan completion order. */
|
|
15
|
+
readonly components: LabelResult;
|
|
16
|
+
/**
|
|
17
|
+
* The condensed DAG from `contract(components.labels)`: node `c` is component `c`, one edge per
|
|
18
|
+
* connected ordered pair of components, no self-loops. Its weights are those of the first source
|
|
19
|
+
* edge of each pair; its `nodeRemap` equals `components.labels`.
|
|
20
|
+
*/
|
|
21
|
+
readonly condensed: DerivedGraph;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Strongly connected components by an iterative Tarjan: roots in index order, neighbours in row
|
|
26
|
+
* order unless `options.arcOrder` gives another, and component `c` is the `c`-th to complete -- the numbering the legacy
|
|
27
|
+
* `stronglyConnectedComponents` gives its result array. Completion order is a reverse topological
|
|
28
|
+
* order of the condensation.
|
|
29
|
+
* @param g - A directed adjacency
|
|
30
|
+
* @param options - The neighbour order
|
|
31
|
+
* @returns The partition, labels in completion order
|
|
32
|
+
* @throws Error when the graph is undirected
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
export function stronglyConnectedComponents(g: AdjacencyView, options: ArcOrderOption = {}): LabelResult {
|
|
36
|
+
const { labels, count } = tarjan(g, options);
|
|
37
|
+
return withGroups(labels, count);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The Tarjan walk behind {@link stronglyConnectedComponents}, also returning every node in the
|
|
42
|
+
* order it left the component stack. Each component leaves as one run, in label order, its members
|
|
43
|
+
* in reverse discovery order -- the order the legacy `stronglyConnectedComponents` lists them in.
|
|
44
|
+
* @param g - A directed adjacency
|
|
45
|
+
* @param options - The neighbour order
|
|
46
|
+
* @returns The labels, their count and the pop order
|
|
47
|
+
* @throws Error when the graph is undirected
|
|
48
|
+
*/
|
|
49
|
+
export function tarjan(g: AdjacencyView, options: ArcOrderOption = {}): { labels: U32; count: number; popped: U32 } {
|
|
50
|
+
if (!g.directed) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
"Strongly connected components require a directed graph. Use connectedComponents for an undirected one.",
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
const { nodeCount, rowPtr, colIdx } = g;
|
|
56
|
+
const arcOrder = checkArcOrder(g, options.arcOrder);
|
|
57
|
+
const index = new Uint32Array(nodeCount).fill(INVALID_INDEX);
|
|
58
|
+
const low = new Uint32Array(nodeCount);
|
|
59
|
+
const cursor = new Uint32Array(nodeCount);
|
|
60
|
+
const onStack = new Uint8Array(nodeCount);
|
|
61
|
+
const callStack = new Uint32Array(nodeCount);
|
|
62
|
+
const sccStack = new Uint32Array(nodeCount);
|
|
63
|
+
const labels = new Uint32Array(nodeCount);
|
|
64
|
+
const popped = new Uint32Array(nodeCount);
|
|
65
|
+
let poppedCount = 0;
|
|
66
|
+
let next = 0;
|
|
67
|
+
let count = 0;
|
|
68
|
+
let sp = 0;
|
|
69
|
+
let top = 0;
|
|
70
|
+
// The body of the recursive call before its loop over neighbours.
|
|
71
|
+
const enter = (u: number): void => {
|
|
72
|
+
index[u] = next;
|
|
73
|
+
low[u] = next;
|
|
74
|
+
next++;
|
|
75
|
+
cursor[u] = rowPtr[u];
|
|
76
|
+
sccStack[sp++] = u;
|
|
77
|
+
onStack[u] = 1;
|
|
78
|
+
callStack[top++] = u;
|
|
79
|
+
};
|
|
80
|
+
for (let r = 0; r < nodeCount; r++) {
|
|
81
|
+
if (index[r] !== INVALID_INDEX) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
enter(r);
|
|
85
|
+
while (top > 0) {
|
|
86
|
+
const x = callStack[top - 1];
|
|
87
|
+
if (cursor[x] < rowPtr[x + 1]) {
|
|
88
|
+
const a = cursor[x]++;
|
|
89
|
+
const v = colIdx[arcOrder === null ? a : arcOrder[a]];
|
|
90
|
+
if (index[v] === INVALID_INDEX) {
|
|
91
|
+
enter(v);
|
|
92
|
+
} else if (onStack[v] === 1 && index[v] < low[x]) {
|
|
93
|
+
low[x] = index[v];
|
|
94
|
+
}
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
// x returns: close its component if it is a root, then pass its low link to the caller.
|
|
98
|
+
top--;
|
|
99
|
+
if (low[x] === index[x]) {
|
|
100
|
+
let w: number;
|
|
101
|
+
do {
|
|
102
|
+
w = sccStack[--sp];
|
|
103
|
+
onStack[w] = 0;
|
|
104
|
+
labels[w] = count;
|
|
105
|
+
popped[poppedCount++] = w;
|
|
106
|
+
} while (w !== x);
|
|
107
|
+
count++;
|
|
108
|
+
}
|
|
109
|
+
if (top > 0 && low[x] < low[callStack[top - 1]]) {
|
|
110
|
+
low[callStack[top - 1]] = low[x];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return { labels, count, popped };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The condensation of a directed graph: its strongly connected components, and the DAG with one
|
|
119
|
+
* node per component that `contract()` builds from their labels. The labels already run `0..k-1`,
|
|
120
|
+
* so contract keeps them as block indices and the condensed node numbering is the component
|
|
121
|
+
* numbering.
|
|
122
|
+
* @param s - A directed snapshot
|
|
123
|
+
* @param options - The neighbour order Tarjan tries arcs in, which fixes the component numbering
|
|
124
|
+
* @returns The components and the condensed graph
|
|
125
|
+
* @throws Error when the snapshot is undirected
|
|
126
|
+
* @public
|
|
127
|
+
*/
|
|
128
|
+
export function condensation(s: GraphSnapshot, options: ArcOrderOption = {}): CondensationResult {
|
|
129
|
+
const components = stronglyConnectedComponents(s, options);
|
|
130
|
+
const condensed = s.contract(components.labels, { selfLoops: "drop", parallel: "merge", weights: "first" });
|
|
131
|
+
return { components, condensed };
|
|
132
|
+
}
|