Vous êtes sur la page 1sur 8

Module TRP Techniques de Rsolution de

Problmes
Travaux pratiques
semestre 1 2015-2016

Introduction
Les TP du module TRP sont obligatoires. Les notions tudies dans les cours et TD de TRP sont considres
comme tant acquises. Vous allez travailler pendant les TP pour implmenter en langage CAML certains des
algorithmes et des concepts que vous avez tudis en cours et TD. Les TP ne doivent pas tre pour vous un
simple exercice de programmation mais doivent vous permettre d'acqurir une comprhension plus profonde du
cours.

Organisation
Il vous faut systmatiquement apporter vos documents de travail. Il vous sera impossible de raliser le travail
demand si vous n'avez pas travaill les cours et TD avant le TP. Il y aura 5 sances de TP, en voici le planning :
Sance

Titre

S1 TP1

Implmentation de lalgorithme A*

S2 TP2

Implmentation de lalgorithme A*

S3 TP3

Implmentation de l'algorithme A*

S4 TP4

Application : Reprsentation interne

S5 TP5

Application : heuristique et tests

Modalits de contrle des connaissances


Le travail ralis en TP de TRP donne lieu une note (sur 20) calcule de la manire suivante :
10% de la note est fonde sur lassiduit aux TP.
90% de la note est fonde sur une preuve crite d'1h en amphi. Cette preuve crite porte sur tous les
TPs.
La note de TP compte pour 30% de la note TRP en 1 session, et est reporte en 2 session avec un poids de
25%. Notez que :
2 absences non justifies auprs de lenseignant de TP entranent automatiquement une note dassiduit
de 0.
Une demande de dispense d'assiduit peut tre adresse au responsable de l'UE et dpose,
accompagne de pices justificatives (certificat mdical, bulletin de salaire) le plus tt possible au
secrtariat. Si la dispense est accorde, le poids de l'assiduit est report sur lpreuve crite de TP.
Une absence non justifie lors de l'preuve crite terminale entrane un 0 pour cette preuve crite. En
cas dabsence justifie, la note attribue lpreuve sera 0 la 1 session mais ne sera pas prise en
compte en 2 session. Une absence est considre comme justifie si un certificat mdical ou de travail
est fourni au secrtariat dans les 10 jours ouvrables.

Conventions respecter pour la programmation


Les fichiers : pour chaque fichier, vous donnerez en en-tte les nom, prnom et nom d'utilisateur du
programmeur, ainsi que la date de la dernire modification.
TP TRP 2015-2016

page 1/8

