laborator 2

13
Programare Logică. Limbajul Prolog Scurt istoric Limbajul Prolog se încadrează în paradigma programării logice ale căror începuturi le sunt atribuite cercetătorilor R. Kowalski şi A. Colmerauer şi se situează la începutul anilor '70. Kowalski a plecat de la o formulă logică de tipul: S 1, S 2, .... S n -> S care are, în logica cu predicate de ordinul întâi semnificaţia declarativă conform căreia S 1 , S 2 .... S n -> S, adică dacă S 1 şi S 2 ... şi S n sunt fiecare adevărate atunci şi S este adevărat, şi a propus o interpretare procedurală asociată. În paralel, A. Colmerauer şi colectivul lui de cercetare de la Universitatea din Marsilia au dezvoltat un limbaj de implementare a acestei abordări, pe care l-au denumit Prolog, abreviere de la "Programmation et Logique". Limbajul Prolog este un limbaj declarativ, cu un cod orientat spre limbajul natural, în care se descrie ce trebuie calculat şi nu cum se calculează, ca în limbajele procedurale. Mai mult, limbajul Prolog este un limbaj declarativ susţinut de o componentă procedurală. Spre deosebire de limbajele procedurale, cum ar fi C sau Pascal, în care rezolvarea problemei este specificată printr-o serie de paşi de execuţie sau acţiuni, într-un limbaj declarativ problema este specificată prin descrierea universului problemei şi a relaţiilor sau funcţiilor existente între obiecte din acest univers. Exemple de astfel de limbaje sunt cele funcţionale, de exemplu LISP, Scheme, ML şi cele logice, de exemplu Prolog. Deşi iniţial a fost gândit pentru un set restrâns de probleme, Prolog a devenit cu timpul un limbaj de uz general, fiind o unealtă importantă în aplicaţiile de inteligenţă artificială. Pentru multe probleme, un program Prolog are cam de 10 ori mai puţine linii decât echivalentul lui în Pascal. Un impuls important pentru dezvoltarea limbajului Prolog l-a constituit programul lansat de japonezi în 1983, de construire a calculatoarelor de generaţia a 5-a, pentru care Prolog ar fi urmat să fie limbajul de asamblare. Planul nu a reuşit, dar acest proiect a marcat o dezvoltare deosebită a interpretoarelor şi compilatoarelor de Prolog, precum şi o creştere mare a numărului de programatori în acest limbaj. 1

Upload: diana-duca

Post on 19-Dec-2015

6 views

Category:

Documents


4 download

DESCRIPTION

ia

TRANSCRIPT

Page 1: Laborator 2

Programare Logică. Limbajul Prolog

Scurt istoric

Limbajul Prolog se încadrează în paradigma programării logice ale căror începuturi le sunt atribuite cercetătorilor R. Kowalski şi A. Colmerauer şi se situează la începutul anilor '70. Kowalski a plecat de la o formulă logică de tipul: S1, S2, .... Sn -> S care are, în logica cu predicate de ordinul întâi semnificaţia declarativă conform căreia S1, S2 .... Sn -> S, adică dacă S1 şi S2 ... şi Sn sunt fiecare adevărate atunci şi S este adevărat, şi a propus o interpretare procedurală asociată.

În paralel, A. Colmerauer şi colectivul lui de cercetare de la Universitatea din Marsilia au dezvoltat un limbaj de implementare a acestei abordări, pe care l-au denumit Prolog, abreviere de la "Programmation et Logique".

Limbajul Prolog este un limbaj declarativ, cu un cod orientat spre limbajul natural, în care se descrie ce trebuie calculat şi nu cum se calculează, ca în limbajele procedurale. Mai mult, limbajul Prolog este un limbaj declarativ susţinut de o componentă procedurală. Spre deosebire de limbajele procedurale, cum ar fi C sau Pascal, în care rezolvarea problemei este specificată printr-o serie de paşi de execuţie sau acţiuni, într-un limbaj declarativ problema este specificată prin descrierea universului problemei şi a relaţiilor sau funcţiilor existente între obiecte din acest univers.

