Sunteți pe pagina 1din 50

TUTORIAL

PROLOG

REALIZAT DE BALANOIU CARMEN-EMILIA


CUPRIN
Scurt
S Satisfacerea
istoric
Procurare clauzelor in
Prolog Prolog(Backtracking)
Introducere Sintaxa limbajului Prolog
Deosebiri intre Controlul procesului de
programarea Backtracking, Cut si Fail
logica si clasica Liste
Cum utilizam Prolog Recursivitate in Prolog
Structura unui Operati de intrare/iesire
program in
Prolog
Un exemlu de
program prolog
Reguli recursive
NEX
Scurt istoric

Cuvântul PROLOG provine de la PROgramming in LOGic.


Ca limbaj de programare a apărut în anul 1972 ca produs
al şcolii franceze de informatică (A. Colmerauer, P.
Roussel), fiind utilizat iniţial în domeniul procesării
limbajului natural.
Un eveniment care a influenţat favorabil evoluţia acestui
limbaj a fost conferinţa de la Tokyo din anul 1981, la care
japonezii au anunţat programul de realizare a noii
generaţii de calculatoare, adică a sistemelor de procesare
a cunoştinţelor.
PROLOG a fost ales de cercetătorii japonezi ca limbaj de
bază pentru calculatoarele din generaţia a cincea.
Actualmente, acest limbaj se bucură de o extindere din ce
în ce mai mare şi, în consecinţă, există mai multe dialecte
dezvoltate şi implementate atât pe min cât şi pe
microcalculatoare.

BACK Cuprins NEXT


Procurare
Prolog
Accesati site-ul www.swi-prolog.org

Click to edit Master text stylesClick to edit Master text styles


Second level Second level
● Third level ● Third level
● Fourth level ● Fourth level
● Fifth level ● Fifth level

1. 2.

BACK Cuprins NEXT


In functie de sistemul de operare folosit
alegeti versiunea de Swi-Prolog care vi se
Salvati fisierul dupa care il instalati.
potriveste.

Click to edit Master text styles Click to edit Master text styles
Second level Second level
● Third level ● Third level
● Fourth level ● Fourth level
● Fifth level ● Fifth level

3 4

BACK Cuprins NEXT


INTRODUCERE
Un program este alcătuit din două elemente, logica şi controlul
. Prin termenul
“logică” se desemnează toate noţiunile care stabilesc CE face
un program, în timp ce termenul “control“ semnifică toate
noţiunile sintactice care stabilesc CUM o face (de exemplu
algoritmul care rezolvă o problemă).
Un program scris în PASCAL sau vreun alt limbaj de
programare tradiţional constă din instrucţiuni care descriu
acţiunile ce trebuie executate pas cu pas de către
calculator pentru ca programul să producă rezultatul dorit.
Dimpotrivă un program în PROLOG este o bază de natură
logică, în care programatorul defineşte obiecte şi relaţii între
aceste obiecte(fie relaţii care există direct între obiecte, fie
regulile după care se pot deduce alte relaţii sauproprietăţi ale
acestora).
Obiectele sunt reprezentate în PROLOG prin nume simbolice.
Relaţiile existente între obiecte se definesc cu ajutorul
clauzelor. Există două feluri de clauze: fapte şi reguli.
Structura sintactică a unui fapt este următoarea:
nume(arg1, arg2, …, argn).
BACK Cuprins NEXT
unde:
� nume este un nume de predicat, adică o succesiune de
� arg1, arg2, …, argn se numesc argumentele predicatului,
iar din punct de vedere sintactic pot fi nume de obiecte sau
nume de variabilă (un nume de variabilă este o succesiune de
caractere astfel încât primul caracter este o literă mare din
alfabet).
O regulă este o construcţie sintactică de forma: cn+1 :- c1, c2,
…, cn.
unde:
� entităţile c1, c2,…, cn, cn+1 sunt de forma nume(arg1,
arg2, …, argk) , nume, arg1, arg2, …, argk având aceeaşi
semnificaţie ca în cazul unei fapte.
� cn+1 se numeşte capul reguli.
� c1, c2,…, cn formează corpul reguli.
Clauza codifică următorul enunţ:
“Dacă c1 şi c2 şi … cn sunt adevărate, atunci cn+1
este adevărată.”
Observăm că orice faptă şi orice regulă se încheie cu
caracterul “.”, iar “,” prezentă în corpul regulii suplineşte
operatorul “şi”. Dacă în loc de “,” utilizăm “;” atunci în locul
operatorului “şi” se consideră operatorul “sau”. Prin urmare
clauza a :- b; c. codifică enunţul “dacă b sau c, atunci a”.
BACK Cuprins NEXT
Deosebiri intre programarea logica
si clasica

În general, într-un limbaj de programare tradiţional, un


program exprimă o funcţie de la intrarea la ieşirea
programului, în timp ce un program într-un limbaj de
programare logică exprimă o relaţie între date. Întrucât
relaţiile sunt mai generale decât funcţiile, programarea
logică are posibilităţi mai mari decât are programarea
tradiţională.
Să luăm drept exemplu un program care citeşte două
numere reale şi îl afişează pe cel mai mare dintre ele.
Pentru a face diferenţa dintre programarea tradiţională
şi programarea logică mai explicită, vom da mai întâi
programul în PASCAL, iar apoi acelaşi program în
PROLOG:

BACK Cuprins NEXT


Program în PASCAL: Program în PROLOG:

var x,y: real; predicates


