@graphty/webgpu-graph-algorithms 0.6.3 → 0.6.4
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 +62 -32
- package/dist/browser.js +1 -1
- package/dist/chunks/{context-BXqgCifx.js → context-Dvq-Cc6v.js} +71 -25
- package/dist/chunks/context-Dvq-Cc6v.js.map +1 -0
- package/dist/node.js +1 -1
- package/dist/src/accelerator.d.ts +8 -6
- package/dist/src/accelerator.d.ts.map +1 -1
- package/dist/src/accelerator.js +57 -6
- package/dist/src/accelerator.js.map +1 -1
- package/dist/src/algorithms/bellman-ford.d.ts +60 -0
- package/dist/src/algorithms/bellman-ford.d.ts.map +1 -0
- package/dist/src/algorithms/bellman-ford.js +301 -0
- package/dist/src/algorithms/bellman-ford.js.map +1 -0
- package/dist/src/algorithms/bfs.d.ts +67 -0
- package/dist/src/algorithms/bfs.d.ts.map +1 -0
- package/dist/src/algorithms/bfs.js +534 -0
- package/dist/src/algorithms/bfs.js.map +1 -0
- package/dist/src/algorithms/closeness.d.ts +53 -0
- package/dist/src/algorithms/closeness.d.ts.map +1 -0
- package/dist/src/algorithms/closeness.js +323 -0
- package/dist/src/algorithms/closeness.js.map +1 -0
- package/dist/src/algorithms/scope.d.ts +5 -3
- package/dist/src/algorithms/scope.d.ts.map +1 -1
- package/dist/src/algorithms/scope.js +3 -0
- package/dist/src/algorithms/scope.js.map +1 -1
- package/dist/src/algorithms/sssp.d.ts +71 -0
- package/dist/src/algorithms/sssp.d.ts.map +1 -0
- package/dist/src/algorithms/sssp.js +585 -0
- package/dist/src/algorithms/sssp.js.map +1 -0
- package/dist/src/constants.d.ts +12 -0
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +12 -0
- package/dist/src/constants.js.map +1 -1
- package/dist/src/index.d.ts +8 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +7 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/kernel/prelude.d.ts +4 -4
- package/dist/src/kernel/prelude.d.ts.map +1 -1
- package/dist/src/kernel/prelude.js +39 -5
- package/dist/src/kernel/prelude.js.map +1 -1
- package/dist/src/kernel/uniform-ring.d.ts +8 -0
- package/dist/src/kernel/uniform-ring.d.ts.map +1 -1
- package/dist/src/kernel/uniform-ring.js +13 -0
- package/dist/src/kernel/uniform-ring.js.map +1 -1
- package/dist/src/kernels.d.ts +44 -4
- package/dist/src/kernels.d.ts.map +1 -1
- package/dist/src/kernels.js +371 -3
- package/dist/src/kernels.js.map +1 -1
- package/dist/src/primitives/advance.d.ts +62 -0
- package/dist/src/primitives/advance.d.ts.map +1 -0
- package/dist/src/primitives/advance.js +95 -0
- package/dist/src/primitives/advance.js.map +1 -0
- package/dist/src/primitives/compact.d.ts +89 -0
- package/dist/src/primitives/compact.d.ts.map +1 -0
- package/dist/src/primitives/compact.js +233 -0
- package/dist/src/primitives/compact.js.map +1 -0
- package/dist/src/primitives/core-shape.d.ts +22 -1
- package/dist/src/primitives/core-shape.d.ts.map +1 -1
- package/dist/src/primitives/core-shape.js +33 -3
- package/dist/src/primitives/core-shape.js.map +1 -1
- package/dist/src/primitives/frontier.d.ts +156 -0
- package/dist/src/primitives/frontier.d.ts.map +1 -0
- package/dist/src/primitives/frontier.js +259 -0
- package/dist/src/primitives/frontier.js.map +1 -0
- package/dist/src/types/accelerator.d.ts +16 -7
- package/dist/src/types/accelerator.d.ts.map +1 -1
- package/dist/src/types/traversal.d.ts +53 -0
- package/dist/src/types/traversal.d.ts.map +1 -0
- package/dist/src/types/traversal.js +10 -0
- package/dist/src/types/traversal.js.map +1 -0
- package/dist/src/wgsl/advance-expand.wgsl.d.ts +19 -0
- package/dist/src/wgsl/advance-expand.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/advance-expand.wgsl.js +69 -0
- package/dist/src/wgsl/advance-expand.wgsl.js.map +1 -0
- package/dist/src/wgsl/bf-relax.wgsl.d.ts +22 -0
- package/dist/src/wgsl/bf-relax.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bf-relax.wgsl.js +58 -0
- package/dist/src/wgsl/bf-relax.wgsl.js.map +1 -0
- package/dist/src/wgsl/bfs-bitset-build.wgsl.d.ts +15 -0
- package/dist/src/wgsl/bfs-bitset-build.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bfs-bitset-build.wgsl.js +24 -0
- package/dist/src/wgsl/bfs-bitset-build.wgsl.js.map +1 -0
- package/dist/src/wgsl/bfs-bottom-up.wgsl.d.ts +20 -0
- package/dist/src/wgsl/bfs-bottom-up.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bfs-bottom-up.wgsl.js +67 -0
- package/dist/src/wgsl/bfs-bottom-up.wgsl.js.map +1 -0
- package/dist/src/wgsl/bfs-contract.wgsl.d.ts +20 -0
- package/dist/src/wgsl/bfs-contract.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bfs-contract.wgsl.js +55 -0
- package/dist/src/wgsl/bfs-contract.wgsl.js.map +1 -0
- package/dist/src/wgsl/bfs-fused.wgsl.d.ts +25 -0
- package/dist/src/wgsl/bfs-fused.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bfs-fused.wgsl.js +78 -0
- package/dist/src/wgsl/bfs-fused.wgsl.js.map +1 -0
- package/dist/src/wgsl/bfs-unvisited-flags.wgsl.d.ts +18 -0
- package/dist/src/wgsl/bfs-unvisited-flags.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/bfs-unvisited-flags.wgsl.js +42 -0
- package/dist/src/wgsl/bfs-unvisited-flags.wgsl.js.map +1 -0
- package/dist/src/wgsl/closeness-reduce.wgsl.d.ts +17 -0
- package/dist/src/wgsl/closeness-reduce.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/closeness-reduce.wgsl.js +65 -0
- package/dist/src/wgsl/closeness-reduce.wgsl.js.map +1 -0
- package/dist/src/wgsl/closeness-sweep.wgsl.d.ts +20 -0
- package/dist/src/wgsl/closeness-sweep.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/closeness-sweep.wgsl.js +96 -0
- package/dist/src/wgsl/closeness-sweep.wgsl.js.map +1 -0
- package/dist/src/wgsl/compact-scatter.wgsl.d.ts +9 -0
- package/dist/src/wgsl/compact-scatter.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/compact-scatter.wgsl.js +17 -0
- package/dist/src/wgsl/compact-scatter.wgsl.js.map +1 -0
- package/dist/src/wgsl/dedupe-claim.wgsl.d.ts +10 -0
- package/dist/src/wgsl/dedupe-claim.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/dedupe-claim.wgsl.js +19 -0
- package/dist/src/wgsl/dedupe-claim.wgsl.js.map +1 -0
- package/dist/src/wgsl/dedupe-filter.wgsl.d.ts +12 -0
- package/dist/src/wgsl/dedupe-filter.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/dedupe-filter.wgsl.js +46 -0
- package/dist/src/wgsl/dedupe-filter.wgsl.js.map +1 -0
- package/dist/src/wgsl/frontier-finalize.wgsl.d.ts +59 -0
- package/dist/src/wgsl/frontier-finalize.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/frontier-finalize.wgsl.js +210 -0
- package/dist/src/wgsl/frontier-finalize.wgsl.js.map +1 -0
- package/dist/src/wgsl/sssp-pred.wgsl.d.ts +28 -0
- package/dist/src/wgsl/sssp-pred.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/sssp-pred.wgsl.js +80 -0
- package/dist/src/wgsl/sssp-pred.wgsl.js.map +1 -0
- package/dist/src/wgsl/sssp-relax.wgsl.d.ts +30 -0
- package/dist/src/wgsl/sssp-relax.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/sssp-relax.wgsl.js +72 -0
- package/dist/src/wgsl/sssp-relax.wgsl.js.map +1 -0
- package/dist/webgpu-graph-algorithms.js +3207 -377
- package/dist/webgpu-graph-algorithms.js.map +1 -1
- package/package.json +5 -4
- package/src/accelerator.ts +65 -7
- package/src/algorithms/bellman-ford.ts +387 -0
- package/src/algorithms/bfs.ts +626 -0
- package/src/algorithms/closeness.ts +395 -0
- package/src/algorithms/scope.ts +13 -3
- package/src/algorithms/sssp.ts +767 -0
- package/src/constants.ts +12 -0
- package/src/index.ts +14 -1
- package/src/kernel/prelude.ts +39 -4
- package/src/kernel/uniform-ring.ts +14 -0
- package/src/kernels.ts +450 -6
- package/src/primitives/advance.ts +130 -0
- package/src/primitives/compact.ts +323 -0
- package/src/primitives/core-shape.ts +41 -3
- package/src/primitives/frontier.ts +388 -0
- package/src/types/accelerator.ts +18 -5
- package/src/types/traversal.ts +56 -0
- package/src/wgsl/advance-expand.wgsl.ts +68 -0
- package/src/wgsl/bf-relax.wgsl.ts +57 -0
- package/src/wgsl/bfs-bitset-build.wgsl.ts +23 -0
- package/src/wgsl/bfs-bottom-up.wgsl.ts +66 -0
- package/src/wgsl/bfs-contract.wgsl.ts +54 -0
- package/src/wgsl/bfs-fused.wgsl.ts +77 -0
- package/src/wgsl/bfs-unvisited-flags.wgsl.ts +41 -0
- package/src/wgsl/closeness-reduce.wgsl.ts +64 -0
- package/src/wgsl/closeness-sweep.wgsl.ts +95 -0
- package/src/wgsl/compact-scatter.wgsl.ts +16 -0
- package/src/wgsl/dedupe-claim.wgsl.ts +18 -0
- package/src/wgsl/dedupe-filter.wgsl.ts +45 -0
- package/src/wgsl/frontier-finalize.wgsl.ts +209 -0
- package/src/wgsl/sssp-pred.wgsl.ts +79 -0
- package/src/wgsl/sssp-relax.wgsl.ts +71 -0
- package/dist/chunks/context-BXqgCifx.js.map +0 -1
package/dist/node.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { W as WebGpuGraphError, G as GpuContext } from "./chunks/context-
|
|
1
|
+
import { W as WebGpuGraphError, G as GpuContext } from "./chunks/context-Dvq-Cc6v.js";
|
|
2
2
|
const INSTALL_HINT = "install the optional peer dependency webgpu@0.4.0";
|
|
3
3
|
function isDawnModule(loaded) {
|
|
4
4
|
return typeof loaded === "object" && loaded !== null && typeof loaded.create === "function";
|
|
@@ -5,19 +5,21 @@
|
|
|
5
5
|
* `@graphty/algorithms` (W1b, algorithms half), `import type`d by src/types/accelerator.ts, so the object built
|
|
6
6
|
* here is checked against the CPU packages' own contracts. It carries P3's `forceAtlas2`, `release` and `dispose`,
|
|
7
7
|
* P5's `fruchtermanReingold` and `springElectrical` (the two other layout members of spec 9.3, landed together once
|
|
8
|
-
* both models were green, P5 PD-19)
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* both models were green, P5 PD-19), P7's seven algorithm members (spec 8.2, 8.3; M8b-T8, PD-14) and P8's four
|
|
9
|
+
* traversal members (spec 8.4; P8-T13 PD-16, PD-19: `breadthFirstSearch`, `sssp`, `bellmanFord`,
|
|
10
|
+
* `closenessCentrality`, each taking the seam's own option type) and nothing else: the CPU-side dispatchers
|
|
11
|
+
* (`accelerated()`, `createSimulation()`) test `acc.betweennessCentrality !== undefined` /
|
|
12
|
+
* `acc.fruchtermanReingold !== undefined` and route to the CPU when the member is absent (spec 2.4 row "method
|
|
11
13
|
* missing"), so a method the GPU does not implement must not exist here -- never a throwing stub. The remaining
|
|
12
|
-
* algorithm members arrive one per shipped algorithm from
|
|
14
|
+
* algorithm members arrive one per shipped algorithm from P9.
|
|
13
15
|
*/
|
|
14
16
|
import { type GpuContext } from "./context.js";
|
|
15
17
|
import { type AcceleratorOptions, type GpuAccelerator } from "./types/accelerator.js";
|
|
16
18
|
/**
|
|
17
19
|
* Spec 3.3 createAccelerator, verbatim: the object implementing AlgorithmAccelerator & LayoutAccelerator
|
|
18
20
|
* structurally; P3's forceAtlas2, release and dispose, P5's fruchtermanReingold and springElectrical (the same
|
|
19
|
-
* `{ ...o, ...options.layout }` shape as forceAtlas2) plus P7's seven algorithm members
|
|
20
|
-
* its algorithm with `ctx.assertReady()` first. The accelerator's algorithm defaults are not consulted by any of
|
|
21
|
+
* `{ ...o, ...options.layout }` shape as forceAtlas2) plus P7's seven algorithm members and P8's four traversal
|
|
22
|
+
* members, each a delegation to its algorithm with `ctx.assertReady()` first. The accelerator's algorithm defaults are not consulted by any of
|
|
21
23
|
* them: only `betweenness` has any, and it belongs to P9. One per call (the app creates one and injects
|
|
22
24
|
* it, spec 2.4); `kind` is "webgpu"; `options` is a frozen deep copy; `forceAtlas2(o)` is
|
|
23
25
|
* `createForceAtlas2(ctx, { ...o, ...options.layout })`, so the GPU tuning given here wins over anything the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accelerator.d.ts","sourceRoot":"","sources":["../../src/accelerator.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"accelerator.d.ts","sourceRoot":"","sources":["../../src/accelerator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAWH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAI/C,OAAO,EACH,KAAK,kBAAkB,EAEvB,KAAK,cAAc,EAGtB,MAAM,wBAAwB,CAAC;AAiFhC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,cAAc,CA4K/F"}
|
package/dist/src/accelerator.js
CHANGED
|
@@ -5,15 +5,21 @@
|
|
|
5
5
|
* `@graphty/algorithms` (W1b, algorithms half), `import type`d by src/types/accelerator.ts, so the object built
|
|
6
6
|
* here is checked against the CPU packages' own contracts. It carries P3's `forceAtlas2`, `release` and `dispose`,
|
|
7
7
|
* P5's `fruchtermanReingold` and `springElectrical` (the two other layout members of spec 9.3, landed together once
|
|
8
|
-
* both models were green, P5 PD-19)
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* both models were green, P5 PD-19), P7's seven algorithm members (spec 8.2, 8.3; M8b-T8, PD-14) and P8's four
|
|
9
|
+
* traversal members (spec 8.4; P8-T13 PD-16, PD-19: `breadthFirstSearch`, `sssp`, `bellmanFord`,
|
|
10
|
+
* `closenessCentrality`, each taking the seam's own option type) and nothing else: the CPU-side dispatchers
|
|
11
|
+
* (`accelerated()`, `createSimulation()`) test `acc.betweennessCentrality !== undefined` /
|
|
12
|
+
* `acc.fruchtermanReingold !== undefined` and route to the CPU when the member is absent (spec 2.4 row "method
|
|
11
13
|
* missing"), so a method the GPU does not implement must not exist here -- never a throwing stub. The remaining
|
|
12
|
-
* algorithm members arrive one per shipped algorithm from
|
|
14
|
+
* algorithm members arrive one per shipped algorithm from P9.
|
|
13
15
|
*/
|
|
16
|
+
import { bellmanFord } from "./algorithms/bellman-ford.js";
|
|
17
|
+
import { breadthFirstSearch } from "./algorithms/bfs.js";
|
|
18
|
+
import { closenessCentrality } from "./algorithms/closeness.js";
|
|
14
19
|
import { connectedComponents } from "./algorithms/components.js";
|
|
15
20
|
import { pageRank, personalizedPageRank } from "./algorithms/pagerank.js";
|
|
16
21
|
import { eigenvectorCentrality, hits, katzCentrality } from "./algorithms/spectral.js";
|
|
22
|
+
import { sssp } from "./algorithms/sssp.js";
|
|
17
23
|
import { createForceAtlas2 } from "./layouts/forceatlas2.js";
|
|
18
24
|
import { createFruchtermanReingold } from "./layouts/fruchterman-reingold.js";
|
|
19
25
|
import { createSpringElectrical } from "./layouts/spring-electrical.js";
|
|
@@ -66,8 +72,8 @@ function freezeOptions(options) {
|
|
|
66
72
|
/**
|
|
67
73
|
* Spec 3.3 createAccelerator, verbatim: the object implementing AlgorithmAccelerator & LayoutAccelerator
|
|
68
74
|
* structurally; P3's forceAtlas2, release and dispose, P5's fruchtermanReingold and springElectrical (the same
|
|
69
|
-
* `{ ...o, ...options.layout }` shape as forceAtlas2) plus P7's seven algorithm members
|
|
70
|
-
* its algorithm with `ctx.assertReady()` first. The accelerator's algorithm defaults are not consulted by any of
|
|
75
|
+
* `{ ...o, ...options.layout }` shape as forceAtlas2) plus P7's seven algorithm members and P8's four traversal
|
|
76
|
+
* members, each a delegation to its algorithm with `ctx.assertReady()` first. The accelerator's algorithm defaults are not consulted by any of
|
|
71
77
|
* them: only `betweenness` has any, and it belongs to P9. One per call (the app creates one and injects
|
|
72
78
|
* it, spec 2.4); `kind` is "webgpu"; `options` is a frozen deep copy; `forceAtlas2(o)` is
|
|
73
79
|
* `createForceAtlas2(ctx, { ...o, ...options.layout })`, so the GPU tuning given here wins over anything the
|
|
@@ -187,6 +193,51 @@ export function createAccelerator(ctx, options) {
|
|
|
187
193
|
ctx.assertReady();
|
|
188
194
|
return await connectedComponents(ctx, gs, o);
|
|
189
195
|
},
|
|
196
|
+
/**
|
|
197
|
+
* Breadth-first search on the device (spec 8.4; P8-T13). The result is bitwise reproducible (P8 PD-14).
|
|
198
|
+
* @param gs - the snapshot
|
|
199
|
+
* @param source - the source node index
|
|
200
|
+
* @param o - the seam's `BfsOptions` (`maxDepth`)
|
|
201
|
+
* @returns depth, parent, the level-grouped order, visitedCount, levels and switches (spec 3.3 line 830)
|
|
202
|
+
*/
|
|
203
|
+
async breadthFirstSearch(gs, source, o) {
|
|
204
|
+
ctx.assertReady();
|
|
205
|
+
return await breadthFirstSearch(ctx, gs, source, o);
|
|
206
|
+
},
|
|
207
|
+
/**
|
|
208
|
+
* Single-source shortest paths on the device (spec 8.4; P8-T13): the near-far queue over f32 distances, or the
|
|
209
|
+
* breadth-first route when every weight is one.
|
|
210
|
+
* @param gs - the snapshot
|
|
211
|
+
* @param source - the source node index
|
|
212
|
+
* @param o - the seam's `SsspOptions` (`cutoff`, `weights`)
|
|
213
|
+
* @returns dist, predArc and reachedCount (spec 3.3 line 831)
|
|
214
|
+
*/
|
|
215
|
+
async sssp(gs, source, o) {
|
|
216
|
+
ctx.assertReady();
|
|
217
|
+
return await sssp(ctx, gs, source, o);
|
|
218
|
+
},
|
|
219
|
+
/**
|
|
220
|
+
* Bellman-Ford on the device with negative-cycle detection (spec 8.4; P8-T13).
|
|
221
|
+
* @param gs - the snapshot
|
|
222
|
+
* @param source - the source node index
|
|
223
|
+
* @param o - the seam's `SsspOptions` (`cutoff`, `weights`)
|
|
224
|
+
* @returns dist, predArc, reachedCount and hasNegativeCycle (spec 3.3 line 832)
|
|
225
|
+
*/
|
|
226
|
+
async bellmanFord(gs, source, o) {
|
|
227
|
+
ctx.assertReady();
|
|
228
|
+
return await bellmanFord(ctx, gs, source, o);
|
|
229
|
+
},
|
|
230
|
+
/**
|
|
231
|
+
* Closeness centrality on the device (spec 8.4; P8-T13): the bit-parallel multi-source sweep, or one `sssp`
|
|
232
|
+
* per source when `weighted`. `maxIterations` / `tolerance` are refused when defined (P8 PD-25).
|
|
233
|
+
* @param gs - the snapshot
|
|
234
|
+
* @param o - the seam's placeholder `HitsOptionsLike` (`weighted`)
|
|
235
|
+
* @returns the f32 scores with `precision: "f32"` (spec 9.7)
|
|
236
|
+
*/
|
|
237
|
+
async closenessCentrality(gs, o) {
|
|
238
|
+
ctx.assertReady();
|
|
239
|
+
return await closenessCentrality(ctx, gs, o);
|
|
240
|
+
},
|
|
190
241
|
/**
|
|
191
242
|
* Destroys every device buffer recorded for the snapshot (spec 4.5); delegates to ctx.release.
|
|
192
243
|
* @param s - the snapshot the app is done with
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accelerator.js","sourceRoot":"","sources":["../../src/accelerator.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"accelerator.js","sourceRoot":"","sources":["../../src/accelerator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bellman-Ford with negative-cycle detection on the device (design 8.4, 3.3 line 809, 9.7; P8-T10, the P8 plan's
|
|
3
|
+
* PD-12 / PD-19 / PD-22 / PD-27 / DEP-P8-E): the edge-parallel relaxation of `bf-relax` over the `edgeList()` view
|
|
4
|
+
* -- every logical edge once, both directions on an undirected snapshot -- in batches of `ROUNDS_PER_BATCH` rounds
|
|
5
|
+
* with the `BfFlags` block (`changed`, `retryExhausted`) zeroed before each batch and read back after it, one
|
|
6
|
+
* `mapAsync` per batch. The loop stops when a batch changed nothing (a reachable negative cycle changes something
|
|
7
|
+
* every round, so nothing has been missed) or when `n - 1` rounds have run, in which case ONE more round runs and
|
|
8
|
+
* `changed` after it IS `hasNegativeCycle`; the last batch is clamped so the reported round count never exceeds
|
|
9
|
+
* `n - 1`. `dist` holds f32 bit patterns and the claim is a BOUNDED compare-exchange (PD-12: `MAX_RETRIES`, because
|
|
10
|
+
* with a negative distance the bit-pattern order reverses and `atomicMin` is wrong, and WGSL lets the exchange fail
|
|
11
|
+
* spuriously): a lane that exhausts the bound raises `retryExhausted`, which the driver treats as changed and runs
|
|
12
|
+
* on -- the lost update is retried by the next round, which examines every edge anyway -- and tallies for the tests;
|
|
13
|
+
* raised in the decision round it is E_VALIDATION, never a guess.
|
|
14
|
+
*
|
|
15
|
+
* The routing is P8-T9's, by the RUN's weight vector (PD-22): `options.weights` when given (`arcCount` long or
|
|
16
|
+
* E_INVALID_ARGUMENT; narrowed to `Float32Array` when it is not one -- a `U32` or `I32` value above 2^24, or the bits
|
|
17
|
+
* of an `F64` value below the f32 ulp, is rounded silently, the package-wide f32 caveat and not a refusal), else the
|
|
18
|
+
* snapshot's column, else none; a run whose vector is all ones, or has none, is the unit-weight BFS of P8-T6 with a
|
|
19
|
+
* depth cap derived from `cutoff` (there is nothing negative to relax) and the flag false; a non-finite weight is
|
|
20
|
+
* E_UNSUPPORTED `bellmanFord.nonFiniteWeights`; `cutoff: NaN` is E_INVALID_ARGUMENT (PD-19); every other cutoff goes
|
|
21
|
+
* to the kernel's `nd <= cutoff` unchanged, a negative one yielding the source alone only when no negative weight
|
|
22
|
+
* can satisfy it. One rule the kernel's shape forces: on an UNDIRECTED snapshot the kernel reads ONE weight per
|
|
23
|
+
* logical edge (its forward arc's) and applies it in both directions, so a caller-supplied override whose two arcs
|
|
24
|
+
* of one edge differ means the caller wanted a directed graph, and the driver REFUSES it (E_UNSUPPORTED
|
|
25
|
+
* `bellmanFord.asymmetricUndirectedWeights`, before any device work) rather than half-honour it; the snapshot's own
|
|
26
|
+
* column never trips it. `edgeToArc` is absent from the residency on a directed snapshot built from a sorted edge
|
|
27
|
+
* list (`flags.arcToEdgeIsIdentity`): edge `e` IS arc `e` there, and the driver binds an `edgeCount`-word iota
|
|
28
|
+
* scratch in that slot (the `fill` kernel's mode 1) so the kernel reads `weights[edgeToArc[e]]` unchanged.
|
|
29
|
+
*
|
|
30
|
+
* `predArc` is P8-T9's predecessor pass under PD-27's tight-subgraph rule (`P.mode 1`): the key is the hop count
|
|
31
|
+
* from the source over every tight arc (`fround(dist[u] + w) == dist[v]`; a tight arc with a negative weight steps to
|
|
32
|
+
* a LARGER distance, so `dist` is no key here), `hops[source] = 0` the only seed and no roots pass, so the chain
|
|
33
|
+
* strictly decreases the key and ends at the source. An ORPHAN -- a reached node the tight subgraph never reaches --
|
|
34
|
+
* can arise only when f32 rounding let a cycle improve a distance once (`s -> a` at 2^24, `a -> b` at +1, `b -> a` at
|
|
35
|
+
* -1: `dist[a]` ends at `2^24 - 1` and the source's arc is no longer tight; exact arithmetic has no such run), and the
|
|
36
|
+
* driver refuses it as E_UNSUPPORTED `bellmanFord.roundedCycle` rather than return a chain that ends short of the
|
|
37
|
+
* source (the seam's walker would hand `arcSourceIn` an `INVALID_INDEX`). With `hasNegativeCycle` the result carries
|
|
38
|
+
* the last round's `dist` and `predArc` and says so: the pass still runs, its chains are still acyclic, a node the
|
|
39
|
+
* tight subgraph does not reach keeps `INVALID_INDEX`, and the orphan refusal is skipped. The tuning entry
|
|
40
|
+
* `bellmanFordWithTuning` (PD-26's shape) is what the tests drive; nothing public exposes it.
|
|
41
|
+
*/
|
|
42
|
+
import { type GraphSnapshot } from "@graphty/graph-format";
|
|
43
|
+
import { type GpuContext } from "../context.js";
|
|
44
|
+
import { type SsspOptions } from "../types/accelerator.js";
|
|
45
|
+
import { type GpuRunOptions } from "../types/run.js";
|
|
46
|
+
import { type GpuBellmanFordResult } from "../types/traversal.js";
|
|
47
|
+
/**
|
|
48
|
+
* Bellman-Ford on the device (spec 3.3 line 809, design 8.4, 9.7): `dist` in f32 (bitwise the f32 Bellman-Ford
|
|
49
|
+
* fixed point, which is `sssp`'s where the weights are non-negative), `predArc` a tight arc one hop of the tight
|
|
50
|
+
* subgraph below each reached node (the chain always ends at the source), `reachedCount`, and `hasNegativeCycle` --
|
|
51
|
+
* true when a negative cycle is reachable from the source, in which case `dist` and `predArc` are the last round's
|
|
52
|
+
* values, not shortest paths; `cutoff` and `weights` as `sssp` reads them (the seam's `SsspOptions`).
|
|
53
|
+
* @param ctx - the context whose device runs the kernels
|
|
54
|
+
* @param s - the snapshot (uploaded through ctx.residency, or found there)
|
|
55
|
+
* @param source - the source node index (E_INVALID_ARGUMENT outside `[0, n)`)
|
|
56
|
+
* @param options - `cutoff` and `weights`, plus dest (a Float32Array of length n for `dist`) / signal / onProgress
|
|
57
|
+
* @returns the distances, the predecessor arcs, the reached count and the negative-cycle flag
|
|
58
|
+
*/
|
|
59
|
+
export declare function bellmanFord(ctx: GpuContext, s: GraphSnapshot, source: number, options?: SsspOptions & GpuRunOptions): Promise<GpuBellmanFordResult>;
|
|
60
|
+
//# sourceMappingURL=bellman-ford.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bellman-ford.d.ts","sourceRoot":"","sources":["../../../src/algorithms/bellman-ford.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAY,KAAK,aAAa,EAAiB,MAAM,uBAAuB,CAAC;AAGpF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAOhD,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAwTlE;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC7B,GAAG,EAAE,UAAU,EACf,CAAC,EAAE,aAAa,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,WAAW,GAAG,aAAa,GACtC,OAAO,CAAC,oBAAoB,CAAC,CAE/B"}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bellman-Ford with negative-cycle detection on the device (design 8.4, 3.3 line 809, 9.7; P8-T10, the P8 plan's
|
|
3
|
+
* PD-12 / PD-19 / PD-22 / PD-27 / DEP-P8-E): the edge-parallel relaxation of `bf-relax` over the `edgeList()` view
|
|
4
|
+
* -- every logical edge once, both directions on an undirected snapshot -- in batches of `ROUNDS_PER_BATCH` rounds
|
|
5
|
+
* with the `BfFlags` block (`changed`, `retryExhausted`) zeroed before each batch and read back after it, one
|
|
6
|
+
* `mapAsync` per batch. The loop stops when a batch changed nothing (a reachable negative cycle changes something
|
|
7
|
+
* every round, so nothing has been missed) or when `n - 1` rounds have run, in which case ONE more round runs and
|
|
8
|
+
* `changed` after it IS `hasNegativeCycle`; the last batch is clamped so the reported round count never exceeds
|
|
9
|
+
* `n - 1`. `dist` holds f32 bit patterns and the claim is a BOUNDED compare-exchange (PD-12: `MAX_RETRIES`, because
|
|
10
|
+
* with a negative distance the bit-pattern order reverses and `atomicMin` is wrong, and WGSL lets the exchange fail
|
|
11
|
+
* spuriously): a lane that exhausts the bound raises `retryExhausted`, which the driver treats as changed and runs
|
|
12
|
+
* on -- the lost update is retried by the next round, which examines every edge anyway -- and tallies for the tests;
|
|
13
|
+
* raised in the decision round it is E_VALIDATION, never a guess.
|
|
14
|
+
*
|
|
15
|
+
* The routing is P8-T9's, by the RUN's weight vector (PD-22): `options.weights` when given (`arcCount` long or
|
|
16
|
+
* E_INVALID_ARGUMENT; narrowed to `Float32Array` when it is not one -- a `U32` or `I32` value above 2^24, or the bits
|
|
17
|
+
* of an `F64` value below the f32 ulp, is rounded silently, the package-wide f32 caveat and not a refusal), else the
|
|
18
|
+
* snapshot's column, else none; a run whose vector is all ones, or has none, is the unit-weight BFS of P8-T6 with a
|
|
19
|
+
* depth cap derived from `cutoff` (there is nothing negative to relax) and the flag false; a non-finite weight is
|
|
20
|
+
* E_UNSUPPORTED `bellmanFord.nonFiniteWeights`; `cutoff: NaN` is E_INVALID_ARGUMENT (PD-19); every other cutoff goes
|
|
21
|
+
* to the kernel's `nd <= cutoff` unchanged, a negative one yielding the source alone only when no negative weight
|
|
22
|
+
* can satisfy it. One rule the kernel's shape forces: on an UNDIRECTED snapshot the kernel reads ONE weight per
|
|
23
|
+
* logical edge (its forward arc's) and applies it in both directions, so a caller-supplied override whose two arcs
|
|
24
|
+
* of one edge differ means the caller wanted a directed graph, and the driver REFUSES it (E_UNSUPPORTED
|
|
25
|
+
* `bellmanFord.asymmetricUndirectedWeights`, before any device work) rather than half-honour it; the snapshot's own
|
|
26
|
+
* column never trips it. `edgeToArc` is absent from the residency on a directed snapshot built from a sorted edge
|
|
27
|
+
* list (`flags.arcToEdgeIsIdentity`): edge `e` IS arc `e` there, and the driver binds an `edgeCount`-word iota
|
|
28
|
+
* scratch in that slot (the `fill` kernel's mode 1) so the kernel reads `weights[edgeToArc[e]]` unchanged.
|
|
29
|
+
*
|
|
30
|
+
* `predArc` is P8-T9's predecessor pass under PD-27's tight-subgraph rule (`P.mode 1`): the key is the hop count
|
|
31
|
+
* from the source over every tight arc (`fround(dist[u] + w) == dist[v]`; a tight arc with a negative weight steps to
|
|
32
|
+
* a LARGER distance, so `dist` is no key here), `hops[source] = 0` the only seed and no roots pass, so the chain
|
|
33
|
+
* strictly decreases the key and ends at the source. An ORPHAN -- a reached node the tight subgraph never reaches --
|
|
34
|
+
* can arise only when f32 rounding let a cycle improve a distance once (`s -> a` at 2^24, `a -> b` at +1, `b -> a` at
|
|
35
|
+
* -1: `dist[a]` ends at `2^24 - 1` and the source's arc is no longer tight; exact arithmetic has no such run), and the
|
|
36
|
+
* driver refuses it as E_UNSUPPORTED `bellmanFord.roundedCycle` rather than return a chain that ends short of the
|
|
37
|
+
* source (the seam's walker would hand `arcSourceIn` an `INVALID_INDEX`). With `hasNegativeCycle` the result carries
|
|
38
|
+
* the last round's `dist` and `predArc` and says so: the pass still runs, its chains are still acyclic, a node the
|
|
39
|
+
* tight subgraph does not reach keeps `INVALID_INDEX`, and the orphan refusal is skipped. The tuning entry
|
|
40
|
+
* `bellmanFordWithTuning` (PD-26's shape) is what the tests drive; nothing public exposes it.
|
|
41
|
+
*/
|
|
42
|
+
import { INVALID_INDEX } from "@graphty/graph-format";
|
|
43
|
+
import { F32_INF_BITS, MAX_LEVELS_PER_SUBMIT } from "../constants.js";
|
|
44
|
+
import { WebGpuGraphError } from "../errors.js";
|
|
45
|
+
import { CommandBatch } from "../kernel/batch.js";
|
|
46
|
+
import { plan1d, planGridStride } from "../kernel/dispatch.js";
|
|
47
|
+
import { BF_FLAGS, BF_PARAMS, FILL_PARAMS, graphBindings, graphOverrides, kernelSpec } from "../kernels.js";
|
|
48
|
+
import { assertWholeCore } from "../primitives/core-shape.js";
|
|
49
|
+
import { assertDeviceComputes } from "../primitives/verify.js";
|
|
50
|
+
import { algorithmScope } from "./scope.js";
|
|
51
|
+
import { aborted, assertSource, bindingOf, bitsOf, checkDest, normaliseCutoff, predBufferWords, predecessorPass, resolveWeights, unitWeightRoute, } from "./sssp.js";
|
|
52
|
+
const ALGORITHM = "bellmanFord";
|
|
53
|
+
/** Design 8.4: the changed flag is read every 8 rounds (one `mapAsync` per batch). */
|
|
54
|
+
const ROUNDS_PER_BATCH = 8;
|
|
55
|
+
/** PD-12: the compare-exchange retry bound per lane (contention is per vertex, not global); `components.ts`'s `MAX_STEPS` idiom. */
|
|
56
|
+
const MAX_RETRIES = 16;
|
|
57
|
+
/**
|
|
58
|
+
* Params slots of the ring, COUNTED (`UniformRing.reserve` wraps silently): a batch of rounds shares ONE `BfParams`
|
|
59
|
+
* record across its dispatches; the setup batch is three `fill`s; the predecessor batch is `MAX_LEVELS_PER_SUBMIT`
|
|
60
|
+
* hop passes, one `fill` and the predecessor pass (34).
|
|
61
|
+
*/
|
|
62
|
+
const RING_SLOTS = MAX_LEVELS_PER_SUBMIT + 16;
|
|
63
|
+
/**
|
|
64
|
+
* The undirected rule (see the file comment): every arc's weight equals its edge's forward arc's, else E_UNSUPPORTED.
|
|
65
|
+
* @param s - the snapshot (undirected)
|
|
66
|
+
* @param vector - the caller's override, narrowed
|
|
67
|
+
*/
|
|
68
|
+
function assertSymmetric(s, vector) {
|
|
69
|
+
const { arcToEdge, edgeToArc } = s;
|
|
70
|
+
for (let a = 0; a < s.arcCount; a++) {
|
|
71
|
+
const forward = edgeToArc[arcToEdge[a]];
|
|
72
|
+
if (vector[a] !== vector[forward]) {
|
|
73
|
+
throw new WebGpuGraphError("E_UNSUPPORTED", `${ALGORITHM}: weights[${a}] = ${vector[a]} differs from weights[${forward}] = ${vector[forward]}, the forward arc of the same undirected edge; the kernel reads one weight per edge`, { feature: "bellmanFord.asymmetricUndirectedWeights", hint: "use a directed snapshot" });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Bellman-Ford with the test knobs of PD-26's shape; `bellmanFord` is this with an empty tuning.
|
|
79
|
+
* @internal
|
|
80
|
+
* @param ctx - the context whose device runs the kernels
|
|
81
|
+
* @param s - the snapshot (uploaded through ctx.residency, or found there)
|
|
82
|
+
* @param source - the source node index
|
|
83
|
+
* @param options - `cutoff` and `weights`, plus dest / signal / onProgress
|
|
84
|
+
* @param tuning - the knobs
|
|
85
|
+
* @returns the result, the rounds run and the retry-exhausted tally
|
|
86
|
+
*/
|
|
87
|
+
export async function bellmanFordWithTuning(ctx, s, source, options, tuning) {
|
|
88
|
+
ctx.assertReady();
|
|
89
|
+
await assertDeviceComputes(ctx);
|
|
90
|
+
const n = s.nodeCount;
|
|
91
|
+
assertSource(ALGORITHM, source, n);
|
|
92
|
+
const maxRetries = tuning.maxRetries ?? MAX_RETRIES;
|
|
93
|
+
if (!Number.isInteger(maxRetries) || maxRetries < 1) {
|
|
94
|
+
throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${ALGORITHM}: maxRetries must be an integer >= 1`, {
|
|
95
|
+
argument: "maxRetries",
|
|
96
|
+
value: maxRetries,
|
|
97
|
+
expected: "an integer >= 1",
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const roundsPerBatch = tuning.roundsPerBatch ?? ROUNDS_PER_BATCH;
|
|
101
|
+
if (!Number.isInteger(roundsPerBatch) || roundsPerBatch < 1 || roundsPerBatch > MAX_LEVELS_PER_SUBMIT) {
|
|
102
|
+
throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${ALGORITHM}: roundsPerBatch must be an integer in [1, ${MAX_LEVELS_PER_SUBMIT}]`, {
|
|
103
|
+
argument: "roundsPerBatch",
|
|
104
|
+
value: roundsPerBatch,
|
|
105
|
+
expected: `an integer in [1, ${MAX_LEVELS_PER_SUBMIT}]`,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
const dest = checkDest(ALGORITHM, options?.dest, n);
|
|
109
|
+
const vector = resolveWeights(ALGORITHM, s, options?.weights);
|
|
110
|
+
const cutoff = normaliseCutoff(ALGORITHM, options?.cutoff);
|
|
111
|
+
if (options?.signal?.aborted) {
|
|
112
|
+
throw aborted(ALGORITHM);
|
|
113
|
+
}
|
|
114
|
+
if (vector === null || vector.allOne) {
|
|
115
|
+
const unit = await unitWeightRoute(ctx, s, source, cutoff, dest, options);
|
|
116
|
+
return { result: { ...unit, hasNegativeCycle: false }, rounds: 0, retryExhaustedRounds: 0 };
|
|
117
|
+
}
|
|
118
|
+
if (!vector.finite) {
|
|
119
|
+
throw new WebGpuGraphError("E_UNSUPPORTED", `${ALGORITHM}: a NaN or infinite weight has no shortest path`, {
|
|
120
|
+
feature: "bellmanFord.nonFiniteWeights",
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
if (!s.directed && vector.override !== null) {
|
|
124
|
+
assertSymmetric(s, vector.override);
|
|
125
|
+
}
|
|
126
|
+
const { arcCount } = s;
|
|
127
|
+
const core = ctx.residency.core(s, ["rowPtr", "colIdx", "weights", "edgeToArc"]);
|
|
128
|
+
assertWholeCore(core, arcCount, ctx.caps.limits.maxStorageBufferBindingSize, ALGORITHM);
|
|
129
|
+
const edges = ctx.residency.view(s, "edgeList");
|
|
130
|
+
const edgeCount = edges.scalars.edgeCount[0];
|
|
131
|
+
const scope = algorithmScope(ctx, ALGORITHM, RING_SLOTS);
|
|
132
|
+
try {
|
|
133
|
+
const wg = ctx.workgroupSize;
|
|
134
|
+
const bytes = 4 * n;
|
|
135
|
+
const dist = bindingOf(scope.scratch(bytes, "dist"), bytes);
|
|
136
|
+
const predWords = predBufferWords(n);
|
|
137
|
+
const pred = bindingOf(scope.scratch(4 * predWords, "pred"), 4 * predWords);
|
|
138
|
+
const flags = bindingOf(scope.scratch(BF_FLAGS.byteLength, "flags"), BF_FLAGS.byteLength);
|
|
139
|
+
// the directed identity snapshot has no edgeToArc segment: edge e IS arc e, so an iota stands in the slot
|
|
140
|
+
let iota = null;
|
|
141
|
+
let { edgeToArc } = core;
|
|
142
|
+
if (edgeToArc === null) {
|
|
143
|
+
iota = bindingOf(scope.scratch(4 * edgeCount, "iota"), 4 * edgeCount);
|
|
144
|
+
edgeToArc = iota;
|
|
145
|
+
}
|
|
146
|
+
const { queue } = ctx.device;
|
|
147
|
+
let weightsBinding;
|
|
148
|
+
if (vector.override !== null) {
|
|
149
|
+
const uploaded = scope.scratch(4 * arcCount, "weights");
|
|
150
|
+
queue.writeBuffer(uploaded, 0, vector.override);
|
|
151
|
+
weightsBinding = bindingOf(uploaded, 4 * arcCount);
|
|
152
|
+
}
|
|
153
|
+
await ctx.allocator.check();
|
|
154
|
+
const overrides = graphOverrides(core, null, weightsBinding);
|
|
155
|
+
const relax = await ctx.pipelines.kernel(kernelSpec("bf-relax", { UNDIRECTED: !s.directed }));
|
|
156
|
+
const predKernel = await ctx.pipelines.kernel(kernelSpec("sssp-pred", { ...overrides, MODE: 0 }));
|
|
157
|
+
const fill = await ctx.pipelines.kernel(kernelSpec("fill"));
|
|
158
|
+
const graph = graphBindings(core, null, weightsBinding);
|
|
159
|
+
const recordFill = (pass, dst, count, value, mode = 0) => {
|
|
160
|
+
const params = scope.params(FILL_PARAMS, { count, value, mode, pad0: 0 });
|
|
161
|
+
fill.dispatch(pass, fill.bind({ dst, P: params.binding }), plan1d(count, wg, ctx.caps), [params.offset]);
|
|
162
|
+
};
|
|
163
|
+
const submit = (batch) => {
|
|
164
|
+
scope.flush();
|
|
165
|
+
return batch.submit();
|
|
166
|
+
};
|
|
167
|
+
// setup: dist = +Inf everywhere, the pred buffer INVALID_INDEX, the iota when needed; then the source at 0
|
|
168
|
+
const setup = new CommandBatch(ctx, `${ALGORITHM}/setup`);
|
|
169
|
+
const setupPass = setup.pass("fill");
|
|
170
|
+
recordFill(setupPass, dist, n, F32_INF_BITS);
|
|
171
|
+
recordFill(setupPass, pred, predWords, INVALID_INDEX);
|
|
172
|
+
if (iota !== null) {
|
|
173
|
+
recordFill(setupPass, iota, edgeCount, 0, 1);
|
|
174
|
+
}
|
|
175
|
+
setup.endPass();
|
|
176
|
+
await submit(setup).readback;
|
|
177
|
+
ctx.assertReady();
|
|
178
|
+
queue.writeBuffer(dist.buffer, dist.offset + 4 * source, Uint32Array.of(0));
|
|
179
|
+
// the rounds: roundsPerBatch per batch, the flags zeroed before and read after; the last batch clamped to
|
|
180
|
+
// n - 1 rounds in all, then the decision round
|
|
181
|
+
const edgePlan = planGridStride(edgeCount, wg, ctx.caps);
|
|
182
|
+
const relaxBindings = {
|
|
183
|
+
edgeSrc: edges.bindings.src,
|
|
184
|
+
edgeDst: edges.bindings.dst,
|
|
185
|
+
edgeToArc,
|
|
186
|
+
weights: graph.weights,
|
|
187
|
+
dist,
|
|
188
|
+
flags,
|
|
189
|
+
};
|
|
190
|
+
const relaxFields = {
|
|
191
|
+
edgeCount,
|
|
192
|
+
stride: edgePlan.stride ?? edgeCount,
|
|
193
|
+
maxRetries,
|
|
194
|
+
cutoffBits: bitsOf(cutoff),
|
|
195
|
+
};
|
|
196
|
+
const zero = new Uint32Array(BF_FLAGS.byteLength / 4);
|
|
197
|
+
const runRounds = async (count, label) => {
|
|
198
|
+
queue.writeBuffer(flags.buffer, flags.offset, zero);
|
|
199
|
+
const batch = new CommandBatch(ctx, `${ALGORITHM}/${label}`);
|
|
200
|
+
const pass = batch.pass("relax");
|
|
201
|
+
const params = scope.params(BF_PARAMS, relaxFields);
|
|
202
|
+
const bound = relax.bind({ ...relaxBindings, P: params.binding });
|
|
203
|
+
for (let round = 0; round < count; round++) {
|
|
204
|
+
relax.dispatch(pass, bound, edgePlan, [params.offset]);
|
|
205
|
+
}
|
|
206
|
+
batch.endPass();
|
|
207
|
+
const request = batch.readback(flags.buffer, flags.offset, BF_FLAGS.byteLength);
|
|
208
|
+
const submitted = submit(batch);
|
|
209
|
+
const back = await submitted.readback;
|
|
210
|
+
ctx.assertReady();
|
|
211
|
+
const block = BF_FLAGS.read(new DataView(back), request.offset);
|
|
212
|
+
return { changed: Number(block.changed), retryExhausted: Number(block.retryExhausted), id: submitted.id };
|
|
213
|
+
};
|
|
214
|
+
let rounds = 0;
|
|
215
|
+
let retryExhaustedRounds = 0;
|
|
216
|
+
let hasNegativeCycle = false;
|
|
217
|
+
for (;;) {
|
|
218
|
+
const remaining = n - 1 - rounds;
|
|
219
|
+
if (remaining <= 0) {
|
|
220
|
+
// the decision round: a change after n - 1 rounds is a negative cycle reachable from the source
|
|
221
|
+
const decision = await runRounds(1, "decision");
|
|
222
|
+
if (decision.retryExhausted !== 0) {
|
|
223
|
+
throw new WebGpuGraphError("E_VALIDATION", `${ALGORITHM}: a lane exhausted the ${maxRetries}-retry compare-exchange bound in the decision round, so its change is not a verdict`, {
|
|
224
|
+
label: `${ALGORITHM}/retry`,
|
|
225
|
+
message: "retryExhausted in the decision round",
|
|
226
|
+
batchId: decision.id,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
hasNegativeCycle = decision.changed !== 0;
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
const count = Math.min(roundsPerBatch, remaining);
|
|
233
|
+
const batch = await runRounds(count, "rounds");
|
|
234
|
+
rounds += count;
|
|
235
|
+
if (batch.retryExhausted !== 0) {
|
|
236
|
+
retryExhaustedRounds += 1;
|
|
237
|
+
}
|
|
238
|
+
if (options?.signal?.aborted) {
|
|
239
|
+
throw aborted(ALGORITHM, batch.id);
|
|
240
|
+
}
|
|
241
|
+
options?.onProgress?.(rounds, n);
|
|
242
|
+
if (batch.changed === 0 && batch.retryExhausted === 0) {
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// the predecessor pass (PD-11, PD-27) under the tight-subgraph rule; the flags block was read after the
|
|
247
|
+
// decision round, so the batch reads dist, the arcs and the pass's two words
|
|
248
|
+
const passed = await predecessorPass({
|
|
249
|
+
algorithm: ALGORITHM,
|
|
250
|
+
ctx,
|
|
251
|
+
scope,
|
|
252
|
+
predKernel,
|
|
253
|
+
recordFill,
|
|
254
|
+
graph,
|
|
255
|
+
dist,
|
|
256
|
+
pred,
|
|
257
|
+
n,
|
|
258
|
+
arcCount,
|
|
259
|
+
source,
|
|
260
|
+
mode: 1,
|
|
261
|
+
});
|
|
262
|
+
if (passed.orphans !== 0 && !hasNegativeCycle) {
|
|
263
|
+
throw new WebGpuGraphError("E_UNSUPPORTED", `${ALGORITHM}: ${passed.orphans} reached node(s) the tight subgraph never reaches (a cycle of weights below one f32 ulp relaxed once)`, {
|
|
264
|
+
feature: "bellmanFord.roundedCycle",
|
|
265
|
+
hint: "a cycle of weights below one f32 ulp relaxed once at a distance above 2^24; scale the weights or shorten the distances",
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
const distOut = dest ?? new Float32Array(n);
|
|
269
|
+
distOut.set(passed.dist);
|
|
270
|
+
let reachedCount = 0;
|
|
271
|
+
for (const d of distOut) {
|
|
272
|
+
if (d !== Infinity) {
|
|
273
|
+
reachedCount += 1;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
result: { dist: distOut, predArc: passed.predArc, reachedCount, hasNegativeCycle },
|
|
278
|
+
rounds,
|
|
279
|
+
retryExhaustedRounds,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
finally {
|
|
283
|
+
scope.dispose();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Bellman-Ford on the device (spec 3.3 line 809, design 8.4, 9.7): `dist` in f32 (bitwise the f32 Bellman-Ford
|
|
288
|
+
* fixed point, which is `sssp`'s where the weights are non-negative), `predArc` a tight arc one hop of the tight
|
|
289
|
+
* subgraph below each reached node (the chain always ends at the source), `reachedCount`, and `hasNegativeCycle` --
|
|
290
|
+
* true when a negative cycle is reachable from the source, in which case `dist` and `predArc` are the last round's
|
|
291
|
+
* values, not shortest paths; `cutoff` and `weights` as `sssp` reads them (the seam's `SsspOptions`).
|
|
292
|
+
* @param ctx - the context whose device runs the kernels
|
|
293
|
+
* @param s - the snapshot (uploaded through ctx.residency, or found there)
|
|
294
|
+
* @param source - the source node index (E_INVALID_ARGUMENT outside `[0, n)`)
|
|
295
|
+
* @param options - `cutoff` and `weights`, plus dest (a Float32Array of length n for `dist`) / signal / onProgress
|
|
296
|
+
* @returns the distances, the predecessor arcs, the reached count and the negative-cycle flag
|
|
297
|
+
*/
|
|
298
|
+
export async function bellmanFord(ctx, s, source, options) {
|
|
299
|
+
return (await bellmanFordWithTuning(ctx, s, source, options, {})).result;
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=bellman-ford.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bellman-ford.js","sourceRoot":"","sources":["../../../src/algorithms/bellman-ford.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAgC,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEpF,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC5G,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAK/D,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACH,OAAO,EACP,YAAY,EACZ,SAAS,EACT,MAAM,EACN,SAAS,EACT,eAAe,EACf,eAAe,EACf,eAAe,EACf,cAAc,EACd,eAAe,GAElB,MAAM,WAAW,CAAC;AAEnB,MAAM,SAAS,GAAG,aAAa,CAAC;AAEhC,sFAAsF;AACtF,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B,oIAAoI;AACpI,MAAM,WAAW,GAAG,EAAE,CAAC;AAEvB;;;;GAIG;AACH,MAAM,UAAU,GAAG,qBAAqB,GAAG,EAAE,CAAC;AAyB9C;;;;GAIG;AACH,SAAS,eAAe,CAAC,CAAgB,EAAE,MAAW;IAClD,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,gBAAgB,CACtB,eAAe,EACf,GAAG,SAAS,aAAa,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,yBAAyB,OAAO,OAAO,MAAM,CAAC,OAAO,CAAC,qFAAqF,EACrL,EAAE,OAAO,EAAE,yCAAyC,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAC1F,CAAC;QACN,CAAC;IACL,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACvC,GAAe,EACf,CAAgB,EAChB,MAAc,EACd,OAAkD,EAClD,MAAyB;IAEzB,GAAG,CAAC,WAAW,EAAE,CAAC;IAClB,MAAM,oBAAoB,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC;IACtB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,WAAW,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,gBAAgB,CAAC,oBAAoB,EAAE,GAAG,SAAS,sCAAsC,EAAE;YACjG,QAAQ,EAAE,YAAY;YACtB,KAAK,EAAE,UAAU;YACjB,QAAQ,EAAE,iBAAiB;SAC9B,CAAC,CAAC;IACP,CAAC;IACD,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,gBAAgB,CAAC;IACjE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,cAAc,GAAG,CAAC,IAAI,cAAc,GAAG,qBAAqB,EAAE,CAAC;QACpG,MAAM,IAAI,gBAAgB,CACtB,oBAAoB,EACpB,GAAG,SAAS,8CAA8C,qBAAqB,GAAG,EAClF;YACI,QAAQ,EAAE,gBAAgB;YAC1B,KAAK,EAAE,cAAc;YACrB,QAAQ,EAAE,qBAAqB,qBAAqB,GAAG;SAC1D,CACJ,CAAC;IACN,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACpD,MAAM,MAAM,GAAwB,cAAc,CAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC3D,IAAI,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QAC3B,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1E,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,oBAAoB,EAAE,CAAC,EAAE,CAAC;IAChG,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,IAAI,gBAAgB,CAAC,eAAe,EAAE,GAAG,SAAS,iDAAiD,EAAE;YACvG,OAAO,EAAE,8BAA8B;SAC1C,CAAC,CAAC;IACP,CAAC;IACD,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAC1C,eAAe,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IACD,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IACjF,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,2BAA2B,EAAE,SAAS,CAAC,CAAC;IACxF,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IACzD,IAAI,CAAC;QACD,MAAM,EAAE,GAAG,GAAG,CAAC,aAAa,CAAC;QAC7B,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC;QAC5E,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC1F,0GAA0G;QAC1G,IAAI,IAAI,GAAmB,IAAI,CAAC;QAChC,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;QACzB,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACrB,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC;YACtE,SAAS,GAAG,IAAI,CAAC;QACrB,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;QAC7B,IAAI,cAAmC,CAAC;QACxC,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,QAAQ,EAAE,SAAS,CAAC,CAAC;YACxD,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChD,cAAc,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC9F,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,GAAG,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAClG,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,CACf,IAA2B,EAC3B,GAAY,EACZ,KAAa,EACb,KAAa,EACb,IAAI,GAAG,CAAC,EACJ,EAAE;YACN,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC1E,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7G,CAAC,CAAC;QACF,MAAM,MAAM,GAAG,CAAC,KAAmB,EAAsC,EAAE;YACvE,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;QAC1B,CAAC,CAAC;QAEF,2GAA2G;QAC3G,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,GAAG,EAAE,GAAG,SAAS,QAAQ,CAAC,CAAC;QAC1D,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;QAC7C,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;QACtD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAChB,UAAU,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC;QAC7B,GAAG,CAAC,WAAW,EAAE,CAAC;QAClB,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAE5E,0GAA0G;QAC1G,+CAA+C;QAC/C,MAAM,QAAQ,GAAG,cAAc,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACzD,MAAM,aAAa,GAAG;YAClB,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG;YAC3B,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG;YAC3B,SAAS;YACT,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,IAAI;YACJ,KAAK;SACR,CAAC;QACF,MAAM,WAAW,GAAG;YAChB,SAAS;YACT,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,SAAS;YACpC,UAAU;YACV,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC;SAC7B,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,KAAK,EACnB,KAAa,EACb,KAAa,EAC8E,EAAE;YAC7F,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACpD,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,KAAK,EAAE,CAAC,CAAC;YAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACjC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;YACpD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,aAAa,EAAE,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YAClE,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC;gBACzC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;YAC3D,CAAC;YACD,KAAK,CAAC,OAAO,EAAE,CAAC;YAChB,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;YAChF,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAChC,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC;YACtC,GAAG,CAAC,WAAW,EAAE,CAAC;YAClB,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAChE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC;QAC9G,CAAC,CAAC;QACF,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,oBAAoB,GAAG,CAAC,CAAC;QAC7B,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAC7B,SAAS,CAAC;YACN,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;YACjC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;gBACjB,gGAAgG;gBAChG,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;gBAChD,IAAI,QAAQ,CAAC,cAAc,KAAK,CAAC,EAAE,CAAC;oBAChC,MAAM,IAAI,gBAAgB,CACtB,cAAc,EACd,GAAG,SAAS,0BAA0B,UAAU,qFAAqF,EACrI;wBACI,KAAK,EAAE,GAAG,SAAS,QAAQ;wBAC3B,OAAO,EAAE,sCAAsC;wBAC/C,OAAO,EAAE,QAAQ,CAAC,EAAE;qBACvB,CACJ,CAAC;gBACN,CAAC;gBACD,gBAAgB,GAAG,QAAQ,CAAC,OAAO,KAAK,CAAC,CAAC;gBAC1C,MAAM;YACV,CAAC;YACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC;YAChB,IAAI,KAAK,CAAC,cAAc,KAAK,CAAC,EAAE,CAAC;gBAC7B,oBAAoB,IAAI,CAAC,CAAC;YAC9B,CAAC;YACD,IAAI,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;gBAC3B,MAAM,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YACvC,CAAC;YACD,OAAO,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACjC,IAAI,KAAK,CAAC,OAAO,KAAK,CAAC,IAAI,KAAK,CAAC,cAAc,KAAK,CAAC,EAAE,CAAC;gBACpD,MAAM;YACV,CAAC;QACL,CAAC;QAED,wGAAwG;QACxG,6EAA6E;QAC7E,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC;YACjC,SAAS,EAAE,SAAS;YACpB,GAAG;YACH,KAAK;YACL,UAAU;YACV,UAAU;YACV,KAAK;YACL,IAAI;YACJ,IAAI;YACJ,CAAC;YACD,QAAQ;YACR,MAAM;YACN,IAAI,EAAE,CAAC;SACV,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC5C,MAAM,IAAI,gBAAgB,CACtB,eAAe,EACf,GAAG,SAAS,KAAK,MAAM,CAAC,OAAO,uGAAuG,EACtI;gBACI,OAAO,EAAE,0BAA0B;gBACnC,IAAI,EAAE,wHAAwH;aACjI,CACJ,CAAC;QACN,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACtB,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;gBACjB,YAAY,IAAI,CAAC,CAAC;YACtB,CAAC;QACL,CAAC;QACD,OAAO;YACH,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE;YAClF,MAAM;YACN,oBAAoB;SACvB,CAAC;IACN,CAAC;YAAS,CAAC;QACP,KAAK,CAAC,OAAO,EAAE,CAAC;IACpB,CAAC;AACL,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC7B,GAAe,EACf,CAAgB,EAChB,MAAc,EACd,OAAqC;IAErC,OAAO,CAAC,MAAM,qBAAqB,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Breadth-first search on the device (design 8.4, 3.3 line 807, 9.7; P8-T6 / P8-T7 / P8-T8, the P8 plan's PD-5 /
|
|
3
|
+
* PD-6 / PD-7 / PD-14 / PD-18 / PD-21 / PD-23 / PD-24 / PD-26 / DEP-P8-B): the direction-optimizing traversal over
|
|
4
|
+
* the `Frontier` of P8-T4, every per-level choice made ON THE DEVICE. Every level is eight recorded dispatches, all
|
|
5
|
+
* DIRECT (2026-09-25, docs/decisions/G8.md G8-F5: Dawn validates every `dispatchWorkgroupsIndirect` with an internal
|
|
6
|
+
* clamp pass costing about 0.4 ms of device time whether or not it dispatches anything, in Node and in Chromium
|
|
7
|
+
* alike, and that was 97 % of a traversal's wall time) -- `frontier-finalize` role 0 (the level boundary: rotates
|
|
8
|
+
* the counts, advances `level`, decides `done`, evaluates Beamer's test and CHOOSES, writing the choice into the
|
|
9
|
+
* block's `path` word: 3 bottom-up, 2 fused for a top-down frontier below `fusedMax` entries, 1 two-phase for any
|
|
10
|
+
* other, 0 done), `advance-expand` (the frontier's rows into the edge queue), `frontier-finalize` role 1 (clamps
|
|
11
|
+
* `edgeCount`, or, when the edge queue overflowed, sets `path` 4 for the fused retry, PD-23), `bfs-contract` (the
|
|
12
|
+
* claim `atomicMin(&depth[v], level + 1)`, the winners packed into the next vertex queue), `bfs-fused` (one workgroup
|
|
13
|
+
* per frontier entry with the same claim inline and no edge queue; the fused level and the retry alike), then the
|
|
14
|
+
* bottom-up trio: a `fill` zeroing the frontier bitset, `bfs-bitset-build` setting the frontier's bits, and
|
|
15
|
+
* `bfs-bottom-up` sweeping the unvisited list over the REVERSE core (each unvisited vertex reads its in-neighbours
|
|
16
|
+
* until the first one in the bitset and claims itself). Every kernel is a grid-stride dispatch of a host-planned
|
|
17
|
+
* grid (`planGridStride`) that loops to its count word and reads the path word first, so exactly one path does the
|
|
18
|
+
* level's work and the others cost one uniform load per workgroup. The unvisited set Beamer's test is against (PD-18) is rebuilt exactly once per submit, before
|
|
19
|
+
* the levels, by `bfs-unvisited-flags` plus `compact` over an iota queue, and maintained between rebuilds by
|
|
20
|
+
* subtraction inside the selector (whose JSDoc states the boundary rule). The host records `MAX_LEVELS_PER_SUBMIT`
|
|
21
|
+
* levels into ONE command buffer, submits, and reads four bytes, the `done` word (PD-7): a road network has
|
|
22
|
+
* thousands of levels and a per-level `mapAsync` would be slower than the CPU. A level recorded past the end is a
|
|
23
|
+
* no-op (its boundary finds `done` set, zeroes its slots and moves no counter), so the loop needs no diameter and
|
|
24
|
+
* ends on `done`; a traversal has at most `n` levels, so more submits than that is E_VALIDATION, never a hang. The
|
|
25
|
+
* thresholds are uniform fields (`FUSED_FRONTIER_MAX`; alpha derived as `max(1, floor(arcCount / n))`, PD-21;
|
|
26
|
+
* `BEAMER_BETA`; `mode 1` pinning top-down -- each unless the tuning says otherwise), so a test forces any path
|
|
27
|
+
* without recompiling; the block's `fusedLevels` / `twoPhaseLevels` / `bottomUpLevels` / `overflowLevels` /
|
|
28
|
+
* `switches` words record which path each level took.
|
|
29
|
+
*
|
|
30
|
+
* There is no dedupe (DEP-P8-B, PD-5): the edge queue holds duplicates -- a vertex with three frontier neighbours
|
|
31
|
+
* appears three times -- but for one level exactly one invocation observes `INVALID_INDEX` at `depth[v]` and
|
|
32
|
+
* exactly that one appends `v`, so the next vertex frontier is duplicate-free by construction and an ownership
|
|
33
|
+
* dedupe would have nothing to remove. `parent` is not written by the claim (PD-24): `sssp-pred` in `MODE 1` runs
|
|
34
|
+
* once over the settled depths and writes the SMALLEST `u` with `depth[u] + 1 == depth[v]` and an arc `u -> v`, so
|
|
35
|
+
* it is bitwise reproducible where a claim-time parent would be a scheduling accident. `order` (PD-14) is one
|
|
36
|
+
* stable radix sort of the node indices by `depth`: grouped by level, ascending by index within a level,
|
|
37
|
+
* `INVALID_INDEX` last, and the first `visitedCount` values are the result. The result batch stages every array
|
|
38
|
+
* into one staging slot, so a traversal maps `ceil(levels / 32) + 1` buffers in all.
|
|
39
|
+
*
|
|
40
|
+
* `maxDepth` reaches the device as a `u32` field of `FrontierParams`, and the uniform writer refuses anything that
|
|
41
|
+
* is not an integer in `[0, 2^32 - 1]`; the host therefore normalises it first, to exactly the CPU port's rule
|
|
42
|
+
* (`algorithms/src/indexed/bfs.ts`: a node at depth `d >= maxDepth` is reached and not expanded, unbounded when
|
|
43
|
+
* absent). The tuning entry `bfsWithTuning` (PD-26) is what the tests drive; nothing public exposes it.
|
|
44
|
+
*
|
|
45
|
+
* A core whose `colIdx` exceeds `maxStorageBufferBindingSize` is bound as arc windows and EXECUTED (P8-T12, DEP-P8-E
|
|
46
|
+
* lifted for the frontier family): `advance-expand`, `bfs-fused` and `sssp-pred` run once per window of the
|
|
47
|
+
* forward core and `bfs-bottom-up` once per window of the reverse core, every window its own dispatch with its own
|
|
48
|
+
* `FrontierParams` record carrying the window's owned arc range (`coreWindows`), and the claims, being `atomicMin`s
|
|
49
|
+
* and an `INVALID_INDEX` entry test, are idempotent across windows. The ring is sized per run by `bfsRingSlots`.
|
|
50
|
+
*/
|
|
51
|
+
import { type GraphSnapshot } from "@graphty/graph-format";
|
|
52
|
+
import { type GpuContext } from "../context.js";
|
|
53
|
+
import { type BfsOptions } from "../types/accelerator.js";
|
|
54
|
+
import { type GpuRunOptions } from "../types/run.js";
|
|
55
|
+
import { type GpuBfsResult } from "../types/traversal.js";
|
|
56
|
+
/**
|
|
57
|
+
* Breadth-first search on the device (spec 3.3 line 807, design 8.4, 9.7): `depth` exact, `parent` the smallest
|
|
58
|
+
* predecessor one depth down (PD-24), `order` grouped by depth and ascending by index within a depth (PD-14), all
|
|
59
|
+
* bitwise reproducible; `maxDepth` as the CPU port reads it (a node at the cap is reached and not expanded).
|
|
60
|
+
* @param ctx - the context whose device runs the kernels
|
|
61
|
+
* @param s - the snapshot (uploaded through ctx.residency, or found there)
|
|
62
|
+
* @param source - the source node index (E_INVALID_ARGUMENT outside `[0, n)`, so the empty graph refuses every source)
|
|
63
|
+
* @param options - `maxDepth`, plus dest (a Uint32Array of length n for `depth`) / signal / onProgress
|
|
64
|
+
* @returns the depths, parents, order, visited count, level count and switches (the direction changes Beamer's test made on the device)
|
|
65
|
+
*/
|
|
66
|
+
export declare function breadthFirstSearch(ctx: GpuContext, s: GraphSnapshot, source: number, options?: BfsOptions & GpuRunOptions): Promise<GpuBfsResult>;
|
|
67
|
+
//# sourceMappingURL=bfs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bfs.d.ts","sourceRoot":"","sources":["../../../src/algorithms/bfs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,EAAE,KAAK,aAAa,EAA2B,MAAM,uBAAuB,CAAC;AAGpF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAmBhD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAohB1D;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAC9B,GAAG,EAAE,UAAU,EACf,CAAC,EAAE,aAAa,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,UAAU,GAAG,aAAa,GACrC,OAAO,CAAC,YAAY,CAAC,CAEvB"}
|