Ministère d Enseignement Supérieur, de Recherche Scientifique et de Technologies *** Ecole Nationale d Ingénieurs de Tunis ***** Département de Technologies d Informations et de Communications ******* Rapport des travaux du bureau d étude Prolog «Programmer en Prolog» Présenté par : Encadré par : Mme. Amira kallal Mlle. Imen Mesbehi Classe : 2AINFO1 Année Universitaire : 2010/2011
2 Sommaire 1. Introduction... 2. Initiation à la manipulation de PROLOG (séance1)... 3. 4. 5. 6. 2.1. Exemple d initiation... 2.2. Exercices :... 2.2.1. Exercice 1 :... 2.2.2. Exercice 2 :... 2.2.3. Exercice 3 :... 2.2.4. Exercice4 :... 1 Arbre généalogique : (séance2)... 3.1. Définition des liens de parenté... 1 3.2. Les règles :... 1 3.3. Le programme :... 1 Les listes en Prlog (séance3)... 4.1. La notion de liste... 1 4.2. Exercice... 1 Gestion d un système de transport (séance3)... 5.1. Le problème :... 2 5.2. Travail demandé :... 2 5.2.1. Définition du domaine... 22 5.2.2. Définition des prédicats... 22 5.2.3. Traduction des questions [1]... 25 5.2.4. Inclure la longueur d un itinéraire... 25 5.2.5. Traduction des questions [2]... 26 conclusion...
3 1. Introduction Prolog est un langage utilisé dans les domaines de l'intelligence Artificielle et la Programmation Logique avec Contraintes. Sa syntaxe et son principe de fonctionnement sont radicalement différents de langages impératifs tels que C ou Java. Le raisonnement se rapproche plus de langages fonctionnels tels que Caml ou Lisp. Pourtant, Prolog n'est pas un langage fonctionnel. Prolog est le premier langage de programmation logique. 2. (séance1) Initiation à la manipulation de PROLOG La 1ère séance commence par u ne représentation de l outil de développement Visual Prolog. Fenêtre du projet Barre de Contrôle Fenêtre du projet Fenêtre d édition Figure 1 : Interface de "Visual Prolog"
4 Donc ce qu on acquit comme nécessaire pour ce logiciel est la création d un projet., la différenciation d es différentes sections d un programme en Prolog selon la structure suivante : options CONSTANTS const1 = definition [GLOBAL] DATABASE [ <databasename> ] [determ] pred1(...) [GLOBAL] DOMAINS dom = <domainedebase> PREDICATES [determ nondeterm] pred1(...) CLAUSES p(...) :- p1(...), p2(...),.... p( ).. GOAL p( ). On a ensuite implémenté un exemple pour se familiariser plus avec le logiciel mais surtout avec le langage Prolog. 2.1. Exemple d initiation Le but (goal) de cet exemple est de déterminer si une personne donnée peut acheter une voiture.
5 include "tp0.inc" domains personne, voiture, couleur = Symbol predicates voiturecouleur(voiture, couleur) aimecouleur(personne, couleur) aprecitvoiture(personne, voiture) peutacheter(personne, voiture) avendre(voiture) possedeargent(personne) clauses aprecitvoiture(x, Y) :aimecouleur(x, C), voiturecouleur(y, C). peutacheter(x, Y) :aprecitvoiture(x, Y), avendre(y), possedeargent(x). voiturecouleur(c3, bleu). voiturecouleur(yaris, gris). aimecouleur(ali, bleu). aimecouleur(sami, gris). avendre(c3). avendre(bmw). possedeargent(ali). possedeargent(sami). goal peutacheter(ali, Y).
6 2.2. Exercices : 2.2.1. Exercice 1 : domains marque,couleur=symbol kilo,prix=real age=integer predicates nondeterm camion(marque,kilo,age,couleur,prix) nondeterm voiture(marque,kilo,age,couleur,prix) nondeterm vehicule(marque,kilo,age,couleur,prix) clauses voiture(chrysher,130.000, 3, rouge, 12.000). voiture(ford, 90.000, 4,gris,25.000). voiture(datsun, 8.000, 1, rouge,30.000). camion(ford,80.000, 6,bleu, 8.000). camion(datsun, 50.000, 5, orange,20.000). camion(toyota, 25.000, 2, noir,25.000). vehicule(x,y,z,t,w):- camion(x,y,z,t,w). vehicule(x,y,z,t,w):- voiture(x,y,z,t,w). goal %voiture(x,y,z,t,p), P<25.000. %camion(_,_,_,gris,p);voiture(ford,_,_,_,p), P<20.000. %vehicule(_,_,a,_,p),a>5,p<20.000. %camion(_,k,_,_,_),k<60.000;camion(_,_,_,_,p),p<10.000. voiture(_,_,age,_,p),p<27.000.
7 Les prédicats à définir ici sont : Vehicule(X,Y,Z,T,W):- camion(x,y,z,t,w). Vehicule(X,Y,Z,T,W):- voiture(x,y,z,t,w). Ils signifient simplement qu un véhicule est soit un camion, soit une voiture. Les réponses aux requêtes : 1) Trouver les voitures dont le prix < 25000 voiture(x,y,z,t,p), P<25.000 2) Trouver les camions gris et les voitures ford dont le prix <20.000 camion(_,_,_,gris,prix);voiture(ford,_,_,_,prix), Prix<20.000. 3) Trouver les véhicules dont l âge >5 et le prix <20.000 vehicule(_,_,age,_,prix),age>5,prix<20.000. 4) Quels sont les camions qui n ont pas encore roulé les 60.000 ou qui coûtent moins que 10.000? camion(marque,kilo,age,couleur,prix),kilo<60.000;camion(marque,kilo,age,cou leur,prix),prix<10.000.
8 5) l âge et le coût des voitures dont le prix <27.000 voiture(_,_,age,_,prix),prix<27.000. 2.2.2. Exercice 2 : Le calcul de n! domains nb,res= Integer predicates nondeterm factoriel(nb,res) clauses factoriel(0,1). factoriel(nb,res):- Nb>0, N=Nb-1,factoriel(N,Res1),Res=Res1*Nb. goal Write("donner un entier"),nl, Readint(X),nl,write("le factoriel de "), factoriel(x,res).
9 Le calcul du factoriel se fait de façon récursive suivant le prédicat : factoriel(0,1). factoriel(nb,res):- Nb>0, N=Nb-1,factoriel(N,Res1),Res=Res1*Nb. 2.2.3. Exercice 3 : Cet exercice calcule la puissance d un nombre. Son algorithme est encore récursif. domains nb= Integer predicates nondeterm puissance(nb,nb,nb) clauses puissance(n,1,n):-!. puissance(nb,p,res):- P1=P-1,puissance(NB,P1,Res1),Res=Res1*Nb. goal Write("donner un entier"),nl,readint(nombre), Write("donner sa puissance"),nl,readint(puissance), nl,write("le résultat "),puissance(nombre,puissance,r).
10 La puissance nième de X est tel qu elle est égale au produit de X avec sa puissance (n-1)ième tant que la puissance qui décrémente est supérieure à 1. Si elle est à 1 elle retourne le même nombre. Il y a donc 2 solutions, soit qu on indique cette condition dans l appel récursif, soit on applique le cut dans la condition d arrêt. puissance(n,1,n):-!. puissance(nb,p,res):- P1=P-1,puissance(NB,P1,Res1),Res=Res1*Nb. Ou : puissance(n,1,n). puissance(nb,p,res):- P>1,P1=P-1,puissance(NB,P1,Res1),Res=Res1*Nb. Write("donner un entier"),nl,readint(nombre), Write("donner sa puissance"),nl,readint(puissance), nl,write("le résultat "),puissance(nombre,puissance,r). 2.2.4. Exercice4 : Cet exercice calcule le PGCD de deux entiers include "exo4.inc" X et Y. domains nb=integer predicates nondeterm pgcd(nb,nb,nb). clauses pgcd(x,x,x). pgcd(x,y,d):-x<y,y1=y-x,pgcd(x,y1,d). pgcd(x,y,d):-x>y,pgcd(y,x,d). goal pgcd(6,3,x).
11 3. si X et Y sont égaux, D vaut X si X < Y alors D est le PGCD de X et de Y - X si Y < X alors échanger le rôle de X et Y pgcd(x,x,x). pgcd(x,y,d):-x<y,y1=y-x,pgcd(x,y1,d). pgcd(x,y,d):-x>y,pgcd(y,x,d). (séance2) Arbre généalogique : Les buts de cette séance sont : - La manipulation du concept de relation. - L implémentation d un programme permettant de définir des liens de parenté dans un arbre généalogique. 3.1. Définition des liens de parenté On va tout d abord traduire l arbre généalogique suivant par un ensemble de relations entre de objets.
12 Figure2 : arbre généalogique 3.2. Les règles : Les règles de bases implémentées sont : Féminin(X), Masculin(Y) et parent(x,y). Les autres comme grandparent et sœur et frère, etc seront déduits consécutivement à partir d premiers. Ils vont nous permettre aussi d écrire des règles récursives. 3.3. Le programme : Dans la partie clauses on a traduit tous les liens de parenté : une quarantaine. Et aussi on a indiqué le sexe de chaque membre. Et ce sont tous les faits essentiels. On passe maintenant à la définition de la règle ancêtre (X,Y) qui est une règle récursive. Elle répond à la question si une personne X est un ancêtre à une autre personne Y. Elle l est quand elle est un parent direct à Y où quand elle est l ancêtre d un parent de Y. Et c est ce qui est traduit dans le prédicat suivant :
13 ancetre(x,z) :- parent(x,z). ancetre(x,z) :- parent(x,y),ancetre(y,z). On demande par exemple le but suivant ancetre(pierre,gisele). Ou bien on peut demander tous les ancêtres de gisele ancetre(x,gisele). Et pour les autres règles : GRANDPARENT (X,Z) : X est un grand parent à Z quand il est un parent à un parent de Y. grandparent(x,z) :- parent(x,y),parent(y,z). Le but qu on peut poser par exemple est de détreminer le grands parents de «pierre» grandparent(x,rolande).
14 ENFANT: Ce prédicat se déduit directement du prédicat parent : il est son inverse à savoir : Enfant(X,Y) :-parent(y,x). afficher les enfants de pierre. FRERE (X,Y) : X est frère à Y si X est de sexe masculin et X et Y ont un parent commun. Aussi on doit ajouter la condition sur le parent qu il soit masculin ou féminin sinon il va répéter les résultats issus du fait que deux frères ont en commun un père et une mère. Ce qui se traduit par la règle : frère(x,y):- parent(z,y),parent(z,x),masculin(x),masculin(z). afficher les frères d «augustine». frere(x,augustine).
15 SŒUR(X,Y) : De même pour le prédicat sœur seulement on modifie le sexe de X afficher les sœurs de «eric». soeur(x,eric). TANTE (X,Y) : X est la tante de Y si elle est la sœur de l un de ses parents. On l écrit donc : tante(x,y):- parent(z,y),soeur(x,z). les tantes de «gerard» tante(x,gerard). ONCLE (X,Y) : De même pour la règle oncle(x,y). oncle(x,y):- parent(z,y),frere(x,z). oncle(x,rolande).
16 COUSIN (X,Y) : X est le cousin de Y s ils ont le même grand parent et qu il soit masculin pour éviter la répétition et aussi il faut en exclure le cas où ils sont frères ou sœurs. cousin(x,y):- grandparent(z,x),grandparent(z,y),masculin(z),not (frere(x,y)),not (soeur(x,y)). tous les cousins de «rolande» 4. cousin(rolande,x). (séance3) Les listes en Prlog Le but de cette séance est l utilisation de la notion de liste en Prolog et la définition de prédicats d utilisation des listes. 4.1. La notion de liste En Prolog, on ne connait que deux choses d'une liste son premier élément (la tête, ou head) le reste de la liste (la queue, ou tail) Le parcours d'une liste se fait de manière récursive sur la queue. La liste vide se note: [].
17 Une liste constituée d'au moins un élément se note [T Q]. Ici, T représente la tête et Q représente la queue. C'est aussi grâce à [T Q] que l'on ajoute un élément en début de liste (par unification). Les différents éléments d'une liste sont séparés par des virgules. Exemple: [1, 2, 3, 4, 5, 6,7]. Ainsi: [1, 2, 3 Q] représente une liste dont les premiers éléments sont 1, 2, 3 et le reste de la liste est unifié avec la variable Q. 4.2. Exercice Cet exercice rassemble les prédicats essentiels à appliquer sur une liste quelconque. ELEMENT (X,L) : elle vérifie si x est un élément de la liste. Il l est lorsqu il est le premier élément de la liste ou lorqu il appartient au reste de la liste, d où l appel récursi f. element(x,[x _]). element(x,[_ R]):- element(x,r). element(c,[a,b,c,d]). LONGUEUR (X,L) : elle donne en terme de nombre d objets la longueur d une liste. Si elle est vide sa longueur est nulle et c est la condition d arrê t, sinon sa longueur est un longueur N avec N=M+1 où M est la longueur du reste de cette liste. long([],0). long([_ R],N):-long(R,M),N=M+1.
18 long([a,b,c,d],longueur). ENLEVER (X,L,LX) : elle élimine de la liste L toutes les occurrences de X. 2 cas soit que X soit le 1 er de la liste il er l enlève et continue à vérifier s il est dans le reste, soit qu il ne l est pas alors il ignore le 1 élément et continue sa recherche dans le reste et ainsi de suite jusqu à ce qu il arrive à la liste vide qui est retournée telle quelle. enlever(_,[],[]). enlever(x,[x ResteListeInitiale],ListeSansX) :enlever(x,restelisteinitiale,listesansx). enlever(x,[pasx ResteListeInitiale],[PasX ListeSansX]) :X<>PasX,enlever(X,ResteListeInitiale,ListeSansX). enlever(a,[a,b,c,a,d],listesansa). UNION (L1,L2,L3) : union fait la fusion de listes L1 et L2 dans une troisième liste L3. On a l union de la liste L1 qui commence par T1 et la liste L2 est une liste qui commence par T1 si aussi l union du reste R1 et L2 donne R3, ce jusqu à l on vide la liste L1 et enfin l union de la liste vide avec la liste L2 donne L2.
19 union([],l2,l2). union([t1 R1],L2,[T1 R3]):-union(R1,L2,R3). union([a,b,c],[e,f,k,a],listefinale). INSERT (X,L,LX) : Elle ajoute l élément X à ma fin de la liste L et retourne LX. Si L est une liste vide alors LX=[X], sinon il l insère dans le reste de la liste. insert(x,[],[x]). insert(x,[r1 R],L) :- insert(x,r,l1),union([r1],l1,l). insert("a",[b,c,d],l). DERN (X,L) : Il donne le dernier élém ent de la liste. X est le dernier de la liste L s il est le dernier de son reste et ainsi de suite jusqu à ce qu il arrive à une liste formée d un seul élément. dern([x],x).
20 dern([_ R],X):-dern(R,X). dern([a,c,d],dernier). But: INVERSE (L,LINV) : L inverse de la liste [X Y] est la liste L2 tel que l inverse de Y est une liste L3 et que l union de L3 et X est L2. inverse([x],[x]). inverse([x Y],L2):-inverse(Y,L3),union(L3,[X],L2). inverse([a,b,c,d],inverse). AFFICHE (L) : Elle sert bien clair à afficher les éléments d une liste L avec le prédicat prédéfini write. affiche([x L]):- write(x),nl,affiche(l). affiche([a,b,c,d]).
21 AFFICHEINVERSE (L) : Elle affiche la liste L inversée. Ce qu elle fait en fait est qu elle utlilise simplement les 2 prédicats affiche et inverse. Elle inverse la liste L dans une autre liste et affiche celle-ci. afficheinverse(l):- inverse(l,l1),affiche(l1). afficheinverse([a,b,c,d]). 5. (séance3) Gestion d un système de transport 5.1. Le problème : On va réaliser un programme Prolog pour la gestion d un système de transport. Plusieurs stations («m», «q», «n», «r», «p», «o» et «s») sont reliées par des bus supposés à sens unique. Chaque arc représente un bus qui relie une station de dép art à une station d arrivée. Nous définissons un itinéraire à partir d une station de départ S1 à une station d arrivée S2 à
22 travers une liste de stations. Il existe un itinéraire de S1 à S2 s il existe une station S3 à laquelle S1 est reliée par un bus et S2 est reliée par un itinéraire. 5.2. Travail demandé : 5.2.1. Définition du domaine On aura besoin d une station et d une liste de stations et puis après d un nombre entier. domains station= Symbol listestation= station* number= Integer 5.2.2. Définition des prédicats BUS(S1,S2): Les faits suivants sont une description complète du graphe composé de stations et de bus qui les relient.
23 ELEMENT (S,LS): Permet de déterminer si la station S est un élément de la liste de stations LS. Ce prédicat est donc le même pour n importe quel type de liste. element(s,[s _]). element(s,[_ R]):- element(s,r). Ce prédicat ne sera pas utile directement dans notre programme mais essentiellement dans le prédicat suivant. ITINERAIRE (S1,S2,L) : Ce prédicat donne le chemin entre 2 stations S1 et S2. Les stations qui constituent les met dans une liste L. En effet, il existe un itinéraire de S1 à S2 s il existe une station S3 à laquelle S1 est reliée par un bus et S2 est reliée par un itinéraire. itineraire(s1,s1,[s1]). itineraire(s1,s2,[s1 R]):-bus(S1,S3),itineraire(S3,S2,R), Not(element(S1,R)). itineraire(a,o,l).
24 PEUTALLER (S1,S2) : Indique si on peut aller de la station S1 à la station S2. C est possible quand il existe un itinéraire entre S1 et S2. peutallera(s1,s2):- itineraire(s1,s2,_). peutallera(a,o). LONGUEUR (L,N): La longueur de la liste en termes de nombre de stations. longueur([],0). longueur([_ R],N):-longueur(R,M),N=M+1. longueur([m,a,n,r,p,o,s],longueur). AFFICHE (LS): Affiche les éléments de la liste de stations LS. affiche([s LS]):- write(s),nl,affiche(ls).
25 affiche([m,a,n,r,p,o,s]). 5.2.3. Traduction des questions [1] a. Peut-on aller de la station «s» à la station «r»? peutallera(s,r). b. Comment se rendre de «a» à «p»? itineraire(a,p,l,_). c. Quels sont les itinéraires aboutissant à «o»? itineraire(_,o,l). d. Quels sont les itinéraires de «m» à «o» avec exactement 2 stations intermédiaires? itineraire(m,o,l,n),longueur(l,nb),nb=2. e. Quels sont les itinéraires de «m» à «o» avec au moins 2 stations intermédiaires? itineraire(m,o,l,n),longueur(l,nb),nb>1. 5.2.4. Inclure la longueur d un itinéraire On va adapter la définition des prédicats bus et itineraire afin de calculer le coût total d un itinéraire. Il suffit juste d ajouter un autre paramètre à chacun de ces prédicats symbolisant le coût. PREDICAT BUS :
26 PREDICAT ITINERAIRE : Le coût total d un itinéraire X est le coût du bus reliant le 1 er élément au deuxième plus le coût de l itinéraire reliant le deuxième à la destination. itineraire(s1,s1,[s1],0). itineraire(s1,s2,[s1 R],X):bus(S1,S3,Y),itineraire(S3,S2,R,NUM),X=NUM+Y, Not(element(S1,R)). itineraire(a,p,l,coût). 5.2.5. Traduction des questions [2] a. Quels sont les itinéraires de «m» à «o» passant par «n» et leurs coûts? itineraire(m,o,l,coût),element(n,l).
27 b. Quels sont les itinéraires issus de «m» et de coût au plus 17? itineraire(m,_,l,n),n<18.
28 6. conclusion Notre atelier a été une confrontation à l utilisation du langage de programmation logique Prolog. Programmer en Prolog, c'est énoncer une suite de faits et de règles puis poser des questions. Tout est relation en Prolog. Tout programme Prolog constitue un petitsystèmeexpert qui va fonctionner en "chaînage-arrière" ou "abduction", c'est-à-dire qui va tester les hypothèses pour prouver une conclusion.