Professional Documents
Culture Documents
PROLOG
Prolog reprezintă o prescurtare de la “Programming în logic”.
Este un limbaj conceput pentru programarea logică (deci un limbaj declarativ).
A fost elaborat în cursul anilor 1970 în Europa (mai ales în Franţa şi Scoţia).
Primul compilator de Prolog a fost creat în 1972 de către Philippe Roussel, la
Universitatea din Marsilia.
Prologul este un limbaj compilat, care utilizează, în locul relaţiilor matematice,
relaţii logice între mulţimi de date.
Exista limbaje algoritmice, orientate obiect si logice.
Limbajele programării logice (Prolog) sunt limbaje declarative. Un limbaj de
programare declarativ scuteşte programatorul de a mai menţiona procedura exactă
pe care trebuie să o execute calculatorul pentru a realiza o funcţie. Programatorii
folosesc limbajul pentru a descrie o mulţime de fapte şi de relaţii astfel încât
utilizatorul să poată interoga apoi sistemul pentru a obţine un anumit rezultat.
La fixarea unui scop Prolog care contine variabile, acestea sunt neinstantiate, iar
sistemul incearca satisfacerea acestui scop cautand printre faptele din baza de cunostinte
un fapt care poate identifica cu scopul, printr-o instantiere adecvata a variabilelor din
scopul dat. Este vorba de fapt de un proces de unificare a predicatului scop cu unul din
predicatele fapte existente in baza de cunostinte. La incercarea de satisfacere a scopului,
cautarea se face intotdeauna pornind de la inceputul bazei de cunostinte. Exista atatea
solutii cate unificari diferite exista. Obtinerea primei solutii este numita satisfacerea
scopului, iar obtinerea altor solutii resatisfacerea scopului. La satisfacerea unui scop
cautarea se face intotdeauna de la inceputul bazei de cunostinte. La resatisfacerea unui
scop cautarea se face incepand de la marcajul stabilit de satisfacerea anterioara a acelui
scop.
deci conjunctia de scopuri. Scopurile din corpul regulii devin subscopuri a caror
satisfacere se va incerca printr-un mecanism similar cu cel al satisfacerii scopului initial.
Comportarea sistemului Prolog in care se incearca in mod repetat satisfacerea si
resatisfacerea scopurilor din conjunctia de scopuri se numeste backtracking.
Programul consta din 6 clauze. Fiecare dintre aceste clauze declara un fapt despre
relatia parinte. Spre exemplu, parinte(tom, bob) este o instantiere particulara a relatiei
parinte. In general, o relatie se defineste ca fiind multimea tuturor instantierilor sale.
Obs.: Acest program simplu nu contine (inca) regului (ci doar fapte).
Interogarea Prologului:
Ex.: Vrem sa aflam daca Bob este parinte al lui Pat. Aceasta intrebare este comunicata
sistemului Prolog tastandu-se la terminal:
?- parinte(bob, pat).
Raspunsul Prologului va fi
yes
X = tom
Y = bob;
X = tom
Y = liz;
…
Obs.: Interogarea
?- parinte(X, Y), parinte(Y, jim).
va produce acelasi rezultat.
X = bob
Y = pat
feminin(pam).
masculin(tom).
masculin(bob).
feminin(liz).
feminin(pat).
feminin(ann).
masculin(jim).
si
sex(pam, feminin).
sex(tom, masculin).
7
Limbaj Prolog – Prelegerea 1 Pastramă Emil
sex(bob, masculin).
…
si
urmas(liz, tom).
…
Obs.: Relatia urmas poate fi definita intr-un mod mult mai elegant prin folosirea
relatiei deja definite parinte.
Pentru toti X si toti Y,
Y este urmas al lui X daca
X este parinte al lui Y.
Aceasta interpretare genereaza o clauza Prolog reprezentata de urmatoarea regula:
urmas(Y, X) :- parinte(X, Y).
Interogarea Prologului cand baza de cunostinte contine si aceasta regula:
?- urmas(liz, tom).
Cum lucreaza Prologul acum: Intrucat nu exista fapte referitoare la urmasi, trebuie
folosita regula, astfel: variabilele X si Y vor fi instantiate in felul urmator
X = tom si Y = liz
Continuare:
- Dupa instantiere se obtine un caz particular al regulii generale. Acest caz
particular este:
urmas(liz, tom) :- parinte(tom, liz).
- Corpul regulii reprezinta partea de conditie, iar antetul ei partea de concluzie.
Prolog incearca sa determine daca partea de conditie este adevarata i.e. daca
parinte(tom, liz) este adevarat. In acest moment, scopul initial, urmas(liz,tom), a
fost inlocuit cu subscopul parinte(tom, liz).
- Noul scop este imediat satisfacut intrucat el reprezinta o fapta Prolog (din baza de
cunostinte).
- Aceasta inseamna ca partea de concluzie este, de asemenea, adevarata, iar Prolog
va raspunde la intrebare cu yes.
1
Limbaj Prolog – Prelegerea 2 Pastramă Emil
sau indirect
predecesor (X, Z) :-
parinte (X, Y),
parinte (Y, Z).
predecesor (X, Z):-
parinte (X, Y1),
parinte (Y1, Y2),
parinte(Y2, Z).
OBS.: Pentru ca relatia predecesor sa lucreze corect in cazul predecesorilor aflati la orice
adancime, definitia ei trebuie gandita in felul urmator:
Pentru toti X si Z,
X este predecesor al lui Z daca
Exista un Y astfel incat
(1) X este parinte al lui Y si
(2) Y este un predecesor al lui Z.
predecesor (X, Z) :-
parinte (X, Y),
predecesor (Y, Z).
4. Doua structuri (a se vedea sintaxa limbajului) sunt egale daca au acelasi functor,
acelasi numar de componente si fiecare componenta dintr-o structura este egala
cu componenta corespunzatoare din cealalta structura.
Constantele definesc:
Obiecte particulare
Relatii particulare
Constantele sunt de urmatoarele tipuri:
atomi – constante simbolice (desemneaza predicate Prolog sau argumente
ale predicatelor)
numere
Atomii pot fi construiti in 3 moduri; ei pot constitui:
1) siruri de litere, cifre si caracterul “underscore”, „_‟, siruri care incep cu o litera
mica;
2) siruri de caractere speciale;
3) siruri de caractere incluse intre paranteze simple (ex.: „South_America‟).
Variabilele:
au denumiri care incep cu litere mari; numele de variabila poate incepe si
cu simbolul “_”, ceea ce indica o variabila anonima;
utilizarea unei variabile anonime semnifica faptul ca nu intereseaza
valoarea la care se va instantia acea variabila;
scopul lexical al unui nume de variabila il constituie o unica clauza. (Daca,
spre exemplu, numele X15 intervine in doua clauze diferite, atunci el
semnifica doua variabile diferite. Fiecare ocurenta a lui X15 in interiorul
aceleiasi clauze semnifica insa o aceeasi variabila).
6
Limbaj Prolog – Prelegerea 2 Pastramă Emil
Operatori
Operatori aritmetici:
- sunt o rescriere infixata a unor structuri si de aceea valoarea
expresiei definite cu ei nu este calculata;
- evaluarea expresiei se face la cerere in cazul in care se foloseste
operatorul predefinit infixat is, ca in exemplul: X is 1+2 (in acest
caz se instantiaza variabila X la valoarea 3).
Operatori relationali:
- sunt predicate predefinite infixate;
- cel mai important este operatorul de egalitate, care functioneaza ca
si cand ar fi definit prin urmatorul fapt: X = X (VEZI
satisfacerea unui scop de tipul X = Y, prin incercarea de a unifica
X cu Y).
Un exemplu:
?- X = 1+2. ?- X is 1+2.
X = 1+2 X=3
deoarece, in primul caz, expresia 1+2 denota o structura (termen) Prolog, unde + este
functorul, iar 1 si 2 sunt argumentele sale. Nimic din acest scop nu declanseaza adunarea,
care este declansata de operatorul is.
- X==Y este adevarat daca termenii X si Y sunt identici, adica au exact aceeasi
structura si toate componentele corespunzatoare coincid. In particular, numele de
variabile trebuie sa fie aceleasi.
- Relatia complementara (de non-identitate) este \==
Un exemplu:
?- f(a, X) == f(a, Y).
no
- Operatorul =:= face numai evaluare aritmetica si nici o instantiere; semnificatia
lui X =:= Y este: valorile expresiilor aritmetice X si Y sunt egale.
Diferenta dintre operatorii = si =:=
?- 1+2 =:= 2+1.
yes
?- 1+2 = 2+1.
no
- Inegalitatea a doua expresii aritmetice se stabileste cu operatorul =\= (vezi folia
anterioara).
Operatii aritmetice
- Exista proceduri incorporate care pot fi utilizate pentru efectuarea operatiilor
aritmetice.
- Efectuarea operatiilor aritmetice trebuie sa fie ceruta in mod explicit de catre
procedura incorporata is.
3
Limbaj Prolog – Prelegerea 3 Pastramă Emil
Exemplu:
:- op (600, xfx, are).
caz in care este legala expresia
coco are pene
Operatori definiti de utilizator – continuare
- Directivele actioneaza ca o definire de noi operatori ai limbajului, in care se
specifica numele, precedenta si tipul (infixat, prefixat sau postfixat) operatorului.
- Nu se asociaza nici o operatie operatorilor definiti de programator.
- Operatorii noi astfel definiti sunt utilizati ca functori numai pentru a combina
obiecte in structuri si nu pentru a executa actiuni asupra datelor.
- Exemplu: In loc de a utiliza structura
are (coco, pene)
4
Limbaj Prolog – Prelegerea 3 Pastramă Emil
Exemplu
:- op (100, xfx, [este, are]).
:- op (100, xf, zboara).
coco are pene.
coco zboara.
coco este papagal.
bozo este pinguin.
- Predicatul cut, notat cu atomul special ! este un predicat standard, fara argumente,
care se indeplineste (este adevarat) intotdeauna si nu poate fi resatisfacut.
- Comportarea predicatului cut este urmatoarea:
Daca D1, D2, … , Dm sunt satisfacute, ele nu mai pot fi resatisfacute datorita lui
cut (se inhiba backtracking-ul).
Daca D1, D2, … , Dm sunt satisfacute, C2 si C3 nu vor mai fi utilizate pentru
resatisfacerea lui H. Resatisfacerea lui H se poate face numai prin resatisfacerea
unuia din scopurile D m+1, … , Dn, daca acestea au mai multe solutii.
Observatie: Exista doua contexte diferite in care se poate utiliza predicatul cut, si
anume: intr-un context predicatul cut se introduce numai pentru cresterea eficientei
programului, caz in care el se numeste cut verde; in celalalt context utilizarea lui cut
modifica semnificatia procedurala a programului, caz in care el se numeste cut rosu. (La
cut-ul verde semnificatia procedurala a programului este aceeasi, adica nu conteaza
ordinea in care se scriu clauzele. La un cut rosu efectul programului este total diferit daca
se schimba ordinea clauzelor).
Cut rosu
astfel:
7
Limbaj Prolog – Prelegerea 3 Pastramă Emil
Exemplu
Ordinea clauzelor de definire a lui min1 poate fi schimbata fara nici un efect
asupra rezultatului programului. In cazul predicatului min2 se utilizeaza un cut rosu,
asemanator structurii
daca_atunci_altfel
Daca se schimba ordinea clauzelor de definire a predicatului min2:
min2(X,Y,Y).
min2(X, Y, X) :- X=<Y, !.
Predicatul fail
Prolog permite exprimarea directa a esecului unui scop cu ajutorul predicatului
fail – un predicat:
standard,
fara argumente,
care esueaza intotdeauna.
Dupa fail nu se mai poate satisface nici un scop.
Introducerea unui predicat fail intr-o conjunctie de scopuri, de obicei la sfarsit
(caci dupa fail nu se mai poate satisface nici un scop), determina intrarea in
procesul de backtracking.
Daca fail se intalneste dupa predicatul cut, nu se mai face backtracking.
Comentariu:
- la prima interogare: din clauza (*) avem rau (gelu) daca bun (gelu), care este
adevarat din primul fapt al bazei de cunostinte; apoi ! este intotdeauna adevarat si
urmeaza fail care genereaza esec; datorita existentei lui cut, clauza (**) nu va mai
fi utilizata pentru resatisfacerea scopului; deci raspunsul ramane no, ca si in al
doilea caz;
- la a treia interogare: pentru clauza (*) ar trebui sa am bun (petru), dar acest fapt
nu exista in baza de cunostinte; deoarece bun(petru) nu a fost satisfacut, am voie
sa utilizez clauza (**); clauza (**) furnizeaza rau (petru), deci satisface scopul
curent; atunci raspunsul este “yes”.
Observatie: Atunci cand este folosit pentru a determina esecul, fail este de obicei
precedat de cut, deoarece procesul de backtracking pe scopurile care il preced este inutil,
scopul esuand oricum, datorita lui fail.
rosu (mar).
rosu (cub).
rosu (soare).
afisare (X) :- rosu (X), write (X), fail.
afisare (_). (*)
Comentariu: Intrucat, pentru fiecare obiect considerat, scopul afisare (X) esueaza
datorita lui fail, se trece la clauza (*), care afiseaza obiectul respectiv, adica raspunde yes.
Trecerea la clauza (*) este posibila deoarece prima clauza nu contine cut inainte de fail.
In acest fel, vor fi afisate toate obiectele rosii cunoscute de programul Prolog, datorita
procesului de backtracking generat de fail; in acest fel se realizeaza, prin fail, o iteratie
peste faptele rosu ( ). Clauza afisare (_) este adaugata pentru ca raspunsul final la
satisfacerea scopului sa fie afirmativ. (Aceasta clauza raspunde yes la orice).
3
Limbaj Prolog – Prelegerea 4 Pastramă Emil
1. Cazul cand NU avem cut inaintea lui fail: programul raspunde YES la orice
(datorita clauzei a doua); afiseaza (datorita lui write (X)) numai obiectele rosii
cunoscute de program (pentru aceste obiecte se scrie denumirea lor si apoi yes).
2. Cazul cand inaintea lui fail exista cut:
Pentru un obiect rosu cunoscut de program este scris numele obiectului si se
raspunde NO (pentru ca, datorita lui cut, nu se mai ajunge la clauza a doua).
Pentru un obiect necunoscut de program nu se mai afiseaza nimic si se
raspunde YES. (Aceasta deoarece, nefiind satisfacute clauzele dinaintea lui
cut, se ajunge la clauza a doua, care genereaza raspunsul YES).
Comentariu: Predicatul cut utilizat aici este un cut rosu. Combinatia !,fail este
utilizata cu rol de negatie (pentru ca fail raspunde no, iar cut ma impiedica sa folosesc
clauza urmatoare). Se mai spune ca limbajul Prolog modeleaza negatia ca esec al
satisfacerii unui scop (negatia ca insucces), aceasta fiind, de fapt, o particularizare a
ipotezei lumii inchise. Combinatia !,fail este echivalenta cu un predicat standard existent
in Prolog, si anume predicatul not.
Predicatul not admite ca argument un predicat Prolog si reuseste daca predicatul
argument esueaza.
In Sicstus Prolog sintaxa pentru predicatul not este \+
Varianta 1 – program:
box(box).
sport(tenis).
sport(polo).
sport(innot).
sport(box).
iubeste(mihai,X):-sport(X),box(X),!,fail.
iubeste(mihai,X):-sport(X).
Exemple de interogari:
?- sport(X).
X=tenis ?;
X=polo ?;
X=innot ?;
X=box ?;
no
5
Limbaj Prolog – Prelegerea 4 Pastramă Emil
?-sport(tenis).
yes
?- iubeste(mihai,tenis).
yes
?- iubeste(mihai,box).
no
Varianta 2 – program:
box(box).
sport(tenis).
sport(polo).
sport(innot).
sport(box).
iubeste(mihai,X) :- sport(X),\+(box(X)).
iubeste(mihai,X) :- sport(X).
Exemple de interogari:
- La primele trei interogari
?- sport(X).
?- sport(tenis).
?-iubeste(mihai,tenis).
rezultatul este identic cu cel de la programul anterior.
- La ultima interogare rezultatul difera:
?- iubeste(mihai,box).
yes
Aici raspunsul este YES deoarece, dupa ce esueaza prima clauza, se trece la
urmatoarea, care este satisfacuta. (Intrucat nu exista predicatul cut, se poate trece la
clauza urmatoare).
6
Limbaj Prolog – Prelegerea 4 Pastramă Emil
Observatie: Chiar daca prima clauza este satisfacuta, se trece oricum la clauza
urmatoare (a doua) pentru ca este posibil ca ea sa furnizeze o noua solutie.
Predicatul call
- call este un alt predicat standard. El admite ca argument un predicat Prolog si are
ca efect incercarea de satisfacere a predicatului argument.
- call reuseste daca predicatul argument reuseste si esueaza in caz contrar.
- Utilizand acest predicat, se poate explicita efectul general al predicatului standard
not astfel:
not(P) :- call(P),!,fail.
not(P).
Observatie: Atat predicatul not, cat si predicatul call sunt predicate de ordinul II in
Prolog, deoarece admit ca argumente alte predicate.
Predicatul bagof
Scopul
bagof(X,P,L)
va produce lista L a tuturor obiectelor X astfel incat sa fie satisfacut un scop P.
varsta (petru,7).
varsta(ana,5).
varsta(patricia,8).
varsta(tom,5).
Atunci putem obtine lista tuturor copiilor care au 5 ani prin urmatoarea interogare:
?-bagof(Copil,varsta(Copil,5),Lista).
Lista = [ana, tom]
Predicatul findall
findall(X,P,L)
produce, de asemenea, o lista de obiecte care satisfac P. Diferenta fata de bagof este
aceea ca sunt colectate toate obiectele X, indiferent de solutii posibil diferite pentru
variabile din P care nu sunt partajate cu X.
Daca nu exista nici un obiect X care sa satisfaca P, atunci findall va avea succes
cu L = [ ].
Predicate standard de intrare / iesire (intotdeauna adevarate)
Predicatul write
Permite citirea unui string sau simbol. Valoarea obtinuta in urma citirii este legata
la X din
readln(X)
LISTE
Operatii cu liste:
1. Apartenenta la o lista
- se foloseste predicatul membru(X,L), unde X este un obiect si L este o lista. X este
membru al lui L daca
(1) X este capul lui L
sau
(2) X este membru al cozii lui L
ADICA
membru(X, [X|Coada]).
membru(X, [Cap|Coada]):-membru(X, Coada).
2. Concatenarea
add(X, L, [X|L]).
9
Limbaj Prolog – Prelegerea 4 Pastramă Emil
Observatie: Inserarea unui element intr-o lista poate fi definita folosind relatia del, astfel:
Subliste
Definitie:
S este o sublista a lui L daca
(1) L poate fi descompusa in doua liste, L1 si L2
si
(2) L2 poate fi descompusa in doua liste, S si o alta lista L3
adica
sublista(S,L) :- conc(L1,L2,L), conc(S,L3,L2).