Exemple de astfel de limbaje sunt cele funcţionale, de exemplu LISP, Scheme, ML şi cele logice, de exemplu Prolog. Deşi iniţial a fost gândit pentru un set restrâns de probleme, Prolog a devenit cu timpul un limbaj de uz general, fiind o unealtă importantă în aplicaţiile de inteligenţă artificială.

Pentru multe probleme, un program Prolog are cam de 10 ori mai puţine linii decât echivalentul lui în Pascal.

Un impuls important pentru dezvoltarea limbajului Prolog l-a constituit programul lansat de japonezi în 1983, de construire a calculatoarelor de generaţia a 5-a, pentru care Prolog ar fi urmat să fie limbajul de asamblare. Planul nu a reuşit, dar acest proiect a marcat o dezvoltare deosebită a interpretoarelor şi compilatoarelor de Prolog, precum şi o creştere mare a numărului de programatori în acest limbaj. Multe clase de probleme poate fi rezolvate în Prolog, în principal cele dedicate prelucrării simbolice sau care necesită un proces de căutare a soluţiei într-un spaţiu posibil de transformări ale problemei.

Câteva din trăsăturile esenţiale ale limbajului Prolog

Prolog este un limbaj de programare pentru rezolvarea problemelor, implicând obiecte şi relaţiile dintre ele.

Acest limbaj permite raţionarea pe marginea obiectelor şi a relaţiilor dintre ele, şi permite prelucrarea simbolică, ne-numerică.

Prelucrarea în Prolog se bazează pe trei concepte fundamentale:

Potrivirea şabloanelor („pattern matching”); Structuri de date bazate pe arbori; Backtracking automat.

Elementele (entităţile) limbajului Prolog

Limbajul Prolog este un limbaj logic, descriptiv, care permite specificarea problemei de rezolvat în termenii unor fapte cunoscute despre obiectele universului problemei şi a relaţiilor existente între aceste obiecte.

1

Page 2: Laborator 2

Execuţia unui program Prolog constă în deducerea implicaţiilor acestor fapte şi relaţii.

Un program Prolog conţine următoarele entităţi:

fapte (facts), despre obiecte şi relaţiile existente între aceste obiecte; reguli (rules – clauses) despre obiecte şi relaţiile dintre ele, care permit

deducerea (inferarea) de noi fapte pe baza celor cunoscute; întrebări (questions), numite şi scopuri (goals), despre obiecte şi relaţiile dintre

ele, la care programul răspunde pe baza faptelor şi regulilor existente.

TURBO PROLOG

1. Este un limbaj de programare logică centrat pe date

Se deosebeşte de Pascal sau C, care sunt limbaje imperative, centrate pe proces. Paradigma fundamentală a programării logice este cea de programare declarativă. Focusul programării logice este identificarea noţiunii de calcul şi noţiunii de deducţie. Mai exact, sistemele de programare logică reduc execuţia unui program la căutarea prin respingere a clauzelor programului împreună cu negaţia propoziţiei ce exprimă întrebarea. Aici se urmează regulă: o respingere e o deducţie de la contrariu. Se bazează pe deducţia liniară folosind clauze Horn. Se foloseşte pentru a exprima relaţii între obiecte şi a obţine informaţii relativ la obiecte şi relaţiile dintre ele.

2. Este un limbaj descriptiv

A scrie un program pentru calculator înseamnă:

< CE >: specificarea exactă a rezultatelor dorite; < CUM >: proiectarea metodei prin care se obţin aceste rezultate.

Un limbaj este descriptiv dacă accentul cade pe primul aspect (CE), alegerea metodei fiind lăsată pe seama calculatorului. Un limbaj procedural este unul în care trebuie proiectată şi metoda de obţinere a rezultatelor.

3. Este folosit în:

- programarea unor aplicaţii în Inteligenţa Artificială; - dezvoltarea sistemelor expert; - procesarea limbajului natural (inclusiv traducere automată);- robotică; - teoria jocurilor; - procesări de natură logică.

Secţiunea de clauze TURBO PROLOG

Secţiunea de clauze („inima” unui program Prolog) este cea în care se pun faptele şi regulile cu care va lucra Turbo Prolog când va încerca să îndeplinească scopul programului. Clauzele care au în partea stângă acelaşi predicat trebuie să fie consecutive (nu trebuie intercalate predicate de alt tip), secvenţa lor numindu-se „procedură”.