begin program
write(‘numar1 = ‘); mai_mare(real,real,real)
readln(x); clauses
write(‘numar2 = ‘); program :- write("n1="),
readln(y); readreal(X), write("n2="),
if (x < y) then writeln(x) readreal(Y),
else writeln(y); mai_mare(X,Y,Z),
end. write(Z), nl.
mai_mare(X,X,X).
mai_mare(X,Y,Y):-X<Y.
mai_mare(X,Y,X):-Y<X.
goal
program

BACK Cuprins NEXT


Secţiunea var (din programul PASCAL) şi secţiunea
predicates (din programul PROLOG) au un caracter
declarativ: în secţiunea var se declară variabilele reale x şi
y, iar în secţiunea predicates se declară predicatele
program (fără argumente) şi mai_mare (cu trei argumente
reale). Programul în PASCAL este doar un şir de
instrucţiuni. Aceste instrucţiuni, care sunt executate în
ordinea indicată de program, constituie “controlul”.
“Elementul logic” în programul din PASCAL se află în
relaţia “>”. Dimpotrivă, programul în PROLOG este o
colecţie de clauze care descriu complet relaţia de ordine
totală a două numere reale, în speţă predicatul
“mai_mare”. Această colecţie de clauze exprimă logica
programului, care are şi rolul dominant într-un program
PROLOG, în timp ce controlul se află în ordinea în care
aranjăm şi definim predicatele. De asemenea lansarea în
execuţie a unui program PROLOG, nu se face definind un
punct de început după care instrucţiunile să fie preluate
secvenţial, aşa cum se întâmplă în
limbajele tradiţionale de programare. Execuţia unui
program cere definirea unui scop (în secţiunea goal), care
trebuie verificat pe baza elementelor din program (în
BACKnostru scopul este
exemplul Cuprins NEXT
dat de predicatul program).
O altă diferenţă între programarea logică şi cea clasică constă în
semnificaţia variabilelor.
Programarea în PROLOG nu utilizează conceptul de atribuire.
Actualizarea variabilelor prin obiecte PROLOG date se realizează
prin unificare. În general, cu unificarea se analizează dacă două
predicate pot fi identice. Dacă ele nu pot fi identice, procedura de
unificare eşuează. Dacă ele pot fi identice, unificarea reuşeşte, iar
rezultatul unificării este actualizarea variabilelor celor două predicate
cu anumite de valori astfel încât cele două predicate să coincidă
(“match”). Pentru
actualizare se foloseşte adesea termenul legare (“binding”) sau
instanţire. O variabilă prezentă într-o clauză are efect local clauzei
respective. Variabilei i se leagă o valoare, iar ieşirea din clauză
determină dezlegarea ei de valoare. Există o variabilă care joacă un
rol special în PROLOG: ea se numeşte variabilă anonimă şi se
reprezintă prin “_”. Prezenţa variabilei anonime pe locul unui
argument precizează că nu interesează valoarea legată de argument
ci numai existenţa unei asemenea valori.

BACK Cuprins NEXT


CUM UTILIZAM PROLOG
Pentru a putea utiliza Prolog trebuie mai Dupa ce am terminat cu fisierul
intai sa deschidem un fisier text(ex. text,intram in meniul “file” al
notepad) in care vom scrie baza de date, si Prologului,unde accesam optiunea
pe care il vom salva cu extensia “pl”(ex. “consult”.Alegem fisierul creat mai
proiect.pl). devreme si suntem gata sa interogam.

Click to edit Master text styles Click to edit Master text styles
Second level Second level
● Third level ● Third level

● Fourth level ● Fourth level

● Fifth level ● Fifth level

BACK Cuprins NEXT


Structura unui program
in prolog
Un program în PROLOG este o descriere a unor obiecte şi relaţii existente între aceste
obiecte. Obiectele sunt reprezentate prin nume simbolice a căror structură sintactică este
determinată de tipul obiectelor. Există două clase de tipuri, tipul elementar şi tipul complex.
Tipul elementar poate fi standard sau definit de utilizator. Tipurile definite de utilizator sunt
de fapt tot tipuri standard, dar definite prin nume date de utilizator, nume ce sugerează
semnificaţia obiectelor de tipul respectiv. Tipul complex la rândul lui se subîmparte în: tipul
compus şi tipul listă. Un nume de tip compus are următoarea structură sintactică: nume
simbolic urmat de unul sau mai multe tipuri separate prin virgulă şi închise între paranteze
rotunde. Un obiect de tip listă este un şir de obiecte de acelaşi tip, separate prin virgulă şi
închise între paranteze drepte. Elementele unei liste pot fi de tip elementar sau de tip
compus.
Din punct de vedere sintactic un program în PROLOG se compune din unul sau mai
multe module. Unul dintre module este definit ca modul principal. Numai acest modul poate
să conţină enunţul unui scop (goal). În general obiectele şi predicatele cu care se lucrează
sunt locale fiecărui modul. Dacă un nume de predicat sau tip de obiecte este utilizat în două
module, el reprezintă predicate diferite, respectiv tipuri diferite.

BACK Cuprins NEXT


