curs 3 - recursivitate în prolog. relatii recursive. aplicatii

48
Curs 3 Recursivitate în PROLOG. Rela¸ tii recursive. Aplica¸ tii Mircea Marin [email protected] octombrie 2014 Mircea Marin Programare logic ˘ a

Upload: vudien

Post on 06-Feb-2017

387 views

Category:

Documents


7 download

TRANSCRIPT

Page 1: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Curs 3Recursivitate în PROLOG. Relatii recursive. Aplicatii

Mircea [email protected]

octombrie 2014

Mircea Marin Programare logica

Page 2: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateO notiune este recursiva daca este definita în functie de sine însasi.

În general, o definitie recursiva este data de una sau mai multereguli, numite si cazuri:

0 sau mai multe cazuri de baza, în care predicatul din capulregulii nu apare in corpul regulii.1 sau mai multe cazuri recursive, în care predicatul dincapul regulii apare in corpul regulii.

Multe definitii sunt recursive în PROLOG. De exemplu:

termen::= constanta | variabila| functor(termen1,...,termenn)

Cazuri de baza: Un termen este o constanta sau o variabila.Aceasta regula poate fi reformulata astfel

1 t este termen daca t este constanta.2 t este termen daca t este variabila.

Caz recursiv: t este termen daca t este de forma f (t1, . . . , tn), f esteun functor cu aritate n iar t1, . . . , tn sunt termeni.

Mircea Marin Programare logica

Page 3: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Recursivitate în PROLOGListe

Listele sunt o structura de date recursiva folosita frecvent încalcule simbolice. În PROLOG, listele sunt definite astfel:Cazul de baza: [ ] este o lista.Cazul inductiv: .(h, t) este lista daca h este un termen si t este

lista.

Observatii

1 Orice lista nevida l este de forma .(h, t) unde h este capul lui l(sau primul element), iar t este coada lui l .

2 Pentru liste, PROLOG permite scrierea abreviata [t1, . . . , tn] în locde .(t1, .(..., .(tn, [])...)). Termenii t1, . . . , tn se numesc elementelelistei, si pot fi orice fel de termeni: constante, variabile saustructuri. De exemplu:[lista, cu,4,elemente,′ :′, [a, A, carte(ion,autor(rebreanu)), _]]

3 În PROLOG, un sir "a1, . . . ,an" este de fapt lista codurilor ASCIIale caracterelor a1, . . . ,an.

Mircea Marin Programare logica

Page 4: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Manipularea listelorCap si coada (engl. head and tail)

Notatie speciala pentru despartirea unei liste L în cap si coada:[X | Y ] = L

B variabila X va fi legata la capul listei LB variabla Y va fi legata la coada listei L.

OBSERVATIE.[X |Y ] este de fapt termenul .(X ,Y ).[X | Y ] nu este o lista!

Exemplu

Lista Cap Coada[a,b, c,d ] a [b, c,d ][a] a [][] (nimic) (nimic)[[cainele, rau],musca] [cainele rau] [musca][X + Y , x + y ] [X + Y ] [x + y ]"abc" 97 [98,99]

Mircea Marin Programare logica

Page 5: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Manipularea listelorCap si coada (engl. head and tail)

Notatie speciala pentru despartirea unei liste L în cap si coada:[X | Y ] = L

B variabila X va fi legata la capul listei LB variabla Y va fi legata la coada listei L.

OBSERVATIE.[X |Y ] este de fapt termenul .(X ,Y ).[X | Y ] nu este o lista!

Exemplu

Lista Cap Coada[a,b, c,d ] a [b, c,d ][a] a [][] (nimic) (nimic)[[cainele, rau],musca] [cainele rau] [musca][X + Y , x + y ] [X + Y ] [x + y ]"abc" 97 [98,99]

Mircea Marin Programare logica

Page 6: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Definitii recursive de predicate

Exemplu 1: Definitia unui predicat de recunoastere a listelor% este_lista(L) inseamna ca L este lista

% Caz de bazaeste_lista([]).

% Caz recursiveste_lista([_|T]) :- este_lista(T).

Exemplu 2: Definitia relatiei de apartenenta la o lista% membru(X,L) inseamna ca X apare in lista L

% Caz de baza: X este capul listei Lmembru(X,[X|_]).

% Caz recursiv: X apare in coada listei Lmembru(X,[Y|T]) :- membru(X,T).

Mircea Marin Programare logica

Page 7: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Definitii recursive de predicate

Exemplu 1: Definitia unui predicat de recunoastere a listelor% este_lista(L) inseamna ca L este lista

% Caz de bazaeste_lista([]).

% Caz recursiveste_lista([_|T]) :- este_lista(T).

Exemplu 2: Definitia relatiei de apartenenta la o lista% membru(X,L) inseamna ca X apare in lista L

% Caz de baza: X este capul listei Lmembru(X,[X|_]).

% Caz recursiv: X apare in coada listei Lmembru(X,[Y|T]) :- membru(X,T).

Mircea Marin Programare logica

Page 8: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Teste de apartenenta

