1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
|
type ’a graphe = { sommets : ’a list ; succ : ’a −> ’a list };;
(* Interface appartient
type : ’a −> ’a list −> bool
arg : a = élément à rechercher
l = liste de recherche
post : true si a appartient à l, false sinon *)
let rec appartient a l = match l with
|[] −> false
|t::q −> if a=t then true else appartient a q
;;
(* Interface miroir
type : ’a list −> ’a list
arg : l = liste à inverser
post : liste éléments de l dans l’odre inverse de celui de l *)
let miroir l =
let rec aux l acc = match l with
|[] −> acc
|t::q −> aux q (t::acc)
in aux l []
;;
(* Interface parcours
type : ’a graphe −> ’a −> ’a list
arg : graphe = graphe à parcourir
x = sommet de départ
pre : x est un sommet de graphe
post : liste des sommets de g rencontrés lors de son parcours en profondeur à partir de son premier
sommet. elle est dans l’odre où les sommets sont rencontrés *)
let parcours graphe x =
(* aux fait le travail de parcours en s’aidant de deux paramètres supplémentaires : *)
(* les successeurs de x et les sommets déjà parcourus *)
(* les sommets sont ajoutés dès leur rencontre : résultat à l’envers *)
let rec aux graphe x succ_x result_temp = match succ_x with
|[] −> result_temp
|t::q −> if appartient t result_temp (* t a−t−il été déjà visité ? *)
then (* on passe à la suite *)
aux graphe x q result_temp
else (* on parcours les successeurs de t avant de continuer avec ceux de x *)
aux graphe x q (aux graphe t (graphe.succ t) (t::result_temp))
in miroir (aux graphe x (graphe.succ x) [x])
;;
(* Interface recherche
type : ’a graphe −> ’a −> ’a −> ’a list −> ’a list −> ’a list −> bool * ’a list * ’a list
arg : graphe
a = sommet où commence la recherche
b = sommet recherché
succ_a = successeurs de a
visites = sommets déjà visités au moment de cet appel
temp = miroir du chemin parcouru pour rechercher arrivee
pre : a et les éléments de succ_a sont des sommets de graphe
post : triplet contenant :
* un booléen vrai si il existe un chemin de graphe entre a et b
* le miroir de ce chemin si il existe, celui du dernier essayé sinon
* la liste des sommets visités *)
let rec recherche graphe a b succ_a temp visites = match succ_a with
|[] −> false,temp,visites
|t::q −> if t=b then true,t::temp,visites (* on est arrivé *)
else if appartient t visites (* sommes−nous déjà passés ici ? *)
then (* on passe à la suite *)
recherche graphe a b q temp visites
else (* on essaye en passant par t... *)
let trouve,temp’,visites’ = recherche graphe t b (graphe.succ t) (t::temp) (t::visites) in
if trouve
then trouve,temp’,visites’ (* ... et ça a marché *)
else recherche graphe a b q temp visites’ (* ... en vain : on passe à la suite *)
;;
(* Interface circuit
type : ’a graphe −> ’a −> ’a list
arg : graphe = graphe où est recherché le circuit
x = sommet que doit contenir le circuit recherché
pre : x est un sommet de graphe
post : un circuit (donc orienté) de graphe passant par x si il existe, la liste vide sinon *)
let circuit graphe x =
let (trouve,chemin,_) = recherche graphe x x (graphe.succ x) [x] [x] in
if trouve then miroir chemin else []
;;
(* Interface pred
type : ’a graphe −> ’a −> ’a list
arg : graphe
x = sommet dont on veut les prédécesseurs
sommets susceptibles d’être des prédécesseurs de x
pre : les éléments de sommets et x sont des sommets de graphe
post : liste des prédécesseurs de x *)
let rec pred graphe x sommets = match sommets with
|[] −> []
|t::q −> if t=x then pred graphe x q
else if appartient x (graphe.succ t) then t::(pred graphe x q)
else pred graphe x q
;;
(* Interface desoriente
type : ’a graphe −> ’a graphe
arg : graphe
post : renvoie graphe modifié de manière à ne plus tenir compte de l’orientation des arcs *)
let desoriente graphe =
(* aux calcule la fonction succ associée au graphe désorienté *)
let rec aux graphe sommets = match sommets with
|[] −> (function x −> failwith "sommet inconnu")
|t::q −> function
|x when (x=t) −> (graphe.succ t)@(pred graphe t graphe.sommets)
|x −> (aux graphe q) x
in let succ’ = aux graphe graphe.sommets
in { sommets = graphe.sommets ; succ = succ’ }
;;
type ’a precedent = Rien | P of ’a;;
(* Interface cycle
type : ’a graphe −> ’a −> ’a list
arg : graphe = graphe où est recherché le cycle
x = sommet que doit contenir le cycle recherché
pre : x est un sommet de graphe
post : un cycle de graphe passant par x si il existe, la liste vide sinon *)
let cycle graphe x =
let back t prec l = match prec with
|Rien −> true
|P(x) −> (t <> x) || appartient t l
in let rec recherche2 graphe a b succ_a prec temp visites = match succ_a with
|[] −> false,temp,visites
|t::q −> if (t=b) && (back t prec q) (* On de doit pas revenir en arrière *)
then true,t::temp,visites (* on est arrivé *)
else if appartient t visites (* sommes−nous déjà passés ici ? *)
then (* on passe à la suite *)
recherche2 graphe a b q prec temp visites
else (* on essaye en passant par t... *)
let trouve,temp’,visites’ = recherche2 graphe t b (graphe.succ t) (P a) (t::temp) (t::visites)
in
if trouve
then trouve,temp’,visites’ (* ... et ça a marché *)
else recherche2 graphe a b q prec temp visites’ (* ... en vain : on passe à la suite *)
in let graphe’ = desoriente graphe in
let (trouve,chemin,_) = recherche2 graphe’ x x (graphe’.succ x) Rien [x] [x] in
if trouve then miroir chemin else []
;;
(* Interface chemin
type : ’a graphe −> ’a −> ’a −> ’a list
arg : graphe = graphe où le chemin est recherché
a = extremité initiale du chemin recherché
b = extrémité finale du chemin recherché
pre : a est un sommet de graphe
post : un chemin de graphe entre a et b si il existe, la liste vide sinon *)
let chemin graphe a b =
let (trouve,reponse,_) = recherche graphe a b (graphe.succ a) [a] [a] in
if trouve then miroir reponse else []
;;
type ’a graphevalue = { sommets : ’a list ; succ : ’a −> (’a * int) list };;
(* Interface retire
type : ’a −> ’a list −> ’a list
arg : a = élément à retirer
l = liste à modifier
post : l privée de la première occurence de a si elle existe (l sinon) *)
let rec retire a l = match l with
| [] −> []
|t::q−> if a=t then q else t::(retire a q)
;;
(* Interface inf
type : int −> int −> bool
arg : a b
post : true si a < b, false sinon, en considérant que −1 = l’infini *)
let inf a b = (a <> −1) && ( (b = −1) || (a < b) );;
(* Interface distmin
type : ’a list −> (’a * int) list −> ’a * int
arg : sbar = liste de sommets
distances = liste de couples (sommet, distance)
pre : sbar et distances sont non vides
post : plus petit couple de distances (en ordonnant les couples par rapport à leur second élément) dont
le premier élément appartient à sbar
raises : si sbar ou distances est vide *)
let rec distmin sbar distances =
(* aux garde le plus petit couple trouvé en paramètre *)
let rec aux sbar distances mintmp = match distances with
| [] −> mintmp
|(i,pi_i)::q −> let (j,pi_j) = mintmp in
if (inf pi_i pi_j) && (appartient i sbar)
then aux sbar q (i,pi_i) (* on a trouvé plus petit : on garde *)
else aux sbar q mintmp
in match distances with (* on cherche un premier mintmp avant d’appeler aux *)
| [] −> failwith "distmin : l’un des arguments est vide"
|(i,pi_i)::q −> if appartient i sbar
then aux sbar q (i,pi_i)
else distmin sbar q
;;
(* Interface longueur_arc
type : (’a * int) list −> ’a −> ’a −> int
arg : succ_i = successeurs de i
i = extrêmité initiale de l’arc recherché
j = son extrêmité finale
post : valeur de l’arc (i,j) si il existe, −1 sinon (représente l’infini) *)
let rec longueur_arc succ_i i j = if i=j then 0 else
match succ_i with
| [] −> −1
|(t,d)::q −> if j=t then d else longueur_arc q i j
;;
(* Interface min2
type : int −> int −> int
arg : a b
pre : a est positif ou infini (égal à −1), b est positif
post : retourne le minimum des deux entiers en tenant compte de la possible infinitude de a *)
let min2 a b =
if a < 0 then b else min a b
;;
(* Interface update
type : ’a graphevalue −> ’a list −> ’a −> int −> (’a * int) list −> (’a * int) list
arg : graphe
sbar = liste de sommets
j = sommet dont on veut mettre à jour les successeurs
pi_j = distance de x0 à j (valeur définitive)
distances = liste des couples (sommet, distance de sommet à x0)
pre : j est un sommet de graphe, pi_j non infini (différent de −1), distances contient les couples de
tous les sommets de graphe
post : pour chaque sommet i de sbar successeur de j, met à jour le couple correspondant si le chemin
passant par j est plus court que l’actuel, ne modifie rien pour les autres *)
let rec update graphe sbar j pi_j distances = match distances with
|[] −> []
|(i,pi_i)::q −> let lji = longueur_arc (graphe.succ j) j i in
if (lji > 0) && (appartient i sbar) (* successeur de j dans sbar ? *)
then (i,min2 pi_i (pi_j + lji))::(update graphe sbar j pi_j q)
else (i,pi_i)::(update graphe sbar j pi_j q) (* on ne modifie pas à i *)
;;
(* Interface init_dist
type : ’a −> ’a list −> (’a * int) list −> (’a * int) list
arg : x = sommet initial des chemins calculés
sommets (du graphe)
succ_x = successeurs de x
post : liste des couples (s, valeur de l’arc (x0,s)), cette valeur étant infinie si l’arc n’existe pas *)
let rec init_dist x sommets succ_x = match sommets with
| [] −> []
|t::q −> (t, longueur_arc succ_x x t)::(init_dist x q succ_x)
;;
(* Interface pluscourtschemins
type : ’a graphevalue −> ’a −> (’a * int) list
arg : graphe (valué)
x = sommet de départ
pre : x est un sommet de graphe
post : liste des couples (s,l) où l est la plus petite des longueurs des chemins de x au sommet s.
Utilise l’algorithme de Dijkstra *)
let pluscourtschemins graphe x =
let rec aux graphe sbar distances = (* on n’a pas besoin de x pour continuer *)
let (j,pi_j) = distmin sbar distances in
if (pi_j < 0) then distances (* si l’infini est la valeur minimum, on a fini *)
else
let sbar’ = retire j sbar in match sbar’ with
| [] −> distances
| _ −> aux graphe sbar’ (update graphe sbar’ j pi_j distances)
in aux graphe (retire x (graphe.sommets)) (init_dist x graphe.sommets (graphe.succ x))
;; |
Partager