Există însă şi posibilitatea de defini a predicate sau tipuri globale (comune
mai multor module). Un modul este alcătuit din mai multe secţiuni.
Enumerăm mai jos aceste secţiuni, precizând şi descrierea sintactică a
elementelor ce compun fiecare secţiune în parte. Utilizăm convenţia de
scriere potrivit căreia elementele opţionale sunt încadrate între paranteze
drepte.
constants
const1 = definiţie
const2 = definiţie
…………………..........
În această secţiune se definesc constantele utilizate în program.
domains
tip_util1 [tip_util2, tip_util3, … ] = tip1; tip2;…
lista1 = tip_element*
…………………………...............................................
tip_util1, tip_util2, tip_util3, … , lista1 reprezintă nume simbolice care
desemnează tipuri de obiecte definite de programator. tip1; tip2;…
reprezintă o listă de tipuri standard sau de tipuri definite de utilizator.
Obiectele de tip lista1 sunt liste ale căror elemente sunt de tip
tip_element.
global domains
În această secţiune programatorul defineşte tipurile globale. Structura
acestei secţiuni este aceeaşi cu cea a secţiunii domains.
BACK Cuprins NEXT
database [-nume]
global database [-nume]
În aceste secţiuni se definesc baze de cunoştinţe dinamice.
predicates
predicat1(tip_arg1, tip_arg2, …., tip_argn)
predicat2(tip_arg1, tip_arg2, …., tip_argk)
………………………………………………………...........
Se definesc predicatele local modului. Pentru fiecare predicat se specifică numele şi tipul
argumentelor sale.
global predicates
predicat1(tip_arg1, tip_arg2, …., tip_argn) – (i, o, …) [language C | pascal |…]
predicat2(tip_arg1, tip_arg2, …., tip_argk)
…………………………………………...................................................................................
În această secţiune se precizează predicatele globale şi tipul argumentelor lor, precum şi
faptul că anumite argumente sunt de intrare şi altele de ieşire, şi eventual, limbajul în care
este scrisă procedura ce corespunde predicatului.
clauses
predicat(arg1, arg2, …, argn).
predicatk+1(…) : - predicat1(…), predicat2(…), …., predicatk(…).
………………………………………………………………………………………………

BACK Cuprins NEXT


Această secţiune este destinată definirii clauzelor.. Toate clauzele care se
referă la acelaşi nume de predicat trebuie grupate.
goal
predicat1(…) [, predicat2(…), …., predicatk(…)]
Scopul (“goal”) unui program PROLOG reprezintă o interogare privind
faptele şi regulile definite în secţiunea clauses. Interogarea se poate realiza
în două moduri: în secţiunea goal a programului sau în fereastra dialog.
Oricare formă din acestea o exclude pe cealaltă. Structura sintactică a unei
interogări este aceeaşi cu structura sintactică a corpului unei reguli.
• Nu toate secţiunile sunt obligatorii.
• Ordinea în care aceste trebuie să apară este următoarea: directive de
compilare, domains, global domains, databas, predicates, global predicates,
clauses.
• Aşezând directiva trace în faţa secţiunii domains, se poate controla pas cu
pas execuţia unui scop.
• Secţiunea goal, dacă apare, se aşează fie înainte fie după secţiunea
clauses.
• Comentariile pot fi incluse oriunde în program. Un comentariu este un text
care începe cu /* şi se termină cu */.
• Scrierea unui program în PROLOG este liberă (se pot scrie mai multe
clauze pe un rând, sau o regulă pe mai multe rânduri, etc.). Sintaxa cere ca
fiecare clauză să se încheie cu punct.
• În cazul în care se utilizează definiţii globale, este de preferat ca acestea
să se BACK Cuprins NEXT
definească într-un fişier separat, care apoi să fie inclus în fiecare modul cu
- Programele Prolog opereaza cu obiecte si cu relatii intre obiecte (fapte si/sau clauze).
- Negatia joaca un rol foarte important in programarea in acest limbaj, deoarece orice proprietate care
nu se poate deduce din entitatile programului este considerata falsa, deci negatia ei este adevarata.
-Prolog foloseste un model de rationament minimal numit ipoteza lumii inchise. Conform acestui

model, tot ceea ce nu este stiut de program, deci afirmat explicit ca fiind adevarat in program, este
considerat fals.
-- Prologul modeleaza negatia ca esec al satisfacerii unui scop (negatia ca insucces), aceasta fiind de

fapt o particularizare a ipotezei lumii inchise.


• O clauza Prolog sau regula este de forma:

H :- B1, B2, … , Bn.


unde: H este capul regulii, iar membrul drept constituie corpul regulii (care este o conjunctie sau o
disjunctie de scopuri).
• Sensul clauzei Prolog anterioare este:

If B1 & B2 & … & Bn then H


• In Prolog constantele se scriu cu litera mica, iar variabilele cu litera mare.

• Simbol…………………………..Sens

:- daca
, conjunctie
; disjunctie
_ variabila universala
(semnifica orice)
• O fapta Prolog este o clauza fara corp, adica de forma H. Ea reprezinta o clauza care este tot timpul

adevarata, deoarece nu este conditionata.

BACK Cuprins NEXT


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.

Obtinerea solutiilor atunci cand baza de cunostinte Prolog contine si reguli:

In acest caz, unificarea scopului se incearca atat cu fapte din baza de


cunostinte,
cat si cu antetul regulilor din baza.
La unificarea unui scop cu antetul unei reguli, pentru a putea satisface acest
scop trebuie satisfacuta regula. Aceasta revine la a satisface toate faptele
din corpul regulii, 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
BACK initial.
Cuprins NEXT
Comportarea sistemului Prolog in care se incearca in mod repetat
Un exemplu de program in
Prolog
(Definirea unor relatii de familie)

Faptul ca Tom este parinte al lui Bob se poate scrie astfel in Prolog:
-

-parinte(tom,bob).

Aici parinte este numele reletiei iar tom si bob reprezinta argumentele sale