Les programmes : ils devront tre comments intelligemment et sans faute dorthographe ; l'algorithme A*
doit tre implment en style fonctionnel uniquement. Pour chaque fonction, le nom doit tre suivi de la liste
des paramtres typs, avec, en commentaire, pour chaque paramtre, son rle ; vous devrez ensuite indiquer en
commentaire le rle de la fonction, ainsi que les variables globales utilises s'il y en a ; vous spcifierez enfin le
type de l'objet retourn par la fonction. Voici un exemple den-tte de fonction :
(************************************************************)
let rec insereA
(************************************************************)
((n,x) : int * 'a)
(* une association
*)
(l : (int * 'a) list) (* une liste d'associations ordonnes *)
(* en ordre croissant
*)
(************************************************************)
(* retourne la liste l augmente de (n,x) range sa place;*)
(* s'il y avait dj une occurrence de x associe un
*)
(* entier m, il n'en reste qu'une associe au minimum
*)
(* de m et n
*)
(************************************************************)
: (int * 'a) list
(************************************************************)
= ....(* code de la fonction *)...

Commentez les parties les plus dlicates du code. Indentez de manire systmatique avec des espaces en dbut
de ligne.

Mise en route
Les projets sont raliser en Objective Caml. Le manuel de rfrence du langage est disponible en ligne
ladresse suivante : http://caml.inria.fr/pub/docs/manual-ocaml. Le langage CAML peut tre
tlcharg ladresse : http://caml.inria.fr/download.fr.html. Un manuel d'initiation OCaml est
disponible l'adresse suivante : http://www-igm.univ-mlv.fr/~beal/Enseignement/Logique/ocaml.pdf.
Loggez-vous et appelez CAML en tapant la commande ocaml dans un shell. On charge un fichier en tapant
linstruction #use "fichier.ml" ;; . On sort de l'interprteur CAML en tapant l'instruction exit
0 ;; . (Vous pouvez galement lancer ocaml depuis Emacs en passant dabord en mode commande : ESC-X
puis en tapant run-caml .)
L'nonc fait rfrence des fichiers que vous pouvez ( condition d'avoir un nom d'accs et un mot de passe)
rcuprer sur Moodle (moodle.ups-tlse.fr) dans la zone TP du module TRP du M1 d'informatique.
Pour raliser les fonctions demandes, nous vous recommandons d'crire des fonctions auxiliaires et de
les tester en vous servant des exemples de problmes donns sur Moodle sous forme de graphes.

TP TRP 2015-2016

page 2/8

TRP TP1, TP2 et TP3


Recherche dans les espaces d'tats, algorithme A*
Dure : 5 h environ

Recherche en profondeur d'abord dans un espace d'tats


Voici ci-contre un exemple d'espace d'tats donn en
extension . Nous utiliserons ce graphe, qui reprsente un
problme de petite taille, pour illustrer l'excution de
l'algorithme que vous devez crire. D'autres graphes de ce
type sont disponibles sur Moodle. Ils doivent uniquement A
vous servir vrifier le bon fonctionnement de votre
algorithme de recherche. Dans de vritables applications, le
graphe d'tats est souvent de taille exponentielle et il ne peut
videmment pas tre reprsent en extension .
On le reprsente donc en intention en donnant les
caractristiques du problme qu'il reprsente :
l'tat initial ;
la fonction qui caractrise le but ;
la fonction qui dfinit les tats successeurs d'un autre tat.

E
D

G
graphe g1 : Exemple d'espace d'tat

Dans le graphe prcdent, chaque sommet reprsente un tat (A,B,CI), les tats buts sont H ou I. Chaque
arc permet de passer d'un tat un tat fils. Ainsi, en partant de A on arrive I en passant par C et D.
Une reprsentation CAML de ce graphe g1 est donne sur Moodle dans le fichier "graphes.ml". Cette
reprsentation se dcompose, pour ce graphe g1, en deux fonctions qui sont les suivantes :
estBut1, de type string -> bool, la fonction qui teste si un tat est un but ;
etatsSuivants1, de type string -> string list, la fonction qui associe chaque tat la
liste des tats fils possibles depuis cet tat ;
On accde aux diffrentes fonctions caractrisant ce graphe g1 ainsi :
# estBut1 "H";;
- : bool = true
# etatsSuivants1 "A";;
- : string list = ["C"; "B"]
On vous demande, dans un premier temps, d'implmenter, en CAML et en style fonctionnel, un algorithme de
recherche dans les espaces d'tats qui travaille en profondeur d'abord. Ce type de recherche est
systmatique et ne ncessite donc pas l'utilisation d'une heuristique. La fonction profondeur devra tre
rcursive et travailler sur une liste reprsentant la file d'attente. Cette fonction utilisera les fonctions estBut et
etatsSuivants supposes dfinies pour le problme courant.
1. Etant donn la description d'un problme grce la dfinition des deux fonctions estBut et
etatsSuivants, crire une premire fonction profondeurBeta qui renvoie le premier tat But atteint par
un parcours en profondeur. Vous pourrez tester votre fonction sur le graphe g1 (en dfinissant les fonctions
estBut e t etatsSuivants comme gales estBut1 e t etatsSuivants1 dfinies dans le fichier
"graphes.ml").
# profondeurBeta ["A"];;
- : string = "H"
Vous pourrez ensuite la tester avec les deux autres fonctions de but proposes : estBut1bis et
estBut1ter.

TP TRP 2015-2016

page 3/8

Afin de permettre un meilleur suivi du droulement de l'algorithme, on va utiliser des fonctions d'affichage en
mme temps que l'on renvoie les valeurs dsires. L'affichage de chanes de caractres se fait au moyen de la
fonction print_string, de type string -> unit (c'est--dire que c'est une fonction qui ne renvoie
aucune valeur).
2. crire la fonction print_list_string, de type string list -> unit qui affiche une liste de
chanes de caractres en les sparant par des espaces et en la terminant par un point, exemple :
# print_list_string ["Aa"; "BBb"; "C"; "D"];;
Aa BBb C D. - : unit = ()
Transformer votre fonction profondeurBeta pour qu'elle renvoie le mme rsultat mais en affichant
l'volution de la file d'attente au fur et mesure (cette faon de programmer n'est pas fonctionnelle car elle
demande dexcuter des instructions d'affichage de faon squentielle avec d'autres instructions, nous
autorisons la programmation non fonctionnelle seulement pour les affichages).
3. Prise en compte des boucles : dans un espace d'tat, il peut y avoir des boucles. Par exemple, avec un jeu de
taquin, on peut revenir un tat donn aprs plusieurs mouvements et, en refaisant la mme suite de
mouvements, tourner indfiniment sans jamais trouver de solution. Pour viter l'algorithme
profondeurBeta de boucler, vous crirez la fonction
profondeurBetaVus a y a n t c o m m e p a r a m t r e
G
B
E
supplmentaire une liste vus dans laquelle vous mmoriserez,
au fur et mesure, les tats dj dvelopps. Si un tat
possde des fils dj vus pendant la recherche, on vite de les A
D
insrer dans la file d'attente.
C

Vous pourrez tester votre fonction profondeurBetaVus


sur le graphe g2, dcrit par estBut2 et etatsSuivants2
dans le ficher "graphes.ml" :
# profondeurBetaVus ["A"] [];;
- : string = "G"

Graphe g2

B
h,4

On considre maintenant que chaque opration a un cot.


Dans le graphe prcdent, chaque arc est associ une
opration de changement dtat, ici h (pour haut ), b (pour
bas ), d (pour droite ) ou g (pour gauche ) et porte
le cot rel de celle-ci. Ainsi, en partant de A et en appliquant
la suite doprations b, g, h cela cote 11. Dans la suite
du texte on note coutParcouru(ch)le cot rel des
oprations d'un chemin ch ; par exemple, le cot rel du
chemin ACD est coutParcouru(ACD) = 3 + 2 = 5.

h,4

E
D

g,2

b,3
C

d,9

h,6

b,7

b,4

h,7
H

b,9
d,7

graphe g1 avec cots des oprations

4. crire une fonction profondeur qui renvoie l'tat but et un chemin solution (sous la forme de la liste des
oprations utilises pour arriver cet tat) ainsi que son cot. Pour cela, la file d'attente devra contenir des
triplets (nom de l'tat, chemin qui y arrive, cot de ce chemin) et non plus de simples tats dvelopper.
La fonction profondeur utilisera la mme fonction estBut que la fonction profondeurBeta, elle utilisera
aussi une deuxime fonction (appele opPoss dans le fichier d'exemples) qui partir d'un tat donne une liste
d'lments o chaque lment dcrit l'opration ralisable, son cot et l'tat rsultant.
Vous pourrez tester votre fonction sur les diffrents graphes fournis dans le fichier "graphes.ml". Pour le graphe
g1, on vous donne la fonction opPoss1, de type string -> (char * string * int) list, qui
associe chaque tat la liste des oprations possibles partir de cet tat, associes aux tats rsultants et aux
cots rels de ces oprations :
# opPoss1 "C";;
- : (char*string*int) list =[('d',"F", 9);('g',"D",2)]

TP TRP 2015-2016

page 4/8

crivez d'abord profondeur sans tester les boucles avec la liste vus (vous pourrez implmenter la version
avec la liste vus dans un deuxime temps).
# profondeur [("A",[],0)] ;;
- : string * char list * int = ("H", ['b'; 'd'; 'b'], 21)

Rappels sur l'algorithme A*


L'algorithme A* est un algorithme de recherche dans les espaces d'tats. Pour un problme donn, l'algorithme
dveloppe une partie de l'espace d'tats du problme. L'espace qui est dvelopp (et que l'on souhaite tre le
plus petit possible) est appel espace de recherche. Partant de l'tat initial, l'algorithme dveloppe donc cet
espace de recherche en essayant de trouver un chemin-solution (compos d'une suite d'oprations) qui permette
d'arriver un tat but. Pour rduire la taille de l'espace de recherche, l'algorithme est guid par une fonction
heuristique qui estime, pour chaque tat tudi, le cot minimal de la suite des oprations (ou chemin) qui
permettrait, partir de cet tat, d'arriver un tat but. Si cette heuristique est minorante, c'est--dire si
l'estimation du cot pour arriver au but est toujours infrieure au cot rel, alors le chemin-solution retourn par
A* est un chemin de cot minimum pour le problme pos.
L'algorithme A* utilise une file d'attente qui mmorise chaque tat atteint ainsi que le chemin partant de l'tat
initial qui a permis de l'atteindre. Au dpart la file d'attente ne contient qu'un seul lment : un chemin vide 1
depuis l'tat initial. Pendant tout le droulement de l'algorithme les chemins de la file d'attente y sont classs
dans l'ordre croissant de leur cot estim (les chemins de plus faible cot sont considrs en premier). Le
cot estim d'un chemin ch d'tat terminal e est gal au cot rel du chemin parcouru pour arriver en e
+ l'estimation (donne par l'heuristique) du chemin qu'il reste parcourir depuis e pour arriver un tat
but. chaque tape de l'algorithme, le chemin le plus prometteur (c'est--dire celui de plus faible cot, donc en
tte de la file d'attente) est dvelopp : il est retir de la file et ses chemins fils sont insrs dans cette mme
file une position qui dpend de leur cot estim (chemins de plus faible cot d'abord). L'algorithme stoppe
quand le chemin extrait de la file d'attente mne un tat but.
L'exemple d'espace d'tats en extension avec une fonction heuristique est donn ci-aprs. Dans l'algorithme A*,
l'espace d'tats peut tre reprsent en intention en prcisant les caractristiques du problme qu'il reprsente :
l'tat initial ;
la fonction qui caractrise le but ;
la fonction qui dtermine les oprations ralisables partir de chaque tat, leur cot, et les tats qui en
rsultent ;
la fonction heuristique qui estime le cot minimal d'un chemin entre chaque tat et un tat but.
Dans le graphe ci-contre, chaque sommet porte la valeur de
la fonction heuristique hEtat qui estime le cot minimal
d'un chemin entre cet tat et l'un des tats buts H ou I. Par
exemple, hEtat(A)=7 signifie que lheuristique estime
que le cot minimal pour aller de A lun des deux tats
buts est de 7. Pour un chemin ch dont l'tat terminal est e,
on note estimChemin(ch) = coutParcouru(ch)
+ hEtat(e) : cela reprsente le cot estim du
prolongement du chemin ch jusqu' un tat but ; ainsi,
estimChemin(ACD) = 5 + hEtat(D) = 5 + 2
= 7. On peut vrifier (en examinant le graphe de manire
exhaustive) que lestimation heuristique sur cet exemple est
minorante, c'est--dire que le cot estim est infrieur au
cot minimal rel pour tout tat du graphe.

Espace d'tats du problme ( gauche : l'tat


initial, en rectangle : les deux tats buts)
B,3
h,4

h,4

E,2 b,4
h,6

b,7

A,7

D,2
g,2

b,3
C,5

d,9

I,0

F,7

h,7
b,9
d,7

H,0
G,

graphe g1

1 Par abus de langage ce terme dsigne un chemin sans aucun arc (contenant seulement un tat).

TP TRP 2015-2016

page 5/8

Partant de l'tat initial, l'algorithme dveloppe l'arbre de recherche comme le montrent les schmas suivants (
lire de gauche droite et de haut en bas). Le nud qui va tre dvelopp est le premier de la file d'attente (en
rouge les nuds qui ont t mis dans la file d'attente).
[(A,0+7)] : au dbut de l'algorithme, seul l'tat
initial est dans la file d'attente
h,4

