Sunteți pe pagina 1din 78

CURS 1: NOȚIUNI INTRODUCTIVE

Logica este știința demonstrației, care studiază formele și legile generale ale
raționării corecte. Prin logică (cuvântul provine din greaca veche λογική, logike) se înțelege
folosirea rațiunii în realizarea anumitor activități. Logica se folosește în mod predominant în
filozofie, matematică și informatică. Pentru Aristotel, logica este știința legilor de raționare.
Prinicipala contribuție a lui Aristotel a fost logica termenilor care stă la baza analizei
propozițiilor. Ea se fundamentează pe un postulat care va dura până la începutul secolului
XX: orice raționament se analizează atribuind un predicat unui subiect. Aristotel a studiat
silogismele, deducții formate din două premise și o concluzie.
Premisa 1: Toți oamenii sunt muritori.
Premisa 2: Grecii sunt oameni.
Concluzie: Deci grecii sunt muritori.
Aplicații ale logicii în informatică:
 arhitectura calculatoarelor (circuite logice);
 software engineering (testare și verificare);
 limbaje de programare (semantică, programare logică);
 baze de date (algebre de relații);
 inteligență artificială (demonstrare automată);
 calculabilitate și complexitate.

1.1. Gândirea

William Shakespeare spunea: “Gândirea este sclava vieţii”.

Definiții
Gândirea (cugetarea) este însușirea creierului omenesc de a reflecta în mod
generalizat și abstract realitatea obiectivă prin teorii, judecăți, etc. (
http://dexonline.ro/definitie/gandire/). Gândirea reprezintă procesul psihic de reflectare a
însușirilor esențiale și generale ale obiectelor fenomenelor, arelațiilor dintre acestea, prin
intermediul noțiunilor, judecăților și raționamentelor. (Zlate M., Psihologia mecanismelor cognitive,
Ed. Polirom 1999, pag 235).
Psihologul american J.P.Guilford, a propus un model larg acceptat al structurii
gândirii, alcătuit din 3 elemente:
a) Operații: evaluare, gândire convergentă, gândire divergentă, memorie, cogniție;
b) Conținuturi: comportamental, semantic, simbolic și figural;
c) Produse: unități, clase, relații, sisteme, transformări și implicații. (Guilford, J. P., The
nature of human intelligence, New York: McGraw-Hill,1967).
Din punct de vedere structural gândirea poate fi definită, pe rând, ca:
a) Sistem de noțiuni, de judecăți și de raționamente (latura de conținut);
b) Sistem de operații (latura relațională);
c) Sistem de produse (latura operatorie a procesului).
Principala caracteristică a gândirii ca instrument de cunoaștere specific uman o
reprezintă stabilirea de relaţii / raporturi corecte în diferitele clase de obiecte. Prin gândire
este sintetizată esenţa lucrurilor în forma noţiunilor (concepte), a judecăţilor (propoziţii
logice) si a raţionamentelor (inferenţe). Formele gândirii constituie atât obiectul de studiu al
psihologiei, cât și al de logicii, însă din perspective de abordare diferite. Psihologia încearcă
să explice modul în care gândesc oamenii si să pună în evidenţă care sunt consecinţele unui
anumit mod de a gândi (o abordare descriptivă), iar logica ne arată care este modul corect de
a gândi, corectează gândirea prin raportare la normă (abordare prescriptivă).
Ipostaze ale gândirii
a) gândirea este cognitivă, dar este inferată din comportament, ea apare intern în minte sau în
sistemul cognitiv, insă trebuie inferată indiect;
b) gândirea este un proces care implică o manipulare sau un set de operaţii asupra
cunoștiinţelor din sistemul cognitiv;
c) gândirea este direcţională și rezultă în comportamentul care rezolvă o problemă sau este
orientat către soluţie.
(Richard E. Mayer, Thinking, Problem Solving, Cognition, W.H.Freeman & Co, New York,
1992)
Uneltele gândirii (după Zlate M)
 conceptele,  propoziţiile,
 silogismele,  modelele mintale,
 scenariile,  cuvintele,
 imaginile,  algoritmii.
 euristicile,

Unităţile de bază ale gândirii (Zlate M, 1999) sunt:


 imaginea (reprezentare mintală a unui obiect - unitate primitivă agândirii);
 simbolul (unitate abstractă a gândirii ce redă obiectul,evenimentul, calitatea; cel mai
simplu simbol este cuvântul);
 conceptul (eticheta pusă une clase de obiecte;
 prototipul (exemplu ce ilustrează un concept);
 operaţia (acţiune reversibilă utilizată în formarea conceptelor sau la rezolvarea
problemelor);
 regula sau legea (cea mai complexă unitate a gândirii; o relaţie între două sau mai
multe concepte).

1.2. Limbajul

Limbajul este: (http://dexonline.ro/definitie/limbaj)


= Procesul de exprimare, de comunicare a ideilor și a sentimentelor prin mijlocirea limbii.
= Sistem de semne servind pentru comunicarea informațiilor.
=Limbaj formalizat = limbaj artificial, alcătuit dintr-un sistem de semne convenționale.
=Limbă - Mod de exprimare.
=Limbaj artistic = modalitate de comunicare specifică artei.

Limbajul poate fi privit ca funcţie de utilizare a limbii în raporturile cu ceilalţi oameni. Limba
este un ansamblu de semne cu ajutorul cărora se poate comunica. Se distinge un vocabular, o
mulţime de cuvinte si operaţii asupra cuvintelor. (G. Albeanu, Logică computațională, Sinteze anul I,
Ed. FRM, București, 2004).
Unul sau mai multe cuvinte ale unei limbi (pentru comunicare) se constituie într-
o propoziţie. Propoziţiile comunică întrebări, ordine, dorinţe, dar și cunostinţe.
Propoziții cognitive = propoziții care comunică cunostinţe.
Propozitiile cognitive pot fi adevarate, false sau probabile! (G. Albeanu, Logică
computațională, Sinteze anul I, Ed. FRM, București, 2004)
O propoziţie cognitivă este adevărată numai dacă informaţia pe care o exprimă
corespunde stării de fapt despre care se vorbește (exemplu: Un trunghi isoscel are 2 laturi
egale). Propoziţia cognitivă este falsă dacă ceea ce ea susţine nu corespunde unei stări de
fapt (exemplu: Trapezul are laturile egale 2 câte 2). Propoziţia cognitivă este probabilă
dacă nu poate fi stabilit nici adevărul si nici falsitatea propoziţiei (exemplu: Numărul
numerelor întregi este impar).
Logica tradiţională se sprijină pe anumite condiţii formale numite principii logice sau
legi de raţionare/legi logice fundamentale, ce reprezintă condiţiile generale ele
raţionamentelor.
Principiul logic = o condiţie fundamentală de raţionalitate, un criteriu
fundamental prin care distingem între corect si incorect, un reper pentru alte condiţii
de raţionalitate.
Principiile logice au fost formulate pentru prima dată de Parmenide (cca. 515 – cca. 450
î.Hr.), deși nu într-o formă exactă.

Orice raţionament trebuie să respecte simultan următoarele principii logice:


(G. Albeanu, Logică computațională, Sinteze anul I, Ed. FRM, București, 2004)

I. PRINCIPIUL IDENTITĂŢII
Orice formă logică este ceea ce este.
Orice obiect este identic numai cu sine însusi, în același timp și sub acelasi raport.
Fiecare obiect are un set de trăsături care-l fac să fie ceea ce este în realitate.
Pentru om, de exemplu, el are însușiri care îi arată apartenența la clasa tuturor oamenilor, dar
în acelasi timp, fiecare om are și însușri particulare (o anumită înălţime, culoare a ochilor,
ocupaţie, dată și loc al nașterii etc.), toate acestea îl fac din fiecare individ un anumit om, și
nu un om în genere, adică ceea ce el este de fapt. La nivelul gândirii logice, această
particularitate elementară se exprimă sub forma principiului identităţii, conform căruia orice
formă logică este ceea ce este, altfel spus, are o individualitate aparte prin care ea este o
anumită formă logică (noţiune, propoziţie etc.).
Orice propoziție p este echivalentă cu sine p ∼ p
Importanţa principiului identităţii: Când operăm cu termeni sau cu propoziţii cărora nu le
cunoaștem suficient înţelesul sau valoarea de adevăr, principiul identităţii ne cere fie să ne
completăm în prealabil cunostinţele, fie să precizăm în ce sens/cu ce valoare folosim termenii
și propoziţiile respective.
Respectarea principiului identităţii asigură claritatea si precizia gândirii.

II. PRINCIPIUL NON-CONTRADICŢIEI


Presupunem că în acelasi timp și sub acelasi raport un obiect nu poate fi în acelasi
timp și sub acelasi raport și A, și non-A. Există însusiri ale obiectelor care coexistă, de
exemplu greutatea și întinderea și însusiri care sunt incompatibile, se exclud reciproc, nu pot
aparţine deodată aceluiasi obiect: nici un copac nu poate fi și fag și stejar, nici un număr nu
poate fi și par și impar. Incompatibilitatea obiectivă a coexistenţei însusirilor incompatibile se
reflectă la nivel logic prin PRINCIPIUL NONCONTRADICŢIEI:
O propoziție nu poate fi în același timp și sub același raport, atât adevărată, cât și
falsă. Exprimarea în același timp arată că anumite însișiri incompatibile pot reveni unui
obiect, dar în moment diferite.
Nerespectarea acestui principiu poate genera contradicţii logice, și deci imposibilitatea de a
deosebi adevărul de fals.
Respectarea acestui principiu conferă gândirii COERENŢĂ.
III. PRINCIPIUL TERŢULUI EXCLUS
Presupune că în același timp și sub același raport sau este acceptată o propoziţie A,
sau este respinsă dintr-un sistem de propoziţii, a treia posibilitate fiind exclusă. Cu referire la
valoarea de adevăr a propoziţiilor cognitive, terţul exclus se formulează:
Oricare ar fi propoziţia, ea are sau nu are o anumită valoare de adevăr. Respectarea
principiului terţului exclus conferă gândirii CONSECVENŢĂ, capacitate de decizie
riguroasă.
Împreună, principiile noncontradicţiei si terţului exclus, fundamentează demonstraţia
prin reducere la absurd – procedeu larg utilizat mai ales în matematică.

IV. PRINCIPIUL RAŢIUNII SUFICIENTE


Presupune că pentru a accepta sau pentru a respinge o propoziţie trebuie să avem o
raţiune suficientă sau, altfel spus, de un temei satisfăcător. Prin rațiune suficientă se înțelege
temei satisfăcător.
Fiind dată o propoziție oarecare p, spunem că dispune de un temei satifăcător q numai
dacă, fiind dat adevărul lui q devine imposibil ca p să nu fie și el adevărat.
Din adevăr trebuie să rezulte adevăr.
Din fals poate rezulta orice - atât propoziții false, cât și adevărate.
Există următoarele tipuri de temeiuri:

Nici necesare, nici suficiente:


Exemplu: În exemplul următor, fiecare propoziție reprezintă pentru cealaltă un temei nici
necesar și nici suficient
Exemplu: 1. Afară plouă. 2. Alex și Adrian sunt prieteni.

Necesare, dar nu și suficiente;

Suficiente, dar nu și necesare;


Exemplu: 1. Eminescu și Creangă au fost contemporani. 2. Eminescu l-a îndemnat pe
Creangă să scrie „Amintiri din copilărie”. Propoziţia 1 este temei necesar, dar nu și suficient
pentru propoziţia 2; Propoziţia 2 este temei suficient, dar nu și necesar pentru propoziţia 1.
Relaţia de la temei la întemeiat se formulează astfel: „dacă…, atunci…”

Necesare și suficiente
Exemplu: 1. Triunghiul ABC este isoscel. 2. Triunghiul ABC are unghiurile de la
bază congruente.
Relaţia de la temei la întemeiat se formulează astfel: „dacă și numai dacă …, atunci …”.
Propoziţia p este un temei necesar pentru propoziţia q, atunci când fără adevărul lui p nu se
poate dovedi adevărul lui q.
Propoziţia p este un temei suficient pentru propoziţia q dacă admiţând adevărul lui p devine
imposibil ca q să nu fie adevărată.
Logica nu acceptă ca argumente care se bazează pe: propoziții false, argumente de
autoritate de tipul pentru ca așa vreau, nici argumente care pot fi corecte, dar sunt incomplete
(precum cele inductive).
Apariția în cadrul limbajelor naturale (mai târziu, chiar în interiorul unor teorii
matematice) a unor propoziții ce nu respectă, principiul necontradicției, propoziții numite
antinomii (Constând dintr-o contradicție aparent insolubilă dintre două teze, legi sau
principii care, deși se exclud reciproc, pot fi demonstrate, fiecare în parte, la fel de
convingător) termen folosit cu precădere de filosofi, fie de paradoxuri orice propoziție corect
construită care este adevărată dacă și numai dacă este falsă, a impulsionat atât logica cât și
matematica spre rezolvarea cu prioritate a problemelor proprii de fundament.
Matematica până la un anumit punct, s-a format, dezvoltat și format pe baza logicii,
ulterior observându-se și o inversare de roluri: logica s-a formalizat utilizând metode
matematice. Există o corespondență perfectă între calculul propozițiilor și operațiile cu
submulțimile unei mulțimi nevide date.
De exemplu, disjuncției a două propoziții îi corespunde reuniunea a două mulțimi, și
reciproc. Din acest motiv, elementele de logică matematică se prezintă împreună cu cele de
teoria mulțimilor, suportul intuitiv al celei din urmă find de un real folos în înțelegerea și
aprofundarea a numeroase construcții logice abstracte. Putem să subliniem că au existat
logicieni (de exemplu Bertrand Russell- care au susținut teza că matematica este o ramură a
logicii). (Logică și teoria mulțimilor, Claudiu Volf & Ioan I. Vrabie
www.math.uaic.ro/~volf/depozit/LTM.pdf )

Definții. Propoziții
Logica operează cu definiții, propoziții (pe care le vom mai numi și enunțuri),
predicate (numite și funcții propoziționale), operatori logici, cuantificatori și reguli de
deducție.
Noțiunea reprezintă forma logică elementară care, în planul cunoașterii raționale,
reprezintă reflectarea claselor de obiecte.
Forma lingvistică ce materializează și comunică o noțiune are rol de nume pentru
elementele clasei refectate de noțiune.
Termenul este ansamblul format dintr-o noțiune și un nume.
Definiția este operația logică prin care se precizează conținutul sau sfera noțiunii,
înțelesul sau aria de aplicabilitate a unui nume.
O definiție are trei părți
1. definitul- (defniendum-lat)=noțiunea sau numele care formează obiectul definiției;
2. definitorul (definiens-lat) ceea ce spune despre obiectul definit;
3. relația de definire (notată :=, sau def ).

Clasificarea=operația logică prin care noțiuni mai puțin generale sunt grupate în baza
anumitor însușiri (sau note) în noțiuni mai generale.
Propoziția sau enunțul reprezintă o constatare spusă, scisă sau exprimată în orice alt
mod, care este fie adevărată (A sau 1), sau falsă (F sau 0). Propozițiile categorice exprimă un
raport între numai două noțiuni absolute.

Valorile de adevăr ale unei propoziții:


Adevărul-verum (lat.)
Falsul –falsum (lat.)
?- pentru proprietăți probabile

Structura propozițiilor categorice


-subiect logic S
-predicat logic P=ceea ce se spune despre subiectul logic.

Clasificare
-propoziții categorice afirmative=concordanță între S și P
-propoziții categorice negative=raport de opoziție între S și P

Enunțul =asamblaj de semne susceptibile de a purta informații, ce cuprinde două părți


 subiectul (subiectele) - despre care se comunică ceva;
 partea predicativă-ceea ce rămâne după eliminarea tuturor subiectelor (este unică).
Subiectele pot fi determinate sau nu. Dacă toate subiectele dintr-o propoziție sunt
determinate avem de a face cu o propoziție, în caz contar enunțul se numește predicat.
Subiectele nedeterminate se numesc variabile libere.

Exemple de propoziții
1. Parisul este capitala Franței.
2. Pătratul are toate laturile congruente.
3. Orice funcție continuă este derivabilă.

Enunțul este un predicat cu variabila liberă x,


Enunțul este un predicat cu variabila liberă x.

Clasificare enunțuri
-enunțuri atomice (simple)
-enunțuri compuse = enunțurile care se obțin folosind operatori logici
(Partea de logică a propozițiilor a fost sistematic construită de catre filozoful grec Aristotel în
urmă cu peste 2300 de ani.)

Definiții:
1. Negația (~p sau p) unei propoziții este falsă dacă și numai dacă p este
adevărată și este adevărată dacă și numai dacă p este falsă.

2. Conjuncția (& sau ˄) este adevărată dacă și numai dacă ambele propoziții
sunt adevărate. În caz contrar, ea este falsă.

Exemplu: Maria este o elevă bună la matematică și la desen.

3. Disjuncția / disjuncția neexclusivă (˅) este falsă dacă și numai dacă ambele
propoziții sunt false. Altfel, ea este adevărată.

Exemplu: Andreea este o elevă bună la matematică sau la desen.


4. Implicația (→ sau dacă p atunci q) este falsă dacă și numai dacă antecedentul
său (ceea ce urmează dupa dacă) este adevărat iar consecventul său (ceea ce urmează
după atunci) este fals.

Exemplu: Dacă ninge, atunci voi putea face oameni de zăpadă.

5. Echivalența (≡ sau ↔ sau dacă și numai dacă p atunci q) este adevărată dacă
și numai dacă propozițiile au aceeași valoare de adevăr. În caz contrar, ea este falsă.

Exemplu: Dacă și numai dacă ninge, atunci voi putea face oameni de zăpadă.

Simbolurile (și = ) sunt folosite pentru a specifica modul de structurare a unui enunț
compus, atunci când nu sunt stabilite alte reguli.
Un enunț format numai cu propoziții (numite și constante propoziționale-notate A,
B,...) dă naștere tot la o propoziție.
Formă propozițională= enunț care conține variabile propoziționale (simboluri ce pot
fi substituite cu constante propoziționale).

Notații
p,q, r... variabile propoziționale.
P, Q, R,...enunțurile (indiferent de natura lor)

Negația propoziției: dreptele d1 și d2 sunt paralele sau necoplanare este dreptele d1 și d2 nu


sunt paralele și nu sunt necoplanare, ceea ce, în virtutea pricipiului dublei negații, se
reformulează: dreptele d1 și d2 nu sunt paralele și sunt coplanare ( deducem că dreptele d1 si d2
sunt concurente). Aceeași negație se mai exprimă sub forma: dreptele d1 si d2 nu sunt paralele
și nici necoplanare.
Exemple:

Propoziția este adevarată într-o zi de marți cu ninsoare și este falsa in orice zi dacă nu e marți
și în orice zi de marți în care nu ninge.

2. Patrulaterul ABCD este romb și are un unghi drept.


Definiţia 6.

Fie F un enunţ în care varaiabila x este liberă (se mai foloseşte notaţia F(x) sau Fx, F
numindu-se variabilă predicativă, iar x variabilă individuală).

Enunţul x F(x) se numeşte cuantificarea universală a enunţului F în raport cu


variabila x. Dacă x este unica variabilă liberă a enunţului F atunci enunţul x F(x) este o
propoziţie.
Enunţul x F(x) se numeşte cuantificarea existenţială a enunţului F în raport cu
variabila x. Dacă x este unica variabilă liberă a enunţului F atunci enunţul x F(x) este o
propoziţie.

În enunţurile x F(x) şi x F(x) variabila x se numeşte variabilă legată.


Logică matematică și computațuională - Cursul 2

Limbajul logicii
Mulţimea constantelor propoziţionale, a variabilelor propoziţionale, a operatorilor logici,
a simbolurilor precum şi a regulilor de formare date prin definiţiile 1 - 5 care pornesc de la
propoziţii şi formează alte propoziţii, formează limbajul logicii propoziţionale. Limbajul logicii
predicatelor se obţine integrând lista de simboluri şi scheme propoziţionale de mai jos împreună
cu regulile de formare a expresiilor logice în limbajul logicii predicatelor.

Lista de simboluri şi scheme propoziţionale:

1. x, y, z, ... variabile individuale; a, b, c, ..., x1, y1 , x2, y2 , ..., constante individuale;

2. F, G, H, ... variabile predicative;

3. Fx, Fy, ... scheme de funcţii propoziţionale. Funcţia propoziţională nu este încă propoziţie,
dar ea poate fi transformată în propoziţie, fie prin substituirea variabilei cu o constantă, fie prin
cuantificare.
4. F(x,y), G(x,y,z), H(x,y,z,t), ... predicate binare, ternare, şi în general n-are;

5. Fa, Fb, Fc, ... scheme de propoziţii individuale;

6. xFx, yGy , ... scheme de propoziţii universale;

7. xFx, yGy, ... scheme de propoziţii existenţiale;

În cadrul teoriei limbajului logicii predicatelor identificăm următoarele reguli de


formare a expresiilor logice (formule bine formate):
1. Orice variabilă propoziţională este expresie logică.

2. Orice schemă de funcţie propoziţională este expresie logică.

3. Dacă E este expresie logică atunci E este expresie logică.

4. Dacă E(x) este o expresie logică cu x variabilă liberă atunci xE(x) şi xE(x) sunt expresii
logice.
5. Dacă E1 şi E2 sunt expresii cu proprietatea că în ele una şi aceeaşi variabilă nu apare într-una
liberă şi în cealălaltă cuantificată, atunci E1 E2, E1 E2, E1E2 şi E1E2 sunt expresii logice.

Exemple: Sunt expresii logice construcţii precum: p, q, r, ..., p, q, r, ..., Fx, G(x,y), Fx,
G(x,y), pFx, p(Fx), ..., p(Fx), ..., FxHy, ... xFxy(Hy), xyG(x,y) , ...
Valori de adevăr
Valoarea de adevăr a unei informaţii reprezintă gradul de concordanţă dintre informaţia
respectivă şi contextul în care aceasta este enunţată. Enunţurile bivalente sunt acele enunțuri
care pot avea ca valoare de adevăr: fals - simbolizat prin 0 - sau adevărat - simbolizat prin 1.
Orice propoziţie este în mod obligatoriu fie adevărată, fie falsă. Nici o propoziţie nu poate fi
simultan şi adevărată şi falsă.
Referitor la predicate, putem întâlni situaţia în care un predicat este ambivalent. Mai
precis, un predicat n-ar F(x1, x2 , ..., xn) este adevărat, respectiv fals, dacă toate propoziţiile
obţinute din acest predicat, prin precizarea variabilelor sale în toate modurile posibile sunt
adevărate, respectiv false. Deci stabilirea valorii de adevăr a unui predicat se reduce la stabilirea
valorii de adevăr pentru toate propoziţiile care generează predicatul.

Fie p şi q propoziţii oarecare. Valoarea de adevăr a propoziţiilor compuse p, pq,


pq, pq, pq se poate determina pornind de la valorile de adevăr ale enunţurilor
componente şi semnificaţia operaţiilor logice respective, conform următoarelor reguli:

Regula 1: Propoziţia p este adevărată dacă şi numai dacă propoziţia p este falsă; rezultă
că propoziţia p este falsă dacă şi numai dacă propoziţia p este adevărată.

Regula 2: Propoziţia pq este adevărată dacă şi numai dacă ambele propoziţii p şi q sunt
adevărate; rezultă că propoziţia pq este falsă dacă cel puţin una dintre propoziţiile p şi q este
falsă.

Regula 3: Propoziţia pq este adevărată dacă şi numai dacă cel puţin una dintre
propoziţiile p şi q este adevărată; rezultă că propoziţia pq este falsă dacă şi numai dacă ambele
propoziţii p şi q sunt false.

Regula 4: Propoziţia pq este o scriere prescurtată a enunţului (p )q.

Regula 5: Propoziţia pq este o scriere prescurtată a enunţului (pq)(qp).

Legile logice sau tautologii sunt propoziţii compuse care sunt adevărate independent de valorile
de adevăr ale enunţurilor component. Contradicţiile sunt propoziţiile care sunt false independent
de valorile de adevăr ale componentelor. Propoziţiile care pot fi adevărate sau false în funcţie de
valorile particulare ale enunţurilor componente se numesc propoziţii realizabile.
Problema deciziei

Problema fundamentală a logicii matematizate este problema deciziei: Fiind dată o expresie
logică să se decidă dacă ea reprezintă o lege logică (tautologie), o contradicţie sau o funcţie
simplu realizabilă.
Această problemă poate fi soluţionată prin mai multe mijloace dintre care amintim:
a) prin eliminarea treptată a necunoscutelor; b) prin algoritmi; c) pe baza metodei axiomatice.