Program Prolog care defineste relatii de familie

parinte(pam,bob).
parinte(tom,bob).
parinte(tom,liz).
parinte(bob,ann).
parinte(bob,pat).
parinte(pat,jim).

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) reguli (ci doar fapte).

BACK Cuprins NEXT


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

Alte exemple de interogari:

?-parinte(liz,pat). •Cine este parinte al cui?


no ?-parinte(X,Y).
?-parinte(tom,ben). X=pam
no Y=bob
• Cine eate parintele lui Liz?
?-parinte(X,liz). X=tom
X=tom Y=bob
•Cine sunt copii lui Bob?
parinte(bob.X). X=tom
X=ann Y=liz
X=pat ................
no

BACK Cuprins NEXT


• Cine este bunic al lui Jim?
(1) Cine este parinte al lui Jim? Presupunem ca aceste este un Y.
(2) Cine este parinte al lui Y? Presupunem ca acesta este un X.

(1) si (2) necesita urmatoarea interogare compusa:


?-parinte(Y,jim),parinte(X,Y).
Raspunsul prologului este:
X=bob
Y=pat
Obs: Interogarea
?-parinte(X,Y),parinte(Y,jim).
va produce acelas rezultat.
•Cine sunt nepotii lui Tom?
?-parinte(tom,X),parinte(X,Y).
X=bob
Y=ann

X=bob
Y=pat

BACK Cuprins NEXT


• Ann si Pat au un parinte comun?
?-parinte(X,ann).parinte(X,pat).
X=bob

Extinderea programului cu reguli:

• Introducem, mai intai, urmatoarele fapte noi:


feminin(pam).
masculin(tom).
masculin(bob).
feminin(liz).
feminin(pat).
feminin(ann).
masculin(jim).
si
sex(pam, feminin).
sex(tom, masculin).
sex(bob, masculin).
…..........................
si
urmas(liz, tom).
…..........................

BACK Cuprins NEXT


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
- 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).

BACK Cuprins NEXT


- Aceasta inseamna ca partea de concluzie este, de asemenea, adevarata, iar Prolog
va raspunde la intrebare cu yes.
• Introducem acum relatii de familie suplimentare:

Ø relatia mama, definita astfel:

mama (X, Y) :- parinte (X,Y), feminin (X).


Ø relatia bunic, definita astfel:

bunic (X, Z) :- parinte (X, Y), parinte(Y, Z).


Ø relatia sora, definita astfel:

sora (X, Y) :-
parinte (Z, X),
parinte (Z, Y),
feminin (X).
• Interogarea Prologului:

Ø daca ann si pat sunt surori

?- sora (ann, pat).


yes
Ø cine este sora lui Pat

?- sora (X, pat).


X = ann;
X = pat

BACK Cuprins NEXT


Obs.: Relatia sora ar trebui sa fie definita dupa cum urmeaza
sora (X, Y) :-
parinte (Z, X),
parinte (Z, Y),
feminin (X),
diferit (X, Y).
unde predicatul diferit (X,Y) trebuie definit astfel incat el sa fie satisfacut daca si numai
daca X e diferit de Y.
Reguli recursive
Ø relatia predecesor: un predecesor poate fi direct (parinte)

predecesor (X, Z) :- parinte (X, Z).


sau indirect
predecesor (X, Z) :-
parinte (X, Y),
parinte (Y, Z).
predecesor (X, Z):-
parinte (X, Y1),
parinte (Y1, Y2),
parinte(Y2, Z).

BACK Cuprins NEXT


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.
Clauza Prolog corespunzatoare (recursiva) este:
Predecesor (X,Z) :-
parinte (X,Y),
predecesor (Y,Z).
Definirea relatiei predecesor:
- consta din doua reguli, una care se refera la predecesori directi si cealalta la predecesori
indirecti. Definitia completa este urmatoarea:
predecesor (X, Z) :-
parinte (X,Z).
predecesor (X, Z) :-
parinte (X, Y),
predecesor (Y, Z).
Exemplu de interogare a Prologului (care sunt succesorii lui Pam):
?- predecesor (pam, X).
X = bob; X=pat
X = ann; X=jim

BACK Cuprins NEXT


Satisfacerea
clauzelor in Prolog
(Backtracking)
Presupunem ca programul nu contine reguli, ci numai fapte
Ø

Ø Presupunem ca avem un program ce contine si reguli

1. Programul nu contine reguli, ci numai fapte:


Daca scopul are forma p1, p2, … , pn, se incearca satisfacerea lui de la stanga la
dreapta. Atunci cand acesta nu contine variabile, daca baza de fapte satisface intreg
scopul, Prolog raspunde cu YES, altfel cu NO. Daca scopul contine variabile, atunci
obiectivul este acela de a gasi toate legaturile posibile pentru variabile, care sa
satisfaca scopul (deci de a da toate solutiile). Mai precis, se parcurge baza de fapte si
se satisface o data p1. Se trece apoi la satisfacerea lui p2. Daca p2 este satisfacut,
atunci se trece la p3.
Daca p2 nu se satisface, atunci se dezleaga variabilele lui p1 si se inspecteaza baza
de fapte pentru a gasi alte valori care legate de variabilele lui p1 sa resatisfaca p1, apoi
se reincearca satisfacerea lui p2 cu noile legaturi. Blocarea acestui proces de
Backtracking se poate face cu predicatul ! (“cut”), asezat intre doua clauze consecutive
pi si pi+1 ale scopului. In acest caz, nu se incearca resatisfacerea lui pi.