B,3
h,4

E,2 b,4
D,2

g,2

b,3
C,5

d,9

I,0

F,7

h,4

h,4

E,2 b,4

A,7

D,2
b,3
C,5

d,9

F,7

I,0

H,0

b,9

b,7

A,7
b,3

g,2
C,5
d,9

E,2 b,4

F,7

F,7

h,7

g,2
C,5

d,9

I,0

h,6

F,7

G,

H,0

b,9
d,7

G,

[(I,11+0) ; (F,12+7)] : I est un tat but fin de


l'algorithme retour du chemin [b;g;h]
I,0

h,7

d,7

G,

E,2 b,4

b,7

b,3

B,3 h,4
h,4

b,9

H,0

b,9

D,2

h,6
D,2

h,4

A,7

[(E,8+2) ; (I,11+0) ; (F,12+7)] : idem

h,4

B,3
h,4

d,7

B,3 h,4

d,9

[(D,5+2) ; (E,8+2) ; (F,12+7)] : idem et D est


mis jour avec un meilleur chemin

h,7

g,2

h,7

g,2

d,7

h,6

b,7

D,2
C,5

I,0

h,6

G,

[(C,3+5);(E,8+2);(D,11+2)] : idem
h,4

E,2 b,4

b,7

b,3

H,0

