Skip to content

Commit 93a2460

Browse files
implemented floydwarshall visualizer
1 parent 79503b2 commit 93a2460

File tree

4 files changed

+588
-0
lines changed

4 files changed

+588
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// src/algorithms/graph/floydWarshall.js
2+
3+
// 🧠 Generator that yields every visualization step
4+
export function* floydWarshallSteps(edges, nodeCount) {
5+
// Initialize distance matrix with Infinity
6+
const dist = Array.from({ length: nodeCount }, () =>
7+
Array(nodeCount).fill(Infinity)
8+
);
9+
10+
// Distance from a node to itself is 0
11+
for (let i = 0; i < nodeCount; i++) {
12+
dist[i][i] = 0;
13+
}
14+
15+
// Set initial distances from edges (use minimum weight for each pair)
16+
for (let edge of edges) {
17+
const from = edge.from - 1;
18+
const to = edge.to - 1;
19+
if (edge.weight < dist[from][to]) {
20+
dist[from][to] = edge.weight;
21+
}
22+
// For undirected graphs, uncomment the next line
23+
// if (edge.weight < dist[to][from]) dist[to][from] = edge.weight;
24+
}
25+
26+
yield {
27+
type: "init",
28+
dist: dist.map((row) => [...row]),
29+
message: "Initial distance matrix created",
30+
};
31+
32+
// Floyd-Warshall algorithm
33+
for (let k = 0; k < nodeCount; k++) {
34+
yield {
35+
type: "intermediate",
36+
k,
37+
dist: dist.map((row) => [...row]),
38+
message: `Using node ${k + 1} as intermediate`,
39+
};
40+
41+
for (let i = 0; i < nodeCount; i++) {
42+
for (let j = 0; j < nodeCount; j++) {
43+
if (i === j) continue;
44+
45+
const oldDist = dist[i][j];
46+
const newDist = dist[i][k] + dist[k][j];
47+
48+
if (newDist < oldDist) {
49+
dist[i][j] = newDist;
50+
yield {
51+
type: "update",
52+
k,
53+
i,
54+
j,
55+
oldDist,
56+
newDist,
57+
dist: dist.map((row) => [...row]),
58+
message: `Updated dist[${i + 1}][${j + 1}] from ${
59+
oldDist === Infinity ? "∞" : oldDist
60+
} to ${newDist}`,
61+
};
62+
} else {
63+
yield {
64+
type: "compare",
65+
k,
66+
i,
67+
j,
68+
oldDist,
69+
newDist,
70+
dist: dist.map((row) => [...row]),
71+
message: `No update: dist[${i + 1}][${j + 1}] = ${
72+
oldDist === Infinity ? "∞" : oldDist
73+
}${newDist === Infinity ? "∞" : newDist}`,
74+
};
75+
}
76+
}
77+
}
78+
}
79+
80+
// Check for negative cycles
81+
let hasNegativeCycle = false;
82+
for (let i = 0; i < nodeCount; i++) {
83+
if (dist[i][i] < 0) {
84+
hasNegativeCycle = true;
85+
break;
86+
}
87+
}
88+
89+
yield {
90+
type: "done",
91+
dist: dist.map((row) => [...row]),
92+
hasNegativeCycle,
93+
message: hasNegativeCycle
94+
? "Algorithm complete - Negative cycle detected!"
95+
: "Algorithm complete - All shortest paths found",
96+
};
97+
}
98+
99+
// Helper function to get shortest path between two nodes
100+
export function getShortestPath(dist, predecessor, start, end) {
101+
if (dist[start][end] === Infinity) {
102+
return null; // No path exists
103+
}
104+
105+
const path = [];
106+
let current = start;
107+
path.push(current);
108+
109+
while (current !== end) {
110+
current = predecessor[current][end];
111+
if (current === undefined || current === null) break;
112+
path.push(current);
113+
}
114+
115+
return path.length > 1 && path[path.length - 1] === end ? path : null;
116+
}
117+
118+
// Helper function to format distance matrix for display
119+
export function formatDistanceMatrix(dist) {
120+
return dist.map((row) =>
121+
row.map((val) => (val === Infinity ? "∞" : val.toString()))
122+
);
123+
}

0 commit comments

Comments
 (0)