?- membru(a,[a,b,c]).true .

?- membru(b,[a,b,c]).true .

?- membru(d,[a,b,c]).false.

Mircea Marin Programare logica

Page 9: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Teste de apartenenta

OBSERVATII

PROLOG verifica 2 conditii, în ordinea urmatoare:1 membru(X,[X|_]). (caz de baza)2 membru(X,[_|T]) :- membru(X,T). (caz recursiv)

În cazul recursiv, lista testata pentru aparitia lui X în eadevine tot mai mica.Lista nu se poate micsora la nesfârsit ⇒ calculul setermina.PROLOG se opreste din testat în 2 situatii:

1 S-a dat de o lista care satisface cazul de baza⇒ testul se termina cu succes (true).

2 S-a ajuns la lista vida⇒ testul se termina cu esec (false).

Mircea Marin Programare logica

Page 10: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Teste de apartenenta

Ce se întâmpla daca PROLOG este pus sa raspunda laîntrebarile urmatoare??- membru(X,[a,b,c]).?- membru(a,X).?- membru(X,Y).?- membru(X,_).?- membru(_,Y).?- membru(_,_).

Mircea Marin Programare logica

Page 11: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Teste de apartenenta

membru(X,[X|Y]). %1membru(X,[Y|T]):-membru(X,T). %2?-membru(a,X).

membru(a,X).

� membru(a,T2).

� membru(a,T3).

membru(X1,[X1|Y1]).X1=a, X=[a|Y1].

membru(X2,[Y2|T2]):-membru(X2,T2).X2=a, X=[Y2|T2].

membru(X3,[X3|Y3]).X3=a, T2=[a|Y3].

membru(X3,[Y3|T3]):-membru(X3,T3).X3=a, T2=[Y3|T3].

Mircea Marin Programare logica

Page 12: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursieProbleme de terminare

Terminare = proprietate a unui program de a se terminadupa un numar finit de pasi.Unele programe nu se termina

parinte(X,Y) :- fiu(Y,X).fiu(Y,X) :- parinte(X,Y).

Motivul: definitiile lui parinte/2 si fiu/2 sunt circulare.⇒ evitati definitiile circulare!

Programul urmator este recursiv la stânga si nu se termina:

om(X):-om(Y), parinte(X,Y).om(adam).

⇒ recursia la stânga trebuie folosita cu grija!

Mircea Marin Programare logica

Page 13: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursieProbleme de terminare

Regulile si faptele se aplica în ordinea în care apar în program

criteriu intuitiv: faptele trebuiesc puse înaintea regulilor.

Uneori, regulile ordonate într-un anumit fel functioneaza bine pentruun anumit tip de întrebari.

Exemplu

este_lista([_|B]):-este_lista(B).este_lista([]).

este un program adecvat pentru întrebarile

?-este_lista([1,2,3]).?-este_lista([]).?-este_lista(f(1,2))

dar nu este adecvat pentru este_lista(X).Ce se întâmpla daca se schimba ordinea clauzelor din program??-este_lista(X).

Mircea Marin Programare logica

Page 14: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateDirectia de construire a solutiilor

Numeroase predicate definite în Prolog fac distinctie întreParametri de intrare (-): trebuie sa aiba valori concrete atunci

când se apeleaza predicatul.Parametri de iesire (+): valorile lor sunt calculate ca raspuns.Parametri arbitrari (?): pot fi fie de intrare sau iesire.

Mircea Marin Programare logica

Page 15: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateExemplu

% nr_elem(+Lista,-N) calculeaza numarul de elemente N al listei% Lista. Lista este param. de intrare, iar N este param. de iesire.nr_elem([],0). %1nr_elem([_|T],N):-nr_elem(T,N1), N is N1+1. %2

nr_elem([a,b],N).

nr_elem([b],N1), N is N1+1.

nr_elem([],N2), N1 is N2+1.

(2)

(2)

(1)N2=0

N1=1

N=2

Observatii:

Solutia pentru numarul de elemente N din lista este construita pe ramura derevenire din recursivitate:

Este de dorit calculul rezultatului pe ramura de avans în recursivitate, pentru aevita crearea de variabile temporare pe stiva.

Mircea Marin Programare logica

Page 16: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateExemplu

% nr_elem(+Lista,-N) calculeaza numarul de elemente N al listei% Lista. Lista este param. de intrare, iar N este param. de iesire.nr_elem([],0). %1nr_elem([_|T],N):-nr_elem(T,N1), N is N1+1. %2

nr_elem([a,b],N).

nr_elem([b],N1), N is N1+1.

nr_elem([],N2), N1 is N2+1.

(2)

(2)

(1)N2=0

N1=1

N=2

Observatii:

Solutia pentru numarul de elemente N din lista este construita pe ramura derevenire din recursivitate:

Este de dorit calculul rezultatului pe ramura de avans în recursivitate, pentru aevita crearea de variabile temporare pe stiva.

Mircea Marin Programare logica

Page 17: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateExemplu

% nr_elem(+Lista,-N) calculeaza numarul de elemente N al listei% Lista. Lista este param. de intrare, iar N este param. de iesire.nr_elem([],0). %1nr_elem([_|T],N):-nr_elem(T,N1), N is N1+1. %2

nr_elem([a,b],N).

nr_elem([b],N1), N is N1+1.

nr_elem([],N2), N1 is N2+1.

(2)

(2)

(1)N2=0

N1=1

N=2

Observatii:

Solutia pentru numarul de elemente N din lista este construita pe ramura derevenire din recursivitate:

Este de dorit calculul rezultatului pe ramura de avans în recursivitate, pentru aevita crearea de variabile temporare pe stiva.

Mircea Marin Programare logica

Page 18: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateExemplu

% nr_elem(+Lista,-N) calculeaza numarul de elemente N al listei% Lista. Lista este param. de intrare, iar N este param. de iesire.nr_elem([],0). %1nr_elem([_|T],N):-nr_elem(T,N1), N is N1+1. %2

nr_elem([a,b],N).

nr_elem([b],N1), N is N1+1.

nr_elem([],N2), N1 is N2+1.

(2)

(2)

(1)N2=0

N1=1

N=2

Observatii:

Solutia pentru numarul de elemente N din lista este construita pe ramura derevenire din recursivitate:

Este de dorit calculul rezultatului pe ramura de avans în recursivitate, pentru aevita crearea de variabile temporare pe stiva.

Mircea Marin Programare logica

Page 19: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateCalculul numarului de elemente al unei liste: Versiunea cu acumulator

Varianta nr_elem1(Lista,N) de calcul al numarului de elemente din L pe ramurade avans în recursivitate se bazeaza pe relatia ajutatoare nr_elemAux(Lista,A,N)unde:

A este un argument suplimentar fata de nr_elem(Lista,N), numit acumulator.A acumuleaza numarul de elemente din lista pe masura ce se avanseaza înrecursivitate.

nr_elem1(Lista,N):-nr_elemAux(Lista,0,N). %1nr_elemAux([],N,N). %2nr_elemAux([_|T],M,N):-P is M+1,nr_elemAux(T,P,N). %3

nr_elem1([a,b],N).

nr_elemAux([a,b],0,N).

(1) nr_elem1(Lista0,N0):-nr_elemAux(Lista0,0,N0).Lista0=[a,b], N0=N.

nr_elemAux([a],1,N).

(3) nr_elemAux([_|T1],M1,N1):-P1 is M1+1,nr_elemAux(T1,P1,N1).T1=[b], M1=0,P1=1.

nr_elemAux([],2,N).

(3) nr_elemAux([_|T2],M2,N2):-P2 is M2+1,nr_elemAux(T2,P2,N2).T2=[], M2=1,P2=2.

(2) nr_elemAux([],N3,N3).N3=2, N=2

Mircea Marin Programare logica

Page 20: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateCalculul numarului de elemente al unei liste: Versiunea cu acumulator

Varianta nr_elem1(Lista,N) de calcul al numarului de elemente din L pe ramurade avans în recursivitate se bazeaza pe relatia ajutatoare nr_elemAux(Lista,A,N)unde:

A este un argument suplimentar fata de nr_elem(Lista,N), numit acumulator.A acumuleaza numarul de elemente din lista pe masura ce se avanseaza înrecursivitate.

nr_elem1(Lista,N):-nr_elemAux(Lista,0,N). %1nr_elemAux([],N,N). %2nr_elemAux([_|T],M,N):-P is M+1,nr_elemAux(T,P,N). %3

nr_elem1([a,b],N).

nr_elemAux([a,b],0,N).

(1) nr_elem1(Lista0,N0):-nr_elemAux(Lista0,0,N0).Lista0=[a,b], N0=N.

nr_elemAux([a],1,N).

(3) nr_elemAux([_|T1],M1,N1):-P1 is M1+1,nr_elemAux(T1,P1,N1).T1=[b], M1=0,P1=1.

nr_elemAux([],2,N).

(3) nr_elemAux([_|T2],M2,N2):-P2 is M2+1,nr_elemAux(T2,P2,N2).T2=[], M2=1,P2=2.

(2) nr_elemAux([],N3,N3).N3=2, N=2

Mircea Marin Programare logica

Page 21: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateCalculul numarului de elemente al unei liste: Versiunea cu acumulator

Varianta nr_elem1(Lista,N) de calcul al numarului de elemente din L pe ramurade avans în recursivitate se bazeaza pe relatia ajutatoare nr_elemAux(Lista,A,N)unde:

A este un argument suplimentar fata de nr_elem(Lista,N), numit acumulator.A acumuleaza numarul de elemente din lista pe masura ce se avanseaza înrecursivitate.

nr_elem1(Lista,N):-nr_elemAux(Lista,0,N). %1nr_elemAux([],N,N). %2nr_elemAux([_|T],M,N):-P is M+1,nr_elemAux(T,P,N). %3

nr_elem1([a,b],N).

nr_elemAux([a,b],0,N).

