Devoirs Hebdomadaire N°8
CDL...DH8

Prolog II


M. Joseph DASSE BRIKA

 

% naive_reverse/2 : retourner/inverser récursivement une liste sur elle même .

naive_reverse([],[]).
naive_reverse([X|Xs],Zs) :- naive_reverse(Xs,Ys), append(Ys,[X],Zs).

% on "dérécursive" ce prédicat en rendant l'appel récursif terminal et en se servant d'un "accumulateur" pour %faire les  calculs "en marchant"

% reverse/2 : retourner/inverser une liste de manière itérative. % prédéfini SWI

renverse(L1,L2):- renverse(L1,[],L2). %remarque : renverse/2 est un prédicat différent de renverse/3

renverse([],L,L). % le travail est terminé : le contenu de l'accumulateur est retourné comme résultat.
renverse([X|L1],Acc,L2) :- renverse(L1,[X|Acc],L2). %on pose un élément de la liste à inverser sur l'accumulateur.

 

QUESTION 1 : Vérifier que ces deux prédicats retournent/inversent correctement la liste [a,z,e,r,t,y,u,i,o,[a,z,e,r,t,y,u,i,o,p]] .

QUESTION 2 : Ces prédicats sont-ils réversibles ? i.e. peut-on inverser une liste en la proposant en deuxième paramètre et en attendant le résultat en premier paramètre ?


En arithmétique de Peano nous avons écrit en ED :

:- op(800 , fy , s).  %pour moins de parenthèses

%On spécifie les entiers naturels par :

nat(z).
nat(s(N)) :- nat(N).

% Donc, 5 s'écrit maintenant : s s s s s z

% Mais cela fait encore beaucoup de symbole alors on spécifie les prédicats de transformation des entiers décimaux en nat %"(int2nat/2)" et de transformation des nat en entiers décimaux nat2int/2.

%A cause de la particularité de 'is' on doit écrire 2 prédicats

int2nat(0 , z).
int2nat(INT , s(NAT)) :- IN is INT-1 , int2nat(IN,NAT).

nat2int(z, 0).
nat2int(s(NAT),INT) :- nat2int(NAT , IN) , INT is IN+1.

% l'addition de 2 entiers: addi/3

addi(z,X,X) :- nat(X).
addi(s(X),Y,s(Z)):- addi(X,Y,Z).

%la multiplication de 2 entiers : mult/3

mult(z,X,z) :- nat(X).
mult(s(X),Y,Z) :- mult(X,Y,W), addi(W,Y,Z).

%fact/2 : factorielle (!)

fact(z, s(z)).
fact(s(N),F) :- fact(N,FF), mult(s(N),FF,F).


Après avoir charger tout ce qui précède sous Prolog répondre aux questions suivantes.

QUESTION 3 : Constater que 5 ! =120 , et que ce résultat est unique.

QUESTION 4 : Constater que fact/2 est réversible (cf. ci dessus , 120=5!)


on dérécusive fact/2 pour "calculer en marchant" : fac/3  (cf. renverse)

fac(z, F , F).
fac(s(N),Acc , R) :- mult(s(N),Acc,F) , fac(N,F , R).

QUESTION 5 : Spécifier fac/2 qui permet d'appeler fac/3 dans les conditions telles que le résultat soit correct. Et constater que fac/2 est toujours réversible.


En arithmétique en Prolog sur les "vrais" entiers la spécification correspondant à fact/2 s'écrit

facti(0, 1).
facti(N,F) :- N >0 %ATTENTION nécessaire pour avoir une seule solution et pas de branche infinie
      NN is N-1 , facti(NN,FF), F is FF*N.

QUESTION 6 : Dérécursiver ce prédicat en donnant les spécifications de faci/3 et faci/2 sur le modèle de fac/3 et fac/2 ci dessus et vérifier qu'on a toujours 5!=120 (?- faci(5 , F). ==> F=120  %solution unique)


Question 1:
  Les 2 prédicats renversent bien la liste suivante : [a,z,e,r,t,y,u,i,o, [a,z,e,r,t,y,u,i,o,p] ]
(note: le dernier element est lui meme une liste, qui n'a pas elle, a être renversée)
?- naive_reverse([a,z,e,r,t,y,u,i,o,[a,z,e,r,t,y,u,i,o,p]],L).

L = [[a, z, e, r, t, y, u, i, o, p], o, i, u, y, t, r, e, z, a] 

Yes
?- renverse( [a,z,e,r,t,y,u,i,o,[a,z,e,r,t,y,u,i,o,p]] ,L).

L = [[a, z, e, r, t, y, u, i, o, p], o, i, u, y, t, r, e, z, a] 

Yes

Question 2:Les 2 prédicats sont réversibles
 
?- naive_reverse(L , [a,b,c,d,e] ).

L = [e, d, c, b, a] 

Yes
?- renverse(L, [a,b,c,d,e]).

L = [e, d, c, b, a] 

Yes

Question 3:5! = 120 :
  (On utilise les predicats int2nat/2 et nat2int/2 afin de faciliter la lecture du résultat)
?- int2nat( 5,NAT), fact( NAT , F), nat2int( F, INT).

NAT = s s s s s z
F = s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s z
INT = 120  

Yes

%Solution unique ?
?- fact( s s s s s z , F).

F = s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s z ;

No

120 est seule solution de 5!


Question 4:On constate que fact/2 est réversible: 120=5!
 
?- int2nat( 120, F ), fact( NAT, F), nat2int( NAT, INT).

F = s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s z
NAT = s s s s s z
INT = 5 
Yes.

Question 5:
  Nouveau prédicat fac/2 : fac(N, F) :- fac(N, s(z), F).
On constate que fac/2 est toujours réversible :
?- int2nat( 5,NAT), fac( NAT , F), nat2int( F, INT).

NAT = s s s s s z
F = s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s z
INT = 120 

Yes
?- int2nat( 120, F ), fac( NAT, F), nat2int( NAT, INT).

F = s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s
s s s s s s s s z
NAT = s s s s s z
INT = 5 

Question 6:
  Soit facti/2 le prédicat prolog de Factorielle sur les vrais entiers:
facti(0, 1).
facti(N,F) :- N >0 , NN is N-1 , facti(NN,FF), F is FF*N.

La version "Dérécursivée" :

faci(0, F, F).
faci(N, Acc, F):- N>0, P is N*Acc, NN is N-1 , faci(NN, P, F).
faci(N, F) :- faci(N, 1, F).


On teste si 5!=120 est solution unique:
?- faci(5,F).

F = 120 ;

No
?- 
 

FIN_dh8

 

ACCUEIL CONTACT FAVORIS ANNALES DH1 DH2 DH3 DH4 DH5 DH6 DH7 DH8 DH9 DH10 DH11 DH12 DH13 DH14 DH15 DH16