BACK Cuprins NEXT


Daca programul contine si reguli:
Satisfacerea scopului se realizeaza in urmatorii pasi:
a) Presupunem: clauzele p1,…, pi au fost satisfacute.
b) In vederea satisfacerii lui pi+1 se inspecteaza mai intai baza de fapte. Daca pi+1 se
satisface cu o fapta, se trece la pi+2. Daca nu exista elemente in baza de fapte care sa
satisfaca pe pi+1, se inspecteaza baza de reguli si se identifica prima
dintre regulile neluate in consideratie pana in prezent, al carei cap se poate unifica cu pi+1 : se
intra in corpul regulii identificate, considerand clauzele care il compun drept componente ale
scopului. Daca una din clauzele corpului nu poate fi satisfacuta, se identifica o alta regula al
carei cap sa se unifice cu pi+1. In cazul in care nu exista o asemenea regula, se incearca
resatisfacerea
clauzelor pi, pi-1, …
Unificare: Satisfacerea unui scop de tipul X = Y se face prin incercarea de a unifica X cu Y.
Din aceasta cauza, dandu-se un scop de tipul X = Y, regulile de decizie care indica daca
scopul se indeplineste sau nu sunt:
1. Daca X este variabila neinstantiata, iar Y este instantiata la orice obiect Prolog, atunci scopul
reuseste. Ca efect lateral, X se va instantia la aceeasi valoare cu cea a lui Y.
2. Daca atat X cat si Y sunt variabile neinstantiate, scopul X = Y reuseste, variabila X este
legata la Y si reciproc, i.e.: ori de cate ori una dintre cele doua variabile se instantiaza la o
anumita valoare, cealalta variabila se va instantia la aceeasi valoare.
3. Atomii si numerele sunt intotdeauna egali cu ei insisi.
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.

BACK Cuprins NEXT


Sintaxa limbajului
Prolog
Constantele definesc:

Ø Obiecte particulare

Ø Relatii particulare

v 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‟).
Numerele: majoritatea implementarilor admit o gama de valori cuprinse intre
– 16383si +16383, dar gama poate fi si mai larga.
• 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). Cuprins
BACK NEXT
• Structurile sunt obiecte ce desemneaza o colectie de obiecte corelate logic,
care formeaza componentele structurii.
Ex: poseda(mihai, carte(prolog, clocksin, 1981))
Ø Sunt folosite la reprezentarea structurilor de date (liste, arbori)

ØO structura se defineste prin specificarea:

• numelui structurii (functorul structurii);

•elementelor sau componentelor structurii.

ØDesi alcatuite din mai multe componente, sunt tratate de program ca obiecte

unice. Pentru combinarea componentelor intr-un unic obiect, este folosit un


functor. Acesta va fi radacina arborelui intr-o reprezentare arborescenta.
• 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).

BACK Cuprins NEXT


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.
Operatori relationali – continuare:
- Operatorul de inegalitate =\= se defineste ca un predicat opus celui de egalitate;
scopul X=\=Y reuseste daca scopul X=Y nu este satisfacut si esueaza daca X=Y
reuseste (semnificatie: valorile lui X si Y nu sunt egale).
- Predicatul == testeaza echivalenta a doua variabile; X==Y reuseste ori de cate ori
X=Y reuseste, dar reciproca este falsa. Este vorba de egalitatea literala a doi
termeni.
- 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 \==

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. ?-1+2=2+1
yes no
BACK
- Inegalitatea a doua expresii aritmetice Cuprins
se stabileste cu operatorul NEXT
=\=
Valorile expresiilor aritmetice pot fi comparate prin intermediul operatorilor
careurmeaza. Acesti operatori forteaza evaluarea argumentelor lor.
X > Y (X este mai mare ca Y)
X < Y (X este mai mic ca Y)
X >= Y (X mai mare sau egal decat Y)
X <= Y (X mai mic sau egal cu Y)
X =:= Y (valorile lui X si Y sunt egale)
X =\= Y (valorile lui X si Y nu sunt egale)
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.


-- Exista proceduri incorporate asociate operatorilor predefiniti +, -, *, /, div si mod.

- In momentul in care se efectueaza evaluarea, toate argumentele trebuie sa fie


deja
instantiate la anumite numere.
-Valorile expresiilor aritmetice pot fi comparate prin intermediul unor operatori cum

ar fi <, =< etc. (vezi folia anterioara). Acesti operatori forteaza evaluarea
argumentelor lor.
•Operatorul infixat mod da restul unei impartiri intregi.

•Operatorul infixat div da catul unei impartiri intregi.

•Operatorul / poate sa desemneze impartire intreaga sau reala, in functie de

implementare. (De obicei se refera la impartirea reala, iar div la cea intreaga).
•Comentariile in Prolog sunt precedate de caracterul %

BACK Cuprins NEXT


ØOperatori definiti de utilizator
- Definirea de noi operatori de catre programator se face prin introducerea in
program a unor clauze de forma speciala, numite directive.
-Definirea de noi operatori se face cu ajutorul directivei op(precedenta_operator,

tip_operator, nume_operator). precedata de simbolul :-


Exemplu:
:- op (600, xfx, are).
caz in care este legala expresia
coco are pene
- 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)
se poate defini un nou operator are
:- op (600, xfx, are).
caz in care este legala expresia
coco are pene
- Operatorii sunt atomi, iar precedenta lor trebuie sa fie o valoare intreaga intr-un
anumit interval si corelata cu precedenta operatorilor predefiniti in limbaj.
- Tipul operatorilor fixeaza caracterul infixat, prefixat sau postfixat al operatorului si
precedenta operanzilor sai. Tipul operatorului se defineste utilizand una din
urmatoarele forme standard:

BACK Cuprins NEXT


(1) operatori infixati: xfx xfy yfx
(2) operatori prefixati: fx fy
(3) operatori postfixati: xf yf
unde f reprezinta operatorul, iar x si y operanzii sai.
- Utilizarea simbolului x sau a simbolului y depinde de precedenta
operandului fata de operator. Precedenta operanzilor se defineste astfel:
üun argument intre paranteze sau un argument nestructurat are

precedenta 0;
ü un argument de tip structura are precedenta egala cu cea a functorului

operator.
- Semnificatiile lui x si y in stabilirea tipului operatorului sunt urmatoarele:
ü x reprezinta un argument (operand) cu precedenta strict mai mica decat

cea a functorului (operatorului) f:


precedenta (x) < precedenta (f)
üy reprezinta un argument (operand) cu precedenta mai mica sau egala cu

cea a functorului (operatorului) f:


precedenta (y) <= precedenta (f)
- Numele operatorului poate fi orice atom Prolog care nu este deja definit
in Prolog. Se poate folosi si o lista de atomi, daca se definesc mai multi
operatori cu aceeasi precedenta si acelasi tip.

BACK Cuprins NEXT


Exemplu
:- op (100, xfx, [este, are]).
:- op (100, xf, zboara).
coco are pene.
coco zboara.
coco este papagal.
bozo este pinguin.

?- Cine are pene.


Cine = coco
?- Cine zboara.
Cine = coco
?- Cine este Ce.
Cine = coco, Ce = papagal;
Cine = bozo, Ce = pinguin;
no
In conditiile in care se adauga la baza de cunostinte anterioara si definitia
operatorilor daca, atunci si si
:- op (870, fx, daca). urmatoarea structura este valida in Prolog
:- op (880, xfx, atunci). daca Animalul are pene
:- op (880, xfy, si). si Animalul zboara
atunci Animalul este pasare.

BACK Cuprins NEXT


Controlul procesului de
Backtracking:
- Predicatul cut, notat cu atomul special ! este un predicat standard, fara
CUT intotdeauna
argumente, care se indeplineste (este adevarat) SI FAIL si nu poate fi
resatisfacut.
- Comportarea predicatului cut este urmatoarea:
(C1) H :- D1, D2, … , Dm, ! , Dm+1, … , Dn.
(C2) H :- A1, … , Ap.
(C3) H.
Ø 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 Dm+1, … , Dn, daca acestea au mai
multe solutii.
Obs: 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.BACK Cuprins este total diferitNEXT
La un cut rosu efectul programului daca se
schimba ordinea clauzelor).
Cut rosu
Introducerea unui cut rosu modifica corespondenta dintre semnificatia declarativa si
semnificatia procedurala a programelor Prolog. El permite exprimarea in Prolog a
unor
structuri de control de tipul
Daca conditie atunci actiune1
altfel actiune2
astfel:
daca_atunci_altfel (Cond, Act1, Act2) :- Cond, !, Act1.
daca_atunci_altfel (Cond, Act1, Act2) :- Act2.
Obs.: Utilizarea predicatului cut in definirea predicatului asociat structurii de control
daca_atunci_altfel introduce un cut rosu deoarece efectul programului este total
diferit daca se schimba ordinea clauzelor.
Ex. Definirea predicatului de aflare a minimului dintre doua numere, in doua
variante:
min1(X, Y, X) :- X=<Y,!. % cut verde
min1(X, Y, Y) :- X>Y.
min2(X, Y, X) :- X=<Y,!. % cut rosu
min2(X, Y, Y).
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, !.
rezultatul programului va fi incorect pentru
Cuprinsvalori X < Y.
BACK NEXT
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.

Exemplul 1 (folosirea predicatului fail pentru a determina esecul):


Enuntul “Un individ este rau daca nu este bun” se poate exprima astfel:
rau (X) :- bun (X),!,fail.
rau (X).
Exemplu de program – folosirea lui fail pentru a determina esecul:
bun (gelu).
bun (vlad).
bun (mihai).
rau (X) :- bun (X),!,fail. (*)
rau (X). (**)
Exemplu de executie a programului:
?- rau (gelu). ?-rau(petru).
no yes
?- rau (mihai).
no BACK Cuprins NEXT
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.
Exemplul 2 – introducerea predicatului fail pentru a genera procesul de
backtracking pe scopurile care il preced:
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 caBACK
raspunsul final la satisfacerea scopului sa fie afirmativ. (Aceasta clauza
Cuprins
raspunde yes la orice).
NEXT
LIST
O lista este de forma [Cap|Coada].
E
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
- se foloseste relatia conc(L1, L2, L3)
- definitia predicatului conc este:
conc([ ], L, L).
conc([X|L1], L2, [X|L3]) :- conc(L1, L2, L3).

BACK Cuprins NEXT