(1) nr_elem1(Lista0,N0):-nr_elemAux(Lista0,0,N0).Lista0=[a,b], N0=N.

nr_elemAux([a],1,N).

(3) nr_elemAux([_|T1],M1,N1):-P1 is M1+1,nr_elemAux(T1,P1,N1).T1=[b], M1=0,P1=1.

nr_elemAux([],2,N).

(3) nr_elemAux([_|T2],M2,N2):-P2 is M2+1,nr_elemAux(T2,P2,N2).T2=[], M2=1,P2=2.

(2) nr_elemAux([],N3,N3).N3=2, N=2

Mircea Marin Programare logica

Page 22: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateCalculul numarului de elemente al unei liste: Versiunea cu acumulator

Varianta nr_elem1(Lista,N) de calcul al numarului de elemente din L pe ramurade avans în recursivitate se bazeaza pe relatia ajutatoare nr_elemAux(Lista,A,N)unde:

A este un argument suplimentar fata de nr_elem(Lista,N), numit acumulator.A acumuleaza numarul de elemente din lista pe masura ce se avanseaza înrecursivitate.

nr_elem1(Lista,N):-nr_elemAux(Lista,0,N). %1nr_elemAux([],N,N). %2nr_elemAux([_|T],M,N):-P is M+1,nr_elemAux(T,P,N). %3

nr_elem1([a,b],N).

nr_elemAux([a,b],0,N).

(1) nr_elem1(Lista0,N0):-nr_elemAux(Lista0,0,N0).Lista0=[a,b], N0=N.

nr_elemAux([a],1,N).

(3) nr_elemAux([_|T1],M1,N1):-P1 is M1+1,nr_elemAux(T1,P1,N1).T1=[b], M1=0,P1=1.

nr_elemAux([],2,N).

(3) nr_elemAux([_|T2],M2,N2):-P2 is M2+1,nr_elemAux(T2,P2,N2).T2=[], M2=1,P2=2.

(2) nr_elemAux([],N3,N3).N3=2, N=2

Mircea Marin Programare logica

Page 23: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateCalculul numarului de elemente al unei liste: Versiunea cu acumulator

Varianta nr_elem1(Lista,N) de calcul al numarului de elemente din L pe ramurade avans în recursivitate se bazeaza pe relatia ajutatoare nr_elemAux(Lista,A,N)unde:

A este un argument suplimentar fata de nr_elem(Lista,N), numit acumulator.A acumuleaza numarul de elemente din lista pe masura ce se avanseaza înrecursivitate.

nr_elem1(Lista,N):-nr_elemAux(Lista,0,N). %1nr_elemAux([],N,N). %2nr_elemAux([_|T],M,N):-P is M+1,nr_elemAux(T,P,N). %3

nr_elem1([a,b],N).

nr_elemAux([a,b],0,N).

(1) nr_elem1(Lista0,N0):-nr_elemAux(Lista0,0,N0).Lista0=[a,b], N0=N.

nr_elemAux([a],1,N).

(3) nr_elemAux([_|T1],M1,N1):-P1 is M1+1,nr_elemAux(T1,P1,N1).T1=[b], M1=0,P1=1.

nr_elemAux([],2,N).

(3) nr_elemAux([_|T2],M2,N2):-P2 is M2+1,nr_elemAux(T2,P2,N2).T2=[], M2=1,P2=2.

(2) nr_elemAux([],N3,N3).N3=2, N=2

Mircea Marin Programare logica

Page 24: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

AcumulatoriAplicatie: Inversarea unei liste

Sa se defineasca relatia rev_lista(L,R) care are loc dacaR este inversa listei L.

Idee: Se foloseste un acumulator care actioneaza ca ostiva în care se pun recursiv toate elementele lui L,începând cu capul lui L.Initial, acumulatorul este [].rev_lista(L,R):-rev_listaAux(L,[],R).

% caz de bazarev_listaAux([],R,R).

%caz recursivrev_listaAux([H|T],A,R):-rev_listaAux(T,[H|A],R).

Mircea Marin Programare logica

Page 25: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

AcumulatoriAplicatie: Inversarea unei liste

Sa se defineasca relatia rev_lista(L,R) care are loc dacaR este inversa listei L.

Idee: Se foloseste un acumulator care actioneaza ca ostiva în care se pun recursiv toate elementele lui L,începând cu capul lui L.

Initial, acumulatorul este [].rev_lista(L,R):-rev_listaAux(L,[],R).

% caz de bazarev_listaAux([],R,R).

%caz recursivrev_listaAux([H|T],A,R):-rev_listaAux(T,[H|A],R).

Mircea Marin Programare logica

Page 26: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

AcumulatoriAplicatie: Inversarea unei liste

Sa se defineasca relatia rev_lista(L,R) care are loc dacaR este inversa listei L.

Idee: Se foloseste un acumulator care actioneaza ca ostiva în care se pun recursiv toate elementele lui L,începând cu capul lui L.Initial, acumulatorul este [].

rev_lista(L,R):-rev_listaAux(L,[],R).

