Next: Chapitre 6
Up: Programmes en Caml
Previous: Chapitre 4
let m =
[| [| 1.0; 0.0; 0.0 |];
[| 0.0; 1.0; 0.0 |];
[| 0.0; 0.0; 1.0 |] |];;
(* La matrice d'adjacence du graphe
donné dans l'exemple.
Attention les sommets sont numérotés
à partir de 0 *)
let g =
[| [| 0; 1; 1; 0; 0; 0 |];
[| 0; 0; 1; 1; 0; 1 |];
[| 0; 0; 0; 0; 0; 1 |];
[| 0; 0; 0; 0; 1; 0 |];
[| 0; 1; 0; 0; 0; 0 |];
[| 0; 0; 0; 1; 0; 0 |] |];;
let lignes m = vect_length m
and colonnes m =
if vect_length m = 0 then failwith "colonnes"
else vect_length m.(0);;
(* Calcule le produit des matrices m1 et m2 *)
let multiplier m1 m2 =
if colonnes m1 <> lignes m2
then failwith "multiplier" else
let résultat =
make_matrix (lignes m1) (colonnes m2) 0 in
for i = 0 to lignes m1 - 1 do
for j = 0 to colonnes m2 - 1 do
let aij = ref 0 in
for k = 0 to colonnes m1 - 1 do
aij := m1.(i).(k) * m2.(k).(j) + !aij;
done;
résultat.(i).(j) <- !aij
done
done;
résultat;;
(* Calcule la somme des matrices m1 et m2 *)
let ajouter m1 m2 =
if colonnes m1 <> lignes m2
then failwith "ajouter" else
let résultat =
make_matrix (lignes m1) (colonnes m2) 0 in
for i = 0 to lignes m1 - 1 do
for j = 0 to colonnes m2 - 1 do
résultat.(i).(j) <- m1.(i).(j) + m2.(i).(j)
done
done;
résultat;;
(* Élève la matrice m à la puissance i *)
let rec puissance m i =
match i with
| 0 -> failwith "puissance"
| 1 -> m
| n -> multiplier m (puissance m (i - 1));;
(* On connaît le nombre de chemins
d'ordre i en calculant puissance m i *)
let nombre_de_chemin_de_longueur_n n i j m =
(puissance m n).(i).(j);;
(* Il y a deux chemins de longueur 2
entre les sommets 0 et 5
(sommets 1 et 6 de la figure 5.3) *)
#nombre_de_chemin_de_longueur_n 2 0 5 g;;
- : int = 2
(* Calcule la somme des puissances n-ième
(pour n <= i) de la matrice m:
sigma i m donne le nombre de chemins
de longueur inférieure à i *)
let sigma i m =
let rec pow i mp =
match i with
| 1 -> mp
| n ->
ajouter mp
(pow (i - 1) (multiplier m mp)) in
pow i m;;
let existe_chemin i j m =
(sigma (colonnes m) m).(i).(j) <> 0;;
#existe_chemin 2 1 g;;
- : bool = true
(* Si u est en relation avec x,
alors on ajoute les arcs u,v
pour tous les v successeurs de x *)
let phi m x =
for u = 0 to colonnes m - 1 do
if m.(u).(x) = 1 then
for v = 0 to colonnes m - 1 do
if m.(x).(v) = 1 then m.(u).(v) <- 1
done
done;;
let fermeture_transitive m =
(* Allocation du résultat *)
let résultat =
make_matrix (lignes m) (colonnes m) 0 in
(* Recopie de m dans le résultat *)
for i = 0 to lignes m - 1 do
for j = 0 to colonnes m - 1 do
résultat.(i).(j) <- m.(i).(j)
done
done;
(* Pour tous les sommets on applique phi *)
for x = 0 to colonnes m - 1 do
phi résultat x done;
résultat;;
(* On accède transitivement à tous les sommets,
sauf au sommet 0 *)
#fermeture_transitive g;;
- : int vect vect =
[|[|0; 1; 1; 1; 1; 1|]; [|0; 1; 1; 1; 1; 1|];
[|0; 1; 1; 1; 1; 1|]; [|0; 1; 1; 1; 1; 1|];
[|0; 1; 1; 1; 1; 1|]; [|0; 1; 1; 1; 1; 1|]|]
(* Listes de successeurs *)
type graphe_point == (int list) vect;;
let omega = -1;;
let transforme_mat_suc m =
let succ =
make_matrix (lignes m) (colonnes m) 0 in
let k = ref 0 in
for i = 0 to lignes m - 1 do
k := 0;
for j = 0 to colonnes m - 1 do
if m.(i).(j) = 1 then begin
succ.(i).(!k) <- j;
incr k end
done;
succ.(i).(!k) <- omega
done;
succ;;
(* ``Listes'' de successeurs,
{\em voir page \pageref{prog:declsucc}} *)
#transforme_mat_suc g;;
- : int vect vect =
[|[|1; 2; -1; 0; 0; 0|]; [|2; 3; 5; -1; 0; 0|];
[|5; -1; 0; 0; 0; 0|]; [|4; -1; 0; 0; 0; 0|];
[|1; -1; 0; 0; 0; 0|]; [|3; -1; 0; 0; 0; 0|]|]
(* Transforme une matrice d'adjacence
en vecteur de listes de successeurs *)
let transforme_mat_list_suc m =
let gpoint = make_vect (colonnes m) [] in
for i = 0 to lignes m - 1 do
for j = 0 to colonnes m - 1 do
if m.(i).(j) = 1
then gpoint.(i) <- j :: gpoint.(i)
done
done;
gpoint;;
#transforme_mat_list_suc g;;
- : int list vect =
[|[2; 1]; [5; 3; 2]; [5]; [4]; [1]; [3]|]
(* succ est dorénavant un tableau de listes *)
let numéro = make_vect (vect_length succ) (-1);;
let num = ref (-1);;
let rec num_prefixe k = begin
incr num;
numéro.(k) <- !num;
do_list
(function x -> if numéro.(x) = -1 then
num_prefixe (x))
succ.(k)
end;;
let numPrefixe() = begin
do_vect
(function x -> if numéro.(x) = -1 then
num_prefixe (x))
numéro
end;;
let num_largeur k =
let f = file_vide() in begin
fajouter k f;
while not (fvide q) do
let k = fvaleur(f) in begin
fsupprimer f;
incr num;
numéro.(k) <- !num;
do_list
(function x -> if numéro.(x) = -1 then
begin
fajouter x f;
numéro.(x) <- 0
end)
succ.(k)
end
done
end;;
let numLargeur() = begin
do_vect
(function x -> if numéro.(x) = -1 then
num_largeur (x))
numéro
end;;
(* comp_connexe calcule la composante connexe
de k et retourne son point d'attache *)
let rec comp_connexe k = begin
incr num; numéro.(k) <- !num;
pajouter k p;
let min = ref !num in begin
do_list
(function x ->
let m = if numéro.(x) = -1 then
comp_connexe (x)
else
numéro.(x)
in if m < !min then
min := m)
succ.(k);
if !min = numéro.(k) then
(try while true do
printf "%d " (pvaleur(p));
numéro.(pvaleur(p)) <- max_int;
psupprimer(p);
if pvaleur(p) = k then raise Exit
done
with Exit -> printf "\n");
!min
end
end;;
let compConnexe() = begin
do_vect
(function x -> if numéro.(x) = -1 then
comp_connexe (x))
numéro
end;;