3. Adaugarea unui element
- elementul adaugat devine noul cap:
add(X, L, [X|L]).
4. Stergerea unui element
- se foloseste relatia del(X, L, L1)
- definitia predicatului del este:
del(X, [X|Coada], Coada).
del(X, [Y|Coada], [Y|Coada1]) :- del(X,Coada, Coada1).
Observatie: Inserarea unui element intr-o lista poate fi definita folosind
relatia del, astfel:
insert(X, Lista, ListaMaiMare):-
del (X, ListaMaiMare, Lista).
Subliste
relatia sublista([c,d,e], [a,b,c,d,e,f]) este adevarata, dar sublista([c,e],
[a,b,c,d,e,f]) nu este
adevarata.
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).
BACK Cuprins NEXT
Recursivitatea in
Prolog
Intuitiv recursivitatea se naşte în clipa în care o schiţă este construită prin
reproducerea ei însăşi, la o altă scară sau la un alt nivel. În cadrul programării
recursivitatea este o tehnică care constă în posibilitatea de a include într-o procedură
apeluri la ea însăşi. În PROLOG, acesta se traduce prin posibilitatea ca un nume de
predicat să apară atât în corpul unei reguli cât şi în capul ei. De exemplu, să
presupunem că vrem să definim relaţia “strămoş” în vederea examinării următoarei
părţi a unui arbore de familie: maria

ion

ana vasile

mihai rodica
Fiecare nod desemnează o persoană iar legătura directă între noduri reprezintă relaţia
“părinte”
(de exemplu ion este părintele anei şi al lui vasile). Soluţia nerecursivă impune
definirea de reguli pentru fiecare grad de descendenţă:
stramos(X, Y) : - parinte(X, Y).
stramos(X, Y) : - parinte(X, Z), parinte( Z, Y).
stramos(X, Y) : - parinte(X, Z1), parinte( Z1, Z2), parinte( Z1, Y).
BACK Cuprins NEXT
De fiecare dată când mergem mai adânc în arborele de familie, trebuie să definim o
nouă regulă.
acest lucru este fără îndoială ineficient din punct de vedere al programării, deoarece un
program este util şi eficient numai dacă rezolvă cazuri generale şi nu doar cazuri
particulare ale unei probleme. Există o cale mai eficientă de a defini relaţia “strămoş”.
Observăm că pentru orice X şi
Y din arborele de familie, X este strămoş pentru Y dacă există un Z astfel încât X este
părinte al
lui Z şi Z este strămoş al lui Y. Astfel, putem scrie următoarea clauză:
stramos(X, Y) : - parinte(X, Z), stramos( Z, Y).
În această definiţie predicatul “stramos” apare şi în corpul regulii şi în corpul ei.
Definiţiile de acest fel se numesc definiţii recursive, iar relaţii pe care le desemnează
se numesc relaţii
recursive. În exemplu nostru controlul relaţiei “stramos” dintre maria şi
mihai este ilustrat de
nivelurile diagramei următoare:
maria maria maria
strămoş
ion ion strămoş ion
nivel 0 strămoş
ana ana
nivel 1
mihai
nivel 2

BACK Cuprins NEXT


Regula introdusă nu ajunge pentru definirea relaţiei “strămoş”. Deşi sub
aspect logic exprimă ceea ce vrem să definim, ea nu dă următorului
programului informaţia necesară pentru răspunsul
la întrebări privind relaţia “strămoş”:
domains
persoana = symbol
predicates
parinte(persoana, persoana)
stramos(persoana, persoana)
clauses
parinte(maria, ion).
parinte(ion, ana).
parinte(ion, vasile).
parinte(ana, mihai).
parinte(ana, rodica).
stramos(X, Y) : - parinte(X, Z), stramos( Z, Y).
Să presupunem că se pune următoare întrebare:
?-stramos(maria, ana)

BACK Cuprins NEXT


PROLOG va încerca să răspundă căutând în spaţiul stărilor descris de arbore următor:
stramos(maria, ana)
X/maria, Y/ana
parinte(maria, Z), stramos(Z, ana)

parinte(maria, Z)
Z/ion
stramos(ion, ana)
X/ion, Y/ana
parinte(ion, Z), stramos(Z, ana)

parinte(ion, Z)
Z/ana Z/vasile
stramos(ana, ana) stramos(vasile, ana)
X/ana, Y/ana X/ana, Y/ana
parinte(ana, Z), stramos(Z, ana) parinte(vasile, Z), stramos(Z, ana)

parinte(ana, Z) parinte(vasile, _)
Z/mihai Z/rodica no
stramos(mihai, ana) stramos(rodica, ana)
X/ana, Y/ana X/ana, Y/ana
parinte(mihai, Z), stramos(Z, ana) parinte(rodica, Z), stramos(Z, ana)

parinte(mihai,_) parinte(rodica,_)

no no

BACK Cuprins NEXT


PROLOG nu reuşeşte să termine corect căutarea în spaţiul stărilor problemei, deoarece
recurenţa
nu are o condiţie de oprire. Oprirea programului este provocată de terminarea parcurgerii
arborelui de familie sau de limitările echipamentului pe care lucrează versiunea de PROLOG în
cauză dacă arborele este foarte adânc. Aşadar ne trebuie o metodă care garantează
terminarea execuţiei unei proceduri recursive date. O astfel de metodă poate fi implementată
folosind o clauză care enunţă condiţiile de margine în care o relaţie este validă. În exemplul
nostru această condiţie este relaţia “părinte”, care are sensul că o relaţie de strămoş” între
două persoane este valabilă la margine, când una dintre persoane este părintele celeilalte. De
aceea trebuie să adăugăm în baza de reguli o clauză. Noul program este
domains
persoana = symbol
predicates
parinte(persoana, persoana)
stramos(persoana, persoana)
clauses
parinte(maria, ion). /*1*/
parinte(ion, ana). /*2*/
parinte(ion, vasile). /*3*/
parinte(ana, mihai). /*4*/
parinte(ana rodica). /*5*/
stramos(X, Y) : - parinte(X, Y). /*6*/
stramos(X, Y) : - parinte(X, Z), stramos( Z, Y). /*7*/
Clauza 6 acţionează ca o condiţie de frontieră a relaţiei definite. În general, pentru rezolvarea
recursivă a unei probleme, împărţim problema în două subgrupe :
Ø Prima subgrupă conţine instanţa “simplă” a problemei (limita recurenţei);