% caz de bazarev_listaAux([],R,R).

%caz recursivrev_listaAux([H|T],A,R):-rev_listaAux(T,[H|A],R).

Mircea Marin Programare logica

Page 27: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

AcumulatoriAplicatie: Inversarea unei liste

Sa se defineasca relatia rev_lista(L,R) care are loc dacaR este inversa listei L.

Idee: Se foloseste un acumulator care actioneaza ca ostiva în care se pun recursiv toate elementele lui L,începând cu capul lui L.Initial, acumulatorul este [].rev_lista(L,R):-rev_listaAux(L,[],R).

% caz de bazarev_listaAux([],R,R).

%caz recursivrev_listaAux([H|T],A,R):-rev_listaAux(T,[H|A],R).

Mircea Marin Programare logica

Page 28: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Inversarea unei liste: varianta cu acumulator

Exemplu ilustrat?-rev_lista([a,b,c],R).

R=[c,b,a]

rev_lista([a,b,c],R).

rev_listaAux([a,b,c],[],R).

rev_lista(L1,R1):-rev_listaAux(L1,[],R1).L1=[a,b,c], R1=R

rev_listaAux([b,c],[a],R).

rev_listaAux([H2|T2],A2,R2):-rev_listaAux(T2,[H2|A2],R2).

H2=[a],T2=[b,c], A2=[],R2=R

rev_listaAux([c],[b,a],R).

rev_listaAux([H3|T3],A3,R3):-rev_listaAux(T3,[H3|A3],R3).

H3=[b],T3=[c], A3=[a],R3=R

rev_listaAux([],[c,b,a],R).

rev_listaAux([H4|T4],A4,R4):-rev_listaAux(T4,[H4|A4],R4).

H4=[c],T4=[], A4=[b,a],R4=R

rev_listaAux([],R5,R5).R5=[c,b,a], R=[c,b,a]

Mircea Marin Programare logica

Page 29: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Inversarea unei liste: varianta cu acumulator

Exemplu ilustrat?-rev_lista([a,b,c],R).

R=[c,b,a]

rev_lista([a,b,c],R).

rev_listaAux([a,b,c],[],R).

rev_lista(L1,R1):-rev_listaAux(L1,[],R1).L1=[a,b,c], R1=R

rev_listaAux([b,c],[a],R).

rev_listaAux([H2|T2],A2,R2):-rev_listaAux(T2,[H2|A2],R2).

H2=[a],T2=[b,c], A2=[],R2=R

rev_listaAux([c],[b,a],R).

rev_listaAux([H3|T3],A3,R3):-rev_listaAux(T3,[H3|A3],R3).

H3=[b],T3=[c], A3=[a],R3=R

rev_listaAux([],[c,b,a],R).

rev_listaAux([H4|T4],A4,R4):-rev_listaAux(T4,[H4|A4],R4).

H4=[c],T4=[], A4=[b,a],R4=R

rev_listaAux([],R5,R5).R5=[c,b,a], R=[c,b,a]

Mircea Marin Programare logica

Page 30: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Inversarea unei liste: varianta cu acumulator

Exemplu ilustrat?-rev_lista([a,b,c],R).

R=[c,b,a]

rev_lista([a,b,c],R).

rev_listaAux([a,b,c],[],R).

rev_lista(L1,R1):-rev_listaAux(L1,[],R1).L1=[a,b,c], R1=R

rev_listaAux([b,c],[a],R).

rev_listaAux([H2|T2],A2,R2):-rev_listaAux(T2,[H2|A2],R2).

H2=[a],T2=[b,c], A2=[],R2=R

rev_listaAux([c],[b,a],R).

rev_listaAux([H3|T3],A3,R3):-rev_listaAux(T3,[H3|A3],R3).

H3=[b],T3=[c], A3=[a],R3=R

rev_listaAux([],[c,b,a],R).

rev_listaAux([H4|T4],A4,R4):-rev_listaAux(T4,[H4|A4],R4).

H4=[c],T4=[], A4=[b,a],R4=R

rev_listaAux([],R5,R5).R5=[c,b,a], R=[c,b,a]

Mircea Marin Programare logica

Page 31: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Inversarea unei liste: varianta cu acumulator

Exemplu ilustrat?-rev_lista([a,b,c],R).

R=[c,b,a]

rev_lista([a,b,c],R).

rev_listaAux([a,b,c],[],R).

rev_lista(L1,R1):-rev_listaAux(L1,[],R1).L1=[a,b,c], R1=R

rev_listaAux([b,c],[a],R).

rev_listaAux([H2|T2],A2,R2):-rev_listaAux(T2,[H2|A2],R2).

H2=[a],T2=[b,c], A2=[],R2=R

rev_listaAux([c],[b,a],R).

rev_listaAux([H3|T3],A3,R3):-rev_listaAux(T3,[H3|A3],R3).

H3=[b],T3=[c], A3=[a],R3=R

rev_listaAux([],[c,b,a],R).

