variables
ou fonctions
ne sont "pas définies" : Unbound constructor
, Unbound value
... pensez à évaluer les cellules au dessus...Shift-Entrée
ou Ctrl-Entrée
Aide > Raccourcis claviers
ou la palette (Ctrl-Shift-p
)Noyau > Redémarrer
type r_barre = Inf | V of int (* On travaille avec des entiers ici, ou des flottants si on veut *)
Remarque : on pourrait aussi travailler directement avec des int
s et max_int
par exemple ; mais ce serait moins dans l'esprit des sujets de concours...
let minimum a b =
match a, b with
| _, Inf -> a
| Inf, b -> b
| V(x), V(y) -> V(min x y)
let somme a b =
match a, b with
| _, Inf -> Inf
| Inf, _ -> Inf
| V(x), V(y) -> V(x+y)
let inferieur a b =
match a, b with
| _, Inf -> true
| Inf, _ -> false
| V(x), V(y) -> x < y
type mat_adj = r_barre array array
let graphe_matrice :mat_adj = [|
[|V 0; V 3; V 8; Inf; V 4|];
[|Inf; V 0; Inf; V 1; V 7|];
[|Inf; V 4; V 0; Inf; Inf|];
[|V 2; Inf; V 5; V 0; Inf|];
[|Inf; Inf; Inf; V 6; V 0|];
|]
(* Ne surtout pas faire : Array.make n (Array.make n Inf), ou vous aurez des surprises*)
let matrice_vide n = Array.make_matrix n n Inf;;
matrice_vide 2
let copie_matrice mat =
let n = Array.length mat in
let copie = matrice_vide n in
for i = 0 to n-1 do
for j = 0 to n-1 do
copie.(i).(j) <- mat.(i).(j)
done
done;
copie
let floyd_warshall graphe =
let d = copie_matrice graphe and n = Array.length graphe in
for k = 0 to n-1 do
for i = 0 to n-1 do
for j = 0 to n-1 do
d.(i).(j) <- minimum d.(i).(j) (somme d.(i).(k) d.(k).(j))
done
done
done;
d;;
floyd_warshall graphe_matrice
type distance = r_barre and sommet = int;;
type liste_adj = (sommet * distance) list array;;
let graphe_liste :liste_adj = [|
[(1, V 3); (2, V 8); (4, V 4)];
[(3, V 1); (4, V 7)];
[(1, V 4)];
[(0, V 2); (2, V 5)];
[(3, V 6)];
|]
(distance, sommet)
.module Fprio = Set.Make(struct type t = distance * sommet let compare = compare end)
(* Structure de donnée non mutable *)
Fprio.singleton (V 0, 0)
List.iter
(* On peut écrire quasiment le même code qu'en Python avec deux boucles for imbriquées
si on manipule un `... array array`. C'est possible... *)
let list_adj_to_mat_adj graphe =
Array.init (Array.length graphe) (fun i -> Array.of_list graphe.(i));;
list_adj_to_mat_adj graphe_liste
(* Avec des références, c'est moche *)
let dijkstra_ref voisins source =
let fileprio = ref Fprio.empty and d = Array.make (Array.length voisins) Inf in
d.(source) <- V 0;
fileprio := Fprio.add (V 0, source) !fileprio;
while not (Fprio.is_empty !fileprio) do
let (du, u) = Fprio.min_elt !fileprio in (* ne modifie PAS fileprio *)
fileprio := Fprio.remove (du, u) !fileprio;
List.iter
(fun (v, dist) -> let nouvelle = somme d.(u) dist in
if inferieur nouvelle d.(v) then (* Attention, pas < *)
begin
d.(v) <- nouvelle;
fileprio := Fprio.add (nouvelle, v) !fileprio
end
)
voisins.(u)
done;
d
dijkstra_ref graphe_liste 0
List.fold_left
let dijkstra voisins source =
let d = Array.make (Array.length voisins) Inf in
d.(source) <- V 0;
let rec parcours fileprio =
if Fprio.is_empty fileprio then d
else begin
let (du, u) = Fprio.min_elt fileprio in
let nouvelle_fileprio = Fprio.remove (du, u) fileprio in
let mise_a_jour file (v, dist) =
let nouvelle = somme d.(u) dist in
if inferieur nouvelle d.(v) then
begin
d.(v) <- nouvelle; (* modifie d *)
Fprio.add (nouvelle, v) file
end
else
file
in parcours (List.fold_left mise_a_jour nouvelle_fileprio voisins.(u))
end
in parcours (Fprio.singleton (V 0, source))
dijkstra graphe_liste 0