Ø A doua problemă conţine instanţele “generale” ale problemei, ale căror soluţii se găsesc

reducându-le la versiuni mai simple ale problemei (recurenţă).

BACK Cuprins NEXT


Considerăm util să încheiem acest capitol cu paragraf de concluzii:
§ Toate clauzele care se referă la acelaşi nume de predicat trebuie grupate. Ordinea clauzelor

în cadrul aceluiaşi grup influenţează modul de execuţie, deoarece ele sunt inspectate în
vederea resatisfacerii în ordinea în care sunt trecute. Ordinea în care sunt aşezate grupurile
de clauze nu prezintă importanţă.
§ Procedeul prin care PROLOG realizează satisfacerea clauzelor este unificarea. În urma

unificării variabilele libere devin legate. Legarea variabilelor este locală (numele unei
variabile dintr-o clauză nu are nici o legătură cu acelaşi nume dintr-o altă clauză).
§ Pentru satisfacerea scopului, sau satisfacerea corpului unei reguli PROLOG utilizează

tehnica backtrackingului. Forţarea backtrackingului se face predicatul fail. Procesul de


resatisfacere prin backtracking poate fi oprit cu ajutorul tăieturii, !.
§ Negaţia în PROLOG poate fi exprimată utilizând o combinaţie tăietură-eşuare (!,fail) sau

utilizând predicatul not. Clauza not(p(arg1, arg2,…, argn)) este satisfăcută dacă şi numai
dacă
clauza p(arg1, arg2,…, argn) nu se poate satisface.
§ PROLOG admite recursivitatea în sensul că acelaşi nume de predicat poate apare şi în

capul unei reguli şi în corpul ei. În situaţia în care se utilizează definiţii recursive este
necesar să se definească condiţii de margine (condiţii de oprire a apelurilor recursive).

BACK Cuprins NEXT


Operatii de intrare/iesire

Exista doua stiluri de operare cu date de intrare/iesire in Prolog:


Ø stilul Edinburg este depasit, dar inca suporta de unele implementari Prolog. Este relativ simplu

de folosit, dar are limitari.


Ø intrare/iesire ISO este standardul suportat de toate implementarile Prolog.

Stilul Edinburg
Scrierea termenilor
Predicacul predefinit write ia orice termen Prolog si il afiseaza pe ecran. Predicatul nl muta
“cursorul” la o linie noua.
?- write ('Hello_ther e ) , nl, write('Goodbye').
Hello there
Goodbye
true.
De notat ca atomii care sunt ciati sunt afisati fara ghilimele (simple). Varianta writeq a lui write
va afisa si ghilimelele.

BACK Cuprins NEXT


Citirea termenilor
Predicatul read accepta orice termen Prolog scris la tastatura.
Predicatul read este satisfacut daca argumentul sau poate fi unificat cu un termen dat de utilizator.
Exemplele anterioare ilustreaza mai multe situatii de folosire.
Lucrul cu fisiere
Predicatul see ia ca argument un fisier, efectul sau este sa deschida fisierul pentru citire, astfel ca Prolog
sa ia date de intrare din fisier, nu de la consola. Preducatul seen inchide toate fisierele deschise, datele de
intrare provin din nou de la consola.
?- see(myfile.txt),
read(X),
read(Y),
read(Z),
seen.
Cand un fisier este deschis, Prolog va retine pozitia “cursorului” in acel fisier.
Predicatul tell deschide un fisier pentru scriere si comuta iesirea la acesta.
Predicatul Told inchide toate fisierele deschise pentru scriere si comuta iesirea la consola.
Intrare/iesire la nivel de caractere
Predicatul put scrie un caracter.
?-put(42).
*
true.
Predicatul get citeste un caracter de la intrarea implicita.
?- get(X).
|%
X=37.

BACK Cuprins NEXT


Standard ISO
Streamuri
Standardul ISO pentru intrare/iesire din Prolog considera notiunea de stream.
Sunt disponibile predicate pentru:
Ødeschiderea si inchiderea streamurilor in diferite moduri.

Øinspectarea starii unui stream, precum si a altor informatii.

Ø scrierea/citirea se face in streamuri.

Exista doua streamuri permanent deschise: user_imput si user_output, corespunzand intrarii si iesirii la consola.
Deschiderea streamurilor
Predicatul open(Filename, Mode, Stream, Obtions) deschide un stream.
Inchiderea streamurilor
Predicatul close(Stream, Obtions) inchide Stream cu obtiunile Obtion.
close(Stream) este versiunea fara obtiuni.
Obtiunile include force(false) (implicit) si force(true) chiar daca exista o eroare, fisierul se considera inchis, fara sa ridice
o eroare.
Proprietati ale streamurilor
Predicatul stream_property(Stream, Property) poate fi folosit pentru detectarea proprietatilor.
Citirea termenilor
read_term(Stream, Term, Obtions)
read_term(Term, Obtions)
read(Stream, Term)
read(Term)
Scrierea termenilor
write_term(Stream, Term, Obtions)
write_term(Term, Obtions)
write(Stream, Term)
Write(term)

BACK Cuprins NEXT