Skip to content

Commit 0eb1c65

Browse files
committed
stuff
1 parent 13ae3a5 commit 0eb1c65

6 files changed

Lines changed: 334 additions & 85 deletions

File tree

packages/app/src/routes/app/spanner/+page.svelte

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import { goto } from '$app/navigation';
1010
import { GreedySpanner } from '@bachelor/core/spanner/gpu';
1111
import { onMount } from 'svelte';
12+
import { drawGraph } from '$lib/_canvas';
1213
1314
const { device } = getWebGPUState();
1415
const { canvas, context } = getCanvasState();
@@ -26,7 +27,7 @@
2627
onMount(async () => {
2728
const graph = await loadGraph(selectedGraph);
2829
29-
spanner = new GreedySpanner({ graph, device, maxDistortion });
30+
spanner = new GreedySpanner({ graph, device });
3031
3132
runGPU();
3233
});
@@ -35,20 +36,21 @@
3536
if (!spanner) return;
3637
3738
console.time('Spanner');
38-
const lol = await spanner.compute();
39+
const graph = await spanner.compute();
3940
console.timeEnd('Spanner');
4041
42+
const graphControl = await loadGraph(selectedGraph);
4143
const spannerControl = await loadSpanner(selectedGraph);
42-
console.log(spannerControl);
43-
console.log(JSON.stringify(spannerControl.toJSON()));
44+
// console.log(spannerControl);
45+
// console.log(JSON.stringify(spannerControl.toJSON()));
4446
45-
console.log(lol);
46-
console.log(JSON.stringify(lol.toJSON()));
47+
// console.log(lol);
48+
// console.log(JSON.stringify(lol.toJSON()));
4749
48-
const isSame = JSON.stringify(spannerControl.toJSON()) === JSON.stringify(lol.toJSON());
49-
console.log({ isSame });
50+
// const isSame = JSON.stringify(spannerControl.toJSON()) === JSON.stringify(lol.toJSON());
51+
// console.log({ isSame });
5052
51-
drawGraphAndBundledEdges({ ctx: context, graph: lol, bundeledEdges: [] });
53+
drawGraph({ ctx: context, graph: spannerControl, drawLabels: false });
5254
}
5355
</script>
5456

packages/core/src/GPUBuffer.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@ import type { BufferData } from './BufferData';
22

33
export type CreateGPUBufferParams = {
44
device: GPUDevice;
5+
label?: string;
56
data: BufferData;
67
usage: GPUBufferUsageFlags;
78
write?: boolean;
89
};
910

1011
export function createGPUBuffer({
1112
device,
13+
label,
1214
data,
1315
usage,
1416
write = true,
1517
}: CreateGPUBufferParams): GPUBuffer {
1618
const buffer = device.createBuffer({
19+
label,
1720
size: data.buffer.byteLength,
1821
usage,
1922
});

packages/core/src/spanner/_gpu.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { Graph } from '../AdjacencyList';
2+
import { AdjacencyMatrix } from '../AdjacencyMatrix';
3+
import { FloydWarshall } from '../shortest-path/floyd-warshall/FloydWarshall';
4+
5+
export type GreedySpannerParams = {
6+
device: GPUDevice;
7+
graph: Graph;
8+
maxDistortion: number;
9+
};
10+
11+
export class GreedySpanner {
12+
graph: Graph;
13+
maxDistortion: number;
14+
#device: GPUDevice;
15+
#floydWarshall: FloydWarshall;
16+
17+
constructor({ device, graph, maxDistortion }: GreedySpannerParams) {
18+
this.graph = graph;
19+
this.maxDistortion = maxDistortion;
20+
this.#device = device;
21+
22+
this.#floydWarshall = new FloydWarshall({
23+
device,
24+
graph: this.graph,
25+
});
26+
}
27+
28+
async compute() {
29+
await this.#floydWarshall.init();
30+
console.time('Floyd Warshall');
31+
await this.#floydWarshall.compute(true);
32+
console.timeEnd('Floyd Warshall');
33+
34+
const spanner = new Graph();
35+
this.graph.nodes.forEach((node) => {
36+
spanner.addNode(node);
37+
});
38+
39+
console.log(this.maxDistortion);
40+
const distanceMatrix = new AdjacencyMatrix(
41+
this.#floydWarshall.distanceMatrix.size,
42+
Float32Array
43+
);
44+
45+
for (let x = 0; x < distanceMatrix.size; x++) {
46+
for (let y = 0; y < distanceMatrix.size; y++) {
47+
distanceMatrix.set(x, y, x === y ? 0 : Infinity);
48+
}
49+
}
50+
const sortedEdges = Array.from(this.graph.edges)
51+
.map(([_, edge]) => edge)
52+
.sort((a, b) => a.weight - b.weight);
53+
54+
let skipped = 0;
55+
for (const edge of sortedEdges) {
56+
console.log(
57+
edge.weight.toFixed(3) ===
58+
this.#floydWarshall.distanceMatrix.get(edge.start, edge.end).toFixed(3)
59+
);
60+
if (
61+
distanceMatrix.get(edge.start, edge.end) >
62+
this.maxDistortion * this.#floydWarshall.distanceMatrix.get(edge.start, edge.end)
63+
) {
64+
spanner.addEdge(edge);
65+
66+
for (let x = 0; x < distanceMatrix.size; x++) {
67+
for (let y = 0; y < distanceMatrix.size; y++) {
68+
const weight = Math.min(
69+
distanceMatrix.get(x, y),
70+
distanceMatrix.get(x, edge.start) + edge.weight + distanceMatrix.get(edge.end, y),
71+
distanceMatrix.get(x, edge.end) + edge.weight + distanceMatrix.get(edge.start, y)
72+
);
73+
distanceMatrix.set(x, y, weight);
74+
}
75+
}
76+
} else {
77+
skipped++;
78+
}
79+
}
80+
81+
console.log({ skipped });
82+
console.log({ skippedPercentage: (skipped / sortedEdges.length) * 100 });
83+
return spanner;
84+
}
85+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Edge } from '../Edge';
2+
import { Graph } from '../Graph';
3+
import { dijkstra } from '../shortest-path/dijkstra/cpu';
4+
5+
export function greedySpanner(graph: Graph, stretchFactor = 2): Graph {
6+
console.time('Greedy Spanner');
7+
const spanner = new Graph(graph.nodes, []).clone();
8+
9+
const edges = Array.from(graph.edges).sort(([_1, a], [_2, b]) => a.weight - b.weight);
10+
11+
let i = 0;
12+
for (const [id, edge] of edges) {
13+
console.log(`Processing spanner edge ${i} of ${edges.length} edges`);
14+
const shortestPath = dijkstra(spanner, edge.start, edge.end);
15+
16+
if (shortestPath === null || shortestPath.length > edge.weight * stretchFactor) {
17+
const start = spanner.nodes.get(edge.start.id)!;
18+
const end = spanner.nodes.get(edge.end.id)!;
19+
const newEdge = new Edge(start, end);
20+
spanner.edges.set(id, newEdge);
21+
}
22+
23+
i++;
24+
}
25+
26+
console.timeEnd('Greedy Spanner');
27+
return spanner;
28+
}

0 commit comments

Comments
 (0)