Sunteți pe pagina 1din 14

1.

Limbajul Prolog

Limbajul Prolog (PROgrammation en LOGique) a fost elaborat la Universitatea din Marsilia


n jurul anului 1970, ca instrument pentru programarea i rezolvarea problemelor ce
implicau reprezentri simbolice de obiecte i relaii dintre acestea.

Prolog are un cmp de aplicaii foarte larg: baze de date relaionale, inteligen artificial,
logic matematic, demonstrarea de teoreme, sisteme expert, rezolvarea de probleme
abstracte sau ecuaii simbolice, etc.

Exist standardul ISO-Prolog.

Nu exist standard pentru programare orientat obiect n Prolog, exist doar extensii:
TrincProlog, SWI-Prolog.

Vom studia implementarea SWI-Prolog sintaxa e foarte apropiat de cea a standardului


ISO-Prolog.

Turbo Prolog, Visual Prolog, GNUProlog, Sicstus Prolog, Parlog, etc.

SWI-Prolog 1986
ofer o interfa bidirecional cu limbajele C i Java
folosete XPCE un sistem GUI orientat obiect
multithreading bazat pe suportul multithreading oferit de limbajul standard C.

Program Prolog
caracter descriptiv: un program Prolog este o colecie de definiii ce descriu relaii sau funcii
de calculat reprezentri simbolice de obiecte i relaii ntre obiecte. Soluia problemelor nu
se mai vede ca o execuie pas cu pas a unei secvene de instruciuni.

program colecie de declaraii logice, fiecare fiind o clauz Horn de forma p,


p q , p1 p 2 ... p n q
concluzie de demonstrat de forma p1 p 2 ... p n

Structura de control folosit de interpretorul Prolog

Se bazeaz pe declaraii logice numite clauze


o fapt ceea ce se cunoate a fi adevrat
o regul - ce se poate deduce din fapte date (indic o concluzie care se tie
c e adevrat atunci cnd alte concluzii sau fapte sunt adevrate)
Concluzie ce trebuie demonstrat - GOAL
o Prolog folosete rezoluia (liniar) pentru a demonstra dac concluzia
(teorema) este adevrat sau nu, pornind de la ipoteza stabilit de faptele i
regulile definite (axiome).
o Se aplic raionamentul napoi pentru a demonstra concluzia
o Programul este citit de sus n jos, de la dreapta la stnga, cutarea este n
adncime (depth-first) i se realizeaz folosind backtracking.

1
p q se transcrie n Prolog folosind clauza q :- p. ( q if p.)

p1 p 2 ... p n q se transcrie n Prolog folosind clauza q : - p1 , p 2 ,..., p n .


se transcrie n Prolog folosind ","
se transcrie n Prolog folosind ";" sau o clauz separat.

Exemple
Logic Prolog
x p ( x) q ( x) r ( x) r ( X ) : - p( X ), q( X ).
x w( x) s ( x) p ( x) p( X ) : -w( X ).
p ( X ) : -s ( X ).
x t ( x) s( x) q( x) s ( X ) : -t ( X ).
q ( X ) : -t ( X ).
t (a ) t (a ).
w(b) w(b) .

Concluzie r (a )

Logic Prolog
x s ( x) p ( x) q ( x) ????

2. Elemente de baz ale limbajului SWI-Prolog

1. Termen
SIMPLU
a. constant
simbol (symbol)
o secven de litere, cifre, _
o ncepe cu liter mic
numr =ntreg, real (number)
ir de caractere (string): text (caracter: c, \t,...)

ATOM = SIMBOL + STRING +IR-DE-CARACTERE-SPECIALE (<--->,===>) + []

b. variabil
secven de litere, cifre, _
ncepe cu liter mare
variabila anonim este reprezentat de caracterul underline (_).
COMPUS (a se vedea Seciunea 13).
o listele (list) sunt o clas special de termeni compui

2
2. Comentariu
% Acesta este un comentariu
/* Acesta este un comentariu */

3. Predicat

a). standard (ex: fail, number, ...)


b). utilizator

