Sunteți pe pagina 1din 8

1

LABORATOR 1


Limbajul Prolog. Introducere.

Pentru dezvoltarea programelor vom folosi implementarea SWI-Prolog versiunea
3.x.x. Lansarea programului SWI-Prolog se face apasnd butonul Start si efectund
selectiile Programs -> SWI-Prolog -> Swi-Prolog. Pe ecran va apare fereastra
aplicatiei si prompterul ?- care arata ca programul asteapta comenzi.

Comenzi uzuale:
?- pwd.
Afiseaza directorul curent.
?-ls.
Afiseaza fisierele din directorul curent.
?-cd('cale').
Schimba directorul curent.

Exemplu:
?-cd(c:\\windows').
Directorul curent devine c:\windows. Se observa ca separatorul folosit in descrierea
directorului este / (la fel ca in UNIX).

?- halt.
Acesta comanda ncheie sesiunea de lucru curenta in SWI-Prolog.
Observatie: Fiecare enunt in Prolog se termina cu caracterul punct (.).
?-help(numecomanda).
Afiseaza informatii despre comanda specificata.

Exemplu:
?-help(pwd).

Cel mai simplu program prolog este format dintr-o multime de fapte. Un fapt este o
constructie de forma
nume_relatie(argument_1,argument_n)
si descrie o relatie intre concepte.

Exemplu:
frate(dan,maria).
'frate' este numele relatiei (sau predicatului) si dan si maria sunt conceptele care intra
in relatie. Se observa ca att numele relatiei cat si constantele 'dan' si 'maria' sunt
scrise ncepnd cu litera mica.

Un program prolog simplu care descrie relatiile existente intr-o familie este urmatorul:


tata(andrei,marius).
tata(andrei,radu).
tata(andrei,dan).
tata(marius,aurel).
tata(dan,carmen).
2
tata(dan,george).
tata(dan,dana).
tata(paul,aurel).

barbat(andrei).
barbat(marius).
barbat(radu).
barbat(dan).
barbat(aurel).
barbat(george).

mama(maria,aurel).

femeie(maria).
femeie(carmen).
femeie(dana).


Pentru a introduce programul anterior tastati comanda
?- edit('prog1.pl').
si raspundeti cu Yes la urmatoarele doua interogari. In final este lansata aplicatia
Notepad care va permite sa introduceti programul in fisierul cu numele 'prog1.pl'.

Observatii:
1. Extensia implicita a unui fisier ce contine un program SWI-Prolog este .pl.
2. Faptele construite cu acelasi nume de relatie (cum ar fi de exemplu 'tata') se afla
unul lnga altul in fisierul sursa. Aceste fapte formeaza definitia relatiei
respective.

nainte de a utiliza un program SWI-Prolog acesta trebuie ncarcat in memorie.
Aceasta operatie este realizata cu ajutorul comenzii:
?-consult('numefisier.ext').
In cazul exemplului nostru vom introduce comanda
?-consult('prog1.pl').

Utilizatorul foloseste un program prolog pentru a obtine raspunsuri la ntrebari pe
baza cunostintelor din acesta. ntrebarile se introduc la prompterul ? si cele mai
simple au structura sintactica identica cu cea a unui fapt.

Exemplu:
Pentru ntrebarea
? - mama(maria, aurel).
(ntrebam daca maria este mama lui aurel) sistemul de prolog va consulta baza de
fapte de care dispune si va raspunde cu
Yes.
La ntrebarea
?- mama(maria,carmen).
raspunsul va fi
No
Pentru ca sistemul nu gaseste in baza de cunostinte nici un fapt care sa corespunda
acestei ntrebari.

3
ntrebarile prezentate pana acum au fost de natura confirmativa (raspunsul la ele era
Yes sau No).

Sa presupunem ca dorim sa aflam care sunt copii lui dan. Pentru aceasta vom
introduce notiunea de variabila. O variabila poate fi vazuta ca o locatie de memorie
care primeste in timpul procesului de rationament o valoare. Odata asignata, valoarea
unei variabile nu mai poate fi schimbata. Numele unei variabile trebuie sa nceapa cu
litera mare.
Pentru a afla copiii lui dan vom folosi interogarea
?-tata(dan,X).
unde X reprezinta o variabila. Sistemul va cauta in baza de fapte un fapt care sa
corespunda interogarii si se va opri la tata(dan,carmen).
Raspunsul la interogare va fi
X=carmen

Pentru a obtine toti copii lui dan vom folosi o interogare mai complicata:
?-tata(dan,X),write(X),nl,fail.
Raspunsul va fi
carmen
george
dana
No.

Virgula desemneaza in prolog operatorul logic 'si' iar fail este o relatie (predicat)
predefinita care esueaza ntotdeauna determinnd cautarea de noi solutii.

Cu operatorul ',' putem construi interogari mai complicate cum ar fi
?-tata(dan,X),barbat(X).
cu ajutorul careia determinam acei copii ai lui X care sunt barbati (fii lui X).
Raspunsul este
X=george.

Exercitiu: Construiti o interogare cu ajutorul careia sa determinati nepotii lui andrei.

Variabilele pot sa apara si in cadrul faptelor dintr-un program pentru a desemna
adevaruri general valabile.
Exemplu: Sa adaugam la program informatia ca tuturor persoanelor existente in baza
le plac garoafele. Pentru aceasta introducem comanda
?-edit('prog1.pl').
si adaugam la program faptul
place(X,garoafe).
cu semnificatia 'oricare ar fi X are loc relatia place(X,garoafe)'.
Rencarcati programul cu comanda
?-consult('prog1.pl').
si introduceti interogarea
?-place(maria,garoafe).

Raspunsul va fi
Yes.

4
Exercitiu: Exprimati printr-un fapt afirmatia: adunnd orice numar cu 0 obtinem tot
numarul initial.

Pana acum am definit relatiile extensional ca multimi de fapte. O relatie poate fi
definita si intensional in functie de alte relatii existente in program. Pentru aceasta
vom folosi constructii sintactice mai complicate numite reguli.
O regula are urmatoarea sintaxa:
nume_relatie(arg1,,argn):- nume_relatie_1(),,nume_relatie_n().
Exemplu: Putem spune ca X este fiul lui Y daca Y este tatal lui X sau Y este mama lui
X si X este de sex masculin. Aceasta definitie va fi codificata prin urmatoarele doua
reguli care trebuie adaugate la programul prog1.pl.

fiu(X,Y) :- tata(Y,X), barbat(X).
fiu(X,Y) :- mama(Y,X), barbat(X).

Operatorul ':-' are in prolog semnificatia 'daca' si poate fi nlocuit cu secventa 'if'.
Dupa ce adaugati cele doua reguli la program si rencarcati programul introduceti
interogarea:
?- fiu(george,X).
Raspunsul va fi
X=dan
Pentru a urmari modul in care este rezolvata interogarea anterioara introduceti
comanda
?-trace.
si apoi repetati interogarea
?- fiu(george,X).
Pe ecran vor apare diferitele subscopuri care trebuie rezolvate de sistemul prolog
pentru a obtine raspunsul la interogare. Pentru a trece de la un subscop la altul apasati
tasta ENTER.
Observatie: Partea din stnga operatorului :- in definitia unei reguli este numita capul
regulii iar cea din dreapta corpul regulii. Un fapt poate fi vazut ca o regula fara corp
(fara conditie). Regulile si faptele care definesc aceeasi relatie (au acelasi nume de
relatie in cap) trebuie grupate in sursa programului. In prolog relatiile sunt numite de
obicei predicate.

Exercitii:

1. Definiti relatiile: soacra, cumnat si ginere pornind de la programul anterior si de la
un predicat cuplu_casatorit(Nume_sot,Nume_Sotie) (adaugati la programul anterior
fapte ce descriu acest predicat).
Exemplu:
cuplu_casatorit(paul,maria).
2. Modificati regulile pentru fiu pentru a obtine regulile pentru relatia fiica.
3. Definiti relatiile frate, sora, unchi, matusa.


n programul prog1.pl anterior am definit prin intermediul faptelor relatiile tata si
mama pentru o familie data. Pe baza acestora, definim n continuare prin intermediul
regulilor relatiile parinte, frate, unchi, var:

unchi(Unchi,Persoana) :-frate(Unchi,Parinte), parinte(Parinte,Persoana).
5

frate(F1,F2) :-
parinte(Parinte,F1), parinte(Parinte,F2), F1 \= F2.

parinte(Parinte,Copil):-tata(Parinte,Copil).
parinte(Parinte,Copil):-mama(Parinte,Copil).

var(Var1,Var2) :-
parinte(Parinte1,Var1),
parinte(Parinte2,Var2),
frate(Parinte1,Parinte2).

Observatie:
1. Operatorul \= are sensul de "diferit"
2. Definitia predicatului parinte poate fi citita astfel: " Parinte este parintele lui Copil
daca Parinte este tatal lui Copil sau mama lui Copil". Observam astfel ca disjunctia
poate fi implementata n Prolog prin intermediul a doua reguli care definesc acelasi
predicat (n cazul nostru predicatul parinte).

Adaugati aceste reguli la programul prog1.pl utiliznd comanda:
?-edit('prog1.pl').
Compilati programul obtinut cu comanda
?-consult('prog1.pl').
si testati-l prin intermediul interogarilor:
?-frate(carmen,george).
Raspuns Yes.

?- unchi(X,carmen).
Raspuns X=marius.

Exercitiu: Utilizati si alte scopuri (interogari) pentru a testa definitiile predicatelor
nou introduse.

Argumentele unui predicat sunt numite termeni. Din exemplele de pna acum
deducem ca constantele si variabilele sunt termeni deoarece au aparut ca argumente
ale predicatelor din programe. Un termen poate sa aiba si o structura compusa de
forma f(t
1
,t
2
,,t
n
) unde f este un simbol de functie si t
1
,t
2
,,t
n
sunt termeni.
Exemplu: Sa consideram urmatoarele informatii: cursul de analiza esteTinut de
profesorul Popescu joi ntre orele 10 si 12 in cladirea centrala sala 136. Le
reprezentam prin intermediul faptului:

curs(analiza,timp(joi,10,12),nume(popescu,marius),sala(cladirea_centrala,136)).

timp(joi,10,12), nume(popescu,marius), sala(cladirea_centrala,136) sunt termeni
compusi iar timp, nume, sala reprezinta nume de functii. Creati un fisier curs.pl si
adaugati n acesta descrierile unor cursuri pe care le urmati dupa modelul de mai sus.
Explicati sensul regulilor de mai jos si ilustrati concluziile dumneavoastra prin
exemple de scopuri.

Observatie. Operatorul is este operatorul de atribuire n Swi-Prolog. Nu l confundati
cu = care desemneaza o comparatie (unificarea)


6

profesor(Profesor,Curs) :-curs(Curs,Timp,Profesor,Localizare).

durata(Curs,Durata) :-
curs(Curs,timp(Zi,Inceput,Sfarsit),Profesor,Localizare),
Durata is Sfarsit-Inceput.

preda(Profesor,Zi) :-
curs(Curs,timp(Zi,Inceput,Sfarsit),Profesor,Localizare).

ocupat(Sala,Zi,Timp) :-
curs(Curs,timp(Zi,Inceput,Sfarsit),Profesor,Localizare),
Inceput =< Timp, Timp =< Sfarsit.


Definirea recursiva a predicatelor:

Un predicat este definit recursiv daca e definit prin intermediul unor reguli si acestea
fac referire direct sau indirect chiar la predicatul nsusi.
Urmatoarele reguli definesc recursiv notiunea de stramos n functie de notiunea de
parinte.

/*
stramos(Stramos,Descendent) :-
Stramos este un stramos al lui Descendent.
*/
stramos(Stramos,Descendent) :-
parinte(Stramos,Descendent).
stramos(Stramos,Descendent) :-
parinte(Stramos,Persoana), stramos(Persoana,Descendent).

/*
Regula 2 din definitia lui stramos face referire n corpul ei chiar la predicatul stramos,
acesta fiind deci definit recursiv. Regula se citeste astfel: Stramos este un stramos al
lui Descendent daca exista o Persoana astfel nct Stramos sa fie parintele lui
Persoana si Persoana sa fie un stramos pentru Descendent. Se observa ca variabilele
care apar numai n corpul unei reguli sunt cuantificate existential (variabila Persoana).
Prima regula constituie conditia de oprire din recursie. Ea se poate citi astfel: Stramos
este un stramos al lui Descendent daca Stramos este parintele lui Descendent
*/

Observatii:
1. n SWI-Prolog un comentariu pe mai multe rnduri inserat ntr-un program trebuie
ncadrat ntre perechile de caractere /* */. Un comentariu pe un singur rnd
poate fi scris precedat de semnul %.
2. De obicei, n Prolog numele variabilelor sunt alese astfel nct sa puna n evidenta
semnificatia (rolul) acestor. Vezi n programul anterior variabilele Stramos,
Descendent, Persoana. La fel se procedeaza si cu numele de predicate.

Scrieti cele doua reguli anterioare ntr-un fisier stramos.pl utiliznd comanda
?- edit('stramos.pl').

Adaugati n acest fisier si urmatoarele trei fapte care constituie definitia predicatului
parinte:
7

parinte(dan,carmen). % dan este parintele lui carmen
parinte(clara,dan). % clara este parintele lui dan
parinte(andrei,dan). %andrei este parintele lui dan

Compilati programul cu ajutorul comenzii
?- consult('stramos.pl').
introdusa la prompterul SWI-Prolog.

La scopul
?- stramos(clara,carmen).
Programul va raspunde Yes.
Pentru scopul
?- stramos(X,carmen).
raspunsul va fi
X=dan

ntrebari:
1. Predicatul parinte este definit recursiv?
2. Ce va afisa programul n cazul interogarii:
?- stramos(X,carmen),write(X),nl,fail.
Puteti explica de ce raspunsul se termina cu No.

Urmatoarea problema cere sa determinati un mod de a reprezenta un graf orientat
ntr-un program Prolog si sa definiti un predicat care sa poata stabili daca ntre doua
noduri exista un drum.

Graful poate fi reprezentat indicnd lista arcelor sale. Un arc de la nodul a la nodul b
poate fi reprezentat printr-un fapt arc_o(a,b). (arc_o - arc orientat).
Urmatoarele fapte
arc_o(a,b).
arc_o(a,c).
arc_o(b,d).
arc_o(c,d).
arc_o(d,e).
arc_o(f,g).
reprezinta graful:

b f

a d e g



c


Predicatul conectat definit n continuare va stabili daca doua noduri din graf sunt
conectate printr-un drum.

/*
conectat(Nod1,Nod2) :- Nod1 este conectat la Nod2 in graful

definit de relatia arc_o/2. /2 arata aritatea relatiei (numarul de argumente).
8
*/

conectat(Nod,Nod).
conectat(Nod1,Nod2) :- arc_o(Nod1,Legatura),
conectat(Legatura,Nod2).


Introduceti definitiile predicatelor arc_o si conectat ntr-un fisier cu numele graf.pl.
Compilati apoi acest fisier.
Comenzile folosite sunt:
?-edit('graf.pl').
?-consult('graf.pl').

Testati definitiile predicatelor cu ajutorul scopului:
?-conectat(a,e).
Raspunsul va fi Yes.

Exercitiu:
Testati definitia predicatului conectat cu alte grafuri, n particular cu grafuri care
contin cicluri. Definitia este suficient de generala?



Bibliografie.

1. NicolaeTandareanu -Introducere n programarea logica, Editura Intarf, 1994