2

Page 3: Laborator 2

Secţiune de predicate

Secţiunea de predicate este cea în care se declară predicatele, adică numele lor şi tipurile (domeniile) argumentelor lor.

Numele trebuie să înceapă cu o literă (de preferat mică), urmată, eventual, de o secvenţă de litere, cifre şi caracterul underscore (_). Lungimea numelui trebuie să fie mai mică de 250.

Forma generală este:predicatesnume_predicat(tip_arg_1,tip_arg_2,...,tip_arg_n)

unde tip_arg_i, i=1..n, sunt predicate standard sau declarate de utilizator în secţiunea „domains”.

Atenţie! Predicatele standard (peste 200 in Turbo Prolog) nu se definesc în secţiunea

predicates. Turbo Prolog avertizează printr-un mesaj de eroare: „201 This name is reserved for a standard predicate”.

Dacă se doreşte scrierea pe aceeaşi linie a mai multor predicate, atunci acestea trebuie separate prin punct.

Aritatea unui predicat este definită ca fiind numărul de argumente; două predicate cu acelaşi nume pot avea arităţi diferite. Ele trebuie declarate în secţiunea de predicate şi corpul lor în secţiunea de clauze.

Secţiunea de domenii serveşte la două lucruri foarte utile:

- de a da o semantică (înţeles) domeniilor, care vor fi tipuri pentru argumentele predicatelor, chiar dacă acele domenii există deja;

- de a declara structuri de date care nu sunt definite prin domenii standard.

Secţiunea de domenii

Secţiunea de domenii este la fel ca în celelalte limbaje de programare. Domeniile de bază sunt: char integer real string symbol

char - caractere intre apostof; Caracterul '\n' înseamna secvenţa escape "new line", adică trecere la

rând nou, iar '\251' înseamnă caracterul ASCII cu codul 251; - integer - reprezintă mulţimea numerelor întregi cuprinse între -32768

şi 32767; - real - dacă notăm prin "D" o cifră (digit), atunci un număr real poate

avea una din formele: DDDDDDD DDDDDDD.DDDDDDD

3

Page 4: Laborator 2

[+|-]DDDDD[.]DDDDDDD[e[+|-]DDD] - Numerele "reale" din acest domeniu sunt din intervalul [10^{-307},10^{308}] reunit cu [-10^{308},-10^{-307}];

- string - reprezintă orice secvenţă de caractere scrise între ghilimele. Lungimea unui sir (string) este mai mică de 255 caractere;

- symbol - sunt permise două forme: o secvenţă de litere, numere şi underscore (_), cu o singură

restricţie ca prima literă este mică; o secvenţă de caractere marcată de ghilimele (aceasta este folosită

când vrem să introducem spaţii sau literă mare la început).

Secţiunea de scopuri

începe cu cuvântul rezervat „goal” conţine scopuri interne.

Secţiunea database

Uneori dorim să actualizăm faptele din program (modificare, ştergere, adăugare). Într-un astfel de caz, faptele constituie o bază de date dinamică sau internă.

Turbo Prolog are o secţiune specială pentru declararea unor fapte care vrem să fie o parte a unei baze de date dinamice; aceasta este secţiunea database.

Cuvantul rezervat „database” declară secţiunea database. Turbo Prolog pune la dispoziţie un număr de predicate ce servesc la gestiunea bazelor de date (assertz, asserta, ...)

Secţiunea constants

Putem declara şi folosi constante simbolice în programele Turbo Prolog. Valorile constantelor nu se pot modifica în timpul execuţiei programului. O secţiune de declarare a constantelor este indicată prin cuvântul rezervat „constants”. Forma generală a definirii unei constante este:

constants const1 = definiţie

const2 = definiţie

Relativ la constante, avem câteva restricţii:

o Nu sunt permise definiţii recursive. Exemplu: x=2*x/2o In secţiunea de constante, acestea pot fi declarate cu literă mare, dar în

secţiunea de clauze acestea trebuie să fie scrise cu litera mică.

Pot exista mai multe secţiuni de declarare a constantelor, dar ele trebuie declarate înainte de a fi folosite. Identificatorii de constante sunt globali şi se declară o singură dată. Dacă nu se respectă aceasta, compilatorul Turbo Prolog afişează mesajul de eroare: "113 This constant is already defined."

Afişarea datelor în PROLOG

write(Arg1,...) (i,...) % pentru afişarea argumentelor

4

Page 5: Laborator 2

nl % pentru trecerea la o linie nouă

writef(SirDeFormate,Arg1,...) (i,i,...) % pentru afişarea formatată a argumentelor

Fiecărui argument trebuie sa-i corespundă un format de afişare:

%d Normal decimal number (chars and integers) %u As an unsigned integer (chars and integers) %R As a database reference number (database reference numbers) %X As a long hexadecimal number (strings, database reference numbers) %x As a hexadecimal number (chars and integers) %s Strings (symbols and strings) %c As a char (chars and integers) %g Reals in shortest posible format (default for reals) %e Reals in exponetial notation %f Reals in fixed notation %lf Only for C compatibility (fixed reals)

Formatul de afişare:

%-m.pt unde

- înseamnă aliniere la stânga (implicit este la dreapta); m înseamnă lungimea minimă a câmpului de afişare; p numărul de zecimale; t unul din tipurile de mai sus.

Citirea datelor în PROLOG

readln(StringVariable) % citeşte o variabilă de tip string

readint(IntgVariable) % citeşte o variabilă de tip integer

readreal(RealVariable) % citeşte o variabilă de tip real

readchar(CharVariable) % citeşte o variabilă de tip char

Se va citi într-o variabila liberă o valoare; dacă nu corespunde tipului se obţine Eroare! readterm(Domain, Variable) - folosit pentru citirea obiectelor compuse. Citeşte o linie şi o converteşte la un obiect al unui domeniu dat.

Exemplul 1: Crearea unei ferestre utilizator.

goalmakewindow(1,7,7,”Primul program”,2,10,20,60),write (”Bine ati venit la laboratorul de Turbo Prolog!”).

Observaţii

1 – numărul ferestrei; 7 - culoarea „interiorului ferestrei”;

5

Page 6: Laborator 2

7 – culoarea chenarului ferestrei; „Primul program” – titlul ferestrei; (2, 10) – coordonatele punctului stânga sus; (20, 60) - coordonatele punctului dreapta jos.

Exemplul 2: Citirea şi scrierea unei variabile întregi în Turbo Prolog.

predicatesciteste_intreg

clausesciteste_intreg :-write (“dati un intreg \n”), nl,readint (X), nl,write (“ati tastat”, X), nl.citeste_intreg :- write (“nu ati tastat un numar intreg \n”).

goalciteste_intreg.

Observaţii

dacă doriţi să urmăriţi pas cu pas execuţia acestui program, atunci adăugaţi la începutul programului predicatul trace;

predicates – cuvânt rezervat folosit pentru specificarea începutului zonei declarării variabilelor;

citeste_intreg – predicat fără argumente folosit pentru citirea unui număr întreg; clauses – cuvânt rezervat folosit pentru specificarea începutului zonei declarării

clauzelor; :- este echivalent cu if şi semnifică separarea capului regulii de corpul său. Acestea

sunt clauze Horn. nl este un predicat care întoarce true şi care are ca efect trecerea la rând nou; readint (X) – citeşte de la tastatură un întreg pe care îl memorează în variabila X;

dacă nu se introduce un întreg, atunci predicatul returnează false.

Exemplul 3: Citirea unui întreg de la tastatură, calculul şi afişarea pătratului său în Turbo Prolog.

predicatesciteste_intreg (integer)calcul_patrat (integer, integer)scrie_rezultat (integer, integer)executa

clausesciteste_intreg (X) :-

write (“dati un intreg \n”), nl,readint (X), nl,write (“ati tastat”, X), nl.

citeste_intreg (X) :- write (“nu ati tastat un numar intreg \n”),

6

Page 7: Laborator 2

fail, X=1.calcul_patrat (X, Y) :-

Y=X*X.scrie_rezultat (X, Y) :-

write (“patratul lui”, X, “este”, Y), nl.executa :-

citeste_intreg (X),calcul_patrat (X, Y),scrie_rezultat (X, Y).

goalexecuta

Observaţie

citeste_intreg (X) – deosebirea faţă de exemplul precedent este că predicatul are acum un argument de tip integer. A doua definiţie a predicatului citeste_intreg (X) este puţin mai complicată. Nu putem pune variabilă anonimă, dar trebuie să adăugăm fail deoarece, în acest caz, executa trebuie să întoarcă false. De asemenea, trebuie legată variabila X la ceva, să zicem X=1.

calcul_patrat (X, Y) – în variabila Y se calculează pătratul lui X. executa – este un predicat fără argumente care are rolul de a „lega” variabilele X,

respectiv Y, folosite în cele trei predicate din program.

Să se implementeze şi să se testeze în PROLOG

1. Să presupunem că ştim următoarele fapte:

predicates îi_place(symbol,symbol) nu_îi_place(symbol,symbol)

clauses îi_place(mihai, ciocolata).

îi_place(mihai, prăjitura).îi_place(maria, ciocolata).îi_place(mihai, gina).nu_îi_place(gina, mihai).

Numele de persoane şi de lucruri sunt de fapt constante (Maria, Mihai, Gina, ciocolata, prăjitura).

Se pot pune următoarele întrebări îi_place(gina, mihai).

Falseîi_place(mihai, banii).

False îi_place (mihai, prăjitura).

True

7

Page 8: Laborator 2

2. Se dau faptele:

papagal(coco).iubeşte(mihai, maria). iubeşte(mihai, ana). frumoasă(ana).bun(gelu).deplasează(cub, camera1, camera2).

Se pot pune diverse întrebări, cum ar fi:iubeste(mihai, maria).Răspuns: True deoarece acest fapt există în baza de cunoştinţepapagal(coco).Truepapagal(mihai).False deoarece acest fapt nu există în baza de cunoştinţe

3.place(elena,tenis).place(maria,inot).place(maria,volei).place(ion,fotbal).place(mihai,baschet).place(dan, Ceva) if

place (maria, Ceva).

Intrebările care se pun sunt:Place(elena,tenis).Place(elena, fotbal).Place(maria,Ce).Place(dan,Ce).Place(Cine,Ce).

4.

place(ellen, tenis).

place(john, fotbal).

place(tom, baseball).

place(eric, înot).

place(mark, tenis).

place(bill, X) :- place(tom, X).

8

Page 9: Laborator 2

Intrebările care se pun sunt:

place(john, X).

place(Y, baseball ).

place(ellen, tenis).

place(ellen, fotbal).

place(bill, baseball).

5. masina(mercedes, albastru, 5).

masina(chrysler, rosu, 4).masina(ford, gri, 8).masina(datsun, rosu, 5).

Intrebările care se pun sunt:

masina(Tip, _ , 5).

masina(Tip, rosu, _ ).

6.masina(mercedes, albastru, 5).

masina(chrysler, rosu, 4).masina(ford, gri, 8).masina(datsun, rosu, 5).

masina_mare(X) :- masina(X, _ , Nr_calatori), Nr_calatori

>= 5.

7.

copil(peter, 9).

copil(paul, 10).

copil(chris, 9).

copil(susan, 9).

pot_juca(Pers1, Pers2) :-

copil(Pers1, Varsta1), copil(Pers2, Varsta2), Varsta1 =

Varsta2.

8.

9

Page 10: Laborator 2

barbat(gelu). barbat(bogdan). barbat(toma).

fumator(toma). fumator(dan).

vegetarian(gelu).

ana_se_intalneste_cu(X) :- barbat(X),

not(fumator(X)).

ana_se_intalneste_cu(X) :- barbat(X), vegetarian(X).

9. parinte(ion, vlad).

parinte(ioana, vlad).

parinte(gica, paul).

parinte(maria, paul).

parinte(mihai, ion).

parinte(ion, paula).

parinte(mihai, maria).

parinte(cristina, maria).

parinte(X, vlad).

barbat(ion).

barbat(vlad).

barbat(mihai).

barbat(gica).

barbat(paul).

femeie(ioana).

femeie(maria).

femeie(paula).

femeie(cristina).

tata(Tata, Copil) :- parinte(Tata, Copil), barbat(Tata).

mama(Mama, Copil) :- parinte(Mama, Copil), femeie(Mama).

10