Eliminarea treptată a necunoscutelor se face pe baza unor raţionamente prescurtate. Câteva


reguli utile, care decurg din definiţia valorii de adevăr a propoziţiilor compuse, sunt:
 dacă un membru al conjuncţiei este fals, atunci conjuncţia este falsă;
 dacă un membru al conjuncţiei este adevărat, atunci valoarea ei de adevăr depinde de
restul componentelor;
 dacă un membru al disjuncţiei este adevărat, atunci disjuncţia este adevărată;
 dacă un membru al disjuncţiei este fals, atunci valoarea ei de adevăr depinde de restul
componentelor;
 dacă q este propoziţie adevărată, atunci enunţul pq este adevărat oricare ar fi valoarea
de adevăr a propoziţiei p;
 dacă p este propoziţie falsă, atunci enunţul pq este adevărat oricare ar fi valoarea de
adevăr a propoziţiei q.

Metoda tablourilor de adevăr este utilă dar devine ineficientă dacă numărul componentelor este
mare. Pentru o propoziţie compusă care porneşte de la n enunţuri atomice sunt necesare 2n
rânduri în tabloul de adevăr, iar numărul de coloane depinde de structura propoziţiei. Pentru a
avea cât mai puţine coloane este necesară transformarea propoziţiei într-una echivalentă, dar cu
număr minim de conjuncţii.

O altă metodă elementară se bazează pe utilizarea regulilor de mai sus şi scrierea propoziţiei
supuse deciziei sub formă normală. Formele normale şi reguli utile pentru minimizarea
expresiilor logice vor fi date în lecţia 3. Metoda axiomatică, va fi prezentată într-una din lecţiile
viitoare.

Principalele legi logice (calculul propoziţiilor)

Primul grup de legi logice exprimă proprietăţile funcţiilor de adevăr denumite comutativitate,
asociativitate, distributivitate, idempotenţă, reflexivitate şi tranzitivitate. Notaţia E1 = E2
înseamna că formulele E1 şi E2 sunt logic echivalente, adică formula E1  E2 este identic
adevărată (tautologie). Următoarele grupuri prezintă tautologiile clasice.

Conjuncţia şi disjuncţia sunt comutative:

( 1) p  q = q  p;

( 2) p  q = q  p;
Conjuncţia şi disjuncţia sunt asociative:

( 3) p  (q  r) = (p  q)  r;

( 4) p  (q  r) = (p  q)  r;

Conjuncţia şi disjuncţia sunt distributive una faţă de alta:

( 5) p  (q  r) = (p  q)  (p  r);

Demonstrație relația (5):

Întrucât sunt 3 variabile propoziționale, în tabel trebuie să avem8 linii, corespunzătoare celor
combinații ale valorilor de adevăr ale lui p, q, r.

p q r pq pr (p  q)  (p  r) qr p  (q  r)


1 1 1 1 1 1 1 1
1 1 0 1 0 1 1 1
1 0 1 0 1 1 1 1
1 0 0 0 0 0 0 0
0 1 1 0 0 0 1 0
0 1 0 0 0 0 1 0
0 0 1 0 0 0 1 0
0 0 0 0 0 0 0 0

Obs: o propoziție compusă din k variabile propoziționale va genera un tabel linii.

( 6) p  (q  r) = (p  q)  (p  r);

Conjuncţia şi disjuncţia sunt idempotente:

( 7) p  p = p;

( 8) p  p = p;

Implicaţia şi echivalenţa sunt reflexive şi tranzitive:

( 9) p  p;

(10) p  p;

(11) ((p  q)  (q  r))  (p  r);

(12) ((p  q)  (q  r))  (p  r);


Relaţii de echivalenţă între expresiile logice:

În acest grup includem şi operaţiile de incompatibilitate (pentru “p este incompatibil cu q”


scriem p/q), excludere sau disjuncție exclusivă (pentru “p exclude q” scriem p W q; operaţia sau
exclusiv –) şi antidisjuncţie (“nici p, nici q”, pentru care scriem pq).

Definiție: O disjunție este exclusivă dacă și numai dacă propozițiile nu au aceeași valoare de
adevăr, în caz contrar ea este falsă.

Exemplu:

- Promovez examenul de Logică sau nu.


- Studenții fie sunt prezenți, fie nu sunt prezenți la examen.

(13) (p  q) = (p)  q;

(14) p / q = (p)  (q); (definiţia operatorului lui Sheffer)

(15) p W q = ((p)  q)  (p  (q));

(16) p  q = ((p)  q)  ((q)  p);

(17) p  q = (p)  (q);

(18) p = p / p;

(19) p  q = (p / q) / (p / q);

(20) p W q = ((p / (q / q)) / (q / (p / p));

(21) p  q = ( (p / (q / q)) / (q / (p / p)) ) / ((p / (q / q)) / (q / (p / p)) );

(22) p  q = ( (p / p) / (q / q) ) / ( (p / p) / (q / q));

(23) p  q = (p / p ) / (q / q);

(24) p  q = p / (q / q);

Legile absorbţiei:

(25) p  (p  q) = p;

(26) p  (p  q) = p;
Legile dublei negaţii:

(27) ((p))  p;

(28) ((p)) = p;

Legile lui De Morgan:

(29) (p  q) = (p)  (q);

(30) (p  q) = (p)  (q);

Legile implicaţiei materiale:

(31) p  (q p); “Adevărul decurge din orice.”

(32) (p)  (p  q); “Falsul implică orice.”

Legile reducerii la absurd:

(33) (p (p))  (p);

(34) ((p  q)  (p  (q)) )  (p);

Conjuncţia implică partea sa:

(35) (p  q)  p;

(36) (p  q)  q;

Disjuncţia este implicată de partea sa:

(37) p  (p  q);

(38) q  (p  q);

Legea “modus ponens”: “Dacă este adevărat p  q şi este adevărat p, atunci este adevărat q.”
(39) ((p  q)  p)  q;

Legea “modus tollens”:


(40) (p  q)  (q)  p;

Legea noncontradicţiei: “Nu este adevărat că p şi non p.”


(41) (p  (p));
Legea terţului exclus: “Este adevărat p sau este adevărat non-p.”
(42) p  (p);

Legile excluderii:
(43) (p  q)  (p  (q)) = p;

(44) (p  q)  (p  (q)) = p;

Legea contrapoziţiei:
(45) (p  q)  ((q)  (p));

Legea silogismului:
(46) (p  q)  ((q  r)  (p  r)).

Echivalenţe logice în calculul predicatelor. Problema deciziei

Cu notaţiile cunoscute au loc următoarele echivalenţe logice:

( 1) xF(x) = (x(F(x)));

( 2) x(F(x)) = (x F(x));

( 3) xF(x) = (x(F(x)));

( 4) xF(x) = (x F(x));

( 5) xyG(x,y) = yxG(x,y);

( 6) xyG(x,y) = yxG(x,y);

Într-o formulă cuantificatorii ocupă diverse locuri. Pentru cuantificatori de acelaşi tip
(omogeni) ordinea este indiferentă, nu acelaşi lucru se întâmplă pentru cuantificatori de tipuri
diferite după cum rezultă din:
( 7) xyG(x,y)  yxG(x,y);

În membrul stâng x este pentru toţi y, iar în membrul drept x depinde de y. Rezultă că
trecerea inversă nu este posibilă.

Proprietatea de distributivitate este întâlnită şi la expresii ale calculului cu predicate:


( 8) x(F(x)  G(x)) = xF(x)  xG(x);

( 9) x (F(x)  G(x)) = xF(x)  xG(x);


(10) x(F(x)  G(x))  (xF(x)  xG(x));

(11) (xF(x)  xG(x))  x(F(x)  G(x));

(12) x(F(x)  G(x))  (xF(x)  xG(x));

(13) (xF(x)  x G(x))  x (F(x)  G(x));

Problema deciziei în logica predicatelor este mult mai complicată decât în calculul propoziţiilor.

Exercițiu:

Construiți tabela de adevăr pentru: (p  q)  p  q

p q q p  q pq (p  q)  p  q
1 1 0 1 1 1
1 0 1 1 0 0
0 1 0 0 0 1
0 0 1 1 0 0

Exemplu:

La curs, profesorul Moisil folosea frecvent exemplul: „Care este negarea propoziției „Plouă, deci
îmi iau umbrela?” ”.

Răspunsul era: „Plouă și nu îmi iau umbrela ”

Propunere temă: Demonstraţi folosind metoda tabelului valorilor de adevăr legile calculului
propoziţional (1) – (46), enunţate mai sus.
Elemente de calcul al predicatelor

Putem spune, fără a exagera, că aproape orice teoremă din


matematică este un enunţ ce conţine unul sau mai multe predicate.

Să considerăm enunţurile:

 „ x+ 5 < 12";
Se vede că dacă înlocuim x cu 8, obţinem propoziţia falsă „8 + 5 < 12".
Dacă facem x =3, obţinem propoziţia adevărată „3 + 5 < 12" etc.

 “x divide y".
Pentru x = 2 şi y= 6 obţinem propoziţia adevărată „2 divide 6".
Pentru x= 4 şi y= 6 obţinem propoziţia falsă „4 divide 6" etc.

Un enunţ care depinde de una sau mai multe variabile şi are


proprietatea că pentru orice „valori " date variabilelor corespunde o
propoziţie (adevărată sau falsă) se numeşte predicat (sau propoziţie cu
variabile).
De fiecare dată când definim un predicat, trebuie să indicăm şi
mulţimile în care variabilele iau valori.

Exemplu.
Predicatul p(x): " x < 8, x ∈ R " are domeniul de referinţă mulţimea
numerelor reale iar partea predicativă constă din textul " …este mai mic
decât … " Predicatul are două subiecte: "x" şi "8", dintre care unul
nedeterminat, prin urmare, este un predicat cu o variabilă.

Exerciţiu.
Fie p(x) predicatul " x < 8, x ∈R ". Care sunt valorile de adevăr ale
propoziţiilor p(2) şi p(14) ?

Exemplu.
Fie p(x, y) predicatul " x+y=5 ". Care sunt valorile de adevăr ale
propoziţiilor p(2,0) şi p(5,0) ?
Soluție:
Propoziţia p(2,0) obţinută atribuind lui x, y valorile x = 2, y = 0 este o
propoziţie falsă, în timp ce propoziţia p(5,0) obţinută atribuind lui x, y
valorile x = 1, y = 0 este o propoziţie adevărată.

Fie p(x), q(x) predicate unare. Cu ajutorul operatorilor logici


construim şi alte predicate unare, anume: p(x), p(x)∨q(x), p(x)∧q(x),
p(x)→q(x), p(x)↔q(x).
Astfel, de exemplu, pentru predicatul p(x), p(x) este predicatul căruia
pentru fiecare valoare x = a îi corespunde propoziţia p(a).
Regulile de negaţie stabilite anterior, sunt valabile şi în cazul general.
Deci pentru orice predicat unar p(x) avem:
a) ((∀x) p(x)) ⇔ (∃x)( p(x))
b) (∃(x) p(x)) ⇔ (∀x) ( p(x))