rev_listaAux([H4|T4],A4,R4):-rev_listaAux(T4,[H4|A4],R4).

H4=[c],T4=[], A4=[b,a],R4=R

rev_listaAux([],R5,R5).R5=[c,b,a], R=[c,b,a]

Mircea Marin Programare logica

Page 32: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Inversarea unei liste: varianta cu acumulator

Exemplu ilustrat?-rev_lista([a,b,c],R).

R=[c,b,a]

rev_lista([a,b,c],R).

rev_listaAux([a,b,c],[],R).

rev_lista(L1,R1):-rev_listaAux(L1,[],R1).L1=[a,b,c], R1=R

rev_listaAux([b,c],[a],R).

rev_listaAux([H2|T2],A2,R2):-rev_listaAux(T2,[H2|A2],R2).

H2=[a],T2=[b,c], A2=[],R2=R

rev_listaAux([c],[b,a],R).

rev_listaAux([H3|T3],A3,R3):-rev_listaAux(T3,[H3|A3],R3).

H3=[b],T3=[c], A3=[a],R3=R

rev_listaAux([],[c,b,a],R).

rev_listaAux([H4|T4],A4,R4):-rev_listaAux(T4,[H4|A4],R4).

H4=[c],T4=[], A4=[b,a],R4=R

rev_listaAux([],R5,R5).R5=[c,b,a], R=[c,b,a]

Mircea Marin Programare logica

Page 33: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Inversarea unei liste: varianta cu acumulator

Exemplu ilustrat?-rev_lista([a,b,c],R).

R=[c,b,a]

rev_lista([a,b,c],R).

rev_listaAux([a,b,c],[],R).

rev_lista(L1,R1):-rev_listaAux(L1,[],R1).L1=[a,b,c], R1=R

rev_listaAux([b,c],[a],R).

rev_listaAux([H2|T2],A2,R2):-rev_listaAux(T2,[H2|A2],R2).

H2=[a],T2=[b,c], A2=[],R2=R

rev_listaAux([c],[b,a],R).

rev_listaAux([H3|T3],A3,R3):-rev_listaAux(T3,[H3|A3],R3).

H3=[b],T3=[c], A3=[a],R3=R

rev_listaAux([],[c,b,a],R).

rev_listaAux([H4|T4],A4,R4):-rev_listaAux(T4,[H4|A4],R4).

H4=[c],T4=[], A4=[b,a],R4=R

rev_listaAux([],R5,R5).R5=[c,b,a], R=[c,b,a]

Mircea Marin Programare logica

Page 34: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Inversarea unei liste: varianta cu acumulator

Exemplu ilustrat?-rev_lista([a,b,c],R).R=[c,b,a]

rev_lista([a,b,c],R).

rev_listaAux([a,b,c],[],R).

rev_lista(L1,R1):-rev_listaAux(L1,[],R1).L1=[a,b,c], R1=R

rev_listaAux([b,c],[a],R).

rev_listaAux([H2|T2],A2,R2):-rev_listaAux(T2,[H2|A2],R2).

H2=[a],T2=[b,c], A2=[],R2=R

rev_listaAux([c],[b,a],R).

rev_listaAux([H3|T3],A3,R3):-rev_listaAux(T3,[H3|A3],R3).

H3=[b],T3=[c], A3=[a],R3=R

rev_listaAux([],[c,b,a],R).

rev_listaAux([H4|T4],A4,R4):-rev_listaAux(T4,[H4|A4],R4).

H4=[c],T4=[], A4=[b,a],R4=R

rev_listaAux([],R5,R5).R5=[c,b,a], R=[c,b,a]

Mircea Marin Programare logica

Page 35: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateAplicatie: Problema trezorierului

Ipoteze:1 Nici un membru al clubului nu are datorii la trezorierul clubului.2 Daca un membru al clubului nu a platit taxa, atunci el are datorii la trezorierul

clubului.3 Trezorierul clubului este un membru al clubului.

Concluzie: Trezorierul clubului a platit taxa.

Sa se rescrie problema ca fapte, reguli si întrebare în Prolog.

%Ipoteza 1fara_datorii(X):-membru_club(X).%Ipotexa 2platit_taxa(X):-fara_datorii(X).%Ipoteza 3membru_club(trezorier).

?-platit_taxa(trezorier).

Observatie: un astfel de program nu este recursiv.

Mircea Marin Programare logica

Page 36: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateAplicatie: Problema trezorierului

Ipoteze:1 Nici un membru al clubului nu are datorii la trezorierul clubului.2 Daca un membru al clubului nu a platit taxa, atunci el are datorii la trezorierul

clubului.3 Trezorierul clubului este un membru al clubului.

Concluzie: Trezorierul clubului a platit taxa.

Sa se rescrie problema ca fapte, reguli si întrebare în Prolog.

%Ipoteza 1fara_datorii(X):-membru_club(X).%Ipotexa 2platit_taxa(X):-fara_datorii(X).%Ipoteza 3membru_club(trezorier).

?-platit_taxa(trezorier).

Observatie: un astfel de program nu este recursiv.