b,9

h,4

A,7

h,7

d,7

B,3

B,3

h,6

b,7

A,7

[(B,4+3) ; (C,3+5)] : on dveloppe le meilleur et


on insre ses fils suivant leur estimation

A,7
H,0
G,

b,3

b,7
g,2
C,5
d,9

E,2 b,4

I,0

h,6
D,2
F,7

h,7
b,9
d,7

H,0
G,

Une reprsentation CAML de ce graphe g1 est donne sur Moodle dans le fichier "graphes.ml". Cette
reprsentation contient la fonction hEtat1 :
hEtat1, de type string -> int, la fonction heuristique, qui associe chaque tat une estimation
du cot minimal d'un chemin allant de cet tat un tat but.

TP TRP 2015-2016

page 6/8

On accde aux diffrentes fonctions caractrisant ce graphe g1 ainsi :


# hEtat1 "A";;
- : int = 7

Algorithme A*
5. En vous inspirant de vos fonctions de recherche en profondeur, implmentez l'algorithme A* en CAML en
style fonctionnel. La fonction aEtoile devra tre rcursive et travailler sur une liste reprsentant la file
d'attente. Pour l'utiliser on lancera aEtoile avec une file d'attente ne contenant que le chemin constitu du
seul tat initial, elle utilisera les fonctions suivantes caractrisant le problme:
estBut : ('a -> bool) le prdicat caractrisant les buts (renvoie vrai si l'tat est un tat but);
opPoss : ('a->('b*'a*int) list) la fonction qui retourne la liste des oprations possibles
partir d'un tat, associes aux tats d'arrive et aux cots de ces oprations ;
hEtat : ('a -> int)la fonction heuristique qui donne une valeur numrique entire tout tat ;
Etant donn la description d'un problme au moyen des 3 fonctions qui le caractrisent, cette fonction aEtoile
renvoie un chemin-solution.
La fonction aEtoile applique au graphe g1 depuis son tat initial A est appele ainsi :
#aEtoile ?? (*file d'attente contenant le chemin associ A*);;
elle utilise les fonctions estBut, opPoss et hEtat fixes pour les tests estBut1, opPoss1 et hEtat1.
Elle donne comme rsultat le chemin ['b' ;'g' ;'h'] de cot 11.

Amlioration de A* : utilisation de la liste vus


Comme il existe gnralement plusieurs chemins qui permettent d'arriver un mme tat, il est possible que
l'algorithme, au cours de sa recherche, arrive un tat e par un premier chemin puis, un peu plus tard, par un
autre, de cot diffrent, potentiellement plus intressant. Pour ne pas stocker des tats dj traits et non
intressants, on utilise une liste vus dans laquelle on mmorise chaque tat que l'on vient de dvelopper (c'est-dire que l'on vient de retirer de la file d'attente pour crer ses fils), associ au meilleur cot du chemin (que
l'on a trouv jusqu'ici) qui permet d'y aboutir. Cette liste vus est optimise en y stockant chaque tat une seule
fois.
La liste vus est utilise lors du traitement d'un tat que l'on extrait de la file d'attente. Cet tat est dvelopp,
c'est--dire que l'on produit ses fils et leurs chemins respectifs associs. Chaque tat fils est ensuite considr
afin de savoir s'il doit ou non tre insr dans la file d'attente :
i) si l'tat fils considr a dj t vu avec un chemin de cot infrieur (il figure dans la liste vus avec ce
dernier cot), il est inutile de le mmoriser dans la file d'attente (on coupe la recherche d'un cheminsolution passant par ce nouvel tat fils et on s'occupe du fils suivant) ;
ii) si l'tat fils considr n'a jamais t vu, on l'insre dans la file d'attente en fonction du cot de son chemin
associ (le nouveau chemin que l'on vient de trouver) ;
iii) si l'tat fils considr a dj t vu mais avec un chemin de cot suprieur, on l'limine de la liste vus et
on l'insre dans la file d'attente en fonction du cot de son chemin associ (le nouveau chemin, de cot
plus faible, que l'on vient de trouver). C'est ce qui se passe l'tape 4 du dveloppement de l'exemple.
6. Amliorez votre implmentation de l'algorithme A* en lui ajoutant une liste vus.

Affichage de statistiques et tests de l'algorithme


7. Pour finir, vous implmenterez une fonction recherche qui ralisera le premier appel la fonction
aEtoile avec une file d'attente ne contenant que le chemin constitu de l'tat initial : les paramtres de la
fonction recherche devront respecter les types suivants :
('a -> bool) le prdicat caractrisant les buts (renvoie vrai si l'tat donn est un tat but.
('a->('b*'a*int) list) la fonction qui retourne la liste des oprations possibles partir d'un
TP TRP 2015-2016

page 7/8

tat, associes aux tats d'arrive et aux cots de ces oprations.


('a -> int) la fonction heuristique qui donne une valeur numrique entire tout tat.
'a l'tat initial de la recherche (de type quelconque)

Etant donn la description d'un problme au moyen des 4 fonctions qui le caractrisent, cette fonction recherche
devra renvoyer un chemin-solution ou, si c'est le cas, signaler que le problme n'admet pas de solution.
La fonction recherche applique au graphe g1 depuis son tat initial A sera appele ainsi :
#recherche
estBut1
opPoss1
hEtat1
"A";;
et donnera comme rsultat le chemin ['b' ;'g' ;'h'] de cot 11.
8. Modifiez votre implmentation afin qu'elle affiche, en fin de recherche, le nombre d'itrations et le nombre
de nuds crs. Pour conserver la mme signature pour la fonction, ces statistiques ne sont pas retourner,
mais seulement afficher la fin de la recherche, avant de retourner le chemin solution.

TP TRP 2015-2016

page 8/8