Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
87
Task/Dijkstras-algorithm/OCaml/dijkstras-algorithm-1.ocaml
Normal file
87
Task/Dijkstras-algorithm/OCaml/dijkstras-algorithm-1.ocaml
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
let list_vertices graph =
|
||||
List.fold_left (fun acc ((a, b), _) ->
|
||||
let acc = if List.mem b acc then acc else b::acc in
|
||||
let acc = if List.mem a acc then acc else a::acc in
|
||||
acc
|
||||
) [] graph
|
||||
|
||||
let neighbors v =
|
||||
List.fold_left (fun acc ((a, b), d) ->
|
||||
if a = v then (b, d)::acc else acc
|
||||
) []
|
||||
|
||||
let remove_from v lst =
|
||||
let rec aux acc = function [] -> failwith "remove_from"
|
||||
| x::xs -> if x = v then List.rev_append acc xs else aux (x::acc) xs
|
||||
in aux [] lst
|
||||
|
||||
let with_smallest_distance q dist =
|
||||
match q with
|
||||
| [] -> assert false
|
||||
| x::xs ->
|
||||
let rec aux distance v = function
|
||||
| x::xs ->
|
||||
let d = Hashtbl.find dist x in
|
||||
if d < distance
|
||||
then aux d x xs
|
||||
else aux distance v xs
|
||||
| [] -> (v, distance)
|
||||
in
|
||||
aux (Hashtbl.find dist x) x xs
|
||||
|
||||
let dijkstra max_val zero add graph source target =
|
||||
let vertices = list_vertices graph in
|
||||
let dist_between u v =
|
||||
try List.assoc (u, v) graph
|
||||
with _ -> zero
|
||||
in
|
||||
let dist = Hashtbl.create 1 in
|
||||
let previous = Hashtbl.create 1 in
|
||||
List.iter (fun v -> (* initializations *)
|
||||
Hashtbl.add dist v max_val (* unknown distance function from source to v *)
|
||||
) vertices;
|
||||
Hashtbl.replace dist source zero; (* distance from source to source *)
|
||||
let rec loop = function [] -> ()
|
||||
| q ->
|
||||
let u, dist_u =
|
||||
with_smallest_distance q dist in (* vertex in q with smallest distance in dist *)
|
||||
if dist_u = max_val then
|
||||
failwith "vertices inaccessible"; (* all remaining vertices are inaccessible from source *)
|
||||
if u = target then () else begin
|
||||
let q = remove_from u q in
|
||||
List.iter (fun (v, d) ->
|
||||
if List.mem v q then begin
|
||||
let alt = add dist_u (dist_between u v) in
|
||||
let dist_v = Hashtbl.find dist v in
|
||||
if alt < dist_v then begin (* relax (u,v,a) *)
|
||||
Hashtbl.replace dist v alt;
|
||||
Hashtbl.replace previous v u; (* previous node in optimal path from source *)
|
||||
end
|
||||
end
|
||||
) (neighbors u graph);
|
||||
loop q
|
||||
end
|
||||
in
|
||||
loop vertices;
|
||||
let s = ref [] in
|
||||
let u = ref target in
|
||||
while Hashtbl.mem previous !u do
|
||||
s := !u :: !s;
|
||||
u := Hashtbl.find previous !u
|
||||
done;
|
||||
(source :: !s)
|
||||
|
||||
let () =
|
||||
let graph =
|
||||
[ ("a", "b"), 7;
|
||||
("a", "c"), 9;
|
||||
("a", "f"), 14;
|
||||
("b", "c"), 10;
|
||||
("b", "d"), 15;
|
||||
("c", "d"), 11;
|
||||
("c", "f"), 2;
|
||||
("d", "e"), 6;
|
||||
("e", "f"), 9; ]
|
||||
in
|
||||
let p = dijkstra max_int 0 (+) graph "a" "e" in
|
||||
print_endline (String.concat " -> " p)
|
||||
56
Task/Dijkstras-algorithm/OCaml/dijkstras-algorithm-2.ocaml
Normal file
56
Task/Dijkstras-algorithm/OCaml/dijkstras-algorithm-2.ocaml
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
type vertex = int
|
||||
type weight = float
|
||||
type neighbor = vertex * weight
|
||||
module VertexSet = Set.Make(struct type t = weight * vertex let compare = compare end)
|
||||
|
||||
let dijkstra (src:vertex) (adj_list:neighbor list array) : weight array * vertex array =
|
||||
let n = Array.length adj_list in
|
||||
let min_distance = Array.make n infinity in
|
||||
min_distance.(src) <- 0.;
|
||||
let previous = Array.make n (-1) in
|
||||
let rec aux vertex_queue =
|
||||
if not (VertexSet.is_empty vertex_queue) then
|
||||
let dist, u = VertexSet.min_elt vertex_queue in
|
||||
let vertex_queue' = VertexSet.remove (dist, u) vertex_queue in
|
||||
let edges = adj_list.(u) in
|
||||
let f vertex_queue (v, weight) =
|
||||
let dist_thru_u = dist +. weight in
|
||||
if dist_thru_u >= min_distance.(v) then
|
||||
vertex_queue
|
||||
else begin
|
||||
let vertex_queue' = VertexSet.remove (min_distance.(v), v) vertex_queue in
|
||||
min_distance.(v) <- dist_thru_u;
|
||||
previous.(v) <- u;
|
||||
VertexSet.add (min_distance.(v), v) vertex_queue'
|
||||
end
|
||||
in
|
||||
aux (List.fold_left f vertex_queue' edges)
|
||||
in
|
||||
aux (VertexSet.singleton (min_distance.(src), src));
|
||||
min_distance, previous
|
||||
|
||||
let shortest_path_to (target : vertex) (previous : vertex array) : vertex list =
|
||||
let rec aux target acc =
|
||||
if target = -1 then
|
||||
acc
|
||||
else
|
||||
aux previous.(target) (target :: acc)
|
||||
in
|
||||
aux target []
|
||||
|
||||
let adj_list =
|
||||
[| [(1, 7.); (2, 9.); (5, 14.)]; (* 0 = a *)
|
||||
[(0, 7.); (2, 10.); (3, 15.)]; (* 1 = b *)
|
||||
[(0, 9.); (1, 10.); (3, 11.); (5, 2.)]; (* 2 = c *)
|
||||
[(1, 15.); (2, 11.); (4, 6.)]; (* 3 = d *)
|
||||
[(3, 6.); (5, 9.)]; (* 4 = e *)
|
||||
[(0, 14.); (2, 2.); (4, 9.)] (* 5 = f *)
|
||||
|]
|
||||
|
||||
let () =
|
||||
let min_distance, previous = dijkstra 0 adj_list in
|
||||
Printf.printf "Distance from 0 to 4: %f\n" min_distance.(4);
|
||||
let path = shortest_path_to 4 previous in
|
||||
print_string "Path: ";
|
||||
List.iter (Printf.printf "%d, ") path;
|
||||
print_newline ()
|
||||
Loading…
Add table
Add a link
Reference in a new issue