Mircea Marin Programare logica

Page 37: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateAplicatie: Problema vecinilor

Sa se formalizeze urmatoarele cunostinte în Prolog:1 Stefan este vecin cu Petre.2 Stefan este casatorit cu o doctorita care lucreaza la Spitalul de Urgenta.3 Petre este casatorit cu o actrita care lucreaza la Teatrul National.4 Stefan este meloman si Petre este vânator.5 Toti melomanii sunt sentimentali.6 Toti vânatorii sunt mincinosi.7 Actritelor le plac barbatii sentimentali.8 Sotii au aceiasi vecini.9 Casatoria si vecinatatea sunt relatii simetrice.

Apoi sa se foloseasca Prolog pentru a afla raspunsul la întrebarea: Îi place sotiei lui

Petre de Stefan?

Mircea Marin Programare logica

Page 38: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

RecursivitateAplicatie: Problema vecinilor.

vecin1(stefan,petre). %1casatorit1(stefan,sotie_stefan). %2doctorita(sotie_stefan). %2lucreaza(sotie_stefan,urgenta). %2casatorit1(petre,sotie_petre). %3actrita(sotie_petre). %3lucreaza(sotie_petre,national). %3meloman(stefan). %4vanator(petre). %4sentimental(X):-meloman(X). %5mincinos(X):-vanator(X). %6place(X,Y):-actrita(X),sentimental(Y). %7vecin(X,Y):-casatorit(X,Z),vecin(Z,Y). %8vecin(X,Y):-vecin1(X,Y). %9vecin(X,Y):-vecin1(Y,X). %9casatorit(X,Y):-casatorit1(X,Y). %9casatorit(X,Y):-casatorit1(Y,X). %9concluzie:-casatorit(petre,Sotie),place(Sotie,stefan).

?-concluzie.

Observatie: Acest program este recursiv.

Mircea Marin Programare logica

Page 39: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Observatii referitoare la relatii simetrice

O relatie binara r este simetrica daca

r(term1,term2) are loc daca si numai daca r(term2,term1) are loc.

Relatiile vecin/2 si casatorit/2 din exemplul precedent sunt simetrice.

Q: Cum se poate specifica o relatie simetrica?

Varianta 1 - Exemplur(a,b). r(a,c).r(X,Y):-r(Y,X).

Observatie: Este esential ca faptele pentru r/2 sa apara înaintea regulii.Problema:

?-r(b,c).

⇒ raspunsul la aceasta întrebare nu va fi obtinut niciodata (calcul infinit).Cum putem evita aceste calcule infinite?

Varianta 2: prin intermediul unei relatiei binare asimetrice r1/2. Exemplu:r1(a,b). r1(a,c).r(X,Y):-r1(X,Y).r(X,Y):-r1(Y,X).

Aceasta varianta a fost folosita pentru a defini relatiile simetrice vecin/2 sicasatorit/2.

Mircea Marin Programare logica

Page 40: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Observatii referitoare la relatii simetrice

O relatie binara r este simetrica daca

r(term1,term2) are loc daca si numai daca r(term2,term1) are loc.

Relatiile vecin/2 si casatorit/2 din exemplul precedent sunt simetrice.

Q: Cum se poate specifica o relatie simetrica?

Varianta 1 - Exemplur(a,b). r(a,c).r(X,Y):-r(Y,X).

Observatie: Este esential ca faptele pentru r/2 sa apara înaintea regulii.Problema:

?-r(b,c).

⇒ raspunsul la aceasta întrebare nu va fi obtinut niciodata (calcul infinit).Cum putem evita aceste calcule infinite?

Varianta 2: prin intermediul unei relatiei binare asimetrice r1/2. Exemplu:r1(a,b). r1(a,c).r(X,Y):-r1(X,Y).r(X,Y):-r1(Y,X).

Aceasta varianta a fost folosita pentru a defini relatiile simetrice vecin/2 sicasatorit/2.

Mircea Marin Programare logica

Page 41: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Observatii referitoare la relatii simetrice

O relatie binara r este simetrica daca

r(term1,term2) are loc daca si numai daca r(term2,term1) are loc.

Relatiile vecin/2 si casatorit/2 din exemplul precedent sunt simetrice.

Q: Cum se poate specifica o relatie simetrica?

Varianta 1 - Exemplur(a,b). r(a,c).r(X,Y):-r(Y,X).

Observatie: Este esential ca faptele pentru r/2 sa apara înaintea regulii.Problema:

?-r(b,c).

⇒ raspunsul la aceasta întrebare nu va fi obtinut niciodata (calcul infinit).Cum putem evita aceste calcule infinite?

Varianta 2: prin intermediul unei relatiei binare asimetrice r1/2. Exemplu:r1(a,b). r1(a,c).r(X,Y):-r1(X,Y).r(X,Y):-r1(Y,X).

Aceasta varianta a fost folosita pentru a defini relatiile simetrice vecin/2 sicasatorit/2.

Mircea Marin Programare logica

Page 42: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Observatii referitoare la relatii simetrice