nume [(obiect[, obiect....)]

numele simbolic al relaiei

Tipuri

1. number (integer, real)


2. atom (symbol, string, ir-de-caractere-speciale)
3. list (secven de elemente) specificat ca list=tip_de_baz*

ex. list (omogen) format din numere ntregi [1,2,3]

% definire tip: el=integer list=el*

!!! lista vid [] este singura list care e considerat n Prolog atom.

Convenii.

n SWI-Prolog nu exist declaraii de predicate, nici declaraii de domenii


(definii de tipuri - ca n Turbo-Prolog).

Specificarea unui predicat

o % definire tipuri, dac e cazul


o % nume [(param1:tip1[,param2:tip2...)]
o % modelul de flux al predicatului (i, o, ...) - vezi Seciunea 4
o % param1 - semnificaia parametrului 1
o % param2 - semnificaia parametrului 2
.

4. Clauza
fapt
o relaie ntre obiecte
o nume_predicat [(obiect [, obiect....)]
regula
o permite deducere de fapte din alte fapte

Exemplu:
fie predicatele

3
tata(X, Y) reprezentnd relaia Y este tatl lui X
mama(X, Y) reprezentnd relaia Y este mama lui X

i urmtoarele fapte corespunztoare celor dou predicate:

mama(a,b).
mama(e,b).
tata(c,d).
tata(a,d).

Se cere: folosind definiiile anterioare s se defineasc predicatele

parinte(X, Y) reprezentnd relaia Y este printele lui X


frate(X, Y) reprezentnd relaia Y este fratele lui X

Clauze n Prolog
parinte(X,Y) :-tata(X,Y).
parinte(X,Y) :-mama(X,Y).
frate(X,Y) :-parinte(X,Z),parinte(Y,Z),X\=Y.

5. Intrebare (goal)

o e de forma predicat1 [(obiect [, obiect....)], predicat2 [(obiect [, obiect....)].... .

Folosind definiiile anterioare, formulm urmtoarele ntrebri:

?- parinte(a,b). ?- parinte(a,X).
true. X=d;
X=b.

? - parinte(a,f).
false.

?- frate(a,X). ?- frate(a,_).
X=c; true.
X=e.

3. Matching. Cum i primesc valori variabilele?


Prolog nu are instruciuni de atribuire. Variabilele n Prolog i primesc valorile prin potrivire
cu constante din fapte sau reguli.
Pn cnd o variabil primete o valoare, ea este liber (free); cnd variabila primete o
valoare, ea este legat (bound). Dar ea st legat atta timp ct este necesar pentru a obine o
soluie a problemei. Apoi, Prolog o dezleag, face backtracking i caut soluii alternative.

Observaie. Este important de reinut c nu se pot stoca informaii prin atribuire de valori unor
variabile. Variabilele sunt folosite ca parte a unui proces de potrivire, nu ca un tip de stocare de
informaii.

4
Ce este o potrivire?
Iat cteva reguli care vor explica termenul 'potrivire':

1. Structuri identice se potrivesc una cu alta


p(a, b) se potriveste cu p(a, b)
2. De obicei o potrivire implic variabile libere. Dac X e liber,
p(a, X) se potriveste cu p (a, b)
X este legat la b.
3. Dac X este legat, se comport ca o constant. Cu X legat la b,
p(a, X) se potriveste cu p(a,b)
p(a, X) NU se potriveste cu p(a, c)
4. Dou variabile libere se potrivesc una cu alta.
p(a, X) se potriveste cu p(a, Y)

Observaie. Mecanismul prin care Prolog ncearc s potriveasc partea din ntrebare pe care
doreste s o rezolve cu un anumit predicat se numeste unificare.

4. Modele de flux

n Prolog, legrile de variabile se fac n dou moduri: la intrarea n clauz sau la ieirea din
clauz. Direcia n care se leag o valoare se numete model de flux. Cnd o variabil este dat
la intrarea ntr-o clauz, aceasta este un parametru de intrare (i), iar cnd o variabil este dat la
ieirea dintr-o clauz, aceasta este un parametru de ieire (o). O anumit clauz poate s aib mai
multe modele de flux. De exemplu clauza

factorial (N, F)

poate avea urmtoarele modele de flux:


(i,i) - verific dac N! = F;
(i,o) - atribuie F := N!;
(o,i) - gsete acel N pentru care N! = F.

Observaie. Proprietatea unui predicat de a funciona cu mai multe modele de flux depinde de
abilitatea programatorului de a programa predicatul n mod corespunztor.

5. Sintaxa regulilor

Regulile sunt folosite n Prolog cnd un fapt depinde de succesul (veridicitatea) altor fapte sau
succesiuni de fapte. O regul Prolog are trei prti: capul, corpul i simbolul if (:-) care le separ
pe primele dou.

Iat sintaxa generic a unei reguli Turbo Prolog:

capul regulii :-

5
subgoal,
subgoal,
...,
subgoal.

Fiecare subgoal este un apel la un alt predicat Prolog. Cnd programul face acest apel, Prolog
testeaz predicatul apelat s vad dac poate fi adevarat. Odat ce subgoal-ul curent a fost
satisfcut (a fost gsit adevrat), se revine i procesul continu cu urmtorul subgoal. Dac
procesul a ajuns cu succes la punct, regula a reuit. Pentru a utiliza cu succes o regul, Prolog
trebuie s satisfac toate subgoal-urile ei, crend o mulime consistent de legri de variabile.
Dac un subgoal eueaz (este gsit fals), procesul revine la subgoal-ul anterior i caut alte
legri de variabile, i apoi continu. Acest mecanism se numete backtracking.

6. Operatori de egalitate

X=Y verific dac X i Y pot fi unificate

Dac X este variabil liber i Y legat, sau Y este variabil liber i X e


legat, propoziia este satisfcut unificnd pe X cu Y.
Dac X i Y sunt variabile legate, atunci propoziia este satisfcut dac
relaia de egalitate are loc.

?- [a,b]=[a,b]. ?- [X,Y]=[a,b]. ?- [a,b]= [X,Y].


true X = a, X = a,
Y = b. Y = b.

X\=Y verific dac X i Y nu pot fi unificate


\+ X=Y
?- [X,Y,Z]\ =[a,b]. ?- [X,Y]\=[a,b]. ?- [a,b]\= [X,Y].
true false false

?- \+ a=a. ?- \+ [X,Y]=[a,b]. ?- \+ [a,b]= [X,Y,Z].


false false true

X ==Y verific dac X i Y sunt legate la aceeai valoare.

?- [2,3]==[2,3]. ?- a==a. ?- R==1.


true true false

X \== Y verific dac X i Y nu au fost legate la aceeai valoare.

?- [2,3]\==[3,2]. ?- a\==a. ?- R\==1.


true false true

6
7. Operatori aritmetici

!!! Important
2+4 e doar o structur, utilizarea sa nu efectueaz adunarea
Utilizarea 2+4 nu e aceeai ca utilizarea lui 6.

Operatori aritmetici

=, \=, ==, \== A se vedea seciunea 6.

?- 2+4=6. ?- 2+4\=6. ?- 6==6. ?-6\=7. ?- 6==2+4.


false true true true false

?- 2+4=2+4. ?- 2+4=4+2. ?- X= 2+4-1.


true false X=2+4-1.

=:= testeaz egalitatea aritmetic


foreaz evaluarea aritmetic a ambelor pri
operanzii trebuie s fie numerici
variabilele sunt LEGATE

=\= testeaz operatorul aritmetic "diferit"

?- 2+4=:=6. ?- 2+4=\=7. ?- 6=:=6.


true true true

is partea dreapt este LEGAT i numeric


partea stng trebuie s fie o variabil
dac variabila este legat, verific egalitatea numeric (ca i =:=)
dac variabila nu este legat, evalueaz partea dreapt i apoi variabila este
legat de rezulatul evalurii

?- X is 2+4-1. ?- X is 5.
X=5 X=5

Inegaliti

< mai mic


=< mai mic sau egal
> mai mare
>= mai mare sau egal

evalueaz ambele pri


variabile LEGATE

?- 2+4=<5+2. ?- 2+4=\=7. ?- 6=:=6.

7
true true true

Cteva funcii aritmetice predefinite SWI-Prolog

X mod Y ntoarce restul mpririi lui X la Y


mod(X, Y)

X div Y ntoarce ctul mpririi lui X la Y


div(X, Y)

abs(X) ntoarce valoarea absolut a lui X


sqrt(X) ntoarce rdcina ptrat a lui X
round(X) ntoarce valoarea lui X rotunjit spre cel mai apropiat ntreg (round(2.56)
este 3, round (2.4) este 2)
...

8. Predicate predefinite

var(X) = adevrat dac X e liber, fals dac e legat


number(X) = adevrat dac X e legat la un numr
integer(X) = adevrat dac X e legat la un numr ntreg
float(X) = adevrat dac X e legat la un numr real
atom(X) = adevrat dac X e legat la un atom
atomic(X) = atom(X) or number(X)
....

9. Predicatul findall (determinarea tuturor soluiilor)

Prolog ofer o modalitate de a gsi toate soluiile unui predicat n acelai timp: predicatul
findall, care colecteaz ntr-o list toate soluiile gsite.

findall (arg1, arg2, arg3)

Acesta are urmtoarele argumente:


primul argument specific argumentul din predicatul considerat care trebuie
colectat n list;
al doilea argument specific predicatul de rezolvat;
al treilea argument specific lista n care se vor colecta soluiile.

10. Negaie - not, \+

not(subgoal(Arg1, ..., ArgN)) adevrat dac subgoal eueaz( nu se poate


demonstra c este adevrat)
\+ subgoal(Arg1, ..., ArgN)

8
?- \+ (2 = 4). ?- not(2 = 4).
true. true.

11. Predicatul ! (cut) tietura

Turbo Prolog conine predicatul cut (!) folosit pentru a preveni backtracking-ul. Cnd se
proceseaz predicatul !, apelul reuete imediat i se trece la subgoalul urmtor. O dat ce s-a
trecut peste o tietur, nu este posibil revenirea la subgoal-urile plasate naintea ei i nu este
posibil backtracking-ul la alte reguli ce definesc predicatul n execuie.

Exist dou utilizri importante ale tieturii:

1. Cnd tim dinainte c anumite posibiliti nu vor duce la soluii, este o pierdere de timp s
lsm sistemul s lucreze. n acest caz, tietura se numete tietur verde.
2. Cnd logica programului cere o tietur, pentru prevenirea lurii n consideraie a subgoal-
urilor alternative, pentru a evita obinerea de soluii eronate. n acest caz, tietura se numete
tietur roie.

Prevenirea backtracking-ului la un subgoal anterior

n acest caz tietura se utilizeaz astfel: r1 :- a, b, !, c.

Aceasta este o modalitate de a spune c suntem multumii cu primele soluii descoperite


cu subgoal-urile a i b. Dei Prolog ar putea gsi mai multe soluii prin apelul la c, nu este
autorizat s revin la a i b. De-asemenea, nu este autorizat s revina la alt clauz care definete
predicatul r1.

Prevenirea backtracking-ului la urmtoarea clauz

Tietura poate fi utilizat pentru a-i spune sistemului Prolog c a ales corect clauza
pentru un predicat particular. De exemplu, fie codul urmtor:
r(1) :- !, a, b, c.
r(2) :- !, d.
r(3) :- !, e.
r(_) :- write("Aici intr resul apelurilor").

Folosirea tieturii face predicatul r determinist. Aici, Prolog apeleaz predicatul r cu un


argument ntreg. S presupunem c apelul este r(1). Turbo Prolog caut o potrivire a apelului. O
gsete la prima clauz. Faptul c imediat dup intrarea n clauz urmeaz o tietur, mpiedic
Prolog s mai caute i alte potriviri ale apelului r(1) cu alte clauze.

Observaie. Acest tip de structur este echivalent cu o instruciune de tip case unde condiia de
test a fost inclus n capul clauzei. La fel de bine s-ar fi putut spune i

r(X) :- X = 1, !, a, b, c.
r(X) :- X = 2, !, d.
r(X) :- X = 3, !, e.
r(_) :- write("Aici intra restul apelurilor").

9
Not. Deci, urmtoarele secvene sunt echivalente:

case X of
v1: corp1; predicat(X) :- X = v1, !, corp1.
v2: corp2; predicat(X) :- X = v2, !, corp2.
... ...
else corp_else. predicat(X) :- corp_else.

De asemenea, urmtoarele secvene sunt echivalente:

if cond1 then predicat(...) :-


corp1 cond1, !, corp1.
else if cond2 then predicat(...) :-
corp2 cond2, !, corp2.
... ...
else predicat(...) :-
corp_else. corp_else.

12. Predicatul fail

Valoarea lui fail este eec. Prin aceasta el ncurajeaz backtracking-ul. Efectul lui este
acelai cu al unui predicat imposibil, de genul 2 = 3. Fie urmtorul exemplu:

predicat(a, b).
predicat(c, d).
predicat(e, f).
toate :-
predicat(X, Y),
write(X),write(Y),nl,
fail.
toate1 :-
predicat(X, Y),
write(X),write(Y),nl.

Predicatele toate i toate1 sunt fr parametri, i ca atare sistemul va trebui s rspund


dac exist X i Y astfel nct aceste predicate s aib loc.

?- toate. ?-toate1.
ab ab
cd true ;
ef cd
false. true ;
ef
true.

10
?-predicat(X,Y).
X = a,
Y=b;
X = c,
Y=d;
X = e,
Y = f.

Faptul c apelul predicatului toate se termin cu fail (care eueaz ntotdeauna) oblig
Prolog s nceap backtracking prin corpul regulii toate. Prolog va reveni pn la ultimul apel
care poate oferi mai multe soluii. Predicatul write nu poate da alte soluii, deci revine la apelul
lui predicat.

Observaii.
Acel false de la sfritul soluiilor semnific faptul c predicatul toate nu a fost
satisfcut.
Dupa fail nu are rost s punei nici un predicat, deoarece Prolog nu va ajunge s-l
execute niciodat.

Not. Secvenele urmtoare sunt echivalente:

ct timp condiie execut predicat :-


corp condiie,
corp,
fail.

13. Obiecte simple i obiecte compuse


Obiecte simple
Un obiect simplu este fie o variabil, fie o constant. O constant este fie un caracter, fie
un numr, fie un atom (simbol sau string).
Variabilele Prolog sunt locale, nu globale. Adic, dac dou clauze conin fiecare cte o
variabil numit X, cele dou variabile sunt distincte i, de obicei, nu au efect una asupra
celeilalte.

Obiecte compuse si functori

Obiectele compuse ne permit s tratm mai multe informaii ca pe un singur element,


ntr-un astfel de mod nct s-l putem utiliza i pe buci. Fie, de exemplu, data de 2 februarie
1998. Const din trei informaii, ziua, luna i anul, dar e util s o tratm ca un singur obiect cu o
structur arborescent:
DATA
/ | \
2 februarie 1998

Acest lucru se poate face scriind obiectul compus astfel:

11
data(2, februarie, 1998)

Aceasta seamn cu un fapt Prolog, dar nu este dect un obiect (o dat) pe care l putem
manevra la fel ca pe un simbol sau numr. Din punct de vedere sintactic, ncepe cu un nume (sau
functor, n acest caz cuvntul data) urmat de trei argumente.

Not. Functorul n Prolog nu este acelai lucru cu funcia din alte limbaje de programare. Este
doar un nume care identific un tip de date compuse i care ine argumentele laolalt.

Argumentele unei date compuse pot fi chiar ele compuse. Iat un exemplu:
natere(persoana(Ioan, Popescu), data(2, februarie, 1918))

Unificarea obiectelor compuse

Un obiect compus se poate unifica fie cu o variabila simpl, fie cu un obiect compus care
se potrivete cu el. De exemplu,

data(2, februarie, 1998)

se potrivete cu variabila liber X i are ca rezultat legarea lui X de data(...). De asemenea,


obiectul compus de mai sus se potrivete i cu

data(Zi, Lu, An)

i are ca rezultat legarea variabilei Zi de valoarea 2, a variabilei Lu de valoarea februarie i a


variabilei An de valoarea 1998.

Observaii
Convenim s folosim urmtoarea declaraie pentru specificarea unui domeniu cu
alternative
% domeniu = alternativa1(dom, dom, ..., dom);
% alternativa2(dom, dom, ..., dom);
% ...
Functorii pot fi folosii pentru controla argumentele care pot avea tipuri multiple
% element = i(integer); r(real); s(string)

14. Optimizarea prin recursivitate de coad (tail recursion)

Recursivitatea are o mare problem: consum mult memorie. Dac o procedur se


repet de 100 ori, 100 de stadii diferite ale execuiei procedurii (cadre de stiv) sunt memorate.

Totui, exist un caz special cnd o procedur se apeleaz pe ea far s genereze cadru
de stiv. Dac procedura apelatoare apeleaz o procedur ca ultim pas al sau (dup acest apel
urmeaz punctul). Cnd procedura apelat se termin, procedura apelatoare nu mai are altceva
de fcut. Aceasta nseamn c procedura apelatoare nu are sens s-i memoreze stadiul
execuiei, deoarece nu mai are nevoie de acesta.

12
Funcionarea recursivitii de coad

Iat dou reguli depre cum s facei o recursivitate de coad:

1. Apelul recursiv este ultimul subgoal din clauza respectiv.


2. Nu exist puncte de backtracking mai sus n acea clauz (adic, subgoal-urile de mai sus
sunt deterministe).

Iat un exemplu:

tip(N) :-
write(N),
nl,
Nou is N + 1,
tip(Nou).

Aceast procedur folosete recursivitatea de coad. Nu consum memorie, i nu se


oprete niciodat. Eventual, din cauza rotunjirilor, de la un moment va da rezultate incorecte, dar
nu se va opri.

Exemple greite de recursivitate de coad

Iat cateva reguli despre cum s NU facei o recursivitate de coad:

1. Dac apelul recursiv nu este ultimul pas, procedura nu folosete recursivitatea de coad.

Exemplu:

tip (N) :-
write(N),
nl,
Nou is N + 1,
tip (Nou),
nl.

2. Un alt mod de a pierde recursivitatea de coad este de a lsa o alternativ nencercat la


momentul apelului recursiv.

Exemplu:

tip(N) :-
write(N),
nl,
Nou is N + 1,
tip(Nou).
tip(N) :-
N < 0,
write(N este negativ.).

13
Aici, prima clauz se apeleaz nainte ca a doua s fie ncercat. Dup un anumit numr
de pai intr n criz de memorie.

3. Alternativa nencercat nu trebuie neaparat s fie o clauza separat a procedurii recursive.


Poate s fie o alternativ a unei clauze apelate din interiorul procedurii recursive.

Exemplu:
tip (N) :-
write(N),
nl,
Nou is N + 1,
verif(Nou),
tip(Nou).
verif(Z) :- Z >= 0.
verif(Z) :- Z < 0.

Dac N este pozitiv, prima clauz a predicatului verif a reuit, dar a doua nu a fost
ncercat. Deci, tip trebuie s-i pastreze o copie a cadrului de stiv.

Utilizarea tieturii pentru pstrarea recursivitii de coad

A doua i a treia situaie de mai sus pot fi nlturate dac se utilizeaz tietura, chiar dac
exist alternative nencercate.

Exemplu la situaia a doua:

tip (N) :-
N>= 0,
!,
write(N),
nl,
Nou = N + 1,
tip(Nou).
tip(N) :-
N < 0,
write("N este negativ.").
Exemplu la situaia a treia:

tip(N) :-
write(N),
nl,
Nou = N + 1,
verif(Nou),
!,
tip(Nou).
verif(Z) :- Z >= 0.
verif(Z) :- Z < 0.

14

S-ar putea să vă placă și