Post on 04-Apr-2015
CSI2520, Hiver 2007
Les entrées-sorties
• Ecriture sur l'écran ou dans un fichier• Lecture à partir du clavier ou d’un fichier• Affichage de termes :
* write(1+2) affiche 1+2 * write(X). affiche la valeur courante de X sur le flot
de sortie courant (par défaut l'écran), * nl permet de passer à la ligne suivante.* writeln(X) :- write(X), nl.* tab tel que tab(N) affiche N espaces
CSI2520, Hiver 2007
Affichage
• Affichage de termes (suite) :* display/1 agit comme write/1 mais en affichant la
représentation sous forme d’arbre* Ex :
write(3+4), nl, display(3+4), nl.
Affiche :
3+4
+(3,4)
YES
CSI2520, Hiver 2007
Lecture
• Lecture de termes :* read/1 admet n’importe quel terme en argument.
* Il lit un terme au clavier et l’unifie avec son argument. Le terme lu doit être obligatoirement suivi d’un point. Certains systèmes Prolog affichent un signe d’invite lorsque le prédicat read/1 est utilisé.
* Exemple :
?- read(X).
: a(1,2).
YES {X = a(1,2)}
CSI2520, Hiver 2007
Exemple
age(X, Y) :- write('Give the age of '), write(X), write(': '), read(Y).?- age(teddy, Z).Give the age of teddy: 22.Z = 22Yes
?- age(teddy, 22).Give the age of teddy: 23.No?- read(abc).:23.No?- read(X + Y).:2 + 3.X = 2Y = 3Yes
CSI2520, Hiver 2007
Un autre exemple
lire des expressions arithmétiques, les évaluer et les imprimer jusqu'à ce que l’utilisateur rentre « fin » au clavier.
calculateur :- repeat, % boucle read(X), % lecture
expression eval(X,Y), %
évaluation write(Y), nl, %
affichage Y = fin, !. %
condition d'arrêteval(fin, fin) :- !. % cas particuliereval(X, Y) :- Y is X. % calcul d’expressions
CSI2520, Hiver 2007
Le repeatLe predicat repeat laisse toujours un point de choix derrière lui.
repeat.repeat :- repeat.
Exemple d’utilisation :?- calculateur.: 2+3 . 5: 3+2*4 -1.10: fin.finYES
Autre exemple avec repeat
CSI2520, Hiver 2007
test :- repeat, write(‘SVP, entrer un nombre’), read(X), (X=:=42).
CSI2520, Hiver 2007
Ouvrir un fichier
– En écriture : * mode write : son contenu est effacé avant que Prolog y
écrive.
* mode append : Prolog écrira à partir de la fin du fichier.
– Ouverture d’un fichier : prédicat open/3 * argument 1 : nom du fichier
* argument 2 : mode d’ouverture write, append ou read
* argument 3 : variable qui va recevoir un identificateur de fichier appelé flux ou stream.
CSI2520, Hiver 2007
Lire et écrire
• Tous les prédicats read, write et autres vus auparavant admettent un second argument : le flux identifiant le fichier.
* Ex : write(Flux, X). où Flux est un identificateur de fichier
* Ex : read(Flux,X), get(Flux, X), get0(Flux,X)
* Fermeture du fichier : prédicat close/1 qui prend en argument le flux associé au fichier.
CSI2520, Hiver 2007
Exemple
ecrire(T) :-
open(‘ test.pl ’, append, Flux), (*ouverture*)
write(Flux, T), nl(Flux), (*écriture*)
close(Flux). (*fermeture*)
CSI2520, Hiver 2007
Les flots d’entrée et de sortie
• see(Filename), le fichier est l’entrée courante.• seen. La console redevient l’entrée courante.• tell(Filename), le fichier est la sortie courante.• told. La console redevient la sortie courante.
CSI2520, Hiver 2007
Les caractères
• put(CodeASCII) : imprime le caractère correspondant au code ASCII.
• get0(Code) : unifie la variable avec le code ASCII du caractère entré.
• get(Code) : même chose que get0, mais saute par-dessus les espaces.
Exemple interactif
CSI2520, Hiver 2007
capitale(ontario,toronto).capitale(quebec,quebec).capitale(cb,victoria).capitale(alberta,edmonton).capitale(terre-neuve,st-jean).capitale(nouvelle-ecosse,halifax).capitale(saskatchewan,regina).capitale(manitoba,winnipeg).capitale(nouveau-brunswick,fredericton).capitale(ipe,charlottetown).start:-write('Les Capitales du Canada'),nl,demander.demander:-write('Province? '),read(Province),reponse(Province).reponse(stop):-write('merci'),nl.reponse(Province):-capitale(Province,Ville),write('la capitale de '), write(Province),write(' est '),write(Ville),nl,nl,demander.
Exemple (suite)
CSI2520, Hiver 2007
?- start.Les Capitales du CanadaProvince? ontario.la capitale de ontario est toronto
Province? cb.la capitale de cb est victoria
Province? stop.mercitrue .
CSI2520, Hiver 2007
Les Listes
• Comme en programmation fonctionnelle, la liste est une structure de donnée de base :– [1, 2, 3, 4]– [] la liste vide ;– [Head | Tail] la tete et le reste de la liste ;– [1, 2, "trois"] une liste de 3 éléments ;– [1, 2 | Tail] une liste d’au moins deux éléments.
CSI2520, Hiver 2007
Format Tête et Queue?- [T | Q] = [1, 2, 3, 4].T= 1,Q= [2,3,4]?- [1 | [2,3,4]] = L.L= [1,2,3,4]?- [1,2,3 | [4]] = L.L= [1,2,3,4]?- [T | Q] = [1].T= 1,Q= []?- [T | Q] = [].no
CSI2520, Hiver 2007
Exemple
readline(Line) :- get0(Ch), readline(Ch, Line).
readline(10, []).readline(Ch, [Ch | RestOfLine]) :- Ch \= 10, get0(NextCh), readline(NextCh, RestOfLine).
Lire des caractères en créant une liste, jusqu’à la fin d’une ligne (code 10)
CSI2520, Hiver 2007
Construction de listes
cons(X, Y, [X|Y]).
?- cons(1, [2,3,4], L).L= [1,2,3,4]
?- cons(X, Y, [1,2,3,4]).X= 1,Y= [2,3,4]
?- cons(1, [2,3,4], [1,2,3,4]).yes
CSI2520, Hiver 2007
Concaténation de listes
notre-append([],Y,Y).notre-append([A|B],Y,[A|W]) :- notre-append(B,Y,W).
?- notre-append([1,2], [3,4], L).L= [1,2,3,4]?- notre-append(X, [3,4], [1,2,3,4]).X= [1,2]?- notre-append([1,2], [3,4], [1,2,3,4]).yes
CSI2520, Hiver 2007
Inversion de listes, version 1
notre-reverse([],[]).notre-reverse([H|T],L) :- notre-reverse(T,LL),
notre-append(LL,[H],L).
?- notre-reverse([1,2,3,4],L).L= [4,3,2,1]
?- notre-reverse(L,[1,2,3,4]).L= [4,3,2,1]
Inversion de listes, version 2
CSI2520, Hiver 2007
renverser([],L,L)-!.renverser([H|T],L,R):- renverser(T,[H|L],R).
notre-reverse([H|T],L,R) :- renverser(L,[],R).
Sans la coupe, il y aurait une boucle infinie après lapremière solution de:?- notre-reverse(L,[1,2,3,4]).
CSI2520, Hiver 2007
Appartenance à une liste
notre-member(X,[X|L]).notre-member(X,[Y|L]) :- notre-member(X,L).
CSI2520, Hiver 2007
Longueur d’une liste
notre-length([],0).notre-length([X|L],N) :- notre-length(L,NN), N is NN+1.
CSI2520, Hiver 2007
Insertion dans une liste
notre-insert(A,L,[A|L]).notre-insert(A,[X|L], [X|LL]) :- notre-insert(A,L,LL).
?- insert(c, [a, b], L).L = [c, a, b] ;L = [a, c, b] ;L = [a, b, c] ;no
CSI2520, Hiver 2007
Insertion dans une liste
?- insert(a, L, [b, a, d, a, f]).L = [b, d, a, f] ;L = [b, a, d, f] ;no
L’insertion et le retrait sont 2 concepts complémentaires!
CSI2520, Hiver 2007
Retrait dans une liste
notre-delete(R,[R|L],L).notre-delete(R,[X|LL], [X|L]) :- notre-delete(R,LL,L).
Retrait dans une liste
CSI2520, Hiver 2007
deleteall(X,[],[]).deleteall(X,[X|T],Result) :- deleteall(X,T,Result),!.deleteall(X,[H|T],[H|Result]) :- deleteall(X,T,Result).
?- deleteall(2,[1,2,4,3,2,6,2,2],L).L = [1, 4, 3, 6].
Qu’arrive-t-il si on retire la coupe?
CSI2520, Hiver 2007
Intersection entre listes
intersection( [], Ys, [] ).
intersection( [ X | Xs ], Ys, Zs ) :-
not member( X, Ys),
intersection( Xs, Ys, Zs ).
intersection( [ X | Xs ], Ys, [ X | Zs ] ) :-
member( X, Ys ),
intersection( Xs, Ys, Zs ).
CSI2520, Hiver 2007
Tri d’une liste
tri([],[]).tri([P|Q],T) :- partition(P,Q,G,D),
tri(G,GG), tri(D,DD),append(GG,[P|DD],T).
partition(P,[X|L],[X|PG],PD) :- X < P, partition(P,L,PG,PD).partition(P,[X|L],PG,[X|PD]) :- X >= P, partition(P,L,PG,PD).partition(P,[],[],[]).
CSI2520, Hiver 2007
Opérations répétitives
• Effectuer un traitement sur les éléments de listes
traite-liste([],[]).
traite-liste([X|L],[Y|T]) :- traite(X,Y), traite-liste(L,T).
somme(L,S) :- somme(L,0,S).
somme([X|L],T,S) :- TT is T+X, somme(L,TT,S).
somme([],S,S).
Les nombres premiers
• Générer tous les nombres premiers de 1 à N
• Crible d'Ératosthène:– Générer tous les entiers de 2 à N– Supprimer tous les multiples de 2, de 3, de 4,
etc. jusqu’à ce que le carré du plus petit entier soit plus grand que le plus grand entier.
CSI2520, Hiver 2007
Les nombres premiers
CSI2520, Hiver 2007
genereListe(0,[]).genereListe(N,[N|Xs]):- N > 0, N1 is N-1,genereListe(N1,Xs).
retireMultiple(X,[],[]).retireMultiple(X,[T|Q],Resultat) :- T>X, T mod X =:= 0, retireMultiple(X,Q,Resultat),!.retireMultiple(X,[T|Q],[T|Resultat]) :- retireMultiple(X,Q,Resultat).
retireTousLesMultiples(N,[],[]).retireTousLesMultiples(1,L,L).retireTousLesMultiples(N,Li,L):- N>1, retireMultiple(N,Li,LL), N1 is N-1, retireTousLesMultiples(N1,LL,L).
premiers(N,L):- genereListe(N,Li), retireTousLesMultiples(N,Li,L).
Inversion d’une liste (double récursion)
CSI2520, Hiver 2007
mirror([ ], [ ]). mirror([X|L1], L2) :-mirror(L1,L3), append(L3, [X], L2). % append will dig into the list a second time
Inversion d’une liste (avec accumulateur)
CSI2520, Hiver 2007
mirror2(Left, Right) :- invert(Left, [ ], Right).invert([X|L1], L2, L3) :- % the list is 'poured' invert(L1, [X|L2], L3). % into the second argument invert([ ], L, L). % at the deepest level, the result L is merely copied
CSI2520, Hiver 2007
Représentation des Listes
• Les listes peuvent être représentée avec le symbole fonctionnel binaire « . »– suite {e1, e2, …} ==> liste (e1.(e2.(…)))
• La liste vide est notée « nil ». Elle sert souvent à marquer la fin de liste.
• Exemples :– suite des variables X et Y => (X.Y)– suite {gateau, fruit, glace} =>(gateau.(fruit.(glace.nil)))
CSI2520, Hiver 2007
Représentation en arbre
• Exemples :
.
X Y
.
.
.
gateau
fruit
glace nil
CSI2520, Hiver 2007
Propriété fondamentale
• Une liste correspond au cas particulier ou les branches gauches sont toujours des feuilles.– On utilise le terme de peigne pour les désigner.
• Exercice : – résoudre l'équation X.Y = gateau.fruit.glace.nil– par identification on a la solution :
• {X = gateau; Y = fruit.glace.nil}
CSI2520, Hiver 2007
Propriété fondamentale (2)
• La notation X.Y représente une liste dont la tête (le 1er élément) est X et la queue (le reste de la liste) est Y.
• Cela constitue la base de l’utilisation des listes dans les programmes Prolog.
• Attention le terme X.Y n’est pas une liste mais plutôt une paire.
CSI2520, Hiver 2007
Prédicats avec nombre de paramètres variables
• Les villes d'une province:province(ontario,toronto,ottawa,hamilton,kitchener,london).province(quebec,montreal,quebec_city,sherbrooke,trois_rivie
res).province(new_brunswick,saint_john,moncton,fredericton).
• Il faut plutôt utiliser une liste (province/2):province(quebec, montreal.( quebec_city .(sherbrooke .(trois_rivieres.nil)))).province(new_brunswick, saint_john .(moncton .(fredericton.nil))).province(ontario, toronto.ottawa.hamilton.kitchener.london.nil).
CSI2520, Hiver 2007
Accès aux éléments d’une liste(1)
• En pratique, on représente une liste avec les '[ ]':montreal .(quebec_city .(sherbrooke .(trois_rivieres. nil)))
est représentée par:[montreal, quebec_city, sherbrooke, trois_rivieres]
• Pour avoir accés aux différents paramètres – on utilise le '|'.– On a donc [tete|queue].
CSI2520, Hiver 2007
Accès aux éléments d’une liste(2)
• Ainsi, on peut écrire:– [saint_john,moncton,fredericton] qui est equivalent a:– [saint_john | [moncton,fredericton]] qui est equivalent a:– [saint_john | [moncton | [fredericton]]] qui est equivalent a:– [saint_john | [moncton | [fredericton | [ ]]]] ou encore:– [saint_john, moncton | [fredericton]] ou:– [saint_john, moncton, fredericton | []]
• De manière générale:– [x | queue] une liste d’au moins un élément.– [x, y | queue] une liste d’au moins deux éléments.
CSI2520, Hiver 2007
Utilisation de memberRegle inProvince/2 qui retourne la province dans laquelle se trouve une ville X:
inProvince(X,P) :- province(P, L), member(X, L).
?- inProvince(ottawa, P). P = ontario ;
No
?- inProvince(V, new_brunswick).C = saint_john ;C = moncton ;C = fredericton ;No
Exemple du fermier
CSI2520, Hiver 2007
% etat(Fermier,Renard,Poule,Blé).
initial(etat([gauche, gauche, gauche, gauche])).final(etat([droite, droite, droite, droite])).
Exemple du fermier
CSI2520, Hiver 2007
traverse(etat([gauche,X,Y,Z]),etat([droite,X,Y,Z]), fermier_traverse).traverse(etat([droite,X,Y,Z]),etat([gauche,X,Y,Z]), fermier_revient).
traverse(etat([gauche,X,gauche,Z]),etat([droite,X,droite,Z]), fermier_amene_poule).traverse(etat([droite,X,droite,Z]),etat([gauche,X,gauche,Z]), fermier_ramene_poule).
traverse(etat([gauche, gauche, X, Y]),etat([droite, droite, X, Y]), fermier_amene_renard).traverse(etat([droite, droite, X, Y]),etat([gauche, gauche, X, Y]), fermier_ramene_renard).
traverse(etat([gauche, X, Y, gauche]),etat([droite, X, Y, droite]), fermier_amene_ble).traverse(etat([droite, X, Y, droite]),etat([gauche, X, Y, gauche]), fermier_ramene_ble).
Exemple du fermier
CSI2520, Hiver 2007
interdit(etat([X, Y, Y, _])) :- X \== Y.interdit(etat([X, _, Y, Y])) :- X \== Y.
riviere(P) :- initial(Depart), final(Arrivee), riviere_aux(Depart, Arrivee, [Depart], P).
Exemple du fermier
CSI2520, Hiver 2007
riviere_aux(A,A,_,[]).
% V sont les états déjà visitéesriviere_aux(A, B,V, P) :- traverse(A,C,Action), not(interdit(C)), not(member(C,V)), riviere_aux(C,B,[C|V],Plan), P = [Action | Plan].
CSI2520, Hiver 2007
Le prédicat setof
aime(jean,pomme).aime(marie,poire).
?- setof([X,Y],aime(X,Y),L).L=[[jean,pomme],[marie,poire]].
age(pierre,5).age(paul,7).age(henri,5).
?- setof(C,age(C,5),L).L=[henri,pierre].
bagof est similaire, sauf qu’il n’élimine pas les répétitions et ne tri pas les éléments.
Exemple
CSI2520, Hiver 2007
bag(2,4,1).bag(3,5,2).bag(7,8,2).bag(4,3,1).bag(5,2,4).bag(2,1,4).bag(2,2,4).bag(7,3,5).bag(7,3,3).
% bagof(Z,bag(X,Y,Z),B).% bagof(Z,(bag(X,Y,Z),Z>2),B).% bagof(Z,X^bag(X,Y,X),B).% setof(Z,X^bag(X,Y,X),B).% bagof(Z,X^Y^bag(X,Y,X),B).% findall(Z,bag(X,Y,X),B).
Exemple
CSI2520, Hiver 2007
connait(vincent,david).connait(vincent,antoine).connait(vincent,alex).connait(melodie,alex).connait(melodie,patrick).connait(patrick,melodie).connait(patrick,ahmed).connait(patrick,eddie).connait(patrick,david).
% setof(X,connait(X,Y),B).% setof(Y,connait(X,Y),B).% setof(Y,X^connait(X,Y),B).% bagof(Y,X^connait(X,Y),B).% setof([X,Y],connait(X,Y),B).
Exemple
CSI2520, Hiver 2007
age(vincent,8).age(melodie,4).age(patrick,3).age(ahmed,7).age(eddie,4).% setof(A,N^age(N,A),B).% setof(A,N^age(N,A),[T|Q]).% setof(A,N^age(N,A),[T|_]).% setof([A,N],age(N,A),[[_,J]|_]).% age(P,A1),\+((age(_,A2),A2<A1)).