O relatie binara r este simetrica daca

r(term1,term2) are loc daca si numai daca r(term2,term1) are loc.

Relatiile vecin/2 si casatorit/2 din exemplul precedent sunt simetrice.

Q: Cum se poate specifica o relatie simetrica?

Varianta 1 - Exemplur(a,b). r(a,c).r(X,Y):-r(Y,X).

Observatie: Este esential ca faptele pentru r/2 sa apara înaintea regulii.Problema:

?-r(b,c).

⇒ raspunsul la aceasta întrebare nu va fi obtinut niciodata (calcul infinit).Cum putem evita aceste calcule infinite?

Varianta 2: prin intermediul unei relatiei binare asimetrice r1/2. Exemplu:r1(a,b). r1(a,c).r(X,Y):-r1(X,Y).r(X,Y):-r1(Y,X).

Aceasta varianta a fost folosita pentru a defini relatiile simetrice vecin/2 sicasatorit/2.

Mircea Marin Programare logica

Page 43: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Reprezentarea multimilor în Prolog

O multime poate fi reprezentata ca o lista în care fiecare elementapare o singura data.

Sa se defineasca recursiv proprietatea este_multime(L) careare loc daca L este o lista în care fiecare element apare osingura data. Exemplu:

?-este_multime([a,b,d,c]).true?-este_multime([a,b,a]).false

Sa se defineasca relatia multime(L,M) care ia ca argumentde intrare o lista L si foloseste M ca parametru de iesire pentrumultimea de elemente care apar în lista L.

?-multime([a,b,a,c],M).M=[a,b,c]

Mircea Marin Programare logica

Page 44: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Reprezentarea multimilor în Prolog

1 este_multime(L)B Cazul de baza: [] este multime.B Cazul recursiv: [H|T] este multime daca H nu apare în T si

T este multime.2 multime(L,M)

B Cazul de baza: Daca L=[] atunci M=[].B Cazul recursiv: Daca L=[H|T] atunci M=[H|R] unde R

este lista obtinuta în 2 pasi:1 Mai întâi se determina lista R1 care se obtine stergând din T

toate aparitiile lui H.Pentru a afla R1, vom defini relatia sterge(H,T,R1) careare loc daca R1 este lista care se obtine din T stergând toateaparitiile lui H.

2 R se obtine recursiv, ca raspuns la întrebareamultime(R1,R).

Mircea Marin Programare logica

Page 45: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Reprezentarea multimilor în Prolog

este_multime([]).este_multime([H|T]):-not(member(H,T)),

este_multime(T).

B not este operator predefinit în Prolog. ?-not(atom) are locdaca si numai daca ?-atom nu are loc.

B member(X,L) este predefinit în Prolog, si are loc daca si numaidaca X este membru al listei L.

multime([],[]).multime([H|T],[H|R]):-sterge(H,T,R1),multime(R1,R).

sterge(H,[],[]).sterge(H,[H|T],R):-sterge(H,T,R).sterge(H,[H1|T],[H1|R]):-H\=H1,

sterge(H,T,R).

Mircea Marin Programare logica

Page 46: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Reprezentarea multimilor în Prolog

este_multime([]).este_multime([H|T]):-not(member(H,T)),

este_multime(T).

B not este operator predefinit în Prolog. ?-not(atom) are locdaca si numai daca ?-atom nu are loc.

B member(X,L) este predefinit în Prolog, si are loc daca si numaidaca X este membru al listei L.

multime([],[]).multime([H|T],[H|R]):-sterge(H,T,R1),multime(R1,R).

sterge(H,[],[]).sterge(H,[H|T],R):-sterge(H,T,R).sterge(H,[H1|T],[H1|R]):-H\=H1,

sterge(H,T,R).

Mircea Marin Programare logica

Page 47: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Operatii cu multimiExercitii

Sa se defineasca recursiv urmatoarele relatii pentru multimi:multimi_egale(A,B) daca A si B sunt multimi egale.reuniune(A,B,C) care are loc daca C reprezintamultimea obtinuta din reuniunea multimilor A si B.intersectie(A,B,C) care are loc daca C reprezintamultimea obtinuta din intersectia multimilor A si B.diferenta(A,B,C) care are loc daca C reprezintamultimea obtinuta prin scaderea multimilor A si B.

Mircea Marin Programare logica

Page 48: Curs 3 - Recursivitate în Prolog. Relatii recursive. Aplicatii

Relatii recursiveQuiz

Se considera relatia next(X,Y,L) definita astfel:

next(X,Y,[X,Y|_]).next(X,Y,[Z|T]):-X\=Z,next(X,Y,T).

1 Care este semnificatia relatiei next(X,Y,Z)?

2 Care este semnificatia predicatului z_u(X,Y) definit de regula

z_u(X,Y):-next(X,Y,[luni,marti,miercuri,joi,vineri,sambata,duminica,luni]).

3 Care este semnificatia predicatului z_u(X,Y) definit de regula

z_p(X,Y):-z_u(Y,X).

Mircea Marin Programare logica