Floyd-Warshall algorithm: Difference between revisions
Content added Content deleted
Line 165: | Line 165: | ||
4 -> 3 1 |
4 -> 3 1 |
||
</pre> |
</pre> |
||
=={{header|Ada}}== |
|||
{{trans|Scheme}} |
|||
<lang ada>-- |
|||
-- Floyd-Warshall algorithm. |
|||
-- |
|||
-- See https://en.wikipedia.org/w/index.php?title=Floyd%E2%80%93Warshall_algorithm&oldid=1082310013 |
|||
-- |
|||
with Ada.Containers.Vectors; |
|||
with Ada.Text_IO; use Ada.Text_IO; |
|||
with Interfaces; use Interfaces; |
|||
with Ada.Numerics.Generic_Elementary_Functions; |
|||
procedure floyd_warshall_task |
|||
is |
|||
Floyd_Warshall_Exception : exception; |
|||
-- The floating point type we shall use is one that has infinities. |
|||
subtype FloatPt is IEEE_Float_32; |
|||
package FloatPt_Elementary_Functions is new Ada.Numerics |
|||
.Generic_Elementary_Functions |
|||
(FloatPt); |
|||
use FloatPt_Elementary_Functions; |
|||
-- The following should overflow and give us an IEEE infinity. But I |
|||
-- have kept the code so you could use some non-IEEE floating point |
|||
-- format and set ENORMOUS_FloatPt to some value that is finite but |
|||
-- much larger than actual graph traversal distances. |
|||
ENORMOUS_FloatPt : constant FloatPt := |
|||
(FloatPt (1.0) / FloatPt (1.0e-37))**1.0e37; |
|||
package FloatPt_IO is new Float_IO (FloatPt); |
|||
use FloatPt_IO; |
|||
-- |
|||
-- Input is a Vector of records representing the edges of a graph. |
|||
-- |
|||
-- Vertices are identified by integers from 1 .. n. |
|||
-- |
|||
type edge is record |
|||
u : Positive; |
|||
weight : FloatPt; |
|||
v : Positive; |
|||
end record; |
|||
package Edge_Vectors is new Ada.Containers.Vectors |
|||
(Index_Type => Positive, Element_Type => edge); |
|||
use Edge_Vectors; |
|||
subtype edge_vector is Edge_Vectors.Vector; |
|||
-- |
|||
-- Floyd-Warshall. |
|||
-- |
|||
type distance_array is |
|||
array (Positive range <>, Positive range <>) of FloatPt; |
|||
type next_vertex_array is |
|||
array (Positive range <>, Positive range <>) of Natural; |
|||
Nil_Vertex : constant Natural := 0; |
|||
function find_max_vertex -- Find the maximum vertex number. |
|||
(edges : in edge_vector) |
|||
return Positive |
|||
is |
|||
max_vertex : Positive; |
|||
begin |
|||
if Is_Empty (edges) then |
|||
raise Floyd_Warshall_Exception with "no edges"; |
|||
end if; |
|||
max_vertex := 1; |
|||
for i in edges.First_Index .. edges.Last_Index loop |
|||
max_vertex := Positive'Max (max_vertex, edges.Element (i).u); |
|||
max_vertex := Positive'Max (max_vertex, edges.Element (i).v); |
|||
end loop; |
|||
return max_vertex; |
|||
end find_max_vertex; |
|||
procedure floyd_warshall -- Perform Floyd-Warshall. |
|||
(edges : in edge_vector; |
|||
max_vertex : in Positive; |
|||
distance : out distance_array; |
|||
next_vertex : out next_vertex_array) |
|||
is |
|||
u, v : Positive; |
|||
dist_ikj : FloatPt; |
|||
begin |
|||
-- Initialize. |
|||
for i in 1 .. max_vertex loop |
|||
for j in 1 .. max_vertex loop |
|||
distance (i, j) := ENORMOUS_FloatPt; |
|||
next_vertex (i, j) := Nil_Vertex; |
|||
end loop; |
|||
end loop; |
|||
for i in edges.First_Index .. edges.Last_Index loop |
|||
u := edges.Element (i).u; |
|||
v := edges.Element (i).v; |
|||
distance (u, v) := edges.Element (i).weight; |
|||
next_vertex (u, v) := v; |
|||
end loop; |
|||
for i in 1 .. max_vertex loop |
|||
distance (i, i) := |
|||
FloatPt (0.0); -- Distance from a vertex to itself. |
|||
next_vertex (i, i) := i; |
|||
end loop; |
|||
-- Perform the algorithm. |
|||
for k in 1 .. max_vertex loop |
|||
for i in 1 .. max_vertex loop |
|||
for j in 1 .. max_vertex loop |
|||
dist_ikj := distance (i, k) + distance (k, j); |
|||
if dist_ikj < distance (i, j) then |
|||
distance (i, j) := dist_ikj; |
|||
next_vertex (i, j) := next_vertex (i, k); |
|||
end if; |
|||
end loop; |
|||
end loop; |
|||
end loop; |
|||
end floyd_warshall; |
|||
-- |
|||
-- Path reconstruction. |
|||
-- |
|||
procedure put_path |
|||
(next_vertex : in next_vertex_array; |
|||
u, v : in Positive) |
|||
is |
|||
i : Positive; |
|||
begin |
|||
if next_vertex (u, v) /= Nil_Vertex then |
|||
i := u; |
|||
Put (Positive'Image (i)); |
|||
while i /= v loop |
|||
Put (" ->"); |
|||
i := next_vertex (i, v); |
|||
Put (Positive'Image (i)); |
|||
end loop; |
|||
end if; |
|||
end put_path; |
|||
example_graph : edge_vector; |
|||
max_vertex : Positive; |
|||
begin |
|||
Append (example_graph, (u => 1, weight => FloatPt (-2.0), v => 3)); |
|||
Append (example_graph, (u => 3, weight => FloatPt (+2.0), v => 4)); |
|||
Append (example_graph, (u => 4, weight => FloatPt (-1.0), v => 2)); |
|||
Append (example_graph, (u => 2, weight => FloatPt (+4.0), v => 1)); |
|||
Append (example_graph, (u => 2, weight => FloatPt (+3.0), v => 3)); |
|||
max_vertex := find_max_vertex (example_graph); |
|||
declare |
|||
distance : distance_array (1 .. max_vertex, 1 .. max_vertex); |
|||
next_vertex : next_vertex_array |
|||
(1 .. max_vertex, 1 .. max_vertex); |
|||
begin |
|||
floyd_warshall (example_graph, max_vertex, distance, next_vertex); |
|||
Put_Line (" pair distance path"); |
|||
Put_Line ("---------------------------------------------"); |
|||
for u in 1 .. max_vertex loop |
|||
for v in 1 .. max_vertex loop |
|||
if u /= v then |
|||
Put (Positive'Image (u)); |
|||
Put (" ->"); |
|||
Put (Positive'Image (v)); |
|||
Put (" "); |
|||
Put (FloatPt'Image (distance (u, v))); |
|||
Put (" "); |
|||
put_path (next_vertex, u, v); |
|||
Put_Line (""); |
|||
end if; |
|||
end loop; |
|||
end loop; |
|||
end; |
|||
end floyd_warshall_task;</lang> |
|||
{{out}} |
|||
<pre>$ gnatmake -q floyd_warshall_task.adb && ./floyd_warshall_task |
|||
pair distance path |
|||
--------------------------------------------- |
|||
1 -> 2 -1.00000E+00 1 -> 3 -> 4 -> 2 |
|||
1 -> 3 -2.00000E+00 1 -> 3 |
|||
1 -> 4 0.00000E+00 1 -> 3 -> 4 |
|||
2 -> 1 4.00000E+00 2 -> 1 |
|||
2 -> 3 2.00000E+00 2 -> 1 -> 3 |
|||
2 -> 4 4.00000E+00 2 -> 1 -> 3 -> 4 |
|||
3 -> 1 5.00000E+00 3 -> 4 -> 2 -> 1 |
|||
3 -> 2 1.00000E+00 3 -> 4 -> 2 |
|||
3 -> 4 2.00000E+00 3 -> 4 |
|||
4 -> 1 3.00000E+00 4 -> 2 -> 1 |
|||
4 -> 2 -1.00000E+00 4 -> 2 |
|||
4 -> 3 1.00000E+00 4 -> 2 -> 1 -> 3</pre> |
|||
=={{header|C}}== |
=={{header|C}}== |