Exemplu:
Să considerăm predicatul p(x): " (∃x∈N) astfel încât x+1=2 " a cărui
valoare de adevăr este adevărul. Negaţia ei este propoziţia p(x): " (∀x∈N) ,
avem x+1≠2" evident o propoziţie falsă.

1) O propoziție care depinde de un parametru este un predicat ce depinde


de o variabilă.
Un predicat este o funcție definită pe mulțimea (clasa) unde se
găsește variabila / parametrul cu valori în mulțimea P a propozițiilor:
P:Γ  P - predicat
P(α) este o propoziție , α  Γ.
2) “ x 2  y 2  x  y x  y , x, y  R ” este un predicat de două variabile.
Mulțimea în care variabilele iau valori a fost precizată.
Se admite omiterea scrierii mulțimii Γ doar dacă aceasta este clară din
context.

“ x 2  1  0 ” este considerată predicat numai dacă precizăm x   , unde Γ


poate fi N, Z, Q, R, C.

P(x): x 2  1  0 cu x  R este un predicat ale cărui valori sunt toate false;


P(x): x 2  1  0 cu x  C este un predicat pentru care P(i) și P(-i) sunt
adevărate iar restul valorilor sunt false.
Un predicat care are toate valorile (propozițiile) egalități se numește
ECUAȚIE. O soluție a ecuației este valoare pentru care egalitatea este
satisfăcută, adică propoziția obținută prin înlocuirea variabilei cu soluția este
adevărată. A rezolva o ecuație înseamnă a găsi mulțimea tuturor soluțiilor ei.

Cuantificatori. Variabile libere. Variabile legate.

Fie predicatul unar p(x), unde x reprezintă un element oarecare din


mulțimea Γ. Pornind de la acest predicat putem forma două enunțuri:
1. ∃ x   astfel încât P(x) este adevărată
2. ∀ x   , P(x) este adevărată.

Subliniem că acestea sunt propoziții și nu predicate.

Fie predicatul de forma


P(x): “x este un câine” este un predicat unar. P poate fi interpretat “ ______
este un câine”. Dacă patrocle este un câine, atunci P(patrocle): “patrocle este
un câine”.
Termenii încep cu literă mică (patrocle, nu Patrocle ca în limbajul
Prolog). Termenii sunt elementele pe care le dăm ca argumente pentru
predicate.
 Orice constantă este un termen (se notează cu litere mici de la
începutul alfabetului);
 Orice variabilă este un termen.

1. Cuantificatorul universal ∀
Scrierea Γ P(x) poate fi interpretată ca o conjuncție extinsă a
tuturor propozițiilor P(x) după x  
x P x   P(x).
Într-adevăr, dacă Γ atunci ∀ x   , P(x) are aceeași
valoare de adevăr cu P(1) P(2) ..... P(n).

2. Cuantificatorul existențial ∃:
(∃ x   )P(x) poate fi interpretată ca o conjuncție extinsă a tuturor
propozițiilor P(x) după x  
x P x   P(x).
Într-adevăr, dacă Γ atunci ∃ x   , P(x) are aceeași
valoare de adevăr cu P(1) P(2) ..... P(n).

Concluzie: Cu ajutorul cuantificatorilor ∀și ∃, pornind de la un


predicat de o variabilă P(x), obținem două propoziții: (∀ x   ), P(x) și (∃
x   ) P(x).

Exemplu: Pornind de la predicatul unde , obținem

- propoziție falsă
(dacă x=0 2*0-1=-1<0);
- propoziție adevărată
(dacă x=5 2*5-1=9>0).

În predicatul “p(x), x   ” x este o variabilă liberă - ia valori


arbitrare din Γ și obținem propoziții adevărate sau false, iar în propoziția (∀
x   ), p(x) are valori bine determinate, independent de variabila x 
variabilă legată. Un predicat este bine precizat de enunțul său și de
mulțimile în care variabilele iau valori (aceste mulțimi formează ceea ce se
numește domeniul de definiție al predicatului).

Afirmația xP(x) este adevărată când P(x) este adevărat pentru orice x
și este falsă când există un x pentru care P(x) este fals, iar afirmația xP(x)
este adevărată când există un x pentru care P(x) este adevărat și este falsă
când P(x) este fals pentru orice x.

Predicate de mai multe variabile.

Fie P(x, y) un predicat binar. Folosind cuantificatorii ∃ și ∀ putem forma


predicatele unare:
(∃x) P(x,y ) și (∀x)P(x,y) unde y este variabila liberă și x este variabila
legată a acestor două predicate. Din aceste predicate unare putem forma
predicatele:
(∃y)( ∃x) P(x, y),
(∀y)(∃x)P(x,y),
(∃y)(∀x)P(x,y),
(∀y)(∀x)P(x,y),
Deasemenea mai putem forma următoarele predicate:
∀x P(x,y) ∃x Q(x,y ),
∀x P(x,y) ∃y Q(x,y ).

În schimb,
∀x P(x,y) ∃y Q(x,y ) nu este predicat deoarece variabila y apare liberă în
primul predicat și legată în al doilea predicat.

În continuare vom arăta cum se deduc legile de negaţie pentru predicatele


binare, din legile de negaţie pentru predicate unare.
Adică:
a) ((∀)y(∃x) p(x,y)) ⇔ ∃y( ∃x) p(x,y)) ⇔ ∃y(∀x) p(x,y))
b) ((∃)y(∃x) p(x,y)) ⇔ ∀y( ∃x) p(x,y)) ⇔ ∀y(∀x) ( p(x,y))

Aceste rezultate se extind analog la predicatele n-are.

Echivalenţe logice în calculul predicatelor. Problema deciziei

Două predicate sunt echivalente dacă oricum am alege valorile


variabilelor, propoziţiile au aceeaşi valoare de adevăr. Echivalenţa a două
predicate se demonstrează la fel ca şi echivalenţa a două propoziţii.

Cu notaţiile cunoscute au loc următoarele echivalenţe logice:


( 1) xF(x) = (x( F(x)));
( 2) x(F(x)) = (x F(x));
( 3) xF(x) = (x( F(x)));
( 4) xF(x) = (x F(x));
( 5) xyG(x,y) = yxG(x,y);
( 6) xyG(x,y) = yxG(x,y);
Într-o formulă cuantificatorii ocupă diverse locuri. Pentru
cuantificatori de acelaşi tip (omogeni) ordinea este indiferentă, nu acelaşi
lucru se întâmplă pentru cuantificatori de tipuri diferite după cum rezultă
din:
( 7) xyG(x,y)  yxG(x,y);
În membrul stâng x este pentru toţi y, iar în membrul drept x depinde
de y. Rezultă că trecerea inversă nu este posibilă.
Proprietatea de distributivitate este întâlnită şi la expresii ale calculului cu
predicate:
( 8) x(F(x)  G(x)) = xF(x)  xG(x);
( 9) x (F(x)  G(x)) = xF(x)  xG(x);
(10) x(F(x)  G(x))  (xF(x)  xG(x));
(11) (xF(x)  xG(x))  x(F(x)  G(x));
(12) x(F(x)  G(x))  (xF(x)  xG(x));
(13) (xF(x)  x G(x))  x (F(x)  G(x));

Exemplu:

Care este negarea afirmației:

“Toți studenții din anul I urmează cursul de Logică matematică și


computațională.” Această afiemație este o cuantificare universală: ∀ x P(x),
unde P(x): “x urmează cursul de Logică matematică și computațională”.
Negația afirmației este: “Există un student din anul I care nu urmează cursul
de Logică matematică și computațională.” – aceasta este cuantificare
existențială a negației funcției propoziționale date de ∀x P(x).

Obs: când domeniul lui P(x) constă din n elemente, regulile de negare
ale afirmațiilor sunt identice cu legile lui De Morgan din logica propozițiilor.
Acesta este motivul pentru care aceste reguli se numesc legile lui De
Morgan pentru cuantificatori.

Exemple:

1.Care sunt negațiile propozițiilor:


a) “Tuturor copiilor le place ciocolata”;
b) “Există un politician cinstit”;
c) “Există un număr natural x a.î. f(x) > 2”.

Soluție:
a) Notăm “x le place ciocolata” cu C(x). Afirmația se scrie xC(x) iar
domeniul este reprezentat de toți copiii. Negația afirmației este
xC(x) care este echivalentă cu x C(x) care se exprimă astefl: ”
Există un copil căruia nu îi place ciocolata”;
b) Notăm “x este cinstit” cu D(x). Afirmația se exprimă xD(x) , iar
domeniul este reprezentat de toți politicienii. Negația afirmației este
xD(x) care este echivalentă cu x D(x), ce se exprimă “Orice
politician este necinstit”;
c) “Pentru orice număr natural avem f(x) ≤ 2”.

2. Se consideră predicatul unar p(x): “ R”. Formulați


propoziția universală xp(x) și cea existențială xp(x) și stabiliți valorile
de de adevăr ale celor două propoziții.

Soluție:
Propoziția universală este: x p(x): “oricare ar fi ”
– propoziția este falsă deoarece pentru x = 0 obținem propoziția “p(0): 6=0”
care este falsă.
Propoziția existențială x p(x): “există R astfel încât ”
– propoziția este adevărată deoarece pentru x1 = -2 și x2= -3 obținem
propoziția “p(-2): 0=0” care este adevărată și “p(-3): 0=0” care este
deasemenea adevărată, așadar există cel puțin un x pentru care propoziția
este adevărată .

3. Arătați că x (P(x)→Q(x)) și x(P(x) Q(x)) sunt logic echivalente.

Soluție:
Din negarea pentru expresii cuantificate avem
x (P(x)→Q(x)) ≡ x (P(x)→Q(x))
(P(x)→Q(x)) ≡ ( P(x) Q(x)) dar din legile lui De Morgan
( P(x) Q(x)) ≡ (P(x) Q(x)) pentru orice x
Datorită faptului că putem subsitui o expresie logică cu una echivalentă
x (P(x)→Q(x)) ≡ x(P(x) Q(x))

4. Exprimați afirmația “Un student din anul I a luat nota 10 la examenul de


logică matematică și computațională” folosind predicate si cuantificatori.

- Există un student x din anul I cu proprietatea că x a luat nota 10 la


examenul de logică matematică și computațională.
- Notăm P(x): “x a luat 10 la examenul de logică matematică și
computațională”
- Domeniul pentru x este format din mulțimea tuturor studenților
din anul I, atunci putem scrie x(P(x)
- Dacă luăm în considerare mulțimea tuturor oamenilor , atunci
“există o persoană x în anul I cu proprietatea că x a luat nota 10 la
examenul de logică matematică și computațională”
- S(x) : “ x este student în anul I”
- Soluția este: x(P(x) S(x)).
Soluția nu se poate scrie / traduce sub forma x(S(x)→ P(x)).

5. Exprimați “Orice student din anul I promovează examenul fie la Algebră


fie la Logică” folosind predicate și cuantificatori.

- Reformulăm: “Pentru orice x din anul I, x cu proprietatea că


promovează examenul fie la Algebră fie la Logică”
- M(x): “x promovează examenul la Algebră”
P(x): “x promovează examenul la Logică”
- Domeniul lui x este format din mulțimea tuturor studenților din
anul I, atunci avem x (M(x) P(x))
Dacă luăm domeniul tuturor oamenilor, atunci reformulăm “Pentru
fiecare persoană x, dacă x este student în anul I, atunci x promovează
examenul fie la Algebră fie la Logică”
- Traducerea x(S(x)→ M(x) P(x)).
Axiomatizarea logicii propoziţiilor

1. Preliminarii

Un sistem axiomatic se construieşte astfel:


a) se specifică lista semnelor;
b) se specifică regulile de formare a formulelor compuse din formule date;
c) se specifică lista de axiome (şi eventuale definiţii);
d) se specifică regulile de deducţie.

Conceptele fundamentale ale unui sistem axiomatic sunt:


- definiţia este o propoziţie sau o formulă prin care unele expresii sunt introduse pe baza
altora;
- regula este o propoziţie cu ajutorul căreia din propoziţii date (una sau mai multe),
respectiv din formule date putem obţine alte propoziţii, respectiv formule;
- teorema este orice propoziţie (resp. formulă) dedusă din axiome pe baza regulilor de
deducţie;.
Axioma este o propoziţie (resp. o formulă) luată ca demonstrată în sistemul considerat.

Un sistemul axiomatic trebuie să fie consistent (necontradictoriu) (deci mulțimea tezelor să nu


coincidă cu mulțimea formulelor).

Un sistem axiomatic poate fi:

 - complet sintactic;
 - complet semantic;
 - independent;
 - deductiv.
2. Sistemul axiomatic Hilbert-Ackerman [1950]
Lista de simboluri:
Variabile propoziţionale: p, q, p1 , p2, …
şi paranteze pentru a indica ordinea de efectuare a operaţiilor.
Operatorii (de bază) :  (or) , (not).
Se acceptă că este mai prioritar decât .
Operatori introduşi prin definiţie: , ,   

Reguli de formare:
1. Variabilele propoziţionale sunt formule;
2. Dacă A este formulă atunci A este de asemenea o formulă;
3. Dacă A şi B sunt formule atunci AB, AB, AB, AB, A  B, A B sunt de
asemenea formule.

Definiţii:
D1: p  q = p  q;
D2: p  q = ( p  q)
D3: p q = ( ( pq)  ( qp) )
D4: p / q = p  q
D5: p q = (pq).

Axiome:
A1: (p  p)  p;
A2: p  (p  q);
A3: (p  q)  (q  p);
A4: ( p  q)  ((r  p)  (r  q))

Reguli de deducţie:

1. Regula detaşării (modus ponens): Dacă este demonstrat A şi dacă este demonstrat
A  B, atunci este demonstrat B. Scriere prescurtată: {A, AB ├ B}.
Exemplu:
Dacă este duminică, mergem la plimbare.
Este duminică, deci mergem la plimbare.

2. Regula substituţiei: Într-o formulă A, o variabilă propoziţională p poate fi substituită


cu o formulă oarecare B, cu condiţia ca variabila p să fie înlocuită cu formula B,
oriunde apare în formula A. Notaţie: s(A, p, B) sau s(p, B) când formula A se
subînţelege.

3. Regula idempotenţei disjuncţiei: A  A ├ A.


Considerăm axioma A1 şi efectuăm s(p, A). Obţinem: (A A)  A. Prin aplicarea regulii
modus ponens obţinem: {A  A, (A A)  A ├ A}.
4. Regula extinderii disjuncţiei: A ├ A  B.
Considerăm A2 şi efectuăm substituţiile s(p, A), s(q, B), adică: A  (A  B). Aplicăm
regula modus ponens şi obţinem: {A, A  (A  B) ├ (A  B)}.

5. Regula comutativităţii disjuncţiei: (A  B) ├ (B  A).


Considerăm A3 şi efectuăm substituţiile s(p, A), s(q, B), adică: (A  B)  (B  A).
Aplicăm regula modus ponens şi obţinem: { A  B, (A  B)  (B  A) ├ (B  A)}.

6. Regula extinderii disjunctive a termenilor implicaţiei:


(AB) ├ ((CA)  (CB)).
Considerăm A4 şi efectuăm substituţiile: s(p, A), s(q, B) şi s(r, C), adică:
(AB)  ((CA)  (CB)). Se aplică regula modus ponens şi rezultă:
{ AB, (AB)  ((CA)  (CB)). ├ (CA)  (CB)}.

Teoreme: Teorema este orice propoziţie (resp. formulă) dedusă din axiome pe baza
regulilor de deducţie. Se poate introduce noţiunea de formulă demonstrabilă sau teoremă că
fiind o formulă pentru care există o demonstraţie formală, adică un şir de formule compus din
substituţii în axiome sau formule demonstrabile şi formule obţinute prin reguli de deducţie din
termeni anteriori ai şirului. Dacă  este formulă demonstrabilă numai din axiome scriem├ .
Observăm că teoremele sunt formule demonstrabile din axiome. Dacă în afară de axiome, în
deducerea formulei , se adaugă şi alte formule dintr-o mulţime H (pe care le vom numi
ipoteze) atunci spunem că  este deductibilă din familia de ipoteze H şi scriem H ├ .
Teorema 1: |- (p  q)  (( r  p)  (r  q))
Justificare: Demonstraţia formală are următorii termeni (cei din coloana a doua):
A4: ( p  q)  ((r  p)  (r  q))
S(r, r) : ( p  q)  (( r  p)  ( r  q))
D1: ( p  q)  (( r  p)  ( r  q)).

Silogismul este o formă de argumentare logică în care o propoziție (concluzia) este


inferată din alte două propoziții (premise).
Exemplu: „Tuturor oamenilor le plac surprizele; toți copiii sunt oameni; deci tuturor
copiilor le plac surpizele”. Aristotel a definit silogismul drept „o vorbire în care, dacă ceva a fost
dat, altceva decât datul urmează cu necesitate din ceea ce a fost dat”. Silogismul reprezintă un
raționament deductive.
Regula silogismului sau regula tranzitivităţii: Dacă este demonstrată formula A  B şi
este demonstrată formula B  C atunci rezultă că este demonstrată formula A  C. Scriere
prescurtată: {A  B, B  C} ├ (A  C).
Termenii demonstraţiei formale (în italic şi regulile aplicate) sunt:
Teorema 1:
(p  q)  (( r  p)  (r  q))
s(r, A), s(p, B), s(q, C):
(B  C)  (( A  B)  (A  C))
modus ponens:
{ B C , (BC)  (( AB)  (AC)) ├ ( A  B)  (A  C)}
modus ponens:{A  B, ( A  B)  (A  C) ├ (A  C) }
Teorema 2: ├ ( p p).
Justificare: Termenii demonstraţiei formale pentru formula ( p p) sunt:
p  (p  q) (axioma A2),
s(q, p): p  (p  p), p  p  p (axioma A1), p  p (modus ponens),
p  p (conform D1)

Teorema 3: ├ (p  p)
Justificare: Rezultă din teorema 2 şi Regula comutativităţii disjuncţiei.

Teorema 4: ├ p  ( p).
Justificare: Conform teoremei 3, formula (p  p) este demonstrabilă. Aplicăm
s(p, p), adică ├ p  p, iar prin D1 obţinem ├ p  p.

Teorema 5: ├ ( p)  p.
Justificare: Avem succesiv: ├ p  ( p) (teorema 4); aplicăm s(p, p) şi rezultă ├ p  p.
Aplicăm regula extinderii disjunctive a termenmilor implicaţiei. Rezultă: p  p  p  p. Dar
├ p  p (teorema 3), aplicăm regula modus ponens şi obţinem: ├ p  p. Prin regula
comutativităţii disjuncţiei obţinem:
├ p  p, iar din definiţia D1 rezultă: ├ p  p.

Teorema 6: ├ (pq) ( q  p).


Justificare: Conform teoremei 4, prin substituirea lui p u q rezultă ├ q  ( q). Prin regula
extinderii disjunctive a termenilor implicaţiei ├ pq p  q. De asemenea, din axioma 3,
prin substituirea lui p cu p, respectiv q cu q. Se obţine ├ p  q  q  p. Folosind regula
silogismului obţinem pq  q  p. Folosind definiţia 1 obţinem ├ (pq) ( q  p).

Regula substituirii expresiilor echivalente. Dacă două formule se deduc una din alta
atunci pot fi puse una în locul alteia.

Proprietățile sistemelor axiomatice

Pentru a fi acceptat, un sistem axiomatic SA trebuie să satisfacă următoarele proprietăți formale:

- NECONTRADICȚIA: Un SA este necontradictoriu dacă și numai dacă, în el, nu poate fi


demonstrată o formulă împreună cu negația ei;
- INDEPENDENȚA: Un SA este independent dacă nici una dintre axiomele sale nu poate
fi dedusă din restul axiomelor (nu toți logicienii consideră acestă cerință obligatorie);
- COMPLETITUDINEA: Un SA este complet dacă adăugându-i o formulă F
nedemonstrabilă în SA, obținem o contradicție.
Aceste proprietăți se verifică, de obicei, cu ajutorul unei intrepretări (adică se trece de la aspectul
sintactic la cel semantic).

Teorema de consistență:
Propoziția 4.1:
a) Pentru ∀m > 0, A1, A2, ….Am ├ Ai, i=1,...m
b) Pentru ∀ N dacă
A1, A2, ...., Am ├ Bi, i=1,...m
iar B1, B2, ....Bp ├ C
atunci A1 , A2, ...., Am ├ C

Justificare: Fiecare apariție a lui B1, B2, ....Bp se înlocuiește cu demonstrția sa


Propoziția 4.2:
a) Dacă ├ A→B, atunci A ├ B;
b) Pentru ∀m > 0, dacă A1, A2, ….Am-1 ├ Am →B, atunci A1, A2, …. Am ├ B.

Teorema deducției:
a) Dacă A ├ B, atunci ├ A →B;
b) Dacă A1, A2, ….Am-1 , Am ├ B, atunci A1, A2, ….Am-1 ├ Am →B.

Teorema de consistență pentru calculul propozițiilor: Orice teoremă (formulă demonstrabilă


din axiome) este o tautologie.

Corolar (Proprietatea necontradicției): Nu există formulă B astefel încât ├ B și ├ B.


Justificare: Presupunem ├ B, ├ B ╞B și ╞ B absurd (rezultat din tabela de adevăr).

Propoziția 4.3: Au loc următoarele reguli de includere / eliminare


a) Dacă H, A├ B, atunci H├ A→B;
b) A, B ├ A˄B;
c) A├ A˅B, B├ A˅B;
d) Dacă H, A├ B și H, A├ B, atunci H├ A;
e) Dacă A →B și B →A, atunci A↔B;
f) A, A →B ├ B;
g) A˄B├ A, A˄B├ B;
h) Dacă H, A ├ C și H, B ├ C, atunci H, A˅B ├ C;
i) A├ A, A, A├B;
j) A↔B├ A →B și A↔B├ B →A.
Propoziția 4.4: Fiecărei intrări (rând) din tabelul de adevăr al oricăruia dintre operatorii
considerați îi corespunde o deducție.
Justificare. Pentru implicaţie, se pot justifica deducţiile:
A B AB
0 0 1 A, B ├ A  B
0 1 1 A, B ├ A  B
1 0 0 A, B ├ ( A  B)
1 1 1 A, B ├ A  B

Propoziția 4.5: Fie E o formulă cu atomii P1 , P2 , ...., Pn . Considerăm tabelul de adevăr pentru E.
Atunci pentru fiecare din cele 2 n rânduri ale tabelului există o deducție.

Propoziția 4.6: Dacă formula E din propoziția 4.5 este tautologie, atunci P1 ˅ P1,..., Pn˅ Pn ├ E.

Teorema de completitudine – calcul propozițional:


Dacă E este tautologie, atunci E este teoremă.

Propunere temă: Să se obţină demonstraţii formale pentru următoarele afirmaţii:


1. ├ (p q)  p  q.
2. ├ p  q  (p q)
3. ├ (pq)  p  q.
4. ├ pq  q  p
5. ├ qp  p  q
6. ├ pq p
7. ├ pq q
8. ├ p(qr)  q(pr)
9. ├ p(qr)  (pq)r
10. ├ (pq)rp(qr)
11. ├ p(qr)(pq)r
12. ├ (pq)rp(qr)
13. ├ p (qpq)
14. ├ p(qr)  (pq) (pr).
INTRODUCERE ÎN PROLOG
Limbajul Prolog (PROgrammation en LOGique) a fost creat de Alan
Calmaureur (1972) de la Universitatea din Marsilia, Franța, s-a afirmat ca un produs
de cercetare pentru inteligență artificială. Prolog este un limbaj simbolic, de calcul
nenumeric, folosit pentru rezolvarea problemelor ce implică obiecte și relații între
obiecte.
Prolog = Programming in Logic. Prolog este un limbaj declarativ ce constă
dintr-o mulțime de fapte și legături logice care descriu problema de rezolvat.
Limbajul Prolog nu descrie cum calculează o soluție. Deosebirea între Prolog și
celelalte limbaje de programare constă în faptul că în Prolog utilizatorul nu trebuie să
ruleze programul pentru afișarea soluției, el doar pune o întrebare (interogare).
Prolog are un câmp de aplicaţii foarte larg: baze de date relaţionale, inteligenţă
artificială, logică matematică, demonstrarea de teoreme, sisteme expert, rezolvarea de
probleme abstracte sau ecuaţii simbolice, etc.
Există standardul ISO-Prolog. Nu există standard pentru programare orientată
obiect ȋn Prolog, există doar extensii: TrincProlog, SWI-Prolog (1986). Exemplele ce
vor urma au fost realizate în SWI-Prolog – sintaxa e foarte apropiată de cea a
standardului ISO-Prolog.
Prolog-ul transformă logica în calcul.

La baza acestui limbaj de programare stă teoria calcului cu predicate de


ordinul întâi.

Scheme de ordinul I:
- rezulta prin aplicarea variabilelor predicative asupra unor variabile individuale;
- aplicarea cuantificatorilor asupra variabilelor individuale conduce la scheme de
ordinul întâi.

Scheme de ordinul II:


- aplicarea cuantificatorilor asupra variabilelor predicative.

În logica calculului predicatelor, obiectele lumii reale sunt modelate cu ajutorul


simbolurilor

Simboluri - de constante (indică un singur individ sau concept);


- de variabile (se referă la momente diferite, la indivizi diferiţi);
- pentru termeni compuşi (se obţin cu ajutorul unui simbol funcţional aplicat
unor simboluri, numite argumente).

FORMA CAUZALĂ

În Prolog formulele calculului cu predicate trebuie scrise sub forma cauzală


(normală).

a) eliminarea implicaţiei pq =  pq

b) mutarea negaţiei în interior

Exemplul 5.1: not(x) or not(y) în loc de not(x and y)


 (pq)=  p q
 (pq)=  p q
 (xFx)= x(  Fx)
 (xFx)= x(  Fx)

c) Skolemizarea formulelor: Eliminarea cuantificatori universali produce formele


Skolem
O formulă existenţială de tipul x FxG(x,y) este înlocuită cu Fx1 G(x1,y).
Pentru o formulă care conţine cuantificatorul universal, înlocuirea se face astfel:

Exemplul 5.2:
Formula “Orice om are o mamă”
[xOm(x)  yMama(x,y)]
poate fi prelucrată
[xOm(x) Mama(x,G(x)]
unde
G(x) furnizează Mama (x)

d) Scoaterea cuantificatorilor universali în exterior


În această etapă cuantificatorii existenţiali au fost deja eliminaţi (punctul c)).
Formula
xFx y (G(y) Z(x,y) ) se transformă
xy (Fx (G(y) Z(x,y))).

e) Aplicarea legii distribuţiei conjuncţiei faţă de disjuncţie:


(pq)r=(pr)  (qr)
p(qr)=(pq)  (pr)

Exemplul 5.3:
Fx  (G(y,x) Py  Qy) se transformă în
(Fx  G(y,x) (Fx  (Py  Qy))

f) Scrierea în formă clauzală (obţinerea formei normale conjunctive care va


furniza clauzele)
Exemplul 5.4:
Formula
persoana( ˮAdamˮ)persoana(ˮEvaˮ)((persoana(x)  mama(x,y))  persoana(y))
are trei clauze:
 clauza 1: persoana ˮAdamˮ
 clauza 2: persoana ˮEvaˮ
 clauza 3: compusă din trei elemente: - persoana (x)
- mama (x,y)
- persoana (y)

predicates
persoana(string)
mama(string, string)
clauses
persoana(“Adam”).
persoana(“Eva”).
persoana(X) :- mama(X, Y), persoana(Y).

Un program Prolog conține:


- Fapte despre obiecte și relațiile existente între obicete. Faptele sunt predicate
de ordinul I de aritate n considerate adevărate. Predicatele stabilesc relațiile între
obiecte. Faptele sunt afirmații despre proprietățile obiectelor și relațiile existente între
ele.

 Fapte de tip proprietate(obiect):


Exemplu: Coco este papagal: papagal(coco).
Oricine (X) este muritor: muritor(X).
 Fapte care exprimă relații între obiecte:
Exemplu: Mihai o iubește pe Maria: iubeste(mihai,maria).
Oricine (X) este egal cu sine însuși: egal(X,X).
Exemplul 5.5:
FAPT ARITATE
elev(maria) 1
surori(maria,andreea) 2
bun(tudor,stefan) 2
mută(calculatoarele,sediul,str.Fabricii) 3

- Reguli depre obiecte și relațiile dintre ele (o regulă exprimă un fapt care
depinde de alte fapte);
O regulă, în limbaj natural, este o frază de forma: Dacă ipoteza1 și . . . și
ipoteza n atunci concluzie ↔ concluzie dacă ipoteza1 și . . . și ipoteza n. Regula
corespunzătoare în PROLOG este expresia: concluzie :- ipoteza1; : : : ;
ipoteza n, unde ipoteza1, . . . , ipoteza n, concluzie sunt atomi.
- Scopuri = întrebări = răspunsul la o întrebare (poate fi afirmativ, yes, sau
negativ, no).

Prolog este un limbaj folosit pentru rezolvarea problemelor ce implică


obiecte și relații între obiecte.

Exemplul 5.6: Tom este părintele lui Bob se scrie: parent(tom,bob) unde parent este
numele relației, iar tom și bob sunt argumentele relației.
Arborele familiei este:

pam tom

bob liz

ann pat

jim

parent(pam,bob)
parent(tom,liz)
parent(tom,bob)
parent(bob,ann)
parent(bob,pat)
parent(pat,jim) – acest program are 6 clauze. Fiecare clauză arată un lucru despre
relația de părinte. De exemplu: parent(tom,bob) este un exemplu/ caz particular
pentru relația de părinte. Un astfel de caz se numește relație. În general, o relație este
definită de toate cazurile sale.
Se pot pune mai multe întrebări depre relația părinte.
- De exemplu: Bob este părintele lui Pat? scriem: ?-parent(bob,pat). După
găsirea acestui fapt în program, Prolog va răspunde: YES.
- Întrebarea : este Liz părintele lui Pat? se scrie ?-parent(liz,pat). Răspunsul pe
care Prolog îl va afișa este NO, deoarece în program nu se precizează nimic
despre faptul că Liz ar fi părintele lui Pat.
- Pentru întrebarea: este Tom părintele lui Sam?, care se scrie sub forma: ?-
parent(tom,sam) Prolog va răspunde NO deoarece Sam nu apare nicăieri.
- La întrebarea: cine este părintele lui Liz, care se scrie sub forma: ?-
parent(X,liz), Prolog va răspunde X=tom deoarece aceasta este valoarea
pentru care propoziția este adevărată.
- La întrebarea: cine sunt copiii lui Bob, care se scrie sub forma: ?-
parent(bob,X), Prolog va răspunde X=ann. Putem cere o altă soluție (scriind o
semicoloană) și Prolog va răspunde și cu X=pat. Dacă mai cerem soluții,
Prolog va răspunde NO deoarece toate soluțiile au fost afișate deja.
- Pentru a scrie întrebarea: “Cine este părintele cui?” mai întâi reformulăm:
găsește X,Y astfel încât X este părintele lui Y și acum putem să scriem
întrebarea: ?-parent(X,Y). Prolog găseste și afișează toate perechile părinte-
copil una după alta dacă îi cerem să afișeze mai mult de o soluție.
Răspunsurile vor fi:
- X=pam
Y= bob;
- X=tom
Y=bob;
- X=tom
Y=liz;
Prin apăsarea tastei ENTER oprim șirul soluțiilor.

Relația de bunic este exprimată prin compunerea a două relații de părinte.


Cine este bunicul lui Jim? Prolog nu știe direct relația bunic, întrebarea se împarte în
doi pași:
1. Cine este părintele lui Jim? Presupune că este un Y.
2. Cine este părintele lui Y? Presupune că este un X.
În Prolog, întrebarea se scrie astfel: ?-parent(Y,jim),parent(X,Y).
Răspunsul va fi:
X=bob
Y=pat.
Întrebarea compusă poate fi citită: găsiți X și Y care satisfac condițiile:
parent(Y,jim),parent(X,Y).
Dacă schimbăm ordinea celor două cerințe, semnificația logică rămâne
aceeași. Deci vom scrie în Prolog ?-parent(X,Y),parent(Y,jim) va produce același
rezultat.
Aplicăm aceeași mod pentru întrebarea: Cine sunt nepoții lui Tom?
?- parent(tom,X),parent(X,Y).
Răspunsul Prolog este:
X=bob
Y=ann
X=bob
Y=pat
Reguli
Prolog-ul ne permite să descriem propoziții prin intermediul predicatelor. Putem
formula reguli de tipul “Un fapt a este adevărat dacă un fapt b și un fapt c sunt adevărate”.
De exemplu: „ X este sora lui Y dacă X este de sex feminin și X și Y au aceiași părinți”.
Regulile în Prolog sunt compuse din cap și coadă. Capul și coada se separă cu ajutorul
simbolului „:-” care înseamnă “dacă”.
Exemplu: Fie baza de fapte:
man(tudor).
woman(maria).
woman(andreea).
woman(mihaela).
parent(maria,mihaela,tudor).
parent(andreea,mihaela,tudor). % parent (X,Y,Z) înseamnă că Y și Z sunt părinții lui X.
sora_lui(X,Y):- % X este sora lui Y dacă
woman(X), % X este femeie și
parent(X,M,T), % M și T sunt părinții lui X și
parent(Y,M,T). % M și T sunt părinții lui Y.
La interogarea „?-sora_lui(maria,X).” (Cui îi este Maria soră?) răspunsul afișat de Prolog
este:
X= andreea;
X=maria;
false. – adică Maria este sora Andreei și a ei însăși. Examinând regula observăm că
nimic nu interzice ca X și Y să primească aceleași valori. Pentru ca regula să fie corectă,
trebuie adăugată o condiție suplimentară care să stabilească faptul că X și Y nu pot
desemna aceeași persoană. Acest fapt se va scrie: „X< >Y”. Prin urmare regula devine:
sora_lui(X,Y):- % X este sora lui Y dacă
woman(X), % X este femeie și
parent(X,M,T), % M și T sunt părinții lui X și
parent(Y,M,T), % M și T sunt părinții lui Y și
X<>Y. % X și Y sunt persoane diferite.

Reguli recursive
Programarea în Prolog depinde mult de recursivitate. Prolog-ul ne învață să
gândim recursiv. Recursivitatea implică definirea unui predicat în funcţie de el însuşi.
Mecanismul recursivității constă în faptul că întotdeauna definim predicatul la o scală
mai mică. Recursivitatea în Prolog este echivalentă cu demonstrarea prin inducţie din
matematică.
O definiție recursivă are două părți: condiția elementară și partea recursivă.
Condiţia elementară defineşte un caz simplu, care ştim că este întotdeauna adevărat.
Partea recursivă simplifică problema eliminând iniţial un anumit grad de complexitate şi
apoi apelându-se ea însăşi. La fiecare nivel, condiţia elementară este verificată:
▫ dacă s-a ajuns la ea, recursivitatea se încheie;
▫ altfel, recursivitatea continuă.

1
Definițiile unor operații sau funcții pot fi analitice sau recursive.

1. De exemplu, definiția analitică a factorialului unui număr este următoarea:


n! 1 2  3  .....  (n  1)  n
care înseamnă că factorialul unui număr este produsul tuturor numerelor de la 1 până la
numărul specificat. De exemplu, 5! 1 2  3  4  5  120 iar 21! 1 2  3  ....  21 .
Numărul n! 1 2  3  ....  (n  1)  n poate fi scris ca n! (n  1)!n deoarece
(n  1)! 1 2  3  ....  (n  1) . Forma n! (n  1)!n se numește recursivă fiindcă
factorialul numărului n se definește prin factorialul numărului n-1.
Definițiile recursive conțin și o parte care nu este recursivă numită baza definiției,
condiția limită sau condiția de terminare a recursiei. Astfel, definiția completă a
factorialului unui număr devine:

 1, dacă n  0
n!  .
n(n  1)!, dacă n  0

Prolog-ul nu conține instrucțiuni de tipul: while, repeat, until ca celelalte limbaje


imperative. O modalitate de elaborare a programelor recursive în Prolog poate fi:
 Pentru a rezolva problema de ordinul N, presupunem că această problemă este
rezolvată pentru un ordin mai mic (de exemplu N-1) iar apoi legăm rezultatul
problemei mici de rezulatatul problemei inițiale;
 Scriem condițiile limită corespunzătoare.

Programul Prolog pentru factorialul unui număr este:


factorial(0,1). % factorialul lui 0 este 1.
factorial(N,F):- % factorialul lui N este F dacă
N>0, % N>0 și
N1 is N-1, % N1 este N-1 și
factorial(N1,F1), % factorialul lui N1 este F1 și
F is N*F1. % F este N*F1.
Acest program este alcătuit din două clauze: prima este o clauză unitate (nu are corp)
iar a doua este o regulă deoarece are corp. Corpul celei de-a doua clauze este la dreapta
semnului „ :-”. Corpul este alcătuit din fapte separate prin „și ( se notează cu „ ,”)” .
Capul clauzei este întreaga clauză dacă este o clauză unitate sau ceea ce este la stânga
semnului „ :-” dacă nu este o clauză unitate. Deci, regula recursivă este regula în
corpul căreia există cel puțin un apel la capul regulii.

 La interogarea „?- factorial (5,X).” răspunsul afișat de Prolog este:


X=120;
false.
- La interogarea „?- factorial (3,X).” răspunsul afișat de Prolog este:
X=6;
false.

2
Considerăm următorul arbore clauzal construit pentru interogarea „?- factorial
(3,X).” . Un arbore clauzal nu conține orice variabilă liberă, dar în schimb are valori ale
variabilelor. Fiecare ramificare de sub un nod este determinată de o clauză din programul
original, folosind valori relevante ale variabilelor; nodul este determinat de unele valori
ale capului clauzei iar corpul clauzei determină „copiii” nodurilor în arborele clauzal.

factorial(3,6)

3>0 2=3-1 factorial(2,2) 6=3*2

2>0 1=2-1 factorial(1,1) 2=2*1

1>0 0=1-1 factorial(0,1) 1=1*1

adevărat

Toate frunzele aritmetice sunt adevărate prin evaluare iar instrucțiunea cea mai joasă
corespunde primei clauze din program.
2. PREDECESOR
Introducem relația predecesor cu ajutorul relației părinte. Definim mai întâi
predecesorii direcți iar apoi pe cei indirecți. X este un predecesor indirect al lui Z dacă
există o legătură parentală între X și Z

parent
X

parent

Z parent

X este predecesor direct


parent

X este predecesor indirect


3
În arborele familiei

Tom este predecesor direct al lui Liz și predecesor indirect al lui Pat.
Putem scrie prima regulă (predecesor direct) sub forma: For all X and Z
X is a predecessor of Z if
X is a parent of Z.
În limbajul Prolog această regulă se va scrie sub forma: predecessor (X,Z):-
parent(X,Z).

În cazul predecesorului indirect, relația se poate defini:

predecessor (X,Z):-
parent(X,Z).

predecessor (X,Z):-
parent(X,Y),
parent(Y,Z).

sau

predecessor (X,Z):-
parent(X,Y),
parent(Y,W),
parent(W,Z).

Exprimată astfel, relația de predecesor este definită doar pentru o anumită adâncime în
arborele familiei. Pentru a face această relație să fie valabilă pentru orice
adâncime/lungime în arborele familiei, o scriem sub forma:
for all X and Z
X is a predecesor of Z if
there is a Y such that
1. X is a parent of Y and
2. Y is a predecesor of Z.

4
În limbaj Prolog:
predecessor (X,Z):-
parent(X,Y),
predecessor(Y,Z).

Majoritatea problemelor cu grad sporit de dificultate se rezolvă folosind recursivitatea.

Interogare: Care sunt succesorii lui Pam?. Interogarea se poate reformula: pentru cine
este Pam predecesor?
În Prolog:
?-predecessor(pam,X).
X=bob;
X=ann;
X=pat;
X=jim;
false.

Considerăm următorul arbore:


parent(pam,bob), % Pam is a parent of Bob (Pam este părinte al lui Bob)
parent(tom,liz),
parent(tom,bob),
parent(bob,ann),
parent(bob,pat),
parent(pat,jim),
female(pam), % Pam is a female (Pam este femeie)
female(liz),
female(ann),
female(pat),
male(tom), % Tom is a male (Tom este bărbat)
male(bob),
male(jim),
mother(X,Y):- % X is a mother of Y if (X este mama lui Y dacă)
parent(X,Y), % X is a parent of Y (X este părinte al lui Y)
female(X). % X is a female (X este femeie).
grandparent(X,Z):- % X is a grandparent of Z if (X este bunicul lui Z dacă)
parent(X,Y), % X is a parent of Y and (Y este părinte al lui Z și)
parent(Y,Z). % Y is a parent of Z (Y este părinte al lui Z).
offspring(Y,X):- % Y is an offspring of X if (Y este copil al lui X dacă)
parent(X,Y). % X is a parent of Y (X este părinte al lui Y).
sister(X,Y):- % X is a sister of Y if (X este sora lui Y dacă)
parent(Z,X), % Z is a parent of X and (Z este părinte al lui X și)
parent(Z,Y), % Z is a parent of Y and (Z este părinte al lui Z și)
female(X), % X is a female (X este femeie)
different(X,Y). % X and Y are different (X și Y sunt diferiți)
predecessor(X,Z):- % Rule pr1: X is a predecessor of Z if
parent(X,Z). % X is a parent of Z ( X este părinte al lui Z).

5
predecessor(X,Z):- % Rule pr2: X is a predecessor of Z if
parent(X,Y),
predecessor(Y,Z).

Relația predecesor se definește prin două clauze. Un set de clauze despre aceeași
relație se numește procedură.
Comentariile sunt marcate prin % și sunt ignorate de Prolog în general. Ele sunt
utile celui care citește programul.

Pornim de la interogarea ?-predecessor(tom,pat). Știm că parent(bob,pat) este un


fapt. Folosind acest fapt și regula pr1, concluzionăm: predecessor(bob,pat). Citim din
parent(bob,pat) și prin regula pr1 rezultă faptul că predecessor(bob,pat). Știm că
parent(tom,bob) este un fapt. El derivă din predecessor (bob,pat) și concluzionăm
predecessor(tom,pat) prin pr2. Așadar am arătat că țelul nostrum (goal) este adevărat.
Scriem parent(bob,pat)→ predecessor(bob,pat).
parent(tom,bob) and predecessor(bob,pat)→ predecessor(tom,pat).
Am arătat ce este o secvență de pași ce satisface un goal, ceea ce conduce la
faptul că goal-ul este adevărat. Numim aceasta o secvență de demonstrație (proof
sequence). Prolog o identifică în ordine inversă decât am arătat. Prolog-ul începe cu
goal-urile, folosind apoi regulile și substituind goal-urile cerute cu cele noi, până când
noile goal-urile devin fapte simple.
Pornim de la interogarea ?-predecessor(tom,pat). Pentru a satisface acest goal
Prolog identifică o clauză din care să rezulte acest fapt. Clauzele sunt pr1 și pr2 – regulile
ce definesc relația predecesor. Spunem că head-urile acestor reguli se potrivesc goal-ului.
Prolog începe cu prima clauză din program: predecessor(X,Z):- parent(X,Z). Cum goal-ul
este predecessor(tom,pat) variabilele din regulă sunt inițiate cu
X=tom, Z=pat.
Goal-ul inițial devine predecessor(tom,pat) și se înlocuiește cu parent(tom,pat). Cum nici
o clauză din program nu are un head care să se potrivească cu goal-ul parent(tom,pat),
Prolog renunță la acest goal. În continuare, Prolog backtracks goal-ul inițial folosind
regula pr2:
predecessor(X,Z):-
parent(X,Y),
predecessor(Y,Z).
- Se inițiază variabilele X=tom, Z=pat, Y nu se inițiază încă;
- Goal-ul predecessor(tom,pat) se înlocuiește cu alte două goal-uri:
1) Parent(tom,Y)
2) Predecessor (Y,pat)
pe care le va satisface în ordinea în care sunt scrise.
- Inițiază Y=bob;
- Primul goal a fost satisfăcut;
- Rîmâne goal-ul : predecessor(bob,pat);
- Se folosește pr1;
Aplicarea a doua oară a regulei pr1 nu are nici o legătură cu aplicarea ei prima oară.
Prolog folosește un nou set de variabile de fiecare dată când aplică regula →
redenumim varaiabilele din regula pr1:

6
predecessor(X’,Z’):-
parent(X’,Z’).
Capul (head-ul) trebuie să se potrivească goal-ului predecessor(bob,pat).
Așadar: X’=bob, Z’=pat
Goal-ul devine: parent(bob,pat). Acest goal este satisfăcut imediat deoarece apare
ca un fapt în program.
Predecessor(tom,pat)

Regula pr1 Regula pr2

Parent(tom,pat) Parent(tom,Y)
Predecessor (Y,pat)
No Y=bob prin faptul parent(tom,bob)

Predecessor(bob,pat)

Regula pr1

Parent(bob,pat)

Yes

 Execuția are formă de arbore;


 Nodurile corespund goal-urilor (unei liste de goal-uri) ce vor fi satisfăcute;
 Arcele dintre noduri corespund aplicării clauzelor, ce transformă goal-urile de la
un nod la altul;
 Goal-ul din vârf este satisfăcut când se găsește o cale de la nodul rădăcină la o
“frunză” etichetată cu un fapt = Yes.

Mecanismul Backtracking.
Procesul de căutare porneşte de la începutul bazei de cunoștinte (fapte și clauze)
pentru a se putea răspunde la întrebarea formulată. Într-o listă de predicate, verificarea
predicatului curent pornește de la începutul listei. Dacă nu sunt soluții posibile se revine
la predicatul anterior. Procesul de căutare a soluțiilor bazat pe revenire în vederea
explorării tuturor alternativelor se numeste backtracking.
Fie urmatoarea bază de cunoştinţe:
frumoasa(ana). %1
bun(vlad). %2
cunoaste(vlad, maria). %3
cunoaste(vlad, ana). %4
iubeste(mihai, maria). %5

7
iubeste(X, Y):- bun(X), cunoaste(X, Y), frumoasa(Y). %6
Pentru a prezenta mecanismul de backtracking în Prolog, vom folosi baza de fapte
dată ca exemplu mai sus. Vom urmari în continuare pașii realizați pentru satisfacerea
scopului:
?- iubeste(X, Y).
Căutarea pornește de la începutul bazei de cunoștințe. Prima potrivire va fi la linia 5, cu
faptul: iubeste(mihai, maria). %5
În urma unificării, variabilele X și Y se vor instanția la constantele mihai și maria
și se va realiza un marcaj la linia respectivă. Pentru a încerca resatisfacerea scopului,
căutarea va începe acum după marcajul făcut anterior. Următoarea potrivire va fi la linia
6, cu regula:
iubeste(X, Y):- bun(X), cunoaste(X, Y), frumoasa(Y). %6
La unificarea scopului cu antetul unei reguli, pentru a putea satisface acest scop trebuie
satisfăcută regula. Aceasta revine la a satisface toate faptele din corpul regulii, deci
conjuncţia de scopuri. Scopurile din corpul regulii devin subscopuri a căror satisfacere se
va încerca printr-un mecanism identic cu cel al satisfacerii scopului iniţial.
În continuare se va încerca satisfacerea scopului bun(X).
Fiind vorba de un nou scop, căutarea va avea loc de la începutul bazei de cunoștințe.
Acest scop va unifica cu predicatul de la linia 2: bun(vlad). %2
În urma unificării, varibila X se va instanția la valoarea vlad.
În continuare se va încerca satisfacerea scopului cunoaste(vlad, Y). care va unifica cu
faptul de la linia 3 și va duce la legarea variabilei Y la maria:
cunoaste(vlad, maria). %3
Ultimul scop care mai trebuie satisfăcut este frumoasa(maria), dar acesta eșueaza
deoarece nu unifică cu niciunul dintre faptele sau regulile din baza de cunoștințe.
Aici intervine mecanismul de backtracking. Se va reveni la scopul satisfăcut anterior,
cunoaste(vlad, Y). și se va încerca resatisfacerea acestuia. Dacă aceasta ar eșua, ne-am
întoarce la scopul dinaintea sa ș.a.m.d. Acest lucru se va repeta pană când se epuizează
toate scopurile din corpul regulii, caz în care unificarea scopului inițial cu antetul regulii
ar eșua, iar raspunsul ar fi false.
În cazul nostru, însă, este necesar un singur pas de întoarcere deoarece
cunoaste(vlad, Y). poate fi resatisfăcut prin unificarea cu faptul de la linia 4:
cunoaste(vlad, ana). %4
În urma unificării, variabila Y va fi legată la ana, iar următorul scop ce va trebui
satisfăcut este frumoasa(ana). Acesta va reuși deoarece unifică cu faptul de la linia 1:
frumoasa(ana). %1
Astfel am obtinut o noua soluție pentru scopul iubeste(X, Y)., având X = vlad și Y = ana.
Procesul nu se oprește însă pana când nu s-au încercat toate unificările posibile pentru
satisfacerea scopului. Tot prin intermediul mecanismului de backtracking, se va reveni la
scopurile anterioare și se va observa dacă acestea pot fi resatisfăcute. În exemplul nostru
acest lucru nu este posibil, deci răspunsul va fi false.
Prin urmare, rezultatul final va fi:
?- iubeste(X, Y).
X = mihai, Y = maria;
X = vlad, Y = ana;
false.

8
Semnificații ale programului Prolog
1. Semnificația declarativă - se referă la relațiile definite în program;
- determină ce va fi output-ul programului
2. Semnificația procedurală - determină cum se obține output-ul
cum sunt relațiile evaluate de Prolog.

Abilitatea Prolog-ului de a rezolva pe cont propriu multe detalii procedurale este


considerată a fi unul dintre avantajele sale specifice. Încurajează programatorul să
considere sensul declarativ al programelor, relativ independent de sensul procedural al
acestora, din moment ce rezultatele programului sunt determinate în principiu de sensul
său declarativ, acesta ar trebui să fie suficient pentru scrierea programului. Acesta
simbolizează o importanță practică deoarece aspectele declarative ale programelor sunt
de obicei mai ușor de înțeles decât detaliile procedurale. Pentru a profita de acest aspect
programatorul ar trebui să se concentreze în special pe sensul declarativ și de fiecare dată
când este posibil să evite a fi distras de detaliile execuționale. Acest aspect ar trebui lăsat
pentru a fi rezolvat de Prolog.
Maniera declarativă face ca programarea în Prolog să fie mai ușoară
comparativ cu alte limbaje de programare. Uneori însă, această manieră nu este suficientă.
În special în programele mari aspectele procedurale nu pot fi ignorate complet de către
programator din motive practice ce țin de eficiența execuțională. Totuși, maniera de a
gândi în stil decalarativ ar trebui încurajată, iar aspectele procedurale ar trebui ignorate în
măsura în care acest aspect este permis de constrângerile practice.
OBS: Un text Prolog poate fi privit din punct de vedere declarativ sau procedural.
Declarativ textul Prolog ne specifică rezultatul unei întrebări. Modul în care se ajunge la
un anumit răspuns este dat de înțelesul procedural. Abilitatea Prologului de a rezolva
detaliile procedurale permite ca programatorul să se concentreze pe aspectul declarativ.
Uneori însă, este nevoie să fim conștienți de modul în care sunt satisfăcute țintele. Pentru
ca la o întrebare să se răspundă pozitiv, variabilele din ținte trebuie legate astfel încât
răspunsul să fie o consecință logică a clauzelor din program.

IDEI PRINCIPALE:
1. Programarea în Prolog constă în definirea relațiilor și interogarea asupra
acestora;
2. Un program Progog constă în clauze. Acestea sunt de trei tipuri: fapte, reguli,
întrebări;
3. O relație poate fi descrisă declarând n-apelurile ale obiectelor care satisfac
relația sau prin declararea regulilor regulilor despre relații;
4. O procedură este un set de clauze despre aceeași relație;
5. Interogarea asupra relațiilor prin intermediul întrebărilor se aseamănă
interogării asupra unei baze de date. Răspunsul Prolog-ului constă ăntr-un set de
obicte care satisfac întrebarea;
6. În Prolog, stabilirea faptului dacă un obiect satisface o cerință, este un
proces ce implică inferențe logice, explorarea alternativelor sau procedura de
back-tracking. Acestea sunt executate de sistemul Prolog și de obicei sunt ascunse
pentru utilizator;

9
7. Se disting două tipuri de sensuri (semnificații) ale programelor Prolog:
declarativ și procedural. Viziunea declarativă este avantajoasă din punct de vedere
al programării, totuși detaliile procedurale trebuie deseori să fie luate în
considerare de către programator.

10
TIPURI DE DATE ȘI MECANISME PROLOG

În limbajul Prolog întalnim următoarele tipuri de date:


- Date simple: atomi, numere, variabile;
- Date structurate

OBIECTE DE DATE

OBIECTE SIMPLE OBIECTE STRUCTURATE

CONSTANTE VARIABILE

ATOMI NUMERE

I. Atomi și numere
Simbolurile propoziționale A, A1, A2, ...B, B1, B2, ...sunt propoziții numite propoziții
atomice sau atomi.
- Litere mari: A, B, ....
- Litere mici: a, b, ...
- Cifre: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
- Caractere speciale: +, -, *, / (÷), <, >, =, :, ., &, _ , ~ .

Modalități de construcție a atomilor:


1. șiruri de litere, cifre și caractere “_” începute cu litere mici:
maria
andreea_ruxandra
a_12AB
a_ _b

2. Șiruri de caractere speciale


<_ _ _>

======>
::=

3. Șiruri de caractere între ghilimele simple (se folosesc pentru atomi ce încep cu literă
mare):
‘Andreea’
‘South_America’
‘Tudor_Ștefan’
II. Numerele folosite în Prolog sunt întregi sau reale.
Prolog nu este un program numeric computațional, este un limbaj simbolic. În
calculul simbolic, numerele întregi sunt deseori folosite, de exemplu, pentru a număra itemii
unei liste, iar numerele reale nu se folosesc adeseori.
Majoritatea implementărilor admit o gamă de valori cuprinse între – 214 și +214+1.

Atomii şi numerele sunt întotdeauna egali cu ei înşişi. De exemplu, următoarele


scopuri au rezultatul marcat drept comentariu:
alex = mihai % eșuează
mare = mare % este satisfăcut
1021 = 1021 % reuşeşte
4010 = 4011 % eşuează.

III. Variabile sunt șiruri de litere, cifre și caractere “underscore”. Variabilele


încep cu litere mari și caractere “underscore”.
X
Obiect1
ShoppingList
Shopping_list
_X24
_1

Când o variabilă apare doar într-o clauză, nu trebuie să dăm un nume pentru ea.
Putem folosi așa-numita variabilă anonimă care se scrie cu un singur caracter underscore.
Utilizarea unei variabile anonime semnifică faptul că nu interesează valoarea la care se va
instanția acea variabilă
De exemplu:
hasachild(X):-parent(X,Y). % orice X are copil dacă X este părinte pentru un Y.
Regula nu depinde de numele copilului deci folosim variabila anonimă.
Clauza se rescrie:
hasachild(X):-parent(X,_).
De fiecare dată când apare un caracter underscore în clauză, el va reprezenta o nouă
variabilă anonimă.
De exemplu:
somebody_has_child:- parent (_,_).
este echivalent cu:
somebody_has_child:- parent (X,Y). ,
este diferit de:
somebody_has_child:- parent (X,X).

Dacă suntem interesați de oameni care au copii, dar nu și de numele copiilor,


întrebăm:
?-parent(X,_).
Dacă un nume, de exemplu X24, apare în două clauze, el semnifică două variabile
diferite. În schimb, apariția numelui X24 în aceeași clauză semnifică aceeași variabilă.
Pentru constante – același atom reprezintă mereu același obiect în orice clauză, pe
parcursul întregului program.

IV. Structuri

Structurile sunt obiecte ce desemnează o colecție de obiecte corelate logic, care formează
componentele structurii. Componentele, pot fi chiar ele, la rândul lor structuri.
O structură se definește prin specificarea:
 numelui structurii ( functorul structurii);
 elementelor sau componentelor structurii.

Exemplu:
Scrierea datei poate fi o structură cu 3 componente: zi, lună, an
date(21, july, 2007)

functor argumente
Componentele din exemplu sunt formate din doi întregi și un atom.

Componentele pot fi variabile sau alte structuri.


Orice dată din luna Iulie se va scrie sub forma: date(Day,july,2007), unde Day este o
variabilă ce poate fi instanțiată cu orice obiect mai târziu în execuția programului.
Din punct de vedere sintactic toate obiectele de date sunt termeni.
De exemplu: july și date(21, july, 2007) sunt termeni.

Deși alcătuite din mai multe componente, sunt tratate de program ca obiecte unice.
Pentru combinarea componentelor într-un unic obiect, este folosit un functor. Acesta va fi
rădacina arborelui într-o reprezentare arborescentă.

Toate structurile pot fi desenate sub formă de arbore.


 Rădăcina arborelui  functor;
 Ramurile arborelui  componentele.
Dacă o componentă este o structură, atunci ea se va reprezenta ca un subarbore al arborelui
structurii întregi.
Două structuri sunt egale dacă au acelaşi functor, acelaşi număr de componente şi
fiecare componentă dintr-o structură este egală cu componenta corespunzătoare din cealaltă
structură. De exemplu, scopul:
autor(eminescu, poezie(lucefărul)) =
autor(X, poezie(Y))
este satisfăcut și au loc instanţierile:
X = eminescu şi Y = luceafărul.
Exemplu:
1. Un punct în spațiul bidimensional are două coordonate;
2. Un segment este definit de două puncte, un triunghi prin 3 puncte.

Alegem functorii:
Point pentru puncte;
Seg pentru segmente de dreaptă;
Triangle pentru triunghiuri.
P1=point(1,1)
P2=point(2,3)
S=seg(P1,P2)=seg(point(1,1), point(2,3))
T=triangle(point(4,2),point(6,4),point(7,1))

P1=point S=seg

1 1 point point

1 1 2 3

T=triangle

Point point point

4 2 6 4 7 1

V. Operatori:

1. Operatori aritmetici:

- sunt o rescriere infixată a unor structuri și de aceea valoarea expresiei definite cu ei nu este calculată;

- evaluarea expresiei se face la cerere în cazul în care se folosește operatorul predefinit infixat is , ca în
exemplul: X is 1+2 (în acestcaz se instanțiază variabila X la valoarea 3).

2. Operatori relaționali:

- sunt predicate predefinite infixate;

- cel mai important este operatorul de egalitate, care funcționează ca și când ar fi definit prin
următorul fapt: X = X.
Un exemplu:

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

Prolog răspunde X =1+2 Prolog raspunde X = 3

deoarece, în primul caz, expresia 1+2 denota o structura (termen) Prolog, unde + este functorul, iar 1 și 2
sunt argumentele sale. Nimic din acest scop nu declanșează adunarea, care este declanșată de operatorul
is.
- Operatorul de inegalitate =\= se definește ca un predicat opus celui de egalitate; scopul X=\=Y
reușește dacă scopul X=Y nu este satisfăcut și eșuează dacă X=Y reușește (semnificație: valorile lui X
și Y nu sunt egale).
- Predicatul = = testează echivalența a două variabile; X==Y reușește ori de câte ori X=Y reușește, dar
reciproca este falsă. Este vorba de egalitatea literală doi termeni.
- X= = Y este adevărat dacă termenii X și Y sunt identici, adică au aceeași structură și toate
componentele corespunzătoare coincid. În particular, numele de variabile trebuie să fie aceleași.
- Relația complementară (de non-identitate) este \= =.

Exemplu:
?-f(a,X) ==f(a,Y).
No

- Operatorul =:= face numai evaluare aritmetică și nici o instanțiere; semnificația lui
X=:=Y este: valorile expresiilor aritmetice X și Y sunt egale.

?- 1+2=:=2+1. ?=1+2=2+1.
yes no

- Inegalitatea a două expresii aritmetice se stabilește cu operatorul =\=

Valorile expresiilor artimetice pot fi comparate prin intermediul operatorilor care


urmează:
Structura programelor PROLOG

Secțiunile PROLOG sunt: constants, domains, predicates, goal, clauses, etc.

Clauses conține fapte şi reguli. Argumentele unei clauze sunt într-o ordine bine definită,
fiecare argument având un anumit tip. Tipul argumentelor, numele predicatului care descrie
un fapt sau o regulă și numărul argumentelor rezultă din declaraţiile specificate în secțiunea
predicates. Dacă mai multe predicate au același nume, dar aritate (număr de argumente)
diferită atunci predicatele sunt diferite. Identificarea va fi corectă datorită implementării
mecanismului polimorfic.

Numele unui predicat este un șir (cu maxim 250) de litere, cifre şi “_” care începe
obligatoriu cu o literă mică. Argumentele pot fi: unul, mai multe sau nici unul. Un predicat
este de forma:
nume_predicat(tip_arg1, tip_arg2, …, tip_argn)

Faptele sunt de forma:

nume_predicat(arg1, arg2, …, argn).

Regulile se pot descrie prin

nume_predicat(arg1, arg2, …, argn) :- expresie_logică.

Argumentele pot fi şi variabile. Ele apar, de obicei, în expresia logică din membrul drept.
O expresie logică utilizează conjuncţii (specificate prin virgulă (,) sau and), disjuncţii
(specificate prin punct_și_virgulă (;) sau or), operatorul not aplicat câte unui predicat (pentru
a specifica negația), predicatul fail (pentru a introduce nedeterminismul) şi predicatul cut
(tăietură, specificat prin !) care are rolul de a oprii căutarea prin mecanismul
backtracking.
Dacă goal nu apare în program, spunem că se lucrează în mod interactiv, prin
interpretarea și identificarea entităţilor din program. La executare se activează fereastra
Dialog și putem lansa interogări.
Când secțiunea goal apare într-un program Turbo Prolog, ea trebuie să fie plasată
după predicates, înainte de clauses. Ea este o clauză sau un şir de clauze conectate logic prin
and (,) sau or (;). Se va termina cu punct. La executarea se va obține o singură soluție (prima
care s-a “potrivit”). Nu se face “backtracking”.
Secțiunea constants permite declararea unor constante. Secțiunea poate apărea
oriunde în program, cu condiția ca o constantă să fi fost declarată înainte de a fi utilizată.
Funcţii aritmetice

O expresie aritmetică PROLOG este o expresie uzuală cu operanzi uniţi prin


operatori. Operanzii pot fi numere sau variabile, iar operatorii sunt: +, -, *, /, div, mod şi
paranteze. Expresia apare în dreapta operatorului =, iar în stânga apare fie o variabilă
nelegată căreia i se atribuie valoarea expresiei , fie o valoare cu care se compară valoarea
expresiei.
Un număr hexazecimal e precedat de $.
$ FFF = 4095

Expresia este calculabilă dacă toate variabilele ce apar în ea (când apar) sunt legate.
Operaţiile sunt executate respectând prioritatea operanzilor. Tipul rezultatului depinde de
tipul operanzilor şi al operatorilor.

Tipul rezultatului:

Operand 1 Operator Operand2 Rezultat

Integer +, -, * integer integer


Real +, -, * integer real
Integer +, -, * real real
Real +, -, * real real
Integer or real / integer or real real

Ordinea efectuării operaţiilor

Ordinea de efectuare a operaţiilor este cea clasică:


Operator Prioritate
+- 1
* / mod div 2
- + (unar) 3

Operatori relaţionali:
Alţi operatori sunt operatorii relaţionali. Ei pot compara nu doar expresii numerice ci şi
caractere (se compară codurile ASCII).
< mai mic
<= mai mic sau egal
= egal
> mai mare
>= mai mare sau egal
<> sau >< diferit
Funcţii şi predicate PROLOG

Funcţiile şi predicatele PROLOG sunt:

Funcţie returnează
X mod Y restul împărţirii lui X la Y:
X div Y parte întreagă a lui X împărţit la Y
abs(X) valoare absolută a lui X
cos(X) cosinus de X
sin(X) sinus de X
tan(X) tangenta de X
arctan(X) arctangentă de X
exp(X) e la puterea X
ln(X) logaritm natural din X
log(X) logaritm în baza 10 din X
sqrt(X) radical din X
random(X) obţine în X un număr aleator din intervalul [0, 1]
random(X,Y) X dat, Ygenerat aleator 0<=Y<X
round(X) X rotunjit
trunc(X) trunchiazăX

Exemple:
1. Presupunând că nu există operatorul predefinit mod, se poate scrie un predicat Prolog cu
efect similar. O definiţie posibilă a predicatului modulo(X, Y, Z), cu semnificaţia
argumentelor Z = X mod Y , presupunând X, Y > 0, este:
% modulo(X, Y, Z)
modulo(X, Y, X) :- X < Y.
modulo(X, Y, Z) :- X >= Y, X1 is X - Y, modulo(X1, Y, Z).
2. Plecând de la predicatul modulo definit anterior, se poate defini predicatul de calcul al
celui mai mare divizor comun al două numere, conform algoritmului lui Euclid,
presupunând X > 0, Y >0, astfel:
% cmmdc(X, Y, C)
cmmdc(X, 0, X).
cmmdc(X, Y, C) :- modulo(X, Y, Z), cmmdc(Y, Z, C).
La întrebarea
?- cmmdc(15, 25, C).
C=5
răspunsul sistemului este corect. În cazul în care se încearcă obţinerea unor noi soluţii (pentru
semnificaţia cmmdc acest lucru este irelevant, dar interesează din punctul de vedere al
funcţionării sistemului Prolog) se observă ca sistemul intră într-o buclă infinită datorita
imposibilităţii resatisfacerii scopului modulo(X, Y, Z) pentru Y = 0. Dacă la definiţia
predicatului modulo se adaugă faptul:
modulo(X, 0, X).
atunci predicatul modulo(X, Y, Z) va genera la fiecare resatisfacere aceeaşi soluţie, respectiv
soluția corectă, la infinit. Cititorul este sfătuit să traseze execuţia predicatului cmmdc în
ambele variante de implementare a predicatului modulo.
3. Calculul ridicării unui număr natural la o putere naturală se poate face definind
următorul predicat:
% expo(N, X, XlaN)
expo( _ , 0, 0).
expo(0, _ , 1).
expo(N, X, Exp) :- N > 0, N1 is N - 1, expo(N1, X, Z), Exp is Z * X.

4. Să se scrie un program care calculează termenul n din sirul lui Fibonacci:


1, 1, 2, 3, 5, 8, 13, 21, ..., in care f(n) = f(n - 1) + f(n - 2), pentru n>2.
% fib(+N, -F)
fibo(1, 1).
fibo(2, 1).
fibo(N, F):-
N > 2, N1 is N - 1,
N2 is N - 2,
fibo(N1, F1),
fibo(N2, F2),
F is F1 + F2.

5.

6. Anecdotă:
“Cerere de lăsare la vatră pe motiv de incompatibilitate legală.
Stimate Domnule Ministru,
Situația mea familială și familiară, ma determină să solicit sprijinul Domniei voastre
în vederea lăsării la vatră. Vă rog să analizați cu atentie, ce mi s-a întâmplat:
(a) Înaintea incorporării, m-am căsătorit cu o vaduvă de 44 de ani.
(b) După scurt timp fiica soției mele, deși avea doar 25 de ani, s-a căsătorit cu tatăl
meu, pe care l-a indrăgit la prima vedere cu prilejul casătoriei mele.
În urma acestei duble căsătorii, tatăl meu mi-a devenit ginere fiindcă s-a căsătorit
cu fiica mea, iar fata mea vitregă mi-a devenit soacră, ea fiind soția tatălui meu.
(c) De Crăciun, soția mea a născut un băiat. Băiatul a devenit astfel fratele soției
tatălui meu, deci cumnat cu tatăl meu. Prin urmare, băiatul meu, fiind frate cu
soacra mea, mi-a devenit unchi.
(d) Culmea face ca în ianuarie anul acesta, și soția tatălui meu a născut un băiat, care
este pe de-o parte fratele meu (fiind fiul tatălui meu) și pe de altă parte nepotul
meu (fiindcă este fiul fiicei soției mele). Am devenit astfel fratele nepotului meu,
și cum soțul unei mame devine tatăl copiilor ei, și eu am devenit tatăl soției mele
și fratele fiului meu. Cu alte cuvinte eu sunt propriul meu bunic! Având în vedere
că legea interzice ca tătal, fiul și nepotul să fie mobilizați în același timp, vă rog
respectuos, stimate Domnule Ministru, să mă lasați la vatră. Contând pe amabilul
dvs. sprijin și binevoitoarea dvs. înțelegere de tată și adult, vă rog să agreați,
stimate Domnule Ministru, salutarile mele de înaltă considerație.

Semnatura indescifrabilă"

PS : Este vorba de o scrisoare veridică expediată de un tânar alsacian Ministrului


Apărării Naționale Francez! Cererea sa a fost acceptată, tânărul fiind rapid reformat pentru
următorul motiv: stare psihică instabilă și preocupată, tulburări mintale agravate de un climat
familial perturbat.
Verificați povestea tânărului folosing Prolog.
Predicate pentru prelucrarea obiectelor

 Findall(X,Goal/Scop,Listă) - obţine din baza de cunoştinţe toţi termenii X care satisfac


goal-ul şi cumulează aceşti termeni în listă. Goal-ul trebuie să fie instanţiat de la un
predicat Prolog în care trebuie să apară X. Dacă goal-ul nu reuşeşte, findall reuşeşte
instanţiind Lista la Listă vidă.
 Bagof(X,Scop,Listă) - colectează în Listă toţi termenii X care satisfac goal, ţinând cont
de diversele instanţieri posibil diferite ale celorlalte variabile din goal. Dacă goal nu
conţine alte variabile în afara lui X, atunci efectul predicatului bagof este acelaşi cu cel al
predicatului findall. Dacă goal nu reuşeşte cel puţin o dată, bagof eşuează.
 Setof(X,Scop,Listă) – colectează în Listă toţi termenii X care satisfac goal, dar spre
deosebire de bagof, valorile cumulate în Listă sunt sortate crescător şi se elimină
apariţiile multiple de valori, deci Lista devine o mulţime ordonată. Dacă Goal nu
reuşeşte cel puţin o dată, setof eşuează.

Exemplu:
1. parent(pam,bob).
parent(tom,liz).
parent(tom,bob).
parent(eva,liz).
parent(eva,bob).
parent(bob,ann).
parent(bob,pat).
parent(pat,jim).
Controlul recursivității în Prolog cu ajutorul predicatelor CUT și FAIL

Sistemul Prolog intră automat într-un proces de backtraking dacă acest lucru este necesar
pentru satisfacerea unui scop. Acest comportament poate fi în unele situaţii deosebit de util, dar
poate deveni foarte ineficient în alte situaţii.
Predicatul cut (tăietură, specificat prin !) este un predicat standard, fără argumente,
care este întotdeauna adevărat și nu poate fi resatisfăcut. Are rolul de a oprii căutarea prin
mecanismul backtracking.
 Toate selecțiile făcute între scopul antet de regulă și cut sunt înghețate la
întâlnirea predicatului cut, ceea ce implică emilinarea oricăror altor soluții
alternative pe această porțiune. Orice încercare de satisfacere a unui scop între
scopul antet și scopul curent va eșua.
 Dacă clauza în care s-a introdus predicatul cut reușește, toate clauzele cu același
antet cu acesta, care urmează clauzeiîn care a apărut cut vor fi ignorate.
Cu alte cuvinte, când execută predicatul cut, calculatorul ignoră alternativele descoperite
înaintea sau după apelul acestei clauze.
Dacă predicatul cut este introdus pentru a crește eficiența programului dar fără a
modifica seminificația procedurală, atunci el se numește green cut. Dacă prin introducerea
predicatului cut se modifică semnificația procedurală a programului, atunci el se numește red
cut.
Exemplu:
Codul Prolog pentru a afișa minimul unui număr este:
min(X,Y,X):- X=<Y.
min(X,Y,Y):- X>Y.
Predicatul fail este folosit pentru a introduce nedeterminismul / pentru a determina eșecul unui
goal/scop. Fail este un predicat standard, fără argumente, care eșuează întotdeauna.
Dacă predicatul fail se introduce după predicatul cut, atunci nu se mai face backtracking.
După fail, nu se mai poate satisface nici un goal. Dacă un predicat fail este introdus într-o
conjuncție de scopuri, atunci el determină intrarea în procesul de backtracking.

Observație: Putem utiliza combinația cut și fail (! și fail) cu rol de negație.

Predicate de clasificare a termenilor


 var(X) - reuşeşte dacă X este o variabilă neinstanţiată şi eşuează dacă X este o variabila
instanţiată sau o constantă.

Exemple:
?- var(3).
no
?- var(alex).
no
?- var(X).
yes
 novar(X) - este adevărat dacă X nu este o variabilă neinstanţiată. Acest predicat este
opusul predicatului var(X) şi îl putem defini astfel:

Exemple:
novar(X) :- var(X), !, fail.
novar( _ ).
 atom(X) - reuşeşte dacă X este un atom Prolog şi eşuează în caz contrar.

Exemple:
?- atom(3).
No
?- atom(alex).
yes
?- atom(X).
No

 integer(X) - reuşeşte dacă X este un număr întreg.


Tehnici și stiluri de programare

Problemele de inteligență artificială fac parte din diverse domenii. Există tehnici specifice
rezolvării problemelor de inteligență artificială. Cum se pot caracteriza aceste tehnici și cum se
poate decide dacă aceste tehnici pot fi utilizate și în rezolvarea unor probleme care nu sunt
considerate a fi probleme de inteligență artificială? Cel mai important este punerea în evidență a
rolului fundamental al cunoștintelor într-un sistem inteligent. Caracteristicile cunoștintelor impun
necesitatea găsirii unor modalități adecvate de reprezentare și prelucrare a cunoștintelor în
sistem.
Programarea în Prolog depinde mult de recursivitate. Prolog-ul ne învață să gândim
recursiv. Recursivitatea implică definirea unui predicat în funcţie de el însuşi. Mecanismul
recursivității constă în faptul că întotdeauna definim predicatul la o scală mai mică.
Recursivitatea în Prolog este echivalentă cu demonstrarea prin inducţie din matematică.
O definiție recursivă are două părți: condiția limită și partea recursivă. Condiţia limită
defineşte un caz simplu, care ştim că este adevărat întotdeauna. Partea recursivă simplifică
problema eliminând iniţial un anumit grad de complexitate şi apoi apelându-se ea însăşi. La
fiecare nivel, condiţia elementară este verificată:
 dacă s-a ajuns la ea, recursivitatea se încheie;
 altfel, recursivitatea continuă.
Limbajul Prolog este total diferit de celelalte limbaje de programare. El intră în
categoria limbajelor descriptive (nu procedurale, ca marea majoritate a celor cunoscute), atât
datele cât și comenzile putând fi manipulate după aceleași reguli.
Limbajul Prolog și orice alt limbaj descriptiv, nu se bazeazã pe un algoritm de rezolvare a
problemei pas cu pas, ci pe un sistem de deducții și inducții logice care, bazându-se pe niște
cunoștințe anterioare și niste reguli de inferentă logică, conduc logic la rezolvarea problemei.
Iată, pe scurt, cum decurg lucrurile în cazul programării logice:
- programatorul formează o bază de cunoștinte, care nu este altceva decât un set de
reguli și acțiuni legate de domeniul tratat;
- programatorul descrie apoi problema de rezolvat;
- limbajul este capabil sã caute informațiile necesare și să facă deducții pentru a rezolva
problema (găsirea soluției);

I. Ce este un program bun?

Sunt mai multe criterii pentru a stabilii dacă un program este bun. Criteriile general
acceptate sunt:
1. Definiția problemei trebuie să fie bine înțeleasă, soluția trebuie dată folosind termenii
cei mai relevanți;
2. Corectitudine;
3. Eficiență;
4. User-friendly;
5. Ușor de citit / înțeles;
6. Documentarea;
Trebuie să spuneţi ce face un program chiar dacă nu spuneţi cum face ceva. Chiar dacă nu
scrieţi programe pentru vînzare este un obicei extrem de util să scrieţi scurte documentaţii pentru
utilizatorii lor sau cei care vor să le modifice. Un model împămîntenit este pagina de manual
interactivă din UNIX (sau comanda „help'' din DOS, într-un fel). O descriere a programului
dumneavoastră ar trebui să conţină următoarele informaţii:
a) numele programului;
b) modul de lansare (argumente, etc);
c) o descriere a comportării;
d) pentru programe interactive indicaţii sumare de folosire;
e) informaţii despre fişierele pe care le foloseşte şi structura lor;
f) versiunea curentă;
g) autorul programului cu adresa lui (nu se recomandă dacă programul este un virus);
h) defecţiuni cunoscute;
i) documentaţii înrudite.

7. Să fie ușor de modificat / extins;


8. Trebuie să raporteze erorile atunci cand datele introduse sunt incorecte;

Pentru a trasforma soluția într-un program se folosește principiul rafinării în trepte:


 Formularea inițială  soluția de la nivelul vârfului
 Formularea finală  soluția de la nivelul bazei

Rafinarea se aplică definițiilor de procedură și structurilor de date.


Avantajele metodei rafinării în trepte sunt:
1. soluția se formulează în termenii cei mai relevanți;
2. soluția va fi succintă și simplă, așadar corectă.

În ceea ce privește fiecare pas de rafinare în Prolog, ne referim la rafinarea relațiilor.


Rafinarea se referă la algoritmi, dacă problema sugerează gândire algoritmică. În acest
caz, adoptăm punctul de vedere procedural al Prologului.

II. Cum gândim programele Prolog

Cum găsim subproblemele optime? Ceea mai des întâlnită metodă este, folosind
recursivitatea. Descompunem problema în:
 Cazuri limită
 Cazuri generale unde soluția este construită pe baza soluțiilor mai simple (vezi Cursul 6:
calculul factorialului)
Exemplu:

maplist(List,F,Newlist) unde
List =lista originală;
F = relație binară (regula de transformare);
Newlist = lista itemilor transformați.
Problema transformării List trebuie separată în două cazuri:
a) Cazul limită: List = [ ]
If List = [ ] then Newlist = [ ] fără a lua în considerare F
b) Cazul general: List = [ X  Tail]

Pentru a transforma lista [ X  Tail] trebuie să:


- transformăm itemul X prin regula F, obţinând astfel NewX
- transformăm lista Tail obţinând NewTail.
Astfel, lista nou transformată devine [ NewX  NewTail].

În Prolog

map list ([ ],_,[ ]).

map list ( [X  Tail ], F, [ NewX  NewTail ]):-

G = .. [F, X, NewX],

call(G),

map list(Tail, F, NewTail).

Presupunen că avem o listă cu numere şi vrem să obţinem o listă cu pătratele lor.

Folosind maplist:

square (X,Y):-

Y is X*X.

?-maplist([2,6,5],square, Squares).

Squares = [4,36,25].
Un motiv pentru care recursivitatea se aplică natural în Prolog este definirea relaţiilor,
deoarece obiectele de date au o structură recursivă.

obiectele

gol

liste arbori → arbori liniari → rădăcină

2 subarbori

goale (caz limită) cap

coadă – ce poate fi listă


Aritmetica numerelor

Expresiile sunt evaluate în următoarele cazuri:


1. ca membru drept al predicatului is;
?- X is 7-2.
X = 5
Yes

2. ca membru stâng şi drept al predicatelor de comparaţie:


=:= (egalitate),
=\= (inegalitate),
<(mai mic),
>(mai mare),
=<(mai mic sau egal),
>=(mai mare sau egal).
?- 5+3 =:= 4+4.
Yes
?- X =:= 4+2.
No

Operatorii și functiile standard din Prolog sunt următoarele:

Operator /
Semantica
Functie
A + B, A - B,
adunare, scadere, inmultire, impartire
A * B, A / B
A // B împărțire cu rest (div)
Remainder (returnează restul împărțirii lui a la b, unde a este
deîmpărțitul și b împărțitorul. Această funcție este des îtâlnită sub
A rem B
denumirea „remainder operation” / „funcția rest” .

A mod B Modulo (reprezintă restul împărțirii a două numere întregi A și B .


N ** N ridicare la putere
-N minus unar
Modul (valoare absolută = returnează întotdeauna ca răspuns un
abs(N)
număr pozitiv)
atan(N1, N2) arctangenta(N1/N2) exprimată în radiani [-pi..pi]
ceiling(N) cel mai mic intreg mai mare decat N
cos(N) cosinus
exp(N) exponential(e**N)
sqrt(N) Radical (rădăcină pătrată)
sign(N) Signum (semnul)
float(N) conversie la numar real
floor(N) cel mai mare intreg mai mic decat N
log(N) ln(N), logaritm natural
truncate(X) trunchiere
round(X) rotunjire

în care A și B denotă argumente întregi, X argumente reale, iar N argumente de orice


tip numeric.
Exemple:

1. Presupunând că nu există operatorul predefinit mod, se poate scrie un predicat


Prolog cu efect similar. O definiţie posibilă a predicatului modulo(X, Y, Z), cu
semnificaţia argumentelor Z = X mod Y , presupunând X, Y > 0, este:

Răspunsul Prologului la interogări va fi:

Liste

O listă este o structură de date ce reprezintă o secvenţă ordonată de zero sau


mai multe elemente. O listă poate fi definită recursiv astfel:
(1) lista vidă (zero elemente);
(2) o listă este o structură cu două componente: primul element din listă: capul
listei (head) şi corpul sau coada listei (tail: formată din următoarele elemente din
listă). De obicei, sfârşitul listei este reprezentat ca listă vidă.
În Prolog structura de listă este reprezentată printr-o structură standard,
predefinită, al cărei functor este caracterul “.” şi are două componente: primul element
al listei şi restul listei. Lista vidă este reprezentată prin atomul special [ ]. De exemplu,
o listă cu un singur element a se reprezintă în Prolog, prin notaţie prefixată astfel:
.(a, [ ]) având sintaxa in ARITY Prolog '.'(a, [ ])
iar o listă cu trei elemene, a, b, c, se reprezintă ca:
.(a, . (b, . (c, [ ]))) cu sintaxa în ARITY Prolog '.'(a, '. '(b, '. '(c, [ ]))).
Prolog-ul oferă o sintaxă alternativă pentru descrierea listelor, formată din
elementele listei separate de virgulă şi încadrate de paranteze drepte. De exemplu,
cele două liste anterioare pot fi exprimate astfel:
[a],
[a, b, c].
O operaţie frecventă asupra listelor este obţinerea primului element dintr-o
listă şi a restului listei, deci a celor două componente ale structurii de listă. Aceasta
operaţie se realizată în Prolog cu ajutorul operatorului de scindare a listelor “|” scris
sub următoarea formă:
[Prim | Rest].
Variabila Prim stă pe postul primului element din listă, iar variabila Rest pe postul
listei care conţine toate elementele din listă cu excepţia primului. Acest operator poate
fi aplicat pe orice listă care conţine cel puţin un element. Dacă lista conţine exact un
element, Rest va reprezenta lista vidă. Încercarea de identificare a structurii [Prim |
Rest] cu o listă vidă duce la eşec. Mergând mai departe, se pot obţine chiar primele
elemente ale listei şi restul listei. Iată câteva echivalenţe:
[a, b, c] = [a | [b, c] ] = [a, b | [c] ] = [a, b, c | [ ] ] = [a | [b | [c] ] ] = [a | [b | [c | [ ] ] ] ].
În Prolog elementele unei liste pot fi atomi, numere, liste şi în general orice
structuri. În consecinţă se pot construi liste de liste.

Exemple:
1. Se poate defini următoarea structură de listă:
[carte(eminescu, poezii), carte(creanga, amintiri_din_copilarie)]
2. Considerând următoarele fapte existente în baza de cunoştinţe Prolog
pred([1, 2, 3, 4]).
pred([maria, sta, in, [banca, treia]]).
se pot pune următoarele întrebări obţinând răspunsurile specificate:

?- pred([Prim | Rest]).
Prim = 1, Rest = [2, 3, 4];
Prim = maria, Rest = [sta, in, [banca, treia]];
no
?- pred([ _, _ , _ , [ _ | Rest]])
Rest = [treia].

3. Un predicat ce testează apartenenţa unui element la o listă se defineşte astfel:


% membru(Element, Lista)
membru(Element, [Element | _ ]).
membru(Element, [ _ | RestulListei]) :- membru(Element, RestListei).

4. Folosind predicatul de concatenare (append) a două liste L1 şi L2, rezultatul


concatenării se obţine în lista L3, iniţial neinstanţiată.
% conc(L1, L2, L3)
conc([], L2, L2). % lista vidă concatenată cu L2 este L2.
conc([Prim1|Rest1], Lista2, [Prim1|Rest3]) :-
conc(Rest1, Lista2, Rest3). % lista rezultată este primul element
% al sublistei curente din L1 concatenat
% cu lista întoarsă de apelul recursiv.
5. Următorul exemplu defineşte predicatul de testare a existenţei unei sortări în ordine
crescătoare a elementelor unei liste de întregi. Predicatul reuşeşte dacă elementele
listei sunt sortate crescător şi eşuează în caz contrar.
% sortcresc(Lista)
sortcresc([ ]). % lista vidă se consideră sortată
sortcresc([ _ ]). % lista cu un singur element este sortată
sortcresc([X, Y | Rest]) :- X = < Y, sortcresc([Y | Rest]).

Dacă se consideră că lista vidă nu este o listă sortată crescător atunci se poate elimina
faptul: sortcresc([ ]). din definiţia predicatului sortcresc, comportarea lui pentru liste
diferite de lista vidă
rămânând aceeaşi.
6. Adăugarea și eliminarea elementelor în / din listă (select,delete).
Select- permite atât inserarea cât și ștergerea elementelor din listă. Acest
predicat selectează elementul indicat din listă și returnează elementele rămase în lista
Rest.

Select nu va elimina decât o apariție a elementului căutat. Select poate fi


utilizat și pentru inserarea de elemente în listă.
Delete șterge toate elementele din Lista1 care unifică simultan cu Elem și
depune rezultatul în Lista2.

Probleme rezolvate în Prolog


1. Să se scrie un predicat cu ajutorul căruia să se determine numărul de vocale dintr-
o listă.

Răspunsul Prologului la interogări va fi:

2. Să se scrie un predicat cu ajutorul căruia să se determine suma a n numere


dintr-o listă.

Răspunsul Prologului la interogări va fi:


Predicate pentru prelucrarea listelor

O listă este o structură de date ce reprezintă o secvenţă ordonată de zero sau mai multe
elemente.
O listă poate fi definită recursiv astfel:
(1) lista vidă (zero elemente);
(2) o listă este o structură cu două componente: primul element din listă: capul listei
(head) şi corpul sau coada listei (tail: formată din următoarele elemente din listă). De obicei,
sfârşitul listei este reprezentat ca listă vidă.

În Prolog structura de listă este reprezentată printr-o structură standard, predefinită, al


cărei functor este caracterul “.” şi are două componente: primul element al listei şi restul listei.
Lista vidă este reprezentată prin atomul special [ ]. De exemplu, o listă cu un singur element a se
reprezintă în Prolog, prin notaţie prefixată astfel:
.(a, [ ]) având sintaxa in ARITY Prolog '.'(a, [ ])
iar o listă cu trei elemene, a, b, c, se reprezintă ca:
.(a, . (b, . (c, [ ]))) cu sintaxa în ARITY Prolog '.'(a, '. '(b, '. '(c, [ ]))).
Prolog-ul oferă o sintaxă alternativă pentru descrierea listelor, formată din elementele
listei separate de virgulă şi încadrate de paranteze drepte. De exemplu, cele două liste anterioare
pot fi exprimate astfel:
[a],
[a, b, c].

Folosind liste, putem acumula o sumedenie de informaţii într-un singur obiect PROLOG.
De exemplu faptele:
luna (1, ianuarie).
luna(2, februarie).
luna(3, martie).
luna(4, aprilie).
luna(5, mai).
luna(6, iunie).
pot fi redate folosind o singură listă sub forma faptului:
luni_prima_jumatate_an([ianuarie, februarie, martie, aprilie, mai, iunie]).

Cele mai frecvente operații asupra listelor se realizează cu ajutorul următoarelor predicate:
1. Predicat ce testează apartenenţa unui element la o listă: membru/member.
Obs: Predicatul membru poate fi utilizat atât pentru testarea apartenenţei unui element la
o listă, cât şi pentru generarea, pe rând, a elementelor unei liste prin resatisfacere succesivă. În
anumite contexte de utilizare această facilitate poate fi folositoare, iar în altele ea poate genera
efecte nedorite atunci când predicatul membru este utilizat în definirea altor predicate.

2. Predicatul de concatenare (append) a două liste L1 şi L2, rezultatul concatenării se


obţine în lista L3, iniţial neinstanţiată.
Dacă predicatul de concatenare are un singur argument neinstanţiat există o singură
soluţie. Dacă primele două argumente sunt neinstanţiate (variabile) se obţin mai multe soluţii,
corespunzătoare tuturor variantelor de liste care prin concatenare generează cea de a treia listă.
Predicatul se poate utiliza pentru a determina o anumită succesiune în listă. De exemplu,
lunile care succed și preced o anumită lună.

De asemenea, putem utiliza predicatul append pentru a găsi predecesorul și succesorul


unei zile din săptămână astfel:

3. Predicatul de testare a existenţei unei sortări în ordine crescătoare a elementelor unei


liste de întregi. Predicatul reuşeşte dacă elementele listei sunt sortate crescător şi eşuează în caz
contrar.

4. Predicatul select/delete – permite adăugarea și eliminarea elementelor în/din listă.


Select- permite atât inserarea cât și ștergerea elementelor din listă. Acest predicat
selectează elementul indicat din listă și returnează elementele rămase în lista Rest.
Select poate fi utilizat și pentru inserarea de elemente în listă.
Delete șterge toate elementele din Lista1 care unifică simultan cu Elem și depune
rezultatul în Lista2.

5. Predicatul sublist / incluziunea listelor: returnează adevăr / true dacă o listă este
sublista unei alte liste. Acest predicat se bazează pe același principiu ca și predicatul membru.
S este sublistă a lui L dacă L se poate descompune în două liste L1 și L2 iar L2 se
poate descompune în două liste S și L3.

Exemplu:

Răspunsul Prologului la interogări va fi:


6. Predicatul max_list / min_list – returnează valoarea maximă / minimă dintr-o listă.
Acest predicat poate reutrna adevărat dacă max/min este cel mai mare/mic element din listă sau
fals în caz contrar.

Exemplu:

7. Predicatul sumlist este folosit pentru a calcula suma elementelor unei liste. Predicatul
este scris sub forma: sumlist(Lista,Suma).

Exemplu:

8. Predicatul numlist – construiește o listă ce conține toate numerele întregi cuprinse


între argumentele întregi Low (mic) și High (mare), cu condiția: Low ≤ High.

Exemplu:

9. Predicatul reverse – inversează ordinea tuturor elementelor dintr-o listă și afișează


rezultatul într-o nouă listă.

Exemplu:
10. Predicatul sort - returnează într-o listă nouă, în ordine crescătoare și eliminând
valorile care se repetă, toate elementele unei liste.

Exemplu:

Sortarea listelor este o operaţie frecvent folosită în aplicaţii. Sortarea listelor înseamnă aranjarea
elementelor listei în ordine crescătoare sau descrescătoare relativ la o anumită relaţie de ordine.
Prezentăm în continuare câţiva algoritmi de sortare care fac apel la strategia “divide et impera”.
“Divide et impera” este o metodă generală de programare care constă în împărţirea repetată a
unor probleme de dimensiune mai mare în două sau mai multe subprobleme de acelaşi tip,
urmată de combinarea soluţiilor subproblemelor rezolvate în scopul obţinerii soluţiei problemei
iniţiale. Algoritmii de sortare care utilizeazăstrategia “divide et impera” presupun divizarea listei
în două subliste, sortarea recursivă a fiecărei subliste şi combinarea rezultatelor într-o singură
listă sortată. În funcţie de metodele de divizare, respectiv de combinare există două posibilităţi:
ƒ
 divizare dificilă şi combinare uşoară - abordare utilizată de sortarea prin selecţie (constă
în alegerea celui mai mic element din listă, sortarea recursivă a restului listei şi adăugarea
apoi în faţă a elementului eliminat) şi de sortarea rapidă (presupune alegerea unui
element oarecare din listă, de regulă primul element, divizarea listei în două subliste
formate din elementele mai mici şi respectiv mai mari decât elementul ales. Cele două
subliste se sortează recursiv şi rezultatele se concatenează, obţinându-se astfel lista
sortată;
 divizare uşoară şi combinare dificilă - abordare utilizată de sortarea prin inserţie (constă
în eliminarea unui element din listă, sortarea listei obţinute şi în final reinserarea
elementului în listă astfel încât lista să rămână sortată) şi de sortarea prin interclasare
(presupune divizarea listei în două subliste aproximativ egale: dacă lista iniţială are n
elemente, atunci una din subliste va fi formată din primele [n/2] elemente iar cealaltă din
următoarele n-[n/2] elemente. Cele două subliste se sortează şi se interclasează rezultatele
(interclasarea este operaţia de obţinere a unei liste sortate din două liste sortate)).

11. Predicatul msort - returnează într-o listă nouă, în ordine crescătoare dar fără a
elimina dublurile, toate elementele unei liste.

Exemplu:

12. Predicatul in_list - returnează true atunci când termenul este o listă reprezentată
prin [ ] sau prin functorul “.” sau false în caz contrar.
Exemplu:

13. Predicatul length – reutrnează un număr întreg care reprezintă lungimea unei liste
(numărul de elemente dintr-o listă).

Exemplu:

14. Predicatul last – este de forma: last(Lista,Element) și returnează răspunsul true


atunci când Element corespunde cu ultimul element al Listei sau returnează răspunsul false în
caz contrar. Dacă Element este o variabilă neinstanțiată, atunci aceasta devine ultimul element
din listă.

Exemplu:

15. Predicatul nextto – returnează valoarea aflată în imediata apropiere a elementului


indicat. Predicatul nextto are forma: nextto(X,Y,Lista).

Exemplu:

16. Predicatul merge – returnează într-o listă nouă (Lista 3) elementele din Lista 1 și
Lista 2 sortate crescător, fără a elimina elementele care se repetă, cu condiția ca elementele
Listei 1 și elementele Listei 2 să fie sortate crescător.

Exemplu:
17. Predicatul permutation generează toate premutările posibile ale elementelor dintr-o
listă dată. Acest predicat are două liste ca argumente, iar una din liste este permutarea celeilalte.

Exemplu:
Lista [1,2,3] are 6 permutări posibile:
[1,2,3]
[1,3,2]
[2,1,3]
[2,3,1]
[3,1,2]
[3,2,1]

Predicatul permutare poate fi formulat astfel:


1. Dacă prima listă este goală atunci și a doua listă trebuie să fie goală (condiția limită a
recursivității),
2. Dacă prima listă nu este vidă, atunci acesta este de forma [X| L] și o permutare poate fi
realizată astfel: permută lista L și obține lista L1 și apoi inserează X pe orice poziție în
L1.

Codul Prolog este

Problema 1:

Fie următoarele enunțuri:


a) Orice om este puternic;
b) Oricine este inteligent și puternic va reuși în viață;
c) Oricine este puternic va reuși în viață sau își va pierde puterea;
d) Există un om inteligent;
e) Tudor este om.
Exprimați enunțurile cu ajutorul predicatelor de ordinul I și scrieți apoi programul SWI-Prolog.

Rezolvare:
a) (x)(om(x)→puternic(x)).
b) (x)(inteligent(x)  puternic(x)→reușește(x)).
c) (x)(puternic(x)→ reușește(x)  pierde_puterea(x)).
d) (x)(om(x)inteligent(x)).
e) Om(‘Tudor’).

Axiomele se transformă în următoarea formă clauzală:


a) ~ om(x)  puternic(x);
b) ~ inteligent(x)  ~ puternic(x)  reușește(x);
c) ~ puternic(x)  reușește(x)  pierde_puterea(x);
d) om
inteligent(a);
e) om(tudor).
Programul SWI-Prolog este următorul:

Răspunsul programului la interogări este:

Problema 2: Problema parteneriatului


Ipoteze:
1) Tudor este corect.
2) Bogdan nu este partener cu Tudor.
3) Dacă două persoane X şi Y sunt corecte, atunci X este partener cu Y.
4) Dacă Bogdan nu este corect, atunci Alex este corect.
5) Dacă o persoană X este partener cu Y, atunci şi Y este partener cu X.

Concluzie:
Alex este partener cu Tudor.

% Ipoteza 1
corect(tudor).
% Ipoteza 2
not_partener(bogdan, tudor).
% Ipoteza 3
partener(X, Y):- corect(X), corect(Y), X \= Y.
% Ipoteza 4, se foloseşte şi ipoteza 3, inversată conform principiului reducerii la absurd: formula
p →q este echivalentă cu !q →!p.
corect(alex) :- not_corect(bogdan).
not_corect(X):- not_ambii_corecţi(X, Y), corect(Y).
% din ipoteza 3
not_ambii_corecţi(X, Y):- not_partener(X, Y).
% Ipoteza 5 este reprezentată în definiţia lui partener (ipoteza 3), care include simetria.

Concluzia
?- partener(alex, tudor).

Codul Prolog este următorul:

Răspunsul Prologului la interogări este:

Problema 3: să se scrie codul tabelei de adevăr pentru expresii logice. Să se definească


predicatele and, or, nand, nor, xor (sau exclusiv), impl (implicație) și equ (echivalență) care
reușesc sau eșuează în funcție de operatori. Apoi să se definească predicatul table care
construiește tabela de adevăr pentru o expresie logică dată.

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