inteligenta artificial a curs
TRANSCRIPT
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 1/183
Programare Logică
Nicolae Constantinescu
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 2/183
2
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 3/183
Cuprins
Prefaţă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
0.1 Introducere. Fapte. Reguli . . . . . . . . . . . . . . . . . . . . . 15
0.1.1 Fundamente teoretice . . . . . . . . . . . . . . . . . . . . 15
0.1.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
0.1.3 Exerciţii propuse . . . . . . . . . . . . . . . . . . . . . . 28
0.1.4 Teme de studiu . . . . . . . . . . . . . . . . . . . . . . . 28
0.2 Termeni. Variabile. Backtracking. Predicatele-sistem trace,
read, write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
0.2.1 Fundamente teoretice . . . . . . . . . . . . . . . . . . . . 29
0.2.2 Exerciţii propuse . . . . . . . . . . . . . . . . . . . . . . 40
0.2.3 Teme de studiu . . . . . . . . . . . . . . . . . . . . . . . 40
0.3 Unificarea. Operaţiile aritmetice . . . . . . . . . . . . . . . . . . 41
0.3.1 Fundamente teoretice . . . . . . . . . . . . . . . . . . . . 41
0.3.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
0.3.3 Exerciţii propuse . . . . . . . . . . . . . . . . . . . . . . 48
0.3.4 Teme de studiu . . . . . . . . . . . . . . . . . . . . . . . 48
3
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 4/183
0.4 Recursivitate. Predicatele !(cut) şi fail . . . . . . . . . . . . . . 49
0.4.1 Fundamente teoretice . . . . . . . . . . . . . . . . . . . . 49
0.4.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . 560.4.3 Exerciţii propuse . . . . . . . . . . . . . . . . . . . . . . 64
0.4.4 Teme de studiu . . . . . . . . . . . . . . . . . . . . . . . 64
0.5 Turnurile din Hanoi. Funcţiile Fibonacci şi Ackermann . . . . . 65
0.5.1 Fundamente teoretice . . . . . . . . . . . . . . . . . . . . 65
0.5.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
0.5.3 Exerciţii propuse . . . . . . . . . . . . . . . . . . . . . . 71
0.5.4 Teme de studiu . . . . . . . . . . . . . . . . . . . . . . . 72
0.6 Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
0.6.1 Fundamente teoretice . . . . . . . . . . . . . . . . . . . . 73
0.6.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
0.6.3 Exerciţii propuse . . . . . . . . . . . . . . . . . . . . . . 98
0.6.4 Teme de studiu . . . . . . . . . . . . . . . . . . . . . . . 99
0.7 Grafuri. Arbori . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
0.7.1 Fundamente teoretice . . . . . . . . . . . . . . . . . . . . 100
0.7.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
0.7.3 Exerciţii propuse . . . . . . . . . . . . . . . . . . . . . . 105
0.7.4 Teme de studiu . . . . . . . . . . . . . . . . . . . . . . . 105
0.8 Probleme speciale . . . . . . . . . . . . . . . . . . . . . . . . . . 106
0.8.1 Problema Damelor . . . . . . . . . . . . . . . . . . . . . 106
0.8.2 Problema mutării calului . . . . . . . . . . . . . . . . . . 108
4
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 5/183
0.8.3 Exerciţii propuse . . . . . . . . . . . . . . . . . . . . . . 110
0.8.4 Teme de studiu . . . . . . . . . . . . . . . . . . . . . . . 110
0.9 Fişiere. Baze de date dinamice . . . . . . . . . . . . . . . . . . . 1120.9.1 Fundamente teoretice . . . . . . . . . . . . . . . . . . . . 112
0.9.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
0.9.3 Exerciţii propuse . . . . . . . . . . . . . . . . . . . . . . 120
0.9.4 Teme de studiu . . . . . . . . . . . . . . . . . . . . . . . 121
1 Probleme de la concursurile de programare 123
1.1 Probleme de la concursurile de programare . . . . . . . . . . . . 1241.1.1 Ascii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
1.1.2 Staţii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
1.1.3 Triplete . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
1.1.4 Spirala . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
1.1.5 Perioada . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
1.1.6 Numere . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
1.1.7 Triunghi . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
1.1.8 Diamant . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
1.1.9 Drum . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
1.1.10 Tabla . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
1.1.11 Şarpele belgian . . . . . . . . . . . . . . . . . . . . . . . 135
1.1.12 Hexagon . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
2 Soluţiile problemelor propuse 139
5
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 6/183
2.1 Introducere. Fapte. Reguli . . . . . . . . . . . . . . . . . . . . . 139
2.1.1 Soluţie teoretică . . . . . . . . . . . . . . . . . . . . . . . 139
2.1.2 Apel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
2.1.3 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . 142
2.2 Termeni. Variabile. Backtracking. Predicatele-sistem trace,
read, write . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
2.2.1 Soluţie teoretică . . . . . . . . . . . . . . . . . . . . . . . 145
2.2.2 Apel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
2.2.3 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . 146
2.3 Unificarea. Operaţiile aritmetice . . . . . . . . . . . . . . . . . . 149
2.3.1 Soluţie teoretică . . . . . . . . . . . . . . . . . . . . . . . 150
2.3.2 Apel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
2.3.3 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . 150
2.4 Recursivitate. Predicatele !(cut) şi fail . . . . . . . . . . . . . . 151
2.4.1 Soluţie teoretică . . . . . . . . . . . . . . . . . . . . . . . 151
2.4.2 Apel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
2.4.3 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . 152
2.5 Turnurile din Hanoi. Funcţiile Fibonacci şi Ackermann . . . . . 152
2.5.1 Soluţie teoretică . . . . . . . . . . . . . . . . . . . . . . . 152
2.5.2 Apel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
2.5.3 Cod Sursă . . . . . . . . . . . . . . . . . . . . . . . . . . 153
2.6 Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
2.6.1 Soluţie teoretică . . . . . . . . . . . . . . . . . . . . . . . 153
6
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 7/183
2.6.2 Apel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
2.6.3 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . 155
2.7 Probleme speciale . . . . . . . . . . . . . . . . . . . . . . . . . . 1562.7.1 Soluţie teoretică . . . . . . . . . . . . . . . . . . . . . . . 156
2.7.2 Apel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
2.7.3 Cod sursă . . . . . . . . . . . . . . . . . . . . . . . . . . 157
2.8 Fişiere. Baze de date dinamice . . . . . . . . . . . . . . . . . . . 158
2.8.1 Soluţia problemei 0.9.1 . . . . . . . . . . . . . . . . . . . 159
2.8.2 Soluţia problemei 0.9.2 . . . . . . . . . . . . . . . . . . . 163
3 Anexa Predicate 167
3.1 Anexa predicate . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
3.1.1 Notaţiile predicatelor . . . . . . . . . . . . . . . . . . . . 168
3.1.2 Încărcarea fişierelor sursă . . . . . . . . . . . . . . . . . . 168
3.1.3 Compararea şi unificarea termenilor . . . . . . . . . . . . 168
3.1.4 Predicate de control . . . . . . . . . . . . . . . . . . . . 169
3.1.5 Baze de date dinamice . . . . . . . . . . . . . . . . . . . 170
3.1.6 Intrări şi Ieşiri . . . . . . . . . . . . . . . . . . . . . . . . 170
3.1.7 Predicate primitive pentru I/O . . . . . . . . . . . . . . 173
3.1.8 Citirea şi scrierea termenilor . . . . . . . . . . . . . . . . 174
3.1.9 Predicate pentru operaţii cu liste . . . . . . . . . . . . . 175
3.1.10 Predicate aritmetice . . . . . . . . . . . . . . . . . . . . 176
3.1.11 Funcţii aritmetice . . . . . . . . . . . . . . . . . . . . . . 177
3.1.12 Urmărirea execuţiei programului . . . . . . . . . . . . . . 179
7
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 8/183
8
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 9/183
Listă de figuri
1 Fereastra pentru trace în mod grafic . . . . . . . . . . . . . . . . 35
1.1 Exemple de apel pentru N=5 şi respectiv N=3 . . . . . . . . . . 124
1.2 Exemplu de display digital . . . . . . . . . . . . . . . . . . . . . 129
1.3 Tabla nemodificată de spiritul rău . . . . . . . . . . . . . . . . . 132
1.4 Tabla alterată . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
1.5 Exemplu de tablă şi reprezentarea corespunzătoare . . . . . . . 134
1.6 Hexagon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
9
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 10/183
10
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 11/183
Listă de tabele
1 Funcţii trigonometrice disponibile în SWI-Prolog . . . . . . . . . 43
2 Funcţii matematice disponibile în SWI-Prolog . . . . . . . . . . 44
3 Predicatele aritmetice in SWI-Prolog . . . . . . . . . . . . . . . 45
4 Câteva valori ale funcţiei Ackermann . . . . . . . . . . . . . . . 70
5 Valorile funcţiei Ackerman calculate în SWI-Prolog . . . . . . . 71
11
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 12/183
Prefaţă
Programarea logică este o paradigmă a programării declarative, bazată pe
logica de ordinul I. Teza potrivit căreia logica de ordinul I este un util şi practic
limbaj de programare non-deterministic de nivel înalt cu un solid fundament
teoretic aparţine lui R. Kowalsky, care dezvoltă un punct de vedere relaţional
al calculabilităţii ca deducţie, sintetizat prin următoarea formulă:
Calculabilitate = Logică + Control
Dacă punem în antiteză relaţia lui Kowalsky cu cea a lui N. Wirth potrivit
căreia:
Program = Structuri de date + Algoritm
observăm că, în domeniul programării
• procedurale - trebuie rezolvate la nivelul codului atât aspectele logice,
cât şi cele de control
• declarative - trebuie rezolvate numai cele de control.
Considerând că un program logic este constituit dintr-o familie de axiome şi
o ţintă, iar regulile de inferenţă determină faptul că axiomele sunt suficiente
pentru a proba veridicitatea ţintei, execuţia unui program logic corespunde
construcţiei unei demonstraţii a ţintei pe baza axiomelor ataşate programu-
lui. Practic, execuţia unei secvenţe de cod în programarea logică este realizată
prin intermediul unui demonstrator rezolutiv de teoreme. Plecând de la aceste
12
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 13/183
observaţii şi analizând relaţia dintre calculabilitate şi deducţie, aşa cum a fost
ea tratată de P. J. Hayes1, putem concluziona că un interpretor al unui limbaj
de programare şi un demonstrator automat de teoreme (motor de inferenţe)au structuri practic identice, iar avantajele de natură practică şi teoretică sunt
obţinute prin combinarea celor două metodologii. În fapt, Kowalsky şi Hayes
propun un comportament convergent pentru deducţie şi calculabilitate.
Teza este similară celei potrivit căreia sistemele de gestiune a bazelor de
date pot fi văzute drept colecţii de structuri relaţionale care definesc logica
datelor.
Colmerauer implementează ideea în construcţia limbajului de programarePROLOG (PROgramming in LOGic), bazându-se şi pe o importantă lucrare
a lui A. Robinson2 şi utilizând de la Kowalsky conceptul de "clauză Horn",
fundamentând astfel strategia bazată pe o demonstraţie lineară cu backtrac-
king şi unificarea capetelor de clauze. Limbajul PROLOG al acestui început
nu era la fel de matur ca limbajul LISP, dar implementarea realizată de H.D.
Warren a condus la îmbunătăţiri substanţiale ale limbajului.
Compilatorul a fost scris aproape integral în PROLOG, translatând clau-zele PROLOG în instrucţiuni ale unei maşini abstracte cunoscută sub numele
de Maşina Abstractă Warren (WAM).
1P. Hayes, Computation and deduction, Proc. 2nd Symp. on Mathematical Foundations
of Computer Science (MFCS), Czechoslovakian Academy of Sciences, Prague, 1973, pp.
105-118.2Robinson J.A., A machine-oriented logic based on the resoulution principle, J. ACM
12,1, pp. 23-41, January 1965.
13
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 14/183
Clocksin şi Mellish continuă efortul de perfecţionare a limbajului obţinând
o versine acceptată ca standard si numită "sintaxă C&M" sau "sintaxă Edin-
burgh". Dintre dialectele limbajului PROLOG amintim Quintus PROLOG,C-PROLOG, Turbo PROLOG, Visual PROLOG, SWI-PROLOG, λPROLOG,
B-PROLOG, BinProlog, GNU Prolog, jPROLOG, SICStus PROLOG , Amzi
PROLOG etc.
Cu toate aceste importante realizări, comunitatea specialiştilor în informa-
tică, în general şi cea a specialiştilor în inteligenţă artificială, în particular, nu
au acordat atenţia cuvenită programării logice.
O schimbare de atitudine s-a înregistrat odată cu lansarea "Japanese FifthGeneration Project", care a redefinit importanţa programării logice pentru ur-
mătoarele generaţii de calculatoare.
Din acel moment limbajul PROLOG a cunoscut o dezvoltare permanentă.
O paradigmă mai recentă este cea a Constraint Language Programming
(CLP), unde domeniul nu este restricţionat la universul Herbrand şi unde uni-
ficarea este înlocuită cu satisfacerea restricţiilor. O instanţă a acestei abordări
poate fi considerată CLP(R) (Constraint Logic Programming over the Realdomain), cu implementarea operatorilor aritmetici (+,-,*,/) şi a funcţiilor sin,
cos etc.
14
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 15/183
0.1 Introducere. Fapte. Reguli
0.1.1 Fundamente teoretice
PROLOGul a fost inventat la începutul anilor ’70 de către Alain Colmerauer
în Franţa (PROgramming in LOGic=PROLOG). Printre aplicaţiile la care
poate fi folosit PROLOG-ul se numără: sisteme expert, limbaje de specifi-
caţie, înţelegerea limbajelor naturale, baze de date, programarea roboţilor şi
automatizarea gândirii artificiale.
Un program este, în general, compus din două elemente din care unul estepredominant, ne referim la noţiunile de logică şi control. Acestea sunt ele-
mentele care descriu ce face un program şi respectiv cum procedează pentru a
ajunge la o soluţie (spre exemplu în programarea structurată prin intermediul
unui algoritm se ajunge la o soluţie, iar secvenţa de instrucţiuni ale algoritmu-
lui este ce se întâmplă pentru a se ajunge la soluţie ).
Limbajele care aparţin programării structurate descriu pas cu pas modul în
care programul trebuie să se comporte pentru ca după un număr finit de paşisă se obţină soluţia, de aceea spunem că programarea structurată urmează
paradigma imperativă. Aceste limbaje nu sunt însă lipsite de componenta
descriptivă, dincolo de modul imperativ. Să spunem că avem nevoie la un
moment dat să calculăm o valoare, printr-o instrucţiune vom descrie şi modul
în care valoarea va fi obţinută.
Prin contrast, programarea logică se bazează pe alegerea predicatelor care de-
scriu cel mai bine relaţiile care există între obiecte, fiindcă ele vor fi cele care vor
15
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 16/183
stabili legătura între datele de intrare şi cele de ieşire. Dacă această legătură
nu va fi corect definită este posibil să primim răspunsuri eronate. Compo-
nenta logică a limbajului PROLOG este deci alegerea predicatelor si stabilirearelaţiilor dintre datele descrise de aceste predicate. Controlul asupra modului
de execuţie al programului se află în felul în care sunt aranjate clauzele, dar
şi în câteva elemente de control structural cum este predicatul "cut" (notat
"!") sau predicatul fail . Din aceste motive programarea logică este o abordare
descriptivă, la care elementul structural imperativ este element de control.
PROLOG-ul şi versiunile sale (printre care şi SWI-Prolog) face parte din ca-
tegoria limbajelor de programare logice si este un limbaj declarativ ceea ceînseamnă că mai degrabă programatorul va scrie un program care conţine o
bază de date cu faptele şi relaţiile logice (regulile) dintre ele, astfel încât
atunci când sistemului i se va adresa o întrebare el va consulta baza de fapte şi
reguli pentru a găsi un răspuns (prin deducţie logică). Programarea în PRO-
LOG nu utilizează conceptele de procedură şi atribuire, concepte foarte
răspândite în alte limbaje de programare, în locul acestora întâlnim concepte
proprii programării logice. Faptul că nu există atribuire se explică prin exis-tenţa unei legături (conceptul de unificare) ce se stabileşte între valoare şi
variabilă. Odată produsă această legătură participă la un lanţ de deducţii ce
au loc pe parcursul programului, iar la terminarea lanţului deductiv variabilele
sunt dezlegate de aceste valori.
Printre calităţile PROLOG-ului se număra ’variabilele logice’ care se comportă
ca variabilele matematice, utilizarea backtrackingului pentru căutarea dovezi-
16
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 17/183
lor şi pentru a se ajunge la o concluzie, structuri de date uniforme. În multe
ocazii vor exista fie mai multe căi de a găsi o soluţie fie mai multe soluţii de
aceea capabilitatea sistemului de a face backtracking se dovedeşte o caracte-ristică importantă.
PROLOG-ul este un limbaj slab în ceea ce priveşte tipurile variabilelor, aceasta
înseamnă că o variabilă de un anumit tip poate conţine, la un moment dat,
date de alt tip.
Exemplele din acest material au fost concepute şi testate în SWI-Prolog ver-
siunea 5.4.3.
0.1.1.1 Structura programului
Aşa cum am spus mai sus un program PROLOG constă în fapte şi reguli , care
se pot grupa sub denumirea generală de date, şi întrebări venite din partea
utilizatorului, la care sistemul trebuie să răspundă.
Datele şi întrebarile sunt clauze Horn de forma:
A(t1, . . . , tn) ←
şi în PROLOG ele sunt notate simbolic prin
A(t1, . . . , tn).
unde A este un predicat iar t1, . . . , tn sunt constante ale limbajului predicatelor.
Simbolul "." marchează finalul unei formule.
O regulă în PROLOG are forma:
A(t1, . . . , tn) : −B1( p1, . . . , pi), . . . , Bn(q1, . . . , q j).
17
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 18/183
unde A, B1, . . . , Bn sunt predicate, iar t1, . . . , tn, p1, . . . , pi, q1, . . . , q j sunt ter-
meni. Se spune adesea că regulile şi faptele alcătuiesc baza de date a progra-
mului.Interogările sunt numite şi scopuri şi sunt clauze Horn de forma:
B1(s1, . . . , si), . . . , Bn(t1, . . . , t j)
în PROLOG aceste clauze au forma:
? − B1(s1, . . . , si), . . . , Bn(t1, . . . , t j).
unde B1, . . . , Bn sunt simboluri de predicate, iar s1, . . . , si, t1 . . . , t j sunt ter-
meni.
Aşadar un program PROLOG este o colecţie de fapte, reguli şi interogări fără
prea multe indicaţii despre fluxul şi controlul programului. Această structură
marchează fineţea cu care în acest limbaj pot fi obţinute extensii şi îmbunătă-
ţiri prin introducerea de fapte sau reguli fără a interveni asupra structurii si
datelor deja existente în program.
0.1.1.2 Faptele
Faptele sunt cea mai simplă formă de predicat în PROLOG. Ele sunt predica-
tele sau acţiunile care se întâmplă fară să depindă de alte acţiuni sau predicate.
Faptele mai pot fi văzute şi ca o bază de cunoştinţe sau ca date de intrare.
Sintaxa este următoarea:
nume_ predicat( param1, param2, ..., paramN ).
18
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 19/183
unde N este numărul de parametri fiind numit aritatea predicatului. Un pre-
dicat de aritate 0 se defineşte astfel: nume_ predicat.
Exemple de fapte:
ploua. - predicat de aritate 0
citeste(emil,literatura). - predicat de aritate 2
frati(emil,ion,george). - predicat de aritate 3
Alegerea numelor predicatelor precum şi a interpretării lor se face de către
programator, este deci foarte important să se aleagă nume care nu prezintăambiguităţi şi interpretarea unui predicat să se păstreze pe tot parcursul pro-
gramului. Spre exemplu considerăm predicatul bunic(dan, andrei). care are
interpretarea "Dan este bunicul lui Andrei" dacă vom mai avea un predicat
bunic(marcel, gabi). pe care îl interpretăm "Gabi este bunicul lui Marcel".
Programul scris de noi nu va întoarce rezultatele aşteptate deoarece interpre-
tările programatorului pentru acelaşi predicat sunt diferite, aceasta conducând
în mod indiscutabil la aşteptări eronate cu privire la rezultatul care va fi ob-ţinut.
0.1.1.3 Regulile
O regulă este o formă de predicat care depinde de alte predicate pentru a fi
îndeplinită. Sintaxa este următoarea :
nume_predicat(arg1,arg2,...,argN):-
predicat1(param1,..,paramN),
19
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 20/183
predicat2(param1,..paramN),
. . . ,
predicatN(param1,...,paramN).Virgula în SWI-Prolog are valoarea unui şi logic. Astfel în exemplul de mai sus
îndeplinirea predicatului de argumente arg1,...,argN depinde de îndeplinirea
tuturor celorlalte predicate, dacă unul din ele întoarce "No" nu se va mai trece
la următorul predicat şi nume_predicat va întoarce şi el "No".
Exemple de reguli:
frate(X,Y):-
parinte(Z,X),parinte(Z,Y).
Această regulă conţine 2 predicate care trebuiesc îndeplinite pentru ca ea să
se îndeplinească. O posibilă traducere a regulii în limbaj natural ar putea fi
următoarea: X este frate cu Y dacă există Z care este părintele lui X şi Z este
părinte şi pentru Y.
picteaza(X):-
pictor(X),tablou(X,Z),
critic_de_arta(Y),
place(Y,Z).
Regula de mai sus conţine 3 sub-scopuri ea poate fi tradusă după cum urmează:
X pictează dacă X este pictor şi el are un tablou Z, Y este un critic de artă şi
îi place tabloul Z.
20
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 21/183
0.1.1.4 Comenzi în SWI-Prolog
Comenzile SWI-Prolog sunt la rândul lor predicate pe care sistemul le pune la
dispoziţia programatorului. O comandă SWI-Prolog se termină întotdeauna
cu caracterul "." deoarece este considerată a fi un fapt. Iată câteva comenzi
uzuale:
?-pwd. - afişează directorul curent.
?-ls. - afişează fisierele din directorul curent. Directoarele vor avea caracterul
final "/" pentru a putea fi deosebite de fişiere.
?-cd(’cale’). - schimbă directorul.
?-halt. - încheie sesiunea de lucru.
?-help(nume_comandă) - afişează informaţii despre nume_comandă .
?- cd(’c:/PROLOG’).
Yes
?- pwd.c:/PROLOG
Yes
?- ls.
alte ex/ L2ex4.pl L5ex1.pl L7ex4.pl L9ex2.pl
grad.pl L2ex5.pl L5ex2.pl L7ex5.pl L9ex3.pl
Yes.
SWI-Prolog dispune de un browser de fişiere în mod grafic, pentru ca
21
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 22/183
utilizatorul să nu fie nevoit să vizualizeze structura de directorare şi fişiere
din linie de comandă. Acest browser este util în special pentru editarea
fişierelor .pl (sursă SWI-Prolog ) care vor fi deschise cu utilitarul Note-pad, dacă un alt program de editare nu este configurat pentru a edita fişiere
cu această extesie. Acesta poate fi accesat din meniul File, opţiunea Navigator.
Pentru a încărca un fişier sursă SWI-Prolog tastăm comanda [numefi-
sier]., dacă sistemul va răspunde cu "Yes", fişierul a fost încărcat cu succes,
altfel vom primi un mesaj de genul "ERROR: source_sink ‘numefisier’does not exist" în cazul în care fişierul nu există. Numele fişierului trebuie
scris cu litere mici, mai precis prima literă din nume, altfel SWI-Prolog va
presupune că este vorba de o listă şi textul conţinut înte paranteze este o
variabilă căreia va încerca să-i dea o valoare. În cazul unei erori de sintaxă
în cadrul clauzelor scrise în fişier mesajul arată în felul următor: "ERROR:
c:/PROLOG/numefisier.pl:2:8: Syntax error: Operator expected", calea
către fişier poate fi alta în funcţie de directorul unde se află fişierul pe caredorim să-l compilăm. O altă metodă de a încărca şi compila un fişier este
folosirea predicatelor-sistem consult(numefisier) şi ensure_loaded(numefisier).
Exemple ale metodelor descrise sunt prezentate mai jos:
?- [l1ex1].
l1ex1 compiled 0.00 sec, 1,188 bytes
Yes
?- ensure_loaded(l3ex1). % l1ex1 compiled 0.00 sec, 1,188 bytes
22
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 23/183
Yes
?- consult(l3ex1).
% l3ex1 compiled 0.00 sec, 0 bytesYes
Pentru a verifica încărcarea corectă a clauzelor putem folosi comanda listing,
prezentată mai jos:
?-listing.
fruct(prune).
are(ion,mere).
...
0.1.2 Exemple
Exemplul 0.1.1.
Fişierul L1ex1.pl conţine clauzele:
are(ion,mere).are(ana,prune).
are(dan,bani).
fruct(mere).
fruct(prune).
Pentru a vedea ce fel de fructe deţine Ion vom apela predicatul are(), indicând
că vrem să aflăm ce fel de fructe deţine prin plasarea pe prima poziţie a ato-
mului "ion" şi pe poziţia secundă variabila X ( variabilele încep cu literă mare
23
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 24/183
în SWI-Prolog ).
?-are(ion,X).
X=mereDe data aceasta dorim să aflăm dacă Ion deţine un fruct însă nu vrem să ştim
ce fel de fruct este. Pentru aceasta folosim underline "_" ( variabila underline
în SWI-Prolog se numeşte variabilă anonimă, iar valorile conţinute de această
variabilă nu sunt relevante pentru scopul urmărit atunci când se execută pro-
gramul. Mai mult, dacă în cadrul aceluiaşi program exită mai multe variabile
"_" ele pot conţine valori diferite în acelaşi timp fără să se afecteze reciproc.
).?-are(ion,_).
Yes
În următorul exemplu dorim să aflăm cine are mere şi cine are prune.
?-are(X,mere),are(Y,prune).
X=ion Y=ana
Are cineva şi mere şi prune ? Observaţi faptul că faţă de exemplul precendent
primul parametru al predicatului are este aceeaşi variabilă X, asfel dorim sădesemnăm faptul că este vorba de aceeaşi persoană care deţine cele 2 tipuri de
fructe.
?-are(X,mere),are(X,prune).
No
Are Dan fructe? Pentru a afla răspunsul trebuie mai întâi să aflăm dacă Dan
deţine ceva. Folosim Predicatul are/2 , punând pe poziţia secundă variabila X,
24
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 25/183
care mai apoi ne întrebăm dacă este fruct . Dacă va fi definit un fapt de forma
fruct(valoareaLuiX). răspunsul va fi afirmativ.
?-are(dan,X),fruct(X).No
Are cineva ceva, dar nu fructe? De data aceasta negăm predicatul fructe prin
predicatul not care este un predicat predefinit în SWI-Prolog.
?-are(X,Y),not(fruct(Y)).
X=dan
Y=bani
Exemplul 0.1.2.
Prezentăm în continuare un exemplu de implementare a unui arbore genealo-
gic. Să observăm faptul că numele personajelor încep cu literă mică, aceasta
deoarece ele sunt atomi (constante sau valori fixate), dacă am fi avut aceste
nume cu literă mare compilatorul SWI-Prolog ar fi considerat că ele sunt va-
riabile. Exemplul este implementat în fişierul L1ex2.pl
parinte(andrei,ionut).parinte(andrei,ilie).
parinte(ilie,emil).
parinte(ilie,irinel).
Cine sunt copii lui andrei? În cazul acesta interogarea are două răspunsuri,
însă sistemul se va opri după găsirea primei soluţii şi va aştepta indicaţii din
partea noastă. Dacă dorim şi afişarea celuilalt răspuns trebuie să apăsam ";",
simbol care reprezintă un sau logic.
25
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 26/183
?-parinte(andrei,X).
X=ionut ;
X=ilie ;No
Are andrei vreun copil?
?-parinte(andrei,_).
Yes
Cine este tatăl lui emil?
?-parinte(Tata,emil).
Tata=ilieDorim o enumerare a tuturor numelor care se află într-o relaţie de tipul tată-
fiu. Pentru a obţine toate răspunsurile şi la această interogare apăsaţi ";" după
fiecare răspuns din partea sistemului.
?-parinte(X,Y).
X = andrei
Y = ionut ;
X = andreiY = ilie ;
X = ilie
Y = emil ;
X = ilie
Y = irinel ;
Este andrei bunic? Avem din nou o interogare compusă, observaţi din nou
26
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 27/183
poziţia variabilei X. Pentru ca andrei să fie bunic el trebuie să fie parintele
lui X ( parintele cuiva ) şi acel cineva să aibă un copil (nepotul lui andrei).
După afişarea tuturor soluţiilor vom obţine "No" deoarece sistemul încearcăsă determine alte soluţii pentru clauzele programului, considerând interogarea
adresată. Alte de soluţii neexistând vom primi răspunsul No.
?-parinte(andrei,X),parinte(X,Nepot).
X=ilie
Nepot=emil;
X=ilie
Nepot=irinel;No
Dacă dorim să nu folosim o interogare compusă putem edita fişierul sursă
pentru a defini predicatul bunic(B, N ), prezentat mai jos, care va putea fi apoi
apelat din linia de comandă SWI-Prolog.
bunic(B,N):-parinte(B,P),parinte(P,N).
?-bunic(andrei,irinel).
Yes?-bunic(andrei,Nepot).
Nepot=emil
Nepot=irinel
No
27
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 28/183
0.1.3 Exerciţii propuse
Exerciţiul 0.1.1.
Definiţi predicatele cumnat, matuşă, unchi, strabunic, soacră.
0.1.4 Teme de studiu
Tema 0.1.1.
Rulaţi în SWI-Prolog exemplele prezentate.
28
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 29/183
0.2 Termeni. Variabile. Backtracking.
Predicatele-sistem trace, read, write
0.2.1 Fundamente teoretice
0.2.1.1 Termenii de baza în PROLOG
Un program SWI-Prolog este alcătuit din predicate şi în general se urmăreşte
obţinerea unui răspuns pentru o interogare. Fiecare predicat poate avea una
sau mai multe clauze.
Exemplul 0.2.1.
masina(ferrari).
masina(dacia).
proprietar(george,ferrari).
În exemplul de mai sus predicatul masina are două clauze, iar predicatul pro-prietar are o singură clauză.
O altă caracteristică a predicatelor este aritatea ( numărul de parametri sau
termeni ). Termenii pot fi :
- Întregi - numere pozitive sau negative.
- Atomi - text care începe cu litera mică. Exemplu: ana, alt_atom, atom3,
douaCuvinte, etc.
29
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 30/183
- Variabile - încep cu litera mare sau "_". Exemplu: X, Y, _z, Variabila,
Masina, Dan, Maria, etc.
- Structuri compuse - ex. listele - [a,b,c,d] sau tuplurile
carte(autor(nume),titlu,data).
0.2.1.2 Variabilele
Variabilele în SWI-Prolog încep întotdeauna cu literă mare sau "_" şi sunt
fără tip, adică pot conţine orice fel de valoare. Totuşi iniţial o variabilă este
doar un loc unde se va stoca la un moment dat în timpul procesării unei clauze
o valoare, care la momentul actual nu este disponibilă. Spunem că variabila
iniţial nu este instanţiată. Această funcţie de loc de stocare a unei variabile
poate fi exemplificată printr-un exemplu simplu:
?- X is 1+1.
în cazul acesta rezultatul operaţiei de adunare nu este cunoscut înainte ca
expresia din dreapta lui "is" să fie evaluată. Variabila X este deci iniţial doar
un loc rezervat pentru o valoare care va deveni disponibilă după evaluarea
expresiei 1 + 1. Dacă considerăm un alt exemplu:
?- X = 1+1.
vom observa că într-o variabilă X, se pot păstra nu numai numere întregi dar
şi structuri de date. În acest caz particular semnul "=" este un atom special
care desemnează egalitatea termenilor, de data aceasta 1 + 1 nu va mai fi
considerată expresie şi nu va mai fi evaluată, X va fi unificat cu o structură de
30
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 31/183
tipul 1 + 1. Aşa cum am văzut în exemplele din secţiunea anterioară valorile
stocate în variabile pot fi recuperate în cadrul aceleiaşi interogări sau clauze,
în exteriorul lor valorile se pierd, chiar dacă numele variabilelor sunt aceleaşi.Aceasta ţine de mecanismul de unificare Prolog, care face ca variabilele din
cadrul altor clauze să fie legate de alte locaţii de memorie.
?- X = 1+2, Y is X.
În acest exemplu X este instanţiată cu termenul 1 + 2 si în interogarea care
urmează se recuperează din X expresia care va fi evaluată, în Y găsindu-se
valoarea rezultată în urma evaluării, şi anume 3.
Un alt tip de variabile sunt variabilele anonime, acestea sunt desemnate de
semnul "_" ( numai semnul acesta este o variabilă anonimă, _abc va fi con-
siderată o variabilă obişnuită ) şi valorile conţinute de ele nu sunt relevante.
Aceste variabile nu vor fi legate de valorile conţinute, şi o valoare a unei astfel
de variabile nu va putea fi accesată deoarece deşi reprezentarea este aceeaşi,
linuţa de subliniere, fiecare variabilă anonimă va desemna o altă zonă de me-
morie, astfel printr-un predicat de genul write(_). nu vom primi rezultatul
aşteptat.
Un concept important în PROLOG este acela de pattern sau model. De fie-
care dată când se întâlneşte o variabilă va căuta în baza de fapte şi reguli o
substituţie pentru care predicatul ce conţine variabila poate fi demonstrat prin
deducţie logică. Dacă acest lucru nu este posibil sistemul va întoarce "No." ca
răspuns. Să considerăm următorul exemplu:
Exemplul 0.2.2.
31
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 32/183
cuvant(buna).
cuvant(ziua).
fraza(A, B) :- cuvant(A), cuvant(B).
salut(A, B) :- fraza(A, B), A = buna.
Programul defineşte două fapte (cuvant(buna). şi cuvant(ziua).) şi două pat-
ternuri(fraza(. . . ) şi salut(. . . )). Întâlnind variabilele A şi B compilatorul
va încerca să găsească o substituţie care să satisfacă patternul sau modelul
din dreapta semnului ":-" ( poate fi interpretat ca fiind if-ul din programareastructurată ) , pentru acest caz particular avem substituţiile:
A=buna, B=buna
A=buna, B=ziua
A=ziua, B=ziua
A=ziua, B=buna
Pentru salut(A,B) însă vom avea o listă de substituţii mai scurtă deoarece
avem o condiţionare în plus (A=buna) care reduce lista substituţiilor care
îndeplinesc patternul ( modelul ) impus. Pentru a obţine totuşi o frază de
salut am putea adăuga încă o condiţionare şi anume B=ziua.
A=buna, B=buna
A=ziua, B=ziua
32
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 33/183
Pentru a ilustra modul de utilizare a variabilelor anonime considerăm progra-
mul precedent cu unele modificari. În cadrul predicatului fraza am adăugat
predicatul prieten(_). Acest predicat se va apela pentru toate predicatele dinbaza de fapte însă valorile din baza de fapte nu vor fi reţinute în variabila _.
Pentru a proba aceasta încercaţi să folosiţi write(_) şi urmăriţi răspunsul din
partea sistemului.
Exemplul 0.2.3.
Fişierul L2ex1.pl conţine programul de mai jos, tastaţi [l2ex1]. în linia de
comandă SWI-Prolog pentru a compila fişierul:cuvant(buna).
cuvant(ziua).
prieten(andrei).
prieten(alin).
prieten(alex).
fraza(A, B) :- cuvant(A), cuvant(B), prieten(_).
salut(A, B) :- fraza(A, B), A = buna , B=ziua.Substituţiile valide pentru exemplul de mai sus sunt în numar de 3 pentru A
şi B vom avea de fiecare dată A=buna, B=ziua iar _ va avea pe rând valorile
andrei, alin, alex.
0.2.1.3 Comanda trace
La fel ca oricare alt mediu de programare SWI-Prolog oferă posibilitatea de a
urmări execuţia programului. Pentru a urmări un program relativ simplu, tot
33
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 34/183
ce trebuie să faceţi este să tastaţi trace. Când veţi apela următorul predicat
pentru care doriţi un răspuns Prolog-ul va genera o listă de apeluri de forma:
Exit: (9) putere(ferrari, 500) ? creepCall: (9) put_min(gicu, _L204) ? creep
Exit: (9) put_min(gicu, 300) ? creep
Pentru a trece mai departe la apelul următor se apasă tasta Enter sau Spaţiu,
cuvântul "creep" apare automat pentru a marca trecerea la apelul curent.
Se poate urmări însă şi execuţia unui singur predicat prin apelul
trace(NumePredicat ). , de asemenea se poate urmări predicatul res-
pectiv numai pentru anumite acţiuni (call, redo, exit, fail). De exemplutrace(salut,+fail). va afişa numai Fail-urile pentru predicatul salut . O co-
mandă de genul trace(salut). este echivalentă cu trace(salut,+all). Putem opri
trace-ul prin comanda trace(salut,-all). Evident trace(salut,-call). sau oricare
altă opţiune va opri trace-ul pentru acea opţiune. Dacă la un moment dat
dorim să întrerupem trace-ul definitiv după ce am executat programul vom
folosi predicatul nodebug.
SWI-Prolog pune la dispoziţie şi un trace în mod grafic, acesta se activeazăprin predicatul guitracer., iar la următorul apel al lui trace pentru un predicat
se va deschide fereastra din figura 1. După cum se poate observa fereastra este
împărţită în 3 zone: în dreapta sus avem lista de apeluri, în stânga sus sunt
enumerate variabilele şi valorile de care sunt legate, iar jos se poate urmări
locaţia în sursă care generează apelul curent. Predicatul noguitracer. opreşte
trace-ul grafic.
34
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 35/183
Figura 1: Fereastra pentru trace în mod grafic
0.2.1.4 Predicatele read/write
O altă abordare eficientă pentru a afla ce se întamplă este aceea de a folosi
predicatele din SWI-Prolog write(<mesaj>). şi nl. Predicatul write va face
să apară în fereastra SWI-Prolog mesajul <mesaj>, iar nl. va trece pe linie
nouă.
Exemplul 0.2.4.
Considerăm programul de mai jos, implementat în fişierul L2ex2.pl
ingredient(zahar).
ingredient(faina).
cauta_ingredient(X):-
write(’Caut: ’),
write(X),
35
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 36/183
nl,
ingredient(X),
write(am_gasit(X)),nl.
Apel: ?- cauta_ingredient(zah).
Caut: zah
No
?- cauta_ingredient(zahar).
Caut: zahar
am_gasit(zahar)Yes
Desigur în timpul execuţiei unor programe dorim să citim variabile de la tas-
tatură. SWI-Prolog pune la dispoziţie predicatul-sistem read(<variabila>).
Exemplul 0.2.5.
Programul de mai jos exemplifică modul de funcţionare al predicatului read .
Implementarea se găseşte în fişierul L2ex3.pl .Program:
start:-
write(’Introduceti o valoare: ’),
read(X),nl,
write(’Ati introdus: ’),
write(X).
Apel: ?- start.
36
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 37/183
Introduceti o valoare: e345sd.
Ati introdus e345sd
YesComentariile în SWI- Prolog se fac în stilul C-ului /* comentariu */ sau co-
mentarii pe un singur rând, care încep cu %, iar tot ce urmează pe linia res-
pectivă va fi ignorat. Comentariile sunt utile întotdeauna într-un cod sursă,
o convenţie unanim acceptată este aceea de a pune comentarii înaintea unui
predicat SWI-Prolog pentru a-l explica.
0.2.1.5 Modul de funcţionare SWI-Prolog -Backtrackingul
În acest paragraf urmărim să arătăm modul de funcţionare al SWI-Prolog,
felul în care răspunde interogărilor utilizatorului , deci felul în care rulează un
program. Dându-i-se o interogare Prolog-ul caută în lista sa de fapte şi reguli
(de sus în jos) căutând în antetul faptelor şi regulilor pe acelea care se potrivesc
interogării (având date un set de variabile legate), atunci când găseşte un fapt
sau o regulă care se potriveşte reţine locul unde a ajuns în căutarea sa pentruca apoi să revină în cazul în care regula se dovedeşte a fi imposibil de rezolvat
prin deducţie. Să presupunem că avem următoarele fapte:
Exemplul 0.2.6.
Programul de mai jos se găseşte în fisierul L2ex4.pl .
pasare(tip(canar), nume(tweety)).
pasare(tip(pinguin), nume(tux)).
37
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 38/183
pasare(tip(pinguin), nume(bambi)).
Pentru o interogare de forma ?- pasare(tip(pinguin), nume(X)). Prolog-ul va
încerca primul fapt din lista de fapte însă va întoarce fail deoarece tipul păsăriieste canar şi nu pinguin. Va trece mai departe şi va încerca să potrivească cel
de-al doilea fapt şi atunci vom obţine X=tux. Totuşi va păstra un pointer
pentru locaţia în care a ajuns pentru ca mai apoi să poată reveni în cazul
în care o interogare sau un subscop va întoace fail sau utilizatorul va cere
un alt răspuns din partea sistemului apăsând ";". Atunci se va încerca să se
resatisfacă predicatul pasare pentru X=bambi.
Să considerăm acum un alt exemplu, avem baza de fapte/reguli de mai jos:
Exemplul 0.2.7.
Programul de mai jos se găseşte în fisierul L2ex5.pl .
animal(leo).
animal(spike).
animal(tweety).
animal(daffy).are_pene(tweety).
are_pene(daffy).
domestic(daffy).
pasare(X):- animal(X), are_pene(X).
pasare_domestica(X):- pasare(X), domestic(X).
Dacă vom adresa interogarea ?- pasare(P) se caută în baza de reguli şi fapte
până se găseşte predicatul pasare(X) şi variabila P va fi instanţiată ca variabila
38
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 39/183
X. Se trece apoi la corpul predicatului pasare(X) şi se încearcă rezolvarea
celor 2 predicate, pentru primul predicat animal(X) se va găsi valoarea X=leo.
însă pentru aceasta nu există un fapt are_pene(leo) sau un predicat, astfelse revine la ultimul predicat pentru care s-a încercat să găsească o potrivire (
şi anume animal(X) ). Acţiunile se repetă şi pentru X=spike. Când variabila
predicatului animal(X) va fi identificată cu "tweety" din faptul animal(tweety),
iar pentru predicatul are_pene(X), X va fi identificat cu "tweety" din faptul
are_pene(tweety)., predicatul parare/1 va întoarce "yes" pentru X=tweety.
Dacă tastăm ";" atunci se va căuta o nouă demonstraţie şi anume pentru
X=daffy.Pentru o nouă interogare , ?- pasare_domestica(X). compilatorul SWI-Prolog
va încerca mai întâi să satisfacă predicatul pasare(X), iar pentru X=tweety
va întoarce fail deoarece nu există faptul domestic(tweety)., pentru încă o
încercare X=daffy. domestic(daffy). există şi raspunsul va fi X=daffy.
În exemplul de mai sus am facut backtracking prin o bază de fapte însă de cele
mai multe ori este nevoie de backtracking prin baza de reguli. Să considerăm
exemplul următor:
Exemplul 0.2.8.
Programul de mai jos se găseşte în fisierul L2ex6.pl .
animal(tweety). /* faptul 1 */
are_pene(tweety). /* faptul 2 */
pinguin(edgar). /* faptul 3 */
pinguin(allan). /* faptul 4 */
39
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 40/183
domestic(allan). /* faptul 5 */
pasare(X):- pinguin(X). /* regula 1 */
pasare(X):- animal(X),are_pene(X). /* regula 2 */pasare_domestica(X):- pasare(X), domestic(X). /* regula 3 */
Fie interogarea pasare(P). , se va apela prima regulă care apelează pinguin(X).
răspunsul va fi X=edgar. apoi se pune în aplicare backtrackingul şi cel de-al
doilea raspuns va fi X=allan. Dacă se încearcă resatisfacera lui penguin(X). nu
mai există clauze pentru acest predicat asfel că se trece mai departe la regula
2 şi se apelează animal(X) şi are_pene(X) vom obţine X=tweety.
0.2.2 Exerciţii propuse
Exerciţiul 0.2.1.
Un om cumpară o maşină dacă îi place şi dacă poate să o ia. Unui om îi place
o maşină dacă are puterea pe care şi-o doreşte. Un om poate să ia o maşină
dacă are destui bani în cont să o cumpere sau dacă fiind căsătorit, soţiei îi
place şi ei maşina şi au împreună bani să o cumpere.
0.2.3 Teme de studiu
Tema 0.2.1.
Utilizaţi comanda trace pentru a urmări execuţia programului de la exerciţiul
propus 0.2.1 .
40
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 41/183
0.3 Unificarea. Operaţiile aritmetice
0.3.1 Fundamente teoretice0.3.1.1 Unificarea
PROLOG-ul este un limbaj de programare cu trăsături mai puţin obişnuite :
unificarea , backtrackingul şi recursivitatea. Unificarea este partea PROLOG-
ului care se ocupă cu potrivirea patternurilor sau modelelor. Ideea din spatele
acestui concept este simplă . Să presupunem că avem predicatul culoare(X,Y),
de asemenea avem o bază de fapte cu urmatoarea structură:
culoare(masina, gri).
culoare(semafor, verde).
Pentru o interogare de forma ?- culoare(X,Y) variabilele X, şi Y vor deveni
variabile legate, X=masina şi Y=gri, vom avea o potrivire a patternurilor.
Aceasta pentru primul fapt dacă apăsăm ";" atunci X şi Y vor fi legate de
valorile semafor şi verde . Dar dacă am fi avut un pattern de forma culoare(X,
X) atunci o potrivire pentru acest pattern nu ar fi fost posibilă. Potrivirea pat-
ternurilor se face între un scop şi antetul unui fapt sau al unei reguli . Variabi-
lele legate ale scopului sunt verificate cu cele din antetul regulii . Alte exemple:
Dacă avem predicatul carte(titlu(X),autor(nume(Nume), prenume(Pren))) la
apelul lui pentru clauza de mai jos:
carte(titlu(teoria_numerelor), autor(nume(georgescu), prenume(ionel))).
41
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 42/183
vom avea următoarele variabile legate:
X = teoria_numerelor
Nume = georgescuPren = ionel
PROLOG-ul examinează expresiile într-o manieră pur structurală, fără a face
o evaluare a lor. Următoarele expresii sunt tratate în mod similar, în aceste
cazuri semnul "=" înseamnă "au o structură identică".
?- 1 + 2 = 3
No
?- X + 2 = 3Y .
No
Totuşi următoarele afirmaţii sunt corecte deoarece au o structură asemănăn-
toare. În aceste cazuri se va produce unificarea variabilelor cu valorile respec-
tive.
?- X + Y = 1 + 2.
X = 1
Y = 2
?- 1 + Y = X + 3.
X = 1
Y = 3
Atomii diferiţi nu pot fi potriviţi astfel pentru o interogare de forma an-
drei=alin. raspunsul primit va fi în toate situaţiile No.
42
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 43/183
0.3.1.2 Operaţii aritmetice
Funcţiile matematice din SWI-Prolog nu întorc valori ci sunt evaluate cu o
valoare corespunzătoare. Predicatele din SWI-Prolog nu pot fi asemănate cu
funcţiile din programarea structurată sau OOP, ele nu întorc valori ! Dacă se
doreşte să se obţină anumite valori în urma apelului unui predicat atunci se
vor adăuga variabile în plus listei de parametri a acelui predicat, aceste varia-
bile vor fi unificate cu valorile care se doresc a fi obţinute înainte de ieşirea
din apelul predicatului. Aceasta se poate realiza prin scrierea unui pattern al
predicatului în care numele variabilelor care conţin valorile este scris pe poziţia
variabilelor libere adăugate, astfel variabilele libere vor fi unificate cu valorile.
Această adăugare trebuie însă facută cu grijă deoarece modificările trebuie fa-
cute la nivelul întregului program.
sin(X) sinus asin(X) arcsin
cos(X) cosinus acos(X) arccos
tan(X) tangenta atan(X) arctg
Tabela 1: Funcţii trigonometrice disponibile în SWI-Prolog
Evaluarea expresiilor matematice în SWI-Prolog se face prin intermediul ope-
ratorului is .
?- X is 5+4.
X=9
43
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 44/183
abs(X) modulul lui X
round(X) rotunjire
exp(X) evaluează e la puterea X
float(X) întoarce un float
sign(X) întoarce 1 pentru X pozitiv
real(X) întoarce un număr real
ceiling(X) primul întreg mai mare ca X
integer(X) întoarce un număr întreg
floor(X) primul întreg mai mic ca X
ln(X),log(X),log10(X) evaluează log din X
sqrt(X) radical din X
Tabela 2: Funcţii matematice disponibile în SWI-Prolog
?-X is 5 ∗ 4, Y is 2^3.
X=20
Y=8?-X is 234556^100.
Error 0:Arithmetic Overflow
0.3.2 Exemple
Exemplul 0.3.1.
Calculaţi aria şi lungimea unui cerc de raza R. Rezolvarea în fişierul L3ex1.pl
44
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 45/183
+ adunare /\ şi logic pe biţi
- scădere \/ sau logic pe biţi
* înmulţire « deplasare la stânga pe biţi
/ împărtire » deplasare la dreapta pe biţi
// împărtire întreagă \ complementul pe biţi
^ ridicare la putere xor sau exclusiv pe biţi
Tabela 3: Predicatele aritmetice in SWI-Prolog
Apel:
?-aria.
Dati raza unui cerc = 1.
Aria cercului este 3.14
Lungimea cercului este 6.28
Program:
aria:- write(’Dati raza unui cerc = ’),
read(R),nl,
write(’Aria cercului este ’),
A is 3.14*R*R,
write(A),nl,
write(’Lungimea cercului este ’),
L is 2*3.14*R,
write(L),nl.
Exemplul 0.3.2.
45
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 46/183
Verificaţi dacă 3 numere sunt laturile unui triunghi. Rezolvarea în fişierul
L3ex2.pl
Apel:
?- introdu.
introdu a= 3.
introdu b= 4.
introdu c= 5.
Aceste numere sunt laturile unui triunghi
Program:
introdu:-write(’introdu a= ’),read(A),
write(’introdu b= ’),read(B),
write(’introdu c= ’),read(C),
A>=0,B>=0,C>=0,A<(B+C),B<(C+A),C<(A+B),
write(’Aceste numere sunt laturile unui triunghi ’),nl.
Exemplul 0.3.3.
Calculaţi media aritmetică a 2 numere. Rezolvarea în fişierul L3ex3.pl
Apel:
?-start1.
HELLO
X=4.
Y=6.
R=5.
46
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 47/183
yes
Program:
scrie1:- write(’HELLO’),nl.medie:- write(’X=’),read(X),write(’Y=’),read(Y),
R is (X+Y)/2,write(’R=’),write(R).
start1:- scrie1,medie,nl.
Exemplul 0.3.4.
Scrieţi un program SWI-Prolog care rezolvă ecuaţia de gradul 2. Rezolvarea
în fişierul L3ex4.plApel:
?- rezolva(1,4,-3).
x1 = 0.645751
x2 = -4.64575
Program:
rezolva(A, B, C) :-
Delta is B*B-4*A*C, % calculez deltacaz(A, B, Delta), nl.
caz(_, _, Delta) :-
Delta < 0,
write("Nu are solutii reale"), !.
caz(A, B, Delta) :-
Delta is 0,
X is (-B)/(2*A),
47
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 48/183
write(’x1=x2= ’),write(X), !.
caz(A, B, Delta) :-
SqrtDelta=sqrt(Delta),X1 is ((-B) + SqrtDelta)/(2*A),
X2 is ((-B) - SqrtDelta)/(2*A),
write(’x1 = ’),write(X1),nl,
write(’x2 = ’),write(X2).
0.3.3 Exerciţii propuse
Exerciţiul 0.3.1.
Scrieţi un predicat care calculează media geometrică a două numere intro-
duse de la tastatură. Rezultatul va fi scris pe ecran.
0.3.4 Teme de studiu
Tema 0.3.1.
Urmăriţi cu trace programele prezentate pentru a înţelege modul în care
se evaluează expresiile aritmetice.
48
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 49/183
0.4 Recursivitate. Predicatele !(cut) şi fail
0.4.1 Fundamente teoretice0.4.1.1 Recursivitatea
Recursivitatea este o tehnică des întâlnită în mediile Prolog. Acest termen,
recursivitate , înseamnă că un predicat este definit de mai multe ori şi se
auto-apelează. Iată un exemplu simplu de recursivitate:
strabun(Bunic,Nepot) :-
parinte(Bunic,Nepot).
strabun(Bunic,Nepot) :-
parinte(Bunic,Tata),
strabun(Tata,Nepot).
Toate definiţiile recursive trebuie să conţină cel puţin 2 clauze clauza de
bază şi clauza recursivă. În clauza de bază trebuie să ne asigurăm că există
o condiţie de oprire şi că există cel puţin o soluţie în cadrul recursivităţii.
Clauza recursivă este cea care reapelează predicatul, observaţi faptul că
parinte/2 se apelează înainte ca predicatul strabun/2 să se auto-apeleze.
Dacă vom modifica programul de mai sus şi îl vom pune sub forma următoare
(implementarea în fişierul L4ex1.pl):
49
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 50/183
parinte(emilia,maria).
parinte(ion,maria).
parinte(maria,petre).strabun(Bunic,Nepot) :-
strabun(Tata,Nepot),
parinte(Bunic,Tata).
strabun(Bunic,Nepot) :-
parinte(Bunic,Nepot).
vom observa că ordinea în care se face apelul predicatelor este importantă
deoarece deşi definiţia programului este logic corectă acesta pentru interogarea?- strabun(X,petre). nu va ajunge la o soluţie.
0.4.1.2 Predicatele !(cut) şi fail
Cut
Cut este un predicat predefinit notat prin "!" în SWI-Prolog, totdeauna
adevărat şi care acţionează asupra motorului de inferenţe. Cu ajutorul luieste posibil să controlăm modul în care lucrează backtrackingul. Folosirea
acestui predicat într-o clauză are următoarele efecte:
1. Poate să forţeze eşecul unei clauze, deoarece după apelul lui clauzele care
îl succed nu se vor mai executa.
2. Poate limita numărul de soluţii prin reducerea arborelui de inferenţă, în
acelaşi timp fiind posibilă oprirea căutării de soluţii pe unele ramuri în cazul
în care programatorul ştie că pe ramurile respective nu sunt soluţii.
50
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 51/183
Exemplul de mai jos prezintă funcţionarea unui program fără predicatul cut.
De observat este faptul că în predicatul test , prima clauză apelează predicatul
conditie , el se va apela pentru fiecare din cele 3 clauze. Observaţi ce seîntâmplă în momentul în care adăugăm "!" în predicatul test după apelul
predicatului conditie . Implementarea acestor predicate se găseste în fişierul
L4ex2.pl
Apel:
?- start.
unu
doitrei
clauza doi predicatul test
No
Program:
conditie(unu).
conditie(doi).
conditie(trei).test(X) :-
conditie(X).
test(’clauza doi predicatul test’).
start:-
test(X), write(X), nl, fail.
Modificăm programul de mai sus astfel:
51
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 52/183
test_cut(X) :-
conditie(X),!. test_cut(’clauza doi test’).
start_cut:- test_cut(X), write(X), nl, fail.Rezultatul va fi următorul:
?- start_cut.
unu
No
Modificăm exemplul de mai sus astfel:
test_cut2(X,Y,Z,K) :-
conditie(X),conditie(Y),!,conditie(Z),conditie(K).test_cut2(’clauza doi test’).
start_cut2:- test_cut2(X,Y,Z,K), write(X - Y - Z - K), nl, fail.
În această ultimă modificare se observă cel mai bine rolul pe care îl are
cut. Deoarece este plasat după al doilea apel al predicatului conditie nu se
va mai încerca resatisfacerea primelor predicate conditie şi pentru celelalte
valori(respectiv "doi" şi "trei"). Altfel spus nu se va încerca resatisfacerea
predicatele conditie(X) si conditie(Y) pentru alte valori decât cele de "unu".Rezultatul este următorul:
?- start_cut2.
unu-unu-unu-unu
unu-unu-unu-doi
unu-unu-unu-trei
unu-unu-doi-unu
52
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 53/183
unu-unu-doi-doi
unu-unu-doi-trei
unu-unu-trei-unuunu-unu-trei-doi
unu-unu-trei-trei
No
Considerăm în continuare o altă implementare pentru a exemplifica predicatul
cut . Predicatele de mai jos se găsesc implementate în fişierul L4ex3.pl
Apel:
?- este_in_forma(X,Y).X = andrei
Y = nesatisfacatoare;
No
Program:
este_in_forma(Sportiv, nesatisfacatoare) :-
max_flotari(Sportiv,P),
P < 15,!.este_in_forma(Sportiv, satisfacatoare).
max_flotari(ionel,20).
max_flotari(andrei,12).
max_flotari(daniel,25).
max_flotari(alin,10).
Cut-ul din prima clauză inseamnă "dacă ai ajuns până aici atunci renunţă să
53
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 54/183
mai cauţi alte soluţii".
Cut-ul este o metodă des utilizată însă în acest caz distruge citirea logică a
clauzelor care îl conţin. Spre exemplu clauza de mai sus ar putea fi interpre-tată "Nu este în formă sportivul care nu poate face mai mult de 15 flotări"
însă cut-ul înlocuieşte negaţia şi foţează încheierea execuţiei programului.
Observaţi că deşi mai sunt soluţii în baza de fapte pentru interogare primim
răspunsul No.
Fail
Când un subscop al unui predicat întoarce "fail" PROLOG încearcă prinbacktracking să resatisfacă toate subscopurile acelui predicat. Este acelaşi
lucru cu a apăsa ";" atunci când dorim să obţinem un nou rezultat pentru o
problemă , dacă el există. Există un predicat (fail) predefinit, care întoarce
fail în orice ocazie, cauzând astfel backtrakingul. Iată un exemplu de utilizare
a predicatului fail/0 (nu are argumente).Exemplul este implementat în fişierul
L4ex4.pl
Apel:?- plante(_).
cartof
cires
garoafa
ficus
Yes
54
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 55/183
Program:
planta(cartof).
planta(cires).planta(garoafa).
planta(ficus).
plante(X):- planta(X),write(X),nl,fail.
plante(_).
Predicatul plante(X) din programul de mai sus, datorită subscopului fail, va
întoarce el însuşi fail, astfel se va încerca resatisfacerea sa pentru alte valori ale
variabilei X. Când nu mai există astfel de valori a doua clauză a predicatuluieste încercată, aceasta fiind un fapt ce are ca parametru o variabilă anonimă
va întoarce Yes .
Un exemplu interesant este următoarea bucată de cod, în care folosind o
combinaţie cut/fail putem înlocui cu succes negaţia.
nuestecopil(X, Y) :- copil(X, Y), !, fail.
nuestecopil(X, Y).
Este acelaşi lucru cu nuestecopil(X, Y) :- not(copil(X, Y)). deoarece în
cazul în care copil (X,Y) întoarce "Yes" cut opreşte backtrackingul, iar fail
întoarce "No", facând asfel ca nuestecopil(X, Y) să întoarcă imediat "No". În
cazul în care copil(X,Y) întoarce "No" atunci nuestecopil(X,Y) va întoarce
"Yes" pentru a 2-a clauză.
55
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 56/183
0.4.2 Exemple
Exemplul 0.4.1.
0.4.2.1 Funcţia factorial
Scrieţi un program Prolog care calculează funcţia factorial pentru un n dat.
Implementare în fişierul L4ex5.pl
Pentru a calcula factorialul unui număr ştim următoarele lucruri:
1 0! = 1 şi 1! = 1
2 n! = n(n − 1)!
Aşa cum am spus mai sus recursivitatea se realizează prin mai multe clauze
ale aceluiaşi predicat, astfel condiţiile de mai sus se pot traduce astfel:
1 condiţia de oprire şi în acelaşi timp o valoare cunoscută pentru funcţia fac-
torial
2 este condiţia de recursie
Apel:
?-fact(3,R).
R=6
Yes
Program:
fact(0,1).
fact(N,R):-fact(N1,R1),N is N1+1,R is R1N.
56
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 57/183
Rezolvarea prezentată se numeşte "calculul factorialului pe retur", deoarece
valoarea lui R (defapt valoarea lui N factorial)va fi calculată la revenirea din
apelurile succesive pentru resatisfacerea lui fact(N1,R1). Să urmărim execuţiaprogramului de mai sus cu trace pentru a observa mai bine modul de lucru al
SWI-Prolog.
?- trace,fact(3,R). <- apelul predicatului
Call: (9) fact(3, _G461) ? creep <- nu se intra pe prima ramură fact(0,1)
deoarece nu se potriveşte antetul predicatelor (avem apel pentru fact(3,R)),
acesta este apelul pentru fact(N,R)
Call: (10) fact(_L215, _L216) ? creep <- apel fact(N1,R1)Exit: (10) fact(0, 1) ? creep <- unificare cu fact(0,1)
^Call: (10) 3 is 0+1 ? creep <- verifică dacă N is 0+1, adică _L215+1
^Fail: (10) 3 is 0+1 ? creep <- fail
Redo: (10) fact(_L215, _L216) ? creep <- se încearcă resatisfacerea lui
fact(N1,R1) pentru alte valori
Call: (11) fact(_L234, _L235) ? creep <- se reapelează predicatul fact pentru
alte variabile care nu sunt legateExit: (11) fact(0, 1) ? creep <- unificare cu fact(0,1)
^Call: (11) _L215 is 0+1 ? creep <- variabilele din primul set vor lua alte
valori
^Exit: (11) 1 is 0+1 ? creep
^Call: (11) _L216 is 1*1 ? creep
^Exit: (11) 1 is 1*1 ? creep
57
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 58/183
Exit: (10) fact(1, 1) ? creep <- se iese din apelul de la (10) adăugându-se
fact(1,1) la baza de fapte şi se verifică din nou dacă N is N1+1
^Call: (10) 3 is 1+1 ? creep^Fail: (10) 3 is 1+1 ? creep
Redo: (11) fact(_L234, _L235) ? creep <- se încearcă din nou satisfacerea lui
fact(N1,R1) însă pentru un al treilea set de variabile
Call: (12) fact(_L246, _L247) ? creep <- din nou unificare cu fact(0,1)
Exit: (12) fact(0, 1) ? creep <- unificarea variabilelor din setul 3 cu valorile 0
şi respectiv 1
^Call: (12) _L234 is 0+1 ? creep <- variabilele din setul 2 vor lua alte valori1 şi respectiv 1
^Exit: (12) 1 is 0+1 ? creep
^Call: (12) _L235 is 1*1 ? creep
^Exit: (12) 1 is 1*1 ? creep
Exit: (11) fact(1, 1) ? creep <- se revine din Redo pentru pasul (11) şi varia-
bilele din setul 1 ia valorile 2 şi respectiv 2
^Call: (11) _L215 is 1+1 ? creep^Exit: (11) 2 is 1+1 ? creep
^Call: (11) _L216 is 1*2 ? creep
^Exit: (11) 2 is 1*2 ? creep
Exit: (10) fact(2, 2) ? creep <- la revenirea la pasul(10) N va fi N1+1 şi se
trece mai departe şi se calculează rezultatul final.
^Call: (10) 3 is 2+1 ? creep
58
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 59/183
^Exit: (10) 3 is 2+1 ? creep
^Call: (10) _G461 is 2*3 ? creep
^Exit: (10) 6 is 2*3 ? creepExit: (9) fact(3, 6) ? creep <- iesire din apel
R = 6
Yes
Exemplul 0.4.2.
Factorial calculat pe tur:
Apel: ?- fact2(4,R).R = 24
Yes
Program:
fact2(N,N,R,R).
fact2(N,N1,R1,R):- N2 is N1+1, R2 is R1*N2 , fact2(N,N2,R2,R).
fact2(N,R):- fact2(N,1,1,R).
Apelul se face asemănător primului program , din fact2(N,R) apelăm pefact2(N,N1,R1,R) , N1 fiind un N intermediar pentru a şti când să ne oprim,
iar R1 este un rezultat intermediar care atunci când se va ajunge la N1 = N
va fi unificat cu R prin faptul fact2(N,N,R,R). care este şi condiţia de oprire
pentru obţinerea rezultatului final. Să urmărim trace-ul pentru acest program:
?- trace,fact2(4,R). <- apel
Call: (8) fact2(4, _G283) ? creep <- predicatul care apelează pe
fact2(N,N1,R1,R)
59
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 60/183
Call: (9) fact2(4, 1, 1, _G283) ? creep <- apel fact2(N,N1,R1,R)
^Call: (10) _L196 is 1+1 ? creep <- calcul N1
^Exit: (10) 2 is 1+1 ? creep <- ieşire calcul N1^Call: (10) _L197 is 1*2 ? creep <- calcul R1
^Exit: (10) 2 is 1*2 ? creep <- ieşire calcul R1
Call: (10) fact2(4, 2, 2, _G283) ? creep <- se reapelează pentru noile valori
^Call: (11) _L217 is 2+1 ? creep <- calcul N1
^Exit: (11) 3 is 2+1 ? creep <- ieşire calcul N1
^Call: (11) _L218 is 2*3 ? creep <- calcul R1
^Exit: (11) 6 is 2*3 ? creep <- ieşire calcul R1Call: (11) fact2(4, 3, 6, _G283) ? creep <- se reapelează factorial
^Call: (12) _L238 is 3+1 ? creep <- calculul valorilor intermediare
^Exit: (12) 4 is 3+1 ? creep
^Call: (12) _L239 is 6*4 ? creep
^Exit: (12) 24 is 6*4 ? creep
Call: (12) fact2(4, 4, 24, _G283) ? creep
Exit: (12) fact2(4, 4, 24, 24) ? creep <- ieşire din factorialExit: (11) fact2(4, 3, 6, 24) ? creep
Exit: (10) fact2(4, 2, 2, 24) ? creep <- observaţi că valorile lui R intermediar
se pierd
Exit: (9) fact2(4, 1, 1, 24) ? creep
Exit: (8) fact2(4, 24) ? creep
R = 24
60
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 61/183
Yes
Exemplul 0.4.3.
0.4.2.2 Cmmdc şi Cmmmc
Scrieţi un program Prolog care calculează cmmdc şi cmmmc pentru două
numere X şi Y. Implementarea se găseşte în fişierul L4ex6.pl
Prezentăm algoritmul lui Euclid pentru cel mai mare divizor comun (cmmdc)
şi cel mai mic multiplu comun (cmmmc).
Apel:
?- cmmdc(6,15,X).
X=3
?-cmmmc(6,7,Y).
Y=42
61
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 62/183
Program:
cmmdc(X,0,X).
cmmdc(X,Y,D):- R is X mod Y, cmmdc(Y,R,D).cmmmc(X,Y,M):- cmmdc(X,Y,D),M is (XY)/D.
Programul defineşte cmmdc(X,Y,D) ca fiind clauza recursivă, în interiorul ei
vom calcula restul conform algoritmului lui Euclid şi vom reapela cmmdc
pentru Y,R şi o a 3-a variabilă D, iar cmmdc(X,0,X) este clauza de oprire
a recursivităţii, la final când această clauză este apelată, variabilele de pe
prima şi ultima poziţie vor fi unificate şi vom obţine cmmdc.
?- trace,cmmdc(14,8,R). <- apel cmdcCall: (9) cmmdc(14, 8, G492) ? creep <- intră pe clauza 2
^Call: (10) L218 is 14 mod 8 ? creep <- se calculează R
^Exit: (10) 6 is 14 mod 8 ? creep
Call: (10) cmmdc(8, 6, G492) ? creep <- se reapealează cmmdc pentru alte
valori
^Call: (11) L237 is 8 mod 6 ? creep <- calculează din nou R
^Exit: (11) 2 is 8 mod 6 ? creepCall: (11) cmmdc(6, 2, G492) ? creep <- se reapealează cmmdc pentru alte
valori
^Call: (12) L256 is 6 mod 2 ? creep <- calculează din nou R
^Exit: (12) 0 is 6 mod 2 ? creep
Call: (12) cmmdc(2, 0, G492) ? creep <- de data aceasta se intră pe clauza
cmmdc(X,0,X)
62
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 63/183
Exit: (12) cmmdc(2, 0, 2) ? creep <- pe poziţia secundă vom avea tot X şi se
revine din calcul
Exit: (11) cmmdc(6, 2, 2) ? creepExit: (10) cmmdc(8, 6, 2) ? creep
Exit: (9) cmmdc(14, 8, 2) ? creep
R = 2
Yes
Exemplul 0.4.4.
0.4.2.3 N la puterea K
Scrieţi un program prolog care calculează N la puterea K. Implementarea în
fişierul L4ex7.pl
Apel:
?-puterea(2,3,R).
R=8
Program:
puterea(N,K,R,K,R).
puterea(N,K,R,K1,Rez):- K2 is K1+1, R1 is N*R ,puterea(N,K,R1,K2,Rez).
puterea(N,K,R):-puterea(N,K,1,0,R).
Rezolvarea de mai sus este un exemplu "de calcul pe tur". Ideea din spatele
programului este de a calcula în două variabile K2 şi R1 puterea la care
s-a ajuns şi respectiv rezultatul intermediar.Astfel condiţia de oprire este
63
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 64/183
puterea(N,K,R,K,R). când se ajunge la puterea K (observaţi cele 2 perechi
de variabile identice , K şi R) acesta este un fapt şi valoarea din prima
variabilă R este unificată cu variabila a doua R. Urmăriţi cu trace modul delucru al acestui program.
0.4.3 Exerciţii propuse
Exerciţiul 0.4.1.
Scrieţi predicatul puterea(N,K,R) care returnează în variabila R pe N la
puterea K, cu calculul puterii pe retur.
0.4.4 Teme de studiu
Tema 0.4.1.
Rulaţi pas cu pas programele prezentate în exemplele de mai sus cât şi pe
cele propuse ca exerciţii.
64
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 65/183
0.5 Turnurile din Hanoi. Funcţiile Fibonacci şi
Ackermann
0.5.1 Fundamente teoretice
Prezentăm în continuare câteva probleme cunoscute ale programării structu-
rate şi modul în care sunt ele abordate în programarea logică şi mediul SWI-
Prolog.
0.5.2 ExempleExemplul 0.5.1.
0.5.2.1 Turnurile din Hanoi
Exista 3 turnuri , stânga, centru, dreapta, pe cel din stânga se gasesc N discuri
de mărimi diferite suprapuse descrescător de la bază spre vârf. Cum pot fi
mutate cele N discuri de pe turnul din stânga pe cel din dreapta, folosind
turnul din centru, astfel încât să fie îndeplinite următoarele condiţii:
- la fiecare operaţie de mutare se mută un singur disc.
- discurile fiind de dimensiuni diferite, un disc oarecare nu poate fi pus peste
altul mai mic.
La fel ca în cazul funcţiei factorial avem nevoie de un caz de bază şi un caz
general care poate fi exprimat prin operaţii de o complexitate redusă. Pentru
65
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 66/183
a sublinia faptul că mutăm un disc folosim predicatul muta(A,B) care în-
seamnă mută primul disc de sus de pe turnul A pe turnul B. De fiecare dată
când mutăm un disc acest predicat va afişa mesajul corespunzător prin inter-mediul predicatului write.
Cazul de bază.
Un caz de bază este mutarea unui singur disc de pe turnul A(stânga) pe trunul
B(dreapta) folosind turnul C(centru). Pentru aceasta am putea folosi predi-
catul hanoi(1, A, B, C):- muta(A,B), defapt pe lângă acest caz există un
caz mult mai simplu şi anume acela în care nu mutăm nici un disc , pentru
acesta vom folosi predicatul hanoi(0, _ , _ , _ ):- !.Cazul recursiv
Pentru cazul inductiv trebuie să transferăm N discuri de pe A pe B, presu-
punem că avem deja un program care transferă N-1 discuri . Paşii pe care îi
urmăm sunt următorii :
1. Transferăm primele N-1 discuri de pe A pe C
2. Transferăm ultimul disc de pe A pe B
3. Transferăm N-1 discuri de pe C pe B
În implementare predicatul corespunzător operaţiilor de mai sus este hanoi(N,
A, B, C) Programul este urmatorul: (implementarea în fişierul L4ex7.pl)
start(N) :- hanoi(N, stanga, centru, dreapta).
hanoi(0, _ , _ , _ ):- !.
hanoi(N, A, B, C):- /*mută de pe A pe B folosind C*/
66
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 67/183
N_1 is N-1,
hanoi(N_1, A, C, B), /*mută de pe A pe C folosind B - pasul 1*/
muta(A, B),/*mută de pe A pe B ultimul disc - pasul 2*/hanoi(N_1, C, B, A). /*mută de pe C pe B folosind A - pasul 3*/
muta(F, T) :- write(muta, F, –>, T), nl.
Apel:
start(3).
Rezultatul va fi următorul:
muta, stanga, (–>), centru
muta, stanga, (–>), dreaptamuta, centru, (–>), dreapta
muta, stanga, (–>), centru
muta, dreapta, (–>), stanga
muta, dreapta, (–>), centru
muta, stanga, (–>), centru
0.5.2.2 Modul de funcţionare al programului:
Se va apela cu start(N)., unde N este un număr natural. Pentru clauza start
se va apela predicatul hanoi(N, stanga, centru, dreapta). care apelează primul
predicat hanoi întâlnit, nu va intra pe ramura hanoi(0,_,_,_) deoarece pat-
ternurile nu sunt identice, şi anume N este diferit de 0 şi celelalte variabile nu
sunt libere, merge mai departe la următoarea clauză, aici va decrementa pe N
până la 0 , va intra pe clauza hanoi(0,_,_,_) unde va face cut, iar pe recursie
67
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 68/183
va afişa modul de aranjare a discurilor.
Exemplul 0.5.2.
0.5.2.3 Şirul lui Fibonacci
Să se definească un predicat care pentru un N dat să calculeze termenul de
rang n din şirul lui Fibonacci. Implementarea se găseşte în fişierul L5ex1.pl
Indicaţii:
Un termen din şirul lui Fibonacci se calculează conform relaţiei de recurenţă
în 2 paşi:
- f(1)= f(2)= 1
- f(n)= f(n-2) + f(n-1), daca n>=3
Şirul lui Fibonacci arată astfel:
- 1, 1, 2, 3, 5, 8, 13, 21, 34, 55...
Apel:?-fib(6,R).
13
68
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 69/183
Program:
fib(1,1).
fib(2,1).fib(N,R):- N>=3,N1 is N-1,N2 is N-2,
fib(N1,R1),fib(N2,R2),R is R1+R2.
Exemplul 0.5.3.
0.5.2.4 Funcţia Ackermann
Funcţia Ackermann este definită recursiv pentru numere întregi pozitive. Esteo funcţie ale cărei valori cresc foarte repede devenind atât de mari încât este
imposibil să fie calculate. De fapt, se spune că scrierea lor sub formă zecimală
nu poate fi stocată în tot universul fizic. Ca un exemplu A(4,2) este mai mare
decât numărul tutror particulelor din univers ridicate la puterea 200. Funcţia
a fost decoperită în 1928 de Wilhelm Ackermann (1896 - 1962) sub o altă formă
şi este un exemplu de funcţie recursivă care nu este însă o funcţie primitiv-
recursivă (exemple de funcţii primitiv-recursive: funcţia constantă egală cu 0,funcţia succesor). Este utilă în special la testarea compilatoarelor pentru a
verifica puterea de recursie a acestora. Spre exemplu dacă un compilator este
capabil să salveze valori ale lui A(2,n) şi A(3,n) pentru a calcula pe ... să
spunem A(3,30) atunci el va reduce numărul computaţiilor cu un factor de
ordinul sutelor de mii.
Există şi o inversă a funcţiei Ackermann care spre deosebire de aceasta
creşte foarte încet, defapt maximul ei este o valoare mai mică decât 5 pentru
69
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 70/183
m/n 0 1 2 3 4
0 1 2 3 4 5
1 2 3 4 5 6
2 3 5 7 9 11
3 5 13 29 61 125
4 13 65533 265536 − 3 A(3,A(4,2)) A(3,A(4,3))
5 65533 A(4,65533) A(4,A(5,1)) A(4,A(5,2)) A(4,A(5,3))
6 A(5,1) A(5,A(5,1)) A(5,A(6,1)) A(5,A(6,2)) A(5,A(6,3))
Tabela 4: Câteva valori ale funcţiei Ackermann
orice valori de intrare posibile. Trebuie reţinut faptul că aceasta nu este inversa
funcţiei Ackermann în sensul strict matematic.
Definiţie formală:
f (m, n) = min{i?1 : A(i,floor(m/n)) > log2n}
unde A(i,j) este funcţia Ackermann.Definiţia funţiei Ackermann:
Ack(0,n) = n+1
Ack(m,0) = Ack(m-1,1) pentru m >0
Ack(m,n) = Ack(m-1,Ack(m,n-1)) pentru m,n>0
Apel:
?- ack(3,5,R).
R = 253
70
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 71/183
m n ack(m,n) A(m,n) în general
0 1 2 n+1
1 1 3 n+2
1 2 4
2 1 5 2n+3
2 2 7
2 3 9
3 2 29 8 × 2n − 3
3 3 61
3 4 stack overflow
Tabela 5: Valorile funcţiei Ackerman calculate în SWI-Prolog
?- ack(3,6,R).
ERROR: Out of local stack
?- ack(4,5,R).
ERROR: Out of local stack
Programul:
ack(0,M,R):-R is M+1,!.
ack(N,0,R):-R1 is N-1,ack(R1,1,R).
ack(N,M,R):-N1 is N-1,M1 is M-1,ack(N,M1,R1),ack(N1,R1,R).
0.5.3 Exerciţii propuse
Exerciţiul 0.5.1.
71
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 72/183
Scrieţi predicatul PROLOG fib(N,R) care returnează în variabila R termenul
N din şirul lui Fibonacci şi care calculează acest termen pe tur.
Exerciţiul 0.5.2.
Scrieţi predicatul PROLOG ackermann(N,M,R) care returnează în varia-
bila R rezultatul funcţiei Ackermann, calculat pe tur.
0.5.4 Teme de studiu
Tema 0.5.1.
Studiaţi cu trace. evoluţia programelor prezentate cât şi a celor de la
"Exerciţii propuse".
72
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 73/183
0.6 Liste
0.6.1 Fundamente teoreticeListele în mediile Prolog sunt o secvenţă ordonată de termeni, conceptual nu
există prea multe asemănări între listele din PROLOG şi şirurile din C. Iată
câteva exemple de liste:
[] - lista vidă
[a,c,s,f,d,h,q,p] - listă cu 8 elemente
[carne, lapte, legume, fructe] - listă cu 4 elemente
[pornit(motor), arde(benzina), conduc(masina)] - lista cu 3 elemente (
cele 3 elemente termeni )
[1,a,[1,c,f,2],[nume(carte),1,a,floare]] - exemplu de listă în listă, cu ele-
mente diferite, care sunt însă atomi.
Deoarece listele sunt structuri ordonate de termeni lista [1,a,b] va fi diferită de[a,1,b].
0.6.1.1 Accesarea elementelor din listă
Accesul la elementele din listă se produce secvenţial, adică pentru a ajunge
la elementul N din listă trebuie să eliminăm din listă primele N-1 elemente.
Am spus "eliminăm" deoarece odată accesat un element din listă nu va mai
aparţine de lista respectivă. Scoatem un element din listă în felul urmator
73
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 74/183
[Element|Coada], elementul Element va fi unul din atomii listei , iar Coada va
fi restul listei care poate fi procesată în continuare.
Extragerea unui element
?- [Element|Coada]=[mere,prune,caise,cirese].
Element = mere
Coada = [prune, caise, cirese]
Introducerea unui element
?- L=[1,2],R=[a,b,c|L].L = [1, 2]
R = [a, b, c, 1, 2]
0.6.2 Exemple
Exemplul 0.6.1.
Scrieţi în ordine inversă elementele unei liste. Implementarea se găseşte înfişierul L6ex1.pl
Apel:
?-scrie([a,b,c]).
c b a
Yes
Program:
74
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 75/183
scrie([]).
scrie([X|R]):-scrie(R),write(X),write(’ ’).
Programul funcţionează pe baza recursiei. Predicatul scrie împarte lista în capşi coadă în antetul clauzei sale şi se reapelează pentru coada listei,R. Prima
clauză a acestui predicat este un fapt ce va întoarce Yes atunci când lista va
fi vidă. În acel moment se va reveni din apelurile succesive ale predicatului şi
pe întoarcere vor fi scrise elementele X extrase din listă.
Exemplul 0.6.2.
Verificaţi dacă o listă are un numar par de elemente. Implementarea se găseşte
în fişierul L6ex2.pl
Apel:
?-par([a,b,c,d]).
Yes
Program:
par([_,_]).
par([_,_|T]):-par(T).
Predicatul par/1 este un predicat recursiv, se scot câte 2 elemente din listă
în două variabile anonime, deoarece nu ne interesează elementele conţinute de
listă. La final, dacă vor rămâne 2 elemente care pot fi scoase din listă atunci
în lista există un număr par de elemente, altfel predicatul va returna Fail .
Exemplul 0.6.3.
Scrieţi un predicat care returnează numărul de elemente dintr-o listă. Imple-
mentarea se găseşte în fişierul L6ex3.pl
75
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 76/183
Exista şi predicatul sistem(built-in): length(Lista,Nr). care întoarce în Nr
numărul elementelor din listă.
Apel:
?-lungime([a,b,[c,d],e],R).
R=4
?-length([a,b,[c,d],e],R).
R=4
Program:
lungime([],0).
lungime([_|T],R):-lungime(T,R1),R is R1+1.Ştim ca în lista vidă sunt 0 elemente, extragem câte un element din listă şi
reapelăm predicatul pentru coada listei şi la revenirea din apelurile succesive
numărăm elementele.
Exemplul 0.6.4.
Verificaţi dacă un element aparţine unei liste. Implementarea se găseşte în
fişierul L6ex4.plApel:
?-member(b,[a,v,b,c]).
Yes
?-member(a,[b,c,g]).
No
Program:
member(X,[X|_]).
76
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 77/183
member(X,[_|T]):-member(X,T).
Predicatul member este tot un exemplu de predicat recursiv. Această definiţie
poate fi asemănată cu un if din programarea structurată. În antetul predi-catului se extrage din listă un element, dacă elementul extras este X, atunci
predicatul întoarce Yes. Altfel vor fi scoase elemente din listă până când în
cele din urmă lista va fi vidă si memeber/2 va întoarce Fail .
Exemplul 0.6.5.
Verificaţi dacă o listă este sau nu mulţime. O listă care este considerată mul-
ţime conţine elemente care nu se reptă. Implementarea se găseşte în fişierulL6ex5.pl
Apel:
?-set([a,b,c,c,d]).
No
set([a,b,c]).
Yes
Program:set([]).
set([X|T]):-not(member(X,T)),set(T).
Şi acest predicat este unul recursiv. Se extrag elemente din listă şi se verifică
dacă elementul extras este membru pentru coada listei. Ne oprim atunci când
lista este vidă, caz în care lista este o mulţime, deoarece toate elementele au
fost extrase şi niciunul nu a fost membru în coada listei. Dacă un element ar
fi fost membru în restul listei atunci predicatul member negat prin not ar fi
77
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 78/183
întors fail şi am fi primit răspunsul No.
Exemplul 0.6.6.
Scrieţi un predicat care face înmulţirea a 2 vectori. Implementarea se găseşte
în fişierul L6ex6.pl
Apel:
?-prodv([1,2,4],[3,2,3],R).
R=[3,4,12]
Yes
Program:prodv([X],[Y],[R]):-R is X*Y.
prodv([H|T],[H1|T1],[R|R1]):-
prodv(T,T1,R1),
R is H*H1.
Gestionăm 3 liste, 2 din ele reprezintă coordonatele vectorilor iar în ultima
avem rezultatul, scoatem elemente din primele 2 liste până cand vom rămâne
cu un singur element în fiecare , atunci ultima coordonată a vectorului rezultateste X*Y şi pe întoarcere calculăm celelalte componente.
Exemplul 0.6.7.
Scrieţi un predicat care găseşte ultimul element al unei liste. Implementarea
se găseşte în fişierul L6ex7.pl
Apel:
?- last([a],R)
78
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 79/183
R=a
?-last([a,b,1,c],X).
X=c?-last([a,b,[c,[d]]],X).
X=[c,[d]]
Program:
last([X],X).
last([H|T],R):-last(T,R).
Scoatem elemente din listă până cand în listă vom avea un singur element pe
care îl unificăm cu variabila liberă X.
Exemplul 0.6.8.
Să verificăm dacă o mulţime intră în toate mulţimile unei liste de mulţimi.
Implementarea se găseşte în fişierul L6ex8.pl
Apel:
?-inclus([a,b],[1,a,c,b]).
Yes?-inclus([],[a,b]).
Yes
?-inclus_multimi([a,b,c],[[a,b,c,d],[m,a,b,c]])
Yes
Program:
inclus([],L).
inclus([H|T],L):- member(H,L),inclus(T,L).
79
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 80/183
Orice mulţime include mulţimea vidă: dacă lista este vidă întoarce lista L.
Împart lista în cap şi coadă şi dacă primul element este în L merg mai departe
şi apelez recursiv predicatul pentru restul listei şi L .inclus_multimi(X,[Y]):- inclus(X,Y).
inclus_multimi(X,[H|T]):- inclus(X,H), inclus_multimi(X,T).
Împart lista de mulţimi în cap şi coadă, coada fiind restul de mulţimi din listă.
Apelez funcţia inclus pentru a vedea dacă X este inclusă în prima listă din
lista de mulţimi, apelez recursiv inclus_multimi pentru a vedea dacă X este
inclusă în restul de mulţimi din listă.
Exemplul 0.6.9.
Incrementaţi toate elementele unei liste. Programul se găseşte implementat în
fişierul L7ex1.pl
Apel:
?-increment (inc,[1,2,3],R).
R=[2,3,4]
Yes
Program:
inc(X,Y):-Y is X+1.
increment(F,[],[]).
increment(F,[H|T],[R|RT]):- L=..[F,H,R],call(L),increment(F,T,RT).
Programul foloseşte lista L pentru a aduna parametrii necesari pentru
predicatul built-in call() care formează un nou scop, în cazul de faţă apelează
80
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 81/183
incrementarea fiecărui element. Apelul are ca parametri predicatul inc , cel
care va incrementa elementele listei , lista şi variabila care va întoarce lista
rezultat.
Exemplul 0.6.10.
Scrieţi un program care înlocuieşte un element într-o listă. Implementarea se
găseşte în fişierul L7ex2.pl
Apel:
?- subst(a,b,[b,b,c,[d,b]],R).
R=[a,a,c,[d,b]]No
Program:
subst(N,V,[],[]):-!.
subst(N,V,[V|T],[N|R]):-subst(N,V,T,R),!.
subst(N,V,[X|T],[X|R]):-subst(N,V,T,R).
Programul substituie un element la nivelul superficial al listei, observaţi că
pentru lista [d,b] , b-ul din această listă nu este înlocuit. Programul estestructurat pe cazuri şi anume , cazul în care din listă poate fi extras elementul V
( cel ce va fi înlocuit ) şi cazul în care se extrage din listă un element oarecare.
În primul caz se face cut pentru a nu se încerca resatisfacerea predicatului
subst pentru alte clauze, dacă acest lucru s-ar întâmpla în lista R nu vom
avea elementele substituite. Pe întoarcere se reconstruieşte lista însă în lista
R ( rezultat ) vom avea lista modificată deoarece atunci când se poate extrage
elementul V în R introducem elementul N (elementul cu care înlocuim V-ul).
81
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 82/183
Exemplul 0.6.11.
Scrieţi un predicat care şterge toate apariţiile unui element într-o listă (nivel
superficial). Implementarea se găseşte în fişierul L7ex4.pl
Apel:
?-sterge(a,[a,c,[a,b],a,f],R).
R=[c,[a,b],f]
Program:
sterge(X,[],[]).
sterge(X,[X|T],R):-sterge(X,T,R),!.
sterge(X,[Y|T],[Y|R]):- sterge(X,T,R).
Programul funcţionează pe acelaşi principiu ca programul care înlocuieşte ele-
mente din listă, însă de data aceasta în locul elementelor extrase nu se va
adăuga un alt element.
Exemplul 0.6.12.
Scrieţi un predicat care şterge toate elementele dintr-o listă dată care apar în
altă listă. Implementarea se găseşte în fişierul L7ex5.plApel:
?-stergere([1,2,3],[1,4,2,5,3,7],R).
R=[4,5,7]
Program:
stergere([],L1,L1).
stergere([H|T],L1,L3):-sterge(H,L1,R2),stergere(T,R2,L3). Predicatul ster-
gere/3 are nevoie ca înainte de a fi apelat să se încarce fişierul de la exemplul
82
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 83/183
precedent (consult(l4ex4).). Principiul de funcţionare este foarte simplu, în
antetul predicatului extragem un element din prima listă pentru care apelăm
predicatul sterge/3 de mai sus. Elementul extras din prima listă va fi şters dina doua listă şi predicatul stergere/3 se reapelează pentru coada primei liste
lista R2 rezultată în urma ştergerii şi o listă L3 care va fi lista ce va conţine
rezultatul final.
Exemplul 0.6.13.
Scrieţi un predicat care inserează un element înaintea unui alt element al unei
liste. Mai jos sunt prezentate două variante de predicat ins/3 şi ins2/3, primulpredicat ins/3 inserează pe X înaintea lui A în lista L, numai la prima apariţie a
lui A, ins2/3 afişează toate posibilităţile de inserare, pentru o listă care conţine
mai multe apariţii ale lui A. Implementarea se găseşte în fişierul L7ex6.pl
Apel:
?- ins(x,b,[d,b,c,b],L).
L=[d,x,b,c,b]
Program:ins(X,A,[],[]).
ins(X,A,[A|T],[X,A|T]):- !.
ins(X,A,[H|T],[H|R]):- ins(X,A,T,R).
Apel:
?- ins2(x,c,[a,c,d],R).
R=[a,x,c,d]
?- ins2(x,c,[a,c,d,c],R).
83
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 84/183
R=[a,x,c,d,c];
R=[a,c,d,x,c]
YesProgram:
ins2(X,A,L,R):- append(L1,[A|L2],L),append(L1,[X,A|L2],R).
Exemplul 0.6.14.
Implementaţi o serie de predicate care primesc ca parametru o listă şi care
trebuie să simuleze o stivă FIFO, FILO, LIFO, LILO. Implementarea se găseşte
în fişierul L7ex3.plFIFO (First In First Out) - primul intrat , primul ieşit.
?-pop([a,b,c],R).
R=a
?-push(m,[a,b,c],R).
R=[m,a,b,c]
pop([H|T],H).
push(X,L,[X|L]).FILO (First In Last Out) - primul intrat, ultimul ieşit.
?-pop1([a,b,c],R).
R=c
?-push1(m,[a,b,c],R).
R=[m,a,b,c]
pop1([X],X).
pop1([H|T],R):-pop1(T,R).
84
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 85/183
push1(X,L,[X|L]).
LIFO (Last In First Out) - ultimul intrat , primul iesit.
?-pop2([a,b,c],R).R=a
?-push2(m,[a,b,c],E).
R=[a,b,c,m]
pop2([H|T],H).
push2(X,L,R):-append(L,[X],R).
LILO (Last In Last Out) - ultimul intrat, ultimul ieşit.
?-pop3([a,b,c],R).R=c
?-push3(m,[a,b,c],E).
R=[a,b,c,m]
pop3([X],X).
pop3([H|T],R):-pop1(T,R).
push3(X,L,R):-append(L,[X],R).
Exemplul 0.6.15.
Scrieţi un predicat care selectează dintr-o listă numerele întregi (numai de pe
nivelul superficial al listei). Implementarea în fişierul L8ex1.pl
Apel:
?-select([1,a,3],R).
R=[1,3]
?-select([1,[a,2],3],R).
85
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 86/183
R=[1,3]
Program:
select([],[]).select([H|T],[H|R]):-integer(H),select(T,R).
select([H|T],R):-select(T,R).
Programul funcţionează asemănător unui if din programarea structurată.
Scoate un element H din listă şi dacă este întreg îl adugă la lista rezultat
şi se reapeleză , altfel dacă interger(H) întoarce fail atunci se încearcă satis-
facerea celei de-a treia clauze, care scoate elementul din listă. Ne oprim când
lista va fi vidă.
Exemplul 0.6.16.
Scrieţi un program care numără câte vocale sunt într-o listă. Implementarea
în fişierul L8ex2.pl
Apel:
?- nr_vocale([a,s],X).
X=1?- nr_vocale([a,r,e,d,i],X).
X=3
?- nr_vocale([s,d],X).
X=0
Program:
member(X,[X|_]).
member(X[_|T]):-member(X,T).
86
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 87/183
vocala(X):-member(X,[a,e,i,o,u]).
nr_vocale([],0).
nr_vocale([X|T],N):-vocala(X),nr_vocale(T,N1),N is N1+1,!.nr_vocale([X|T],N):-nr_vocale(T,N).
Încă un exemplu de predicat recursiv. Predicatul este structurat pe 2 cazuri
simple, dacă litera este sau nu vocală. Dacă este, atunci se reapelează pentru
restul listei şi o variabilă liberă N1, care atunci când lista va fi vidă va fi
unificată cu 0, la revenirea din apeluri se vor număra vocalele. Dacă litera
nu este vocală predicatul se reaprelază pentru restul listei. Cazul de bază este
prima clauză a predicatului, care semnifică faptul că în lista vidă sunt 0 vocale.
Exemplul 0.6.17.
Selectaţi dintr-o listă primele şi ultimele N elemente. Implementarea se găseşte
în fişierul L8ex3.pl
Ultimul element dintr-o listă:
?- ultimul([1,2,3,4],R).
R=4last(L,R):- append(X,[R],L).
Primul element dintr-o listă:
?- primul([1,2,3,4],R).
R = 1
primul(L,R):- append([R],X,L).
Se observă modul în care predicatul-sistem append/3 răspunde interogărilor.
Se poate construi foarte uşor un predicat care să întoarcă primele şi ultimele
87
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 88/183
N elemente.
Apel:
?- prim([1,2,3,4,5,6],3,R).R = [1, 2, 3]
Yes
4 ?- ultim([1,2,3,4,5,6],3,R).
R = [4, 5, 6]
Yes
Program:
ultim(L,N,R):- append(X,R,L),length(R,N).prim(L,N,R):- append(R,X,L),length(R,N).
Predicatul sistem append/3 fiind apelat cu primele variabile nelegate va încerca
toate posibilităţile pentru care din R şi X se obţine lista L, aceea care va avea
lungimea N va fi lista care ne interesează. Remarcaţi că lista rezultat R, se
află pe poziţii diferite în funcţie de fiecare apel append.
Exemplul 0.6.18.
Scrieţi un predicat care simulează o listă circulară. Implementarea se găseşte
în fişierul L8ex4.pl
Apel:
?- circular([a,b,c,d],R).
R=[a,b,c,d]
R=[b,c,d,a]
R=[c,d,a,b]
88
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 89/183
R=[d,a,b,c]
R=[d,a,b,c]
Program:
circ(_,[],_).
circ([H|T],[_|Rest],R):- concat(T,[H],R),write(R),nl,circ(R,Rest,R1).
circular(L,R):-circ(L,L,R).
Luăm lista [a,b,c,d] şi punem primul element a la coadă. Lista rezultat R
(R=[b,c,d,a]) va intra din nou în buclă şi din nou punem primul element la
coadă. Când ştim să ne oprim? Introducem încă o variabilă pe care o iniţia-
lizăm cu lista [a,b,c,d]. De fiecare dată când obţinem o lista circulară nouăscoatem din L=[_|Rest] un element şi continuăm cu Rest. În momentul în
care lista va fi vidă ne oprim.
Exemplul 0.6.19.
Scrieţi un predicat care sortează crescător o listă de numere întregi. Imple-
mentarea în fişierul L8ex5.pl
Apel:?- sort_ins([13,2,6,1,5,9,7],R).
R = [1, 2, 5, 6, 7, 9, 13]
Yes
Program:
sort_ins(List,Sort):-i_sort(List,[],Sort).
i_sort([],A,A).
i_sort([H|T],A,Sort):-insert(H,A,NA),i_sort(T,NA,Sort).
89
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 90/183
insert(X,[Y|T],[Y|NT]):-X>Y,insert(X,T,NT).
insert(X,[Y|T],[X,Y|T]):-X=<Y.
insert(X,[],[X]).
Exemplul 0.6.20.
Scrieţi un predicat care permută o listă folosind ştergerea din listă. Prezentăm
mai întâi predicatele de ştergere utilizate pentru a permuta lista. Implemen-
tarea în fişierul L8ex6.pl
Apel:
?-sterge(a,[a,c,[a,b],f],R).R=[c,[a,b],f]
?-sterge(X,[a,b,c],R).
X=a
R=[b,c]
X=b
R=[a,c]
X=cR=[a,b]
Predicat:
sterge(X,[X|T],T).
sterge(X,[Y|T],[Y|R]):-sterge(X,T,R).
Predicatul de mai sus şterge un element dintr-o listă.
Apel:
?-sterge_lista([1,2,3],[1,4,2,5,3,7],R).
90
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 91/183
R=[4,5,7].
Predicat
sterge_lista([],L1,L1).sterge_lista([H|T],L1,L3):-sterge(H,L1,L2),sterge_lista(T,L2,L3).
Predicatul de mai sus şterge elementele unei liste dintr-o listă, folosind şterge-
rea unui singur element dintr-o listă.
?-permutare([a,b,c],L).
L = [[a, b, c], [a, c, b], [b, a, c], [b, c, a], [c, a, b], [c, b, a]]
Predicat:
permutare(L,R):- findall(X,sterge_lista(X,L,[]),R).Predicatul sistem findall/3 găseşte toate soluţiile predicatului sterge_lista/3
pe care le va returna în variabila R. Rezultatele intermediare vor fi obţinute
în variabila X.
Exemplul 0.6.21.
Scrieţi un predicat care afişează toate permutările unei liste folosind adăugă-
rile în listă.(scoate pe rând fiecare element şi îl adaugă în dreptul fiecărui altelement). Implementarea în fişierul L8ex7.pl
Apel:
?- permutari([1,2],R).
R=[[1,2],[2,1]]
Predicate folosite:
?-adaug(a,[b,c,d],X).
X=[a,b,c,d]
91
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 92/183
X=[b,a,c,d]
X=[b,c,a,d]
X=[b,c,d,a]?-permut([a,b,c],X).
X=[a,b,c]
X=[b,a,c]
X=[b,c,a]
X=[a,c,b]
X=[c,a,b]
X=[c,b,a]Program:
adaug(X,L,[X|L]).
adaug(X,[L|H],[L|R]):-adaug(X,H,R).
permut([],[]).
permut([L|H],R):-permut(H,R1),adaug(L,R1,R).
permutari(L,R):- findall(P,permut(L,P),R).
Exemplul 0.6.22.
Scrieţi un predicat care găseşte toate combinările unei mulţimi luate câte K.
Implementarea în fişierul L8ex8.pl
Apel:
?- combinari([a,b,c],2,R).
R=[[a,b],[a,c],[b,c]]
?- adauga(a,[[b],[c]],I).
92
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 93/183
I=[[a,b],[a,c]]
Program:
combinari(L,N,[L]):-length(L,N),!.
combinari(L,1,R):- pune_paranteze(L,R).
combinari([H|T],K,R):-
K1 is K-1,
combinari(T,K1,R1),
adauga(H,R1,R2),
combinari(T,K,R3),concat(R2,R3,R).
adauga(X,[L],[[X|L]]).
adauga(X,[H|T],[[X|H]|R]):-adauga(X,T,R).
pune_paranteze([],[]).
pune_paranteze([H|T],[[H]|R]):-
pune_paranteze(T,R).
Exemplul 0.6.23.
Scrieţi un predicat SWI-Prolog care "împachetează" elemente consecutive iden-
tice dintr-o listă. Implementarea în fişierul L9ex1.pl
Apel:
?- impacheteaza([a,a,a,a,b,c,c,a,a,d,e,e,e,e],X).
X = [[a,a,a,a],[b],[c,c],[a,a],[d],[e,e,e,e]]
Program:
93
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 94/183
transfer(A, [], [], [A]).
transfer(A, [B|C], [B|C], [A]) :-
A\=B.transfer(A, [A|B], C, [A|D]) :-
transfer(A, B, C, D).
impacheteaza([], []).
impacheteaza([A|B], [C|D]) :-
transfer(A, B, E, C),
impacheteaza(E, D).
Predicatul împachetează elementele din lista B formând o listă, D, cu aceleaşielemente însă conţinute în subliste ale lui D. Predicatul transfer/4 este folosit
pentru a scoate elementele identice din lista B şi a depune rezultatul în lista
D care va fi lista rezultat. La încheierea acestei operaţii predicatul impache-
teaza/2 se reapelează pentru restul listei. Ne vom opri când ambele liste vor
fi goale, lista procesată şi lista rezultat, deoarece dacă prima listă a devenit
vidă şi lista rezultat va fi vidă, la revenirea din apeluri lista rezultat va con-
ţine sublistele cu elemente identice, care au fost introduse în antetul clauzeiimpacheteaza([A|B], [C|D]).
Exemplul 0.6.24.
Având programul de mai sus scrieţi un program care codifică o listă ast-
fel: pentru termeni consecutivi , identici vom avea o listă de liste de forma
[[N,X],[M,Y]] unde N şi M sunt numărul de apariţii ale lui X, respectiv Y.
Implementarea în fişierul L9ex2.pl
94
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 95/183
Predicatul ensure_loaded( fisier ) asigură faptul că fişierul fisier a fost încărcat.
El trebuie apelat înainte de a compila L9ex2.pl
?- ensure_loaded(L9ex1).Yes
Apel:
?- codifica[a,a,a,a,b,c,c,a,a,d,e,e,e,e],X).
X = [[4,a],[1,b],[2,c],[2,a],[1,d][4,e]]
Program:
codifica(L1,L2) :- impacheteaza(L1,L), transform(L,L2).
transform([],[]).transform([[X|Xs]|Ys],[[N,X]|Zs]) :-
length([X|Xs],N), transform(Ys,Zs).
Exemplul 0.6.25.
Având exemplul de mai sus , scrieţi un predicat SWI-Prolog care decodifică
listele obţinute cu programul din exemplul precedent. Implementarea în fişierul
L9ex3.plApel:
?- decodifica([[4,a],[1,b],[2,c],[2,e]],R).
R = [a, a, a, a, b, c, c, e, e]
Program:
decodifica([],[]).
decodifica([X|Ys],[X|Zs]) :-
is_list(X), decodifica(Ys,Zs).
95
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 96/183
decodifica([[1,X]|Ys],[X|Zs]) :- decodifica(Ys,Zs).
decodifica([[N,X]|Ys],[X|Zs]) :-
N > 1, N1 is N - 1,decodifica([[N1,X]|Ys],Zs).
Exemplul 0.6.26.
Scrieţi un predicat care întoarce o listă L2 obţinută din lista L1 prin adăugarea
la L2 a elementelor dintre indecşii I şi K. Implementarea în fişierul L9ex4.pl
Apel:
trunc([a,b,c,d,e,f,g,h,i,k],3,7,L).
L = [c,d,e,f,g]
Program:
trunc([X|_],1,1,[X]).
trunc([X|Xs],1,K,[X|Ys]) :-
K > 1,
K1 is K - 1,
trunc(Xs,1,K1,Ys).
trunc([_|Xs],I,K,Ys) :- I > 1,
I1 is I - 1,
K1 is K - 1,
trunc(Xs,I1,K1,Ys).
Exemplul 0.6.27.
Scrieţi un predicat SWI-Prolog care şterge toate elementele din N în N dintr-o
listă. Implementarea în fişierul L9ex5.pl
96
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 97/183
Apel:
?- sterge([a,b,c,d,e,f,g,h,i,k],3,R).
R = [a,b,d,e,g,h,k]Program:
sterge([],_,[],_).
sterge([_|Xs],N,Ys,1) :-
sterge(Xs,N,Ys,N).
sterge([X|Xs],N,[X|Ys],K) :-
K > 1, K1 is K - 1,
sterge(Xs,N,Ys,K1).
Exemplul 0.6.28.
Scrieţi un predicat SWI-Prolog care simulează o loterie. Şi anume se extrag N
numere în din intervalul 1..M care vor fi introduse într-o listă L. Implementarea
în fişierul L9ex5.pl
Apel:
?- extrage(5,20,L).L = [2, 15, 4, 7, 9]
În exemplul de mai sus N=5, M=20.
Program:
sterge(X,[X|Xs],1,Xs).
sterge(X,[Y|Xs],K,[Y|Ys]) :-
K > 1, K1 is K - 1,
sterge(X,Xs,K1,Ys).
97
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 98/183
select(_,0,[]).
select(Xs,N,[X|Zs]) :- N > 0,
length(Xs,L),I is random(L) + 1,
sterge(X,Xs,I,Ys),
N1 is N - 1,
select(Ys,N1,Zs).
interval(I,I,[I]).
interval(I,K,[I|L]) :-
I < K, I1 is I + 1,interval(I1,K,L).
extrage(N,M,L) :-
interval(1,M,R),
select(R,N,L).
0.6.3 Exerciţii propuse
Exerciţiul 0.6.1.
Scrieţi un predicat SWI-Prolog care simulează pe liste reuniunea, intersecţia
şi diferenţa pentru mulţimi.
Exerciţiul 0.6.2.
Scrieţi un predicat SWI-Prolog care caută o listă intr-o listă de liste.
Exerciţiul 0.6.3.
98
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 99/183
Scrieţi un predicat SWI-Prolog care afişează intersecţia a două liste care conţin
alte liste.
Exerciţiul 0.6.4.
Scrieţi un program care afişează reuniunea a două liste de liste.
0.6.4 Teme de studiu
Tema 0.6.1.
Rulaţi cu trace exemplele prezentate.
99
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 100/183
0.7 Grafuri. Arbori
0.7.1 Fundamente teoretice
0.7.1.1 Probleme de reprezentare
Reprezentarea datelor joacă un rol important în programare, în general o formă
de reprezentare sau alta poate uşura munca unui programator. De aceea ca
mod de reprezentare a muchiilor unui graf alegem forma de mai jos a clauzelor,
care credem că este cea mai potrivită pentru problemele prezentate în acest
material.- muchie(A,B). - prin aceasta simbolizăm faptul că există muchie de la A la B.
Reprezentarea de mai sus este suficientă pentru grafurile orientate. Dacă se
doreşte adăugarea de costuri pentru muchii aceasta se poate face prin adău-
garea la predicatul muchie a unei variabile care să reprezinte costul traversării
muchiei de la A la B.
Dorim în continuare pentru grafurile neorientate să avem un predicat care să
reprezinte faptul că muchiile sunt neorientate sau că se poate circula în ambelesensuri. Pentru aceasta am putea adopta o construcţie de forma:
- muchie(A,B):- muchie(B,A). în felul acesta programul va intra într-un ciclu
infinit.
O soluţie la problemă ar putea fi crearea de fapte de tipul muchie(a,b). şi
muchie(b,a). însă în felul acesta dublăm numărul predicatelor, iar pentru un
graf de dimensiuni considerabile efortul tastarii programului este prea mare
(această abordare poate fi o soluţie pentru reprezentarea grafurilor orientate).
100
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 101/183
Vom folosi predicatul următor pentru rezolvarea acestei probleme.
legatura(X,Y) :- muchie(X,Y) ; muchie(Y,X).
Semnul ";" reprezintă o disjuncţie ( sau logic ). Predicatul de mai sus ar fi
putut fi scris şi sub forma:
legatura(X,Y):- muchie(X,Y).
legatura(X,Y):- muchie(Y,X).
Pentru reprezentarea arborilor vom folosi acelaşi predicat muchie(a,b).
şi legatura(X,Y).
0.7.2 Exemple
Exemplul 0.7.1.
Considerăm graful de mai jos, scrieţi un program SWI-Prolog care găseşte
toate drumurile între oricare 2 vârfuri ale grafului. Implementarea în fişierul
L10ex1.pl.
101
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 102/183
Apel:
drum(1,5,R).
R = [1, 3, 5] ;R = [1, 3, 6, 5] ;
R = [1, 3, 2, 8, 4, 5] ;
R = [1, 7, 5] ;
R = [1, 6, 5] ;
R = [1, 6, 3, 5] ;
R = [1, 6, 3, 2, 8, 4, 5] ;
NoProgram:
muchie(1,3). muchie(1,7). muchie(1,6).
muchie(2,3). muchie(2,8).
muchie(3,5). muchie(3,6).
muchie(4,5). muchie(4,8).
muchie(5,6). muchie(5,7).
legatura(X,Y) :-muchie(X,Y) ; muchie(Y,X).
drum(A,B,Drum) :-
mergi(A,B,[A],L),
reverse(L,Drum).
mergi(A,B,P,[B|P]) :-
legatura(A,B).
102
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 103/183
mergi(A,B,V,Drum) :-
legatura(A,C),
C \== B,not(member(C,V)),
mergi(C,B,[C|V],Drum).
Exemplul 0.7.2.
Având programul de mai sus scrieţi un predicat SWI-Prolog care găseşte un
drum închis plecând dintr-un vârf dat. Programul trebuie să returneze toate
drumurile prin backtracking. Implementarea în fişierul L10ex2.pl
Apel:
?- ciclu(1,Drum).
Drum = [1, 7, 5, 3, 1] ;
Drum = [1, 7, 5, 6, 3, 1] ;
Drum = [1, 7, 5, 4, 8, 2, 3, 1] ;
. . .
Program:
ciclu(A,P) :-
legatura(B,A),
drum(A,B,P1),
length(P1,L),
L > 2,
append(P1,[A],P).
Exemplul 0.7.3.
103
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 104/183
Având graful de mai sus şi reprezentarea lui în SWI-Prolog scrieţi un pre-
dicat care calculează gradul unui nod. Implementarea în fişierul L10ex3.pl
Apel:
?- grad(1,R).
R = 3
Yes
Predicat:
grad(Nod,R):- findall(X,muchie(Nod,X),L),length(L,R).
Pentru acest predicat folosim reprezentarea grafului din figura de mai sus şi
predicatele built-in findall/3 şi length/2 . Predicatul findall/3 va găsi toatemuchiile care există de la Nod la X si va întoarce în lista L veciniii lui Nod .
Predicatul length/2 returnează lungimea unei liste în cel de-al doilea parame-
tru care trebuie să fie o variabilă liberă la apel, dacă este o variabilă legată şi
primul parametru este liber atunci va crea o listă aleatoare cu număr egal de
elemente cu valoarea celuilalt parametru.
Exemplul 0.7.4.
Scrieţi un predicat SWI-Prolog care întoarce într-o listă toate nodurile unui
graf şi lungimea listei. Implementarea în fişierul L10ex3.pl
Apel:
varfuri(R,N).
R = [1, 2, 3, 4, 5, 6, 7, 8]
N = 8
Yes
104
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 105/183
Predicat:
varfuri(R,N):-
findall(X,(muchie(X,_); muchie(_,X)),L),sort(L,R),length(R,N).
Predicatul built-in sort/2, după cum îi spune şi numele, sortează lista L şi
întoarce rezultatul în variabila R.
0.7.3 Exerciţii propuse
Exerciţiul 0.7.1.
Modificaţi primul program prezentat (drum în graf) pentru a afla fluxul
maxim dintre 2 noduri (A şi B) ale grafului. Fluxul maxim este valoarea
minimă a muchiilor grafului pe care le parcurgem pentru a ajunge din punctul
A în B.
0.7.4 Teme de studiu
Tema 0.7.1.
Scrieţi un program SWI-Prolog care parcurge un arbore.
105
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 106/183
0.8 Probleme speciale
0.8.1 Problema Damelor
Aceasta este o problemă clasică în programarea calculatoarelor, după cum se
ştie trebuie să plasăm pe o tablă de şah, de dimensiune N×N, N dame astfel
încât să nu se atace reciproc. Două dame se atacă atunci când se găsesc pe
aceeaşi linie, coloană sau diagonală.
Reprezentăm poziţia celor N dame printr-o listă de dimensiune N astfel :
dacă avem lista [4,2,7,3,6,8,5,1] aceasta înseamnă că dama de pe coloana 1se găseşte pe linia 4, dama de pe coloana 2 se găseşte pe linia 2 , ş.a.m.d. .
Folosind acest mod de reprezentare a informaţiilor şi folosind permutări ale
numerelor între 1 şi N ne asigurăm că oricare 2 dame nu se vor găsi pe aceeaşi
linie sau coloană. Singurul test care ne mai rămâne este testul diagonalelor,
astfel o damă plasată pe coloana X şi rândul Y ocupă două diagonale notate
prin C (diagonala secundară) şi D (diagonala principală) acestea vor fi un
număr C=X-Y şi D= X+Y , aceste valori , ale diagonalelor deja ocupate vorfi reţinute în două liste Cs şi Ds.
Apel:
?- dame_1(4,R).
R = [2, 4, 1, 3] ;
R = [3, 1, 4, 2] ;
?- dame_1(8,R).
R = [1, 5, 8, 6, 3, 7, 2, 4] ;
106
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 107/183
R = [1, 6, 8, 3, 7, 4, 2, 5] ;
R = [1, 7, 4, 6, 8, 2, 5, 3] ;
R = [1, 7, 5, 8, 2, 4, 6, 3] ;. . .
Program:
Predicatul dame_1(N,Qs) :- Qs este o soluţie de aşezare a celor N dame.
dame_1(N,Qs) :- intre(1,N,Rs), permuta(Rs,Qs), test(Qs).
Predicatul intre(A,B,L) :- L este o listă de numere între A şi B.
intre(A,A,[A]).
intre(A,B,[A|L]) :- A < B, A1 is A+1, intre(A1,B,L).
Predicatul permuta(Xs,Zs) :- lista Zs este o permutare a listei Xs.
permuta([],[]).
permuta(Qs,[Y|Ys]) :- del(Y,Qs,Rs), permuta(Rs,Ys).
del(X,[X|Xs],Xs).
del(X,[Y|Ys],[Y|Zs]) :- del(X,Ys,Zs).
Predicatul test(Qs) :- Lista Qs reprezintă o soluţie a damelor care nu
se atacă reciproc.
test(Qs) :- test(Qs,1,[],[]).
Predicatul test(Qs,X,Cs,Ds) :- Damele din Qs, reprezentând coloanele
de la X la N, nu sunt în conflict cu diagonalele Cs şi Ds.
107
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 108/183
test([],_,_,_).
test([Y|Ys],X,Cs,Ds) :-
C is X-Y, not(memberchk(C,Cs)),D is X+Y, not(memberchk(D,Ds)),
X1 is X + 1,
test(Ys,X1,[C|Cs],[D|Ds]).
Iată o a doua versine în care permutarea este verificată înainte de a trece mai
departe .
dame_2(N,Qs) :-
intre(1,N,Rs),permuta_test(Rs,Qs,1,[],[]).
permuta_test([],[],_,_,_).
permuta_test(Qs,[Y|Ys],X,Cs,Ds) :-
del(Y,Qs,Rs),
C is X-Y, not(member(C,Cs)),
D is X+Y, not(member(D,Ds)),
X1 is X+1,permuta_test(Rs,Ys,X1,[C|Cs],[D|Ds]).
Programul se găseşte implementat în fişierul L11ex1.pl
0.8.2 Problema mutării calului
Se dă o tablă de sah de dimensiuni N×N, se cere să se mute un cal pe tablă
în asa fel încât la final calul să fi trecut prin toate pătratele tablei.
108
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 109/183
Predicatul cal(N,Cal) :- Cal este o listă ce conţine rezultatul problemei sub
elemente de forma linie/coloană reprezentând poziţiile pe care se poate muta
calul.cal(N,Cal) :- M is N*N-1,cal(N,M,[1/1],Cal),write(Cal).
Predicatul drum_inchis/2 calculează dacă există un drum închis, şi anume
calul trebuie să se întoarcă în acelaşi pătrat din care a pornit.
drum_inchis(N,Cal) :-
cal(N,Cal),
Cal = [X/Y|_],
sare(N,X/Y,1/1).cal(_,0,Cal,Cal).
cal(N,M,Visited,Cal) :-
Visited = [X/Y|_],
sare(N,X/Y,U/V),
not(memberchk(U/V,Visited)),
M1 is M-1,
cal(N,M1,[U/V|Visited],Cal).Predicatul sare/3 specifică modul în care calul poate sări pe tablă de la pătratul
A/B la C/D.
sare(N,A/B,C/D) :-
sare_dist(X,Y),
C is A+X, C > 0, C =< N,
D is B+Y, D > 0, D =< N.
109
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 110/183
Baza de cunoştinţe cu distanţele pe care le poate sări calul.
sare_dist(1,2).
sare_dist(2,1).sare_dist(2,-1).
sare_dist(1,-2).
sare_dist(-1,-2).
sare_dist(-2,-1).
sare_dist(-2,1).
sare_dist(-1,2).
Apel:?- cal(5,R).
Cal=[1/5, 3/4, 5/5, 4/3, 5/1, 3/2, 1/3, 2/5, 4/4, 5/2, 3/1, 1/2, 2/4, 4/5, 5/3,
4/1, 2/2, 1/4, 3/3, 2/1, 4/2, 5/4, 3/5, 2/3, 1/1]
0.8.3 Exerciţii propuse
Exerciţiul 0.8.1.
O firmă de cartografie urmăreşte să coloreze o hartă a N tări cu M culori în
aşa fel încât două ţări vecine să nu fie colorate cu aceeaşi culoare. Scrieţi un
program Prolog care să afişeze toate soluţiile posibile pentru N şi M date.
0.8.4 Teme de studiu
Tema 0.8.1.
110
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 111/183
Rulaţi programele prezentate folosind comanda trace.
111
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 112/183
0.9 Fişiere. Baze de date dinamice
0.9.1 Fundamente teoretice
0.9.1.1 Fişiere
SWI-Prolog dispune de 2 modalităţi de lucru cu fişiere: Stilul Edinburgh care
presupune gestionarea unui stream implicit, predicatele referă în mod implicit
stream-ul curent, şi stilul ISO Input and Output Streams, în care stream-urile
sunt explicite si sunt create cu predicatul open/3 sau open/4. Fiecare stream
astfel creat are un identificator unic folosit de alte predicate pentru a citi sauscrie pe streamul respectiv.
Prezentăm în continuare stilul Edinburgh.
În acest stil, stream-ul este conectat în mod implicit la terminal ( monitor +
tastatură pentru ieşiri respectiv intrări), el poate fi schimbat cu predicatele:
- see(+SrcDest) Deschide SrcDest pentru citire şi îl face stream-ul curent de
intrare.
- tell(+SrcDest) Deschide SrcDest pentru scriere şi îl face să fie stream-ul cu-rent de ieşire.
- append(+File) Similar cu tell/1, dar poziţionează pointerul de scriere la fi-
nalul fişierului.
- seeing(?SrcDest) şi telling(?SrcDest) nu returnează numele fişierului deschis
pentru citire/scriere ci returnează indentificatorul de stream.
- seen şi told închid stream-ul curent.
SrcDest poate fi un fişier, terminalul sau un termen desemnat prin
112
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 113/183
’pipe(Comanda)’. Iată câteva exemple pentru SrcDest:
?- see(f.txt). % citeşte din fişierul ’f.txt’
?- tell(user). % Scrie pe terminal.?- tell(pipe(lpr)). % Scrie la imprimantă
În exemplul de mai sus user şi lpr sunt cuvinte rezervate în SWI-Prolog.
Stilul ISO Input and Output Streams presupune crearea stream-urilor prin in-
termediul predicatului open/3 sau open/4. Identificatorul de stream rezultat
este apoi transmis predicatelor care fac citiri şi scrieri pentru a specifica sursa
sau destinaţia datelor. Predicatele built-in care respectă acest stil/standard
sunt:open(+SrcDest, +Mode, -Stream, +Options) SrcDest specifică una din
opţiunile de mai sus, Mode poate fi read, write, append sau update, Stream
poate fi fie o variabilă care la final va conţine identificatorul de stream fie un
atom şi în cazul acesta atomul va fi identificatorul de stream. Options pate fi
:
- type(Type) se foloseşte pentru a putea scrie în mod text în mod compatibil
cu sistemul de operare. Dacă se foloseşte tipul binar octeţii vor fi scrişi fără afi traduşi. De menţionat că pe sistemele Unix nu se face diferenţă între modul
text şi binar.
- alias(Atom) dă unui stream un nume. Atenţie la această opţiune deoarece
numele de stream-uri sunt globale. Exemplu:
?- open(data, read, Fd, [alias(input)]). , ...,read(input, Term),...
- eof_action(Action) defineşte ce se întamplă în momentul în care se ajunge
113
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 114/183
la final de fişier.
- buffer(Buffering) defineste posibilitatea de a avea un buffer.
- close_on_abort(Bool) închide stream-ul dacă în timpul execuţiei programu-lui se apelează predicatul abort/0.
- lock(LockingMode) încearcă să blocheze fişierul pentru ca alte procese să nu îl
modifice în timpul executiei programului. În mod implicit fişierul nu va fi blo-
cat , însă locking mode poate fi read sau shared , adică alte procese(programe)
pot accesa fişierul numai pentru citire.
open(+SrcDest, +Mode, ?Stream) este echivalent cu open/4 cu lista de
opţiuni vidă.open_null_stream(?Stream) deschide un stream vid. Toate funcţiile sunt
active pentru un asemenea stream, dar o încercare de a citi de pe un astfel de
stream returnează end_of_file.
close(+Stream) închide stream-ul specificat. Dacă acest stream este stream-
ul curent pentru intrare/ieşire atunci terminalul este făcut stream curent
pentru intrare/ieşire.
set_stream(+Stream, +Attribute) setează stream-ului atributele prezen-tate mai sus la predicatul open.
0.9.1.2 Baze de date dinamice.
Un program este o bază de date deoarece programul oferă posibilitatea intero-
gării "bazei de date" compusă din fapte şi reguli. O astfel de bază de date se
numeşte "statică" deoarece ea nu poate fi modificată în timpul execuţiei pro-
114
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 115/183
gramului. În SWI-Prolog există posibilitatea de a crea baze de date dinamice,
acestea se referă la faptul că la un moment dat putem avea o bază de fapte
creată în timpul execuţiei programului. Spre exemplu în timpul executiei pro-gramului dorim să mai adăugăm la baza de fapte încă o clauză. SWI-Prolog
pune la dispoziţie următoarele predicate-sistem pentru lucrul cu baze de date
dinamice:
- assert(+Term) adaugă un fapt la baza de date ca ultim fapt sau clauză a
predicatului corespunzător.
- asserta(+Term) echivalent cu predicatul de mai sus, dar Term este adăugat
ca primă clauză sau fapt al unui predicat.- assertz(+Clause) echivalent cu assert/1 .
- retract(+Term) atunci când Term este atom sau termen el este unificat cu
primul fapt sau prima clauză din baza de date , iar faptul sau clauza este şters
din baza de date.
- retractall(+Head) toate fapte sau clauzele cu care Head se poate unifica
sunt şterse din baza de date.
- abolish(+PredSpec) şterge toate predicatele specificate de PredSpec, undePredSpec este de forma Predicat/Aritate. Tot ce are legătura cu predicatul
specificat este şters din sistem.
0.9.2 Exemple
Exemplul 0.9.1.
Scrieţi un program care citeşte litere dintr-un fişier(litere.txt), le separă în
115
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 116/183
vocale şi consoane, apoi le scrie în fişiere diferite (vocale.txt şi consoane.txt).
Implementarea în fişierul L12ex1.pl(Atenţie la formatul fişierului! Literele sunt
scrise pe câte un rând urmate de "." doarece SWI-Prolog le consideră fapte.)Apel:
?- start.
Yes
Program:
vocala(’a’).
vocala(’e’).
vocala(’i’).vocala(’o’).
vocala(’u’).
citeste(L):-
read(X),
X \= end_of_file,
append(L,[X],Rez),
citeste(Rez).citeste(L):-
separ(L,Vocale,Consoane),
vocale(Vocale),
consoane(Consoane).
separ([],[],[]).
separ([Litera|R],[Litera|Cons],Voc):-
116
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 117/183
not(vocala(Litera)),
separ(R,Cons,Voc).
separ([Litera|R],Cons,[Litera|T]):-vocala(Litera),
separ(R,Cons,T).
vocale(V):-
tell(’vocale.txt’),scrie(V),told.
consoane(C):-
tell(’consoane.txt’),scrie(C),told.
scrie([]).scrie([C|Rest]):-
write(C),scrie(Rest).
start:-
see(’litere.txt’),citeste([]),seen.
Programul se rulează apelând start. şi nu va avea nici un output pe consolă
deoarece prelucrează fişierul litere.txt , iar rezultatul va fi scris sub formă de
fişiere în directorul curent în fişierele vocale.txt şi consoane.txt . Predicatulciteste/1 citeşte din fişierul litere.txt şi dacă nu s-a ajuns la finalul fişierului
adaugă la o listă, dacă se ajunge la final când se va face Redo din clauza
secundă a predicatului citeste/1 se va procesa lista şi vor fi scrise fişierele cu
vocale şi consoane.
Exemplul 0.9.2.
Scrieţi un program SWI-Prolog care introduce într-o bază de date dinamică
117
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 118/183
predicate de forma divizor(X,Y) şi par(X) , unde divizor este un predicat
care semnifică faptul că Y este divizorul lui X, iar par(X) semnifică faptul că
X este un număr par. Implementarea în fişierul L12ex2.plApel: ?- apel.
Continuati?(da/nu)d.
X=4.
Y=2.
Continuati?(da/nu)d.
X=8.
Y=4.Continuati?(da/nu)d.
X=10.
Y=5.
Continuati?(da/nu)n.
Yes
?- listing(are).
:- dynamic are/2.are(2, 1).
are(2, 1).
are(4, 2).
are(4, 2).
are(8, 4).
are(10, 5).
118
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 119/183
Yes
?- listing(par).
:- dynamic par/1.par(2).
par(2).
par(4).
par(4).
par(8).
Yes
?-Program:
start:-
write(’X=’),read(X),
write(’Y=’),read(Y),
M is X mod Y,M=0,
adauga(X,Y),go.
adauga(X,Y):- assertz(are(X,Y)),fail.adauga(X,Y):- par(Y),assertz(par(X)).
adauga(_,_).
go:-
write(’Continuati?(da/nu)’),read(R),
R=’d’,start.
% go:- retract(are(_,_)),fail.
119
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 120/183
% go:- retract(par(_)),fail.
go.
apel:- asserta(par(2)),go.Programul funcţionează pe principiul: dacă Y divide pe X şi Y este număr
par atunci X este număr par. Liniile 6 şi 7 din program sunt comentate
deoarece nu vrem ca programul să şteargă predicatele adăugate în baza de
date dinamică, în cazul în care nu se continuă introducerea de numere. Pentru
a urmări însă modul în care funcţionează predicatul retract ele trebuiesc
decomentate.
0.9.3 Exerciţii propuse
Exerciţiul 0.9.1.
Scrieţi un program Prolog care citeşte de la tastatură informaţii de forma
persoana(nume(NumePrenume),telefon(NrTel)). le introduce în baza de date
dinamică şi le salvează într-un fişier specificat de utilizator, care mai apoi
poate fi citit şi încărcat în baza de date dinamică.
Exerciţiul 0.9.2.
Modificaţi programul de mai sus referitor la baze de date dinamice astfel
încât să nu se adauge de mai multe ori acelaşi fapt în baza de date.
120
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 121/183
0.9.4 Teme de studiu
Tema 0.9.1.
Rulaţi programele prezentate ca exemple, folosind comanda trace.
121
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 122/183
122
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 123/183
Capitolul 1
Probleme de la concursurile de
programare
123
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 124/183
1.1 Probleme de la concursurile de programare
1.1.1 Ascii
Pentru un N dat scrieţi un predicat cross/1 unde cross(N) desenează figura de
mai jos. În stânga este figura corespunzătoare penru N=5, săgeţile indicând
dimensiunile , iar în dreapta este figura corespunzătoare pentru N=3. Progra-
mul trebuie să funcţioneze pentru orice număr impar între 3 şi 23. Adăugarea
de spaţii în faţa celui mai din stânga asterix nu este permisă.
Figura 1.1: Exemple de apel pentru N=5 şi respectiv N=3
(The 10th Prolog Programming Contest - 20th International Conference on
Logic Programming, ICLP 2004, Saint-Malo, Franţa)
124
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 125/183
1.1.2 Staţii
Belgia este o ţară a căilor ferate. În 5 mai 1835 primul tren din Europaconecta capitala Bruxelles de oraşul Mechelen. În scurt timp au apărut mult
mai multe linii ferate , născându-se astfel o reţea feroviară densă. Totuşi
trenurile întârzie şi nu se poate face nimic pentru a preveni acest lucru.
Însă orice belgian poate locui în orice parte a ţării şi poate călători cu trenul
până la serviciu fără să piardă prea mult timp pe drum. Şi cum nu depărtarea
faţă de locul de muncă sau de staţiile mijloacelor de transport în comun nu
este o problemă , alte lucruri stau la baza alegerii unui loc pentru a locui .Scrieţi un predicat statie/1 care returnează staţia ( deci şi oraşul ) unde este
bine să locuiască un belgian. Predicatul trebuie să întoarcă un oraş sau fail în
cazul în care un astfel de oraş nu există.
Un oraş în care este bine să locuieşti este un oraş care nu este mare. Un
oraş mare este acela care are mai mult de 2 legături directe cu mai mult de 2
alte oraşe. În plus un oraş mic în care este bine să locuieşti se află la fel de
aproape de alte 2 oraşe mari.Informaţiile despre legăturile între oraşe sunt reprezentate ca fapte cale/2.
Toate căile ferate sunt bidirecţionale şi la fel de lungi. Răspunsul nu trebuie
să conţină fapte. Iată exemple de răspunsuri :
cale(bruxel,mechelen).
cale(bruxel, antwerpen).
cale(bruxel,gent).
cale(antwerp,mechelen).
125
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 126/183
cale(antwerp,gent).
cale(gent,brugge)
?- statie(X).X=mechelen
cale(bruxel,charleroi).
cale(bruxel,haacht).
cale(haacht,mechelen).
cale(mechelem,berchem).
cale(berchem,antwerp).cale(bruxel,boom).
cale(boom,antwerp).
cale(antwerp,eindhoven).
?-statie(X).
X=boom
(The 10th Prolog Programming Contest - 20th International Conference on
Logic Programming, ICLP 2004, Saint-Malo, Franţa)
1.1.3 Triplete
Să se genereze toate tripletele (X,Z,Y) care sunt numere întregi din intervalul
[0,9] şi (10*X+Y)/(10*Y+Z)=X/Z. Datele de ieşire trebuie să fie sub forma
următoare:
3 5 9
126
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 127/183
3 1 6
Dacă (3,5,9) şi (3,1,6) sunt soluţii.
(Prolog Programming Contest - 14 Noiembrie 1994 , Ithaca, ILPS’94)
1.1.4 Spirala
Se dau a şi b două numere întregi pozitive, se cere să se afişeze pe ecran un
dreptunghi cu lungimea b şi lăţimea a care conţine numerele de la 1 la a*b
aşezate în spirală. Pentru a=4 şi b=3 rezultatul este următorul:
1 2 3
10 11 4
9 12 5
8 7 6Coloanele trebuie aliniate la dreapta şi trebuie să ocupe N+1 poziţii, unde N
este numărul cifrelor reprezentării zecimale a lui a*b.
(Prolog Programming Contest - 14 Noiembrie 1994 , Ithaca, ILPS’94)
1.1.5 Perioada
Scrieţi un predicat perioada/3 care se apelează cu primii 2 parametri numere
întregi pozitive şi cel de-al treilea este o variabilă liberă. Un astfel de apel
trebuie să unifice cel de-al treilea parametru cu o listă de întregi (de la 0 la 9)
care reprezintă perioada obţinută atunci când primul argument este împărţit
la argumentul secund. Exemple:
?- perioada(3,4,P).
127
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 128/183
P=[0] % deoarece 3/4 = 0,250000. . .
?- perioada(4,3,P).
P=[3] % deoarece 4/3 = 1.33333. . .?- perioada(1,7,P).
P=[1,4,2,8,5,7] % deoarece 1/7 = 0.142857142857. . .
În ultimul exemplu P=[2,8,5,7,1,4] este de asemenea , un răspuns corect, orice
permutare a listei fiind un răspuns corect.
(Second Prolog Programming Contest - 4 Decembrie 1995 , Portland , Oregon
ILPS’95)
1.1.6 Numere
Se consideră o grilă infinită care are un număr finit de puncte luminoase (a se
vedea figura de mai jos). Aceste puncte luminoase sunt reprezentate de fapte
de forma iluminat/4 şi au un punct de start şi un punct de final ca argumente.
Asemănător unui unui ceas electronic aceste puncte pot forma numere de la
0 la 9. Se cere să se scrie predicatul numere/1 care returnează o listă (fărăduplicate, ordinea nefiind importantă) a tuturor numereleor care pot fi recu-
noscute dându-se setul de fapte pentu punctele luminoase. Pentru figura 1
avem numerele:
?- numere(L).
L=[0,1,2,3,4,5,6,7,8,9]
Figura 1 conţine într-adevăr toate numerele de la 0 la 9. Pentru a întelege cum
128
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 129/183
Figura 1.2: Exemplu de display digital
este format un număr punctul din centru este considerat ca având coordona-tele (0,0) , astfel numărul 3 poate fi reprezentat prin următorul set de fapte:
iluminat(1,2,2,2). iluminat(2,2,2,3). iluminat(2,4,2,3). iluminat(2,3,1,3). ilu-
minat(2,4,1,4).
Nu este permisă scalarea numerelor , de exemplu numărul 8 din figura 2 nu
trebuie recunoscut. Pe de altă parte însă numerele pot fi rotite si/sau părţi
care pot fi recunoscute din configuraţia unor puncte luminoase. Spre exemplu
se consideră figura 3 :?- numere(L).
L=[1,3,4,7]
Orientarea numerelor nu este aceeaşi în toate cazurile, iar un punct luminos
poate fi folosit ca parte componentă pentru mai multe numere (de exemplu
numărul 9 poate ascunde numărul 4 şi numărul 1, el însuşi poate fi conside-
rat un 6 rotit). (Second Prolog Programming Contest - 4 Decembrie 1995 ,
Portland , Oregon ILPS’95)
129
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 130/183
1.1.7 Triunghi
Un triunghi de mărimea 5 arată pe ecran în felul următor:
Remarcaţi faptul că există un spaţiu între fiecare steluţă de pe un rând orizon-
tal. Între vârful unui triunghi de dimensiune N şi partea stângă a ecranului nu
trebuie să fie mai mult de N+2 spaţii. Scrieţi predicatul triunghi/1 care este
apelat cu un întreg mai mare decât 0 şi care desenează triunghiul de dimen-
siunea respectivă pe ecran.
(Second Prolog Programming Contest - 4 Decembrie 1995 , Portland , Oregon
ILPS’95)
1.1.8 Diamant
Desenaţi pe ecran un diamant de forma prezentată mai jos. Generalizaţi din
exemple. Predicatul diamant/1 va trebui apelat cu un întreg mai mare decât
0, reprezentând dimensiunea diamantului. Iată exemple de apel ale acestui
predicat:
?- diamant(2).
130
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 131/183
1
3 2
4?-diamant(3).
1
4 2
7 5 3
8 6
9?-diamant(8).
(Second Prolog Programming Contest - 4 Decembrie 1995 , Portland , Oregon
ILPS’95)
1.1.9 Drum
Se consideră o tablă pătratică de dimensiune N (considerăm N=4 în acest
exemplu, acest lucru este dat în program de faptul dimensiune(4)), există un
punct de început (întotdeauna pătratul cu coordonatele 1,1) şi un punct de final
131
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 132/183
(dat în program de faptul mergi(1,4,f)). Există un drum corect între punctul de
început şi punctul de sfârşit, acest drum este marcat , fiecare pătrat conţinând
informaţii despre cum se ajunge la următorul pătrat , sub forma unui fapt:mergi(1,1,u). % de la 1,1 mergi în sus , adică spre 1,2
mergi(1,2,u).
mergi(1,3,r). % de la 1,3 mergi la dreapta , adica spre 2,3
mergi(2,3,r).
mergi(3,3,d). % de la 3,3 mergi în jos , adică spre 3,2
mergi(3,2,d)
mergi(3,1,r)Dacă am fi avut un l acesta ar fi însemnat la stânga , desigur f înseamnă
destinaţia finală. Informaţia de mai sus reprezintă tabla următoare:
Figura 1.3: Tabla nemodificată de spiritul rău
Pe o astfel de tablă nu este desigur dificil să se găsească drumul de la 1,1 la
1,4, însă un spirit rău a şters unele informaţii de pe tablă şi fapte de forma
mergi/3 astfel încât drumul nu mai are o reprezentare completă. Totuşi nu a
fost suficent de rău deoarece 2 pătrate vecine din drum nu au informaţie lipsă ,
132
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 133/183
punctul de final de asemenea nu lipseşte şi cel mult 2 vecini ai pătratelor lipsă
aparţin drumului corect (pătratele în diagonală nu sunt considerate vecine)
drumul şi în acest caz este uşor de găsit. Un al doilea spirit , mult mai răudecât primul a introdus informaţii pentru fiecare pătrat care NU se află pe
drumul spre pătratul final, informaţiile sunt de aşa natură încât dacă sunt
considerate corecte fie se iese de pe tablă fie formează un cerc . (în mod
particular nu vor fi întâlnite pătrate goale).
Figura 1.4: Tabla alterată
Se cere să se scrie un predicat drum/1 care returnează drumul corect sub forma
unei liste începând cu 1,1 şi terminând cu punctul final , lista fiind ordonată de-
a lungul drumului parcurs. Pentru exemplul de mai sus drum/1 dă următorul
rezultat:
X=[(1,1),(1,2),(1,3),(2,3),(3,3),(3,2),(3,1),(4,1)]
(Prolog Programming Contest - 14 Noiembrie 1994 , Ithaca ILPS’94)
133
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 134/183
1.1.10 Tabla
Se dă o tablă de dimensiune 4x4 şi în fiecare pătrat un operator binar şi unoperand număr întreg, Se porneşte cu 0 ca valoare curentă şi se alege un drum
pe tablă astfel încât să se viziteze fiecare pătrat o singură dată. De fiecare dată
se execută operaţia având ca operand stâng valoarea curentă şi continuând cu
rezultatul ca valoare curentă. La finalul drumului, valoarea curentă depinde
de drumul ales, această valoare se numeşte valoarea drumului. Trebuie găsită
valoarea maximă a tuturor drumurilor şi numărul drumurilor care au această
valoare. O astfel de tablă şi reprezentarea corespunzătoare ei se găseşte înfigura 1.5.
Predicatul tabla/3 are ca prim argument tabla (datele de intrare) şi produce
Figura 1.5: Exemplu de tablă şi reprezentarea corespunzătoare
ca argument secund valoarea maximală a drumurilor, argumentul numărul 3
fiind numărul drumurilor care au această valoare maximală.
134
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 135/183
1.1.11 Şarpele belgian
Şarpele belgian este un animal care are pe corp un tipar, dar acest tipar nu serepetă de un număr integral de ori. Un tipar este o secvenţă de inele, iar un
inel are un identificator care este un atom de lungime 1. De asemenea, şar-
pele belgian este un animal căruia îi place să stea încolăcit într-un fel anume:
întotdeauna se asează într-un dreptunghi cu capul în colţul din stânga-sus al
dreptunghiului şi corpul întinzându-se pe fiecare rând. Se cere să se scrie un
predicat sarpe/3 care să afişeze un astfel de şarpe belgian. Acel predicat va fi
apelat cu următoarele trei argumente:- o listă de atomi care reprezintă tiparul care se află pe corpul şarpelui.
- o listă a cărei lungime este numărul de inele care acoperă o linie din drep-
tunghiul în care stă şarpele (lista nu este vidă) .
- o listă a cărei lungime este numărul de inele care acoperă o coloană din
dreptunghiul în care stă şarpele (lista nu este vidă).
Predicatul trebuie să aibă următorul rezultat pe ecran:
?- sarpe([a,b,c,d],[_,_,_,_,_],[_,_,_]).(şarpele întins arată astfel a b c d a b c d a b c d a b c)
a b c d a
b a d c b
c d a b c
Înainte de a începe implementarea acestui predicat trebuie ştiut că şarpele bel-
gian dezaprobă operatorii aritmetici, astfel soluţia acestui predicat nu trebuie
să conţină nici un fel de operatori aritmetici. Folosirea următoarelor predicate
135
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 136/183
este interzisă:
is < > =< >= + - * name arg functor =..
(4th Annual Prolog Programming Contest 9 iulie 1997, Leuven)
1.1.12 Hexagon
Se consideră un hexagon compus din hexagoane mai mici numerotate (vezi
figura 1.6). Se cere să se genereze mulţimea hexagoanelor mici aflate la
distanţa N (cu N dat) faţă de un hexagon H dat. Predicatul hex/4 are ca
argumente dimensiunea S a hexagonului mare (adică numărul de hexagoanemici din prima coloană a hexagonului mare) , al doilea argument este H,
numărul hexagonului mic, iar al treilea argument este distanţa N. Predicatul
hex/4 trebuie să unifice ce de-al patrulea argument cu lista tuturor numerelor
hexagoanelor mici aflate la distanţa N de hexagonul H. Lista trebuie să fie
sortată.
Exemple de apel pentru predicatul hex/4:
?- hex(3,1,0,L).L=[3]
?- hex(3,1,1,L).
L=[2,4,5]
?- hex(3,1,2,L).
L= [3,6,8,9,10]
?- hex(3,1,3,L).
L = [7,11,13,14,15]
136
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 137/183
?- hex(3,1,4,L).
L = [12,16,17,18,19]
?- hex(3,1,5,L).L = []
(4th Annual Prolog Programming Contest 9 iulie 1997, Leuven)
Figura 1.6: Hexagon
137
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 138/183
138
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 139/183
Capitolul 2
Soluţiile problemelor propuse
2.1 Introducere. Fapte. Reguli
Rezolvarea 2.1.1.
Definiţi predicatele cumnat, matuşă, unchi, strabunic, soacră.
2.1.1 Soluţie teoretică
Pentru a putea defini predicatele cerute de exerciţiu avem nevoie de un ar-
bore genealogic care se va traduce în PROLOG prin mai multe predicate de
tipul fapt.Predicatul barbat(X) simbolizează faptul ca X este bărbat , acest
fapt ne va fi util în definirea celorlalte predicate. Predicate de forma casato-
rit(gicu,elena). se traduc în limbaj natural în faptul "gicu este căsătorit cu
elena", lucru valabil şi în cazul predicatelor parinte/2 şi frate/2. După ce am
stabilit un arbore genealogic trecem la scrierea predicatelor de tip fapte, pentru
139
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 140/183
toate relaţiile cerute avem nevoie de predicatele casatorit(A,B), parinte(A,B),
frate(A,B), vom înlocui variabilele A şi B cu numele persoanelor din arborele
nostru genealogic. Pentru a arăta că dacă A este casatorit cu B şi reciproca esteadevărată folosim predicatul casatoriti(A,B):- casatorit(A,B);casatorit(B,A).
unde semnul ";" are valoarea unui sau logic, folosim aceeaşi construcţie pentru
predicatele frati şi parinti. Predicatul cumnat(X,Y) va găsi soluţii dacă se rea-
lizează frati(Y,Z) şi casatoriti(X,Z) prin aceasta vrem să simbolizăm faptul că
X este cumnatul lui Y dacă Y are o soră (adică Y cu Z sunt fraţi, iar Z nu este
bărbăt) şi sora lui Y este căsătorită cu X. Predicatul unchi(A,B) se realizează
dacă A este barbat, C este părintele lui B şi C cu A sunt fraţi. Acest predicatmai are o posibilitate de a se realiza, aceasta dacă D este părintele lui B, D este
frate cu C, C este căsatorită cu A şi A este bărbat. Predicatul matusa are si el
2 posibilităţi de a se realiza deoarece pentru matusa(A,B) avem posibilitatea
ca A să fie mătuşa lui B dacă parinti(C,B) adică unul parintii lui B sunt C
care poate fi frate cu A şi bineînteles A nu este bărbat. Posibilitatea a doua A
este căsătorită cu C şi B are părinte D , C şi D sunt fraţi şi în plus A nu este
bărbat. Predicatul strabunic(A,B) folosim predicatul bunic(B,C) prezentat şiadăugăm condiţia C să fie părinte pentru B. Predicatul soacră are 3 conditii
care trebuie îndeplinite soacra(M,N) dacă N şi Z sunt căsătoriţi, M este părinte
pentru Z şi bineînteles Y nu este bărbat. Codul sursă al programului se găseşte
în fişierul L1r1.pl .
140
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 141/183
2.1.2 Apel
Pentru cine este gicu cumnat??- cumnat(gicu,X).
X = gigel
Are gigel cumnat?
?- cumnat(X,gigel).
X = gicu
Cine este mătusa alinei?
?- matusa(X,alina).X = ioana ;
X = anca ;
Pentru cine este mătuşă elena?
?- matusa(elena,X).
X = costi ;
X = gabi ;
X = catalin ;No
Cine este unchiul lui costi?
?- unchi(X,costi).
X = gicu ;
X = gigel ;
No
Nepoţii lui gicu sunt:
141
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 142/183
?- unchi(gicu,X).
X = costi ;
X = gabi ;X = catalin ;
No
Cine este soacra mariei?
?- soacra(X,maria).
X = monica ;
No
maria este soacră pentru:?- soacra(maria,X).
X = gigel ;
X = elena ;
X = anca ;
No
Străbunicul alinei este X:
strabunic(X,alina).X = marin ;
No
2.1.3 Cod sursă
barbat(marin).
barbat(ion). barbat(gicu).
142
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 143/183
barbat(george). barbat(gigel).
barbat(andrei). barbat(costi).
barbat(gabi). barbat(catalin).casatorit(marin,monica).
casatorit(ion,maria).
casatorit(gicu,elena).
casatorit(george,anca).
casatorit(gigel,ioana).
casatoriti(A,B):- casatorit(A,B);casatorit(B,A).
parinte(marin,ion). parinte(monica,ion).parinte(ion,gicu). parinte(maria,gicu).
parinte(ion,george). parinte(maria,george).
parinte(ion,ioana). parinte(maria,ioana).
parinte(gicu,andrei). parinte(elena,andrei).
parinte(gicu,alina). parinte(elena,alina).
parinte(george,costi). parinte(anca,costi).
parinte(gigel,gabi). parinte(gigel,catalin).parinte(ioana,gabi). parinte(ioana,catalin).
parinti(A,B):-parinte(A,B);parinte(B,A).
frate(gicu,george). frate(gicu,ioana). frate(george,ioana).
frate(andrei,alina). frate(gabi,catalin).
frati(A,B):- frate(A,B);frate(B,A).
soacra(M,N):-
143
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 144/183
casatoriti(N,Z),parinte(M,Z),not(barbat(M)).
cumnat(X,Y):-
frati(X,Z),not(barbat(Z)),casatoriti(Z,Y).matusa(A,B):-
parinte(C,B),frati(C,A),not(barbat(A)).
matusa(A,B):-
casatoriti(A,C),parinte(D,B),frati(C,D),not(barbat(A)).
unchi(A,B):-
parinte(C,B),frati(C,A),barbat(A).
unchi(A,B):-parinte(D,B),frati(C,D),casatoriti(C,A),barbat(A).
bunic(A,B):-
parinte(C,B),parinte(A,C).
strabunic(A,B):-
bunic(A,C),parinte(C,B),barbat(A).
2.2 Termeni. Variabile. Backtracking.
Predicatele-sistem trace, read, write
Rezolvarea 2.2.1.
Un om cumpară o maşină dacă îi place şi dacă poate să o ia. Unui om
îi place o maşină dacă are puterea pe care şi-o doreşte. Un om poate să ia
o maşină dacă are destui bani în cont să o cumpere sau dacă fiind casatorit,
144
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 145/183
soţiei îi place şi ei maşina şi au împreună bani să o cumpere.
2.2.1 Soluţie teoretică
Pentru a rezolva această problemă definim predicate pentru diferite tipuri de
maşini: pret_masina(masina,pret) este predicatul care defineşte pretul unei
maşini, putere reprezintă puterea unei maşini, putere_minima(masina,putere)
este puterea minimă pe care şi-o doreşte un om de la o maşină. Definim de
asemenea şi fapte pentru suma pe care o are un om în cont şi pentru faptul de
a fi căsătorit sau nu. Avem apoi predicatul place(X,Y) şi vrem să simbolizăm
faptul că lui X îi place maşina Y dacă are puterea T şi puterea_minimă nu
este mai mică decât T. X va putea cumpăra maşina Y dacă are în cont T
şi T este mai mare decât T1, preţul maşinii. Există şi o a doua posibilitate
de a cumpăra maşina şi pentru aceasta redefinim (adăugăm încă o clauză)
predicatul poate astfel dacă sotul lui X este R şi R place maşina Y şi sumele
adunate din conturile lor sunt mai mari decât T, pretul maşinii, atunci vor
cumpăra maşina. Ne mai rămâne să apelăm predicatele de mai sus într-un
predicat general cumpara(X,Y) dacă îi place şi dacă poate .
2.2.2 Apel
?- cumpara(ion,ferrari).
No
23 ?- cumpara(gicu,ferrari).
Yes
145
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 146/183
2.2.3 Cod sursă
Codul sursă al programului de mai jos se găseşte în fişierul L2r1.plpret_masina(ferrari,15000).
pret_masina(mazda,12000).
pret_masina(skoda,1100).
pret_masina(dacia,350).
putere(ferrari,500).
putere(dacia,65).
putere(mazda,350).putere(skoda,75).
cont(ion,11000).
cont(gicu,13000).
cont(nicu,7000).
cont(ana,5000).
cont(anda,10000).
putere_minima(ion,150).putere_minima(gicu,300).
putere_minima(nicu,500).
putere_minima(ana,300).
putere_minima(anda,350).
sot(gicu,ana).
sot(nicu,anda).
place(X,Y):-putere(Y,T),putere_minima(X,T1),T>=T1.
146
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 147/183
poate(X,Y):-cont(X,T),pret_masina(Y,T1),T>=T1.
poate(X,Y):-sot(X,R),place(R,Y),cont(X,T1),cont(R,T2),
pret_masina(Y,T),TT=T1+T2,TT>=T.cumpara(X,Y):-place(X,Y),poate(X,Y).
Prezentăm în continuare modul în care functionează trace pentru un apel
particular al predicatului cumpara/2:
?- trace,cumpara(gicu,ferrari). <- linia de comanda
Call: (9) cumpara(gicu, ferrari) ? creep <- apelul predicatului cumparaCall: (10) place(gicu, ferrari) ? creep <- predicatul cumpara se satisface dacă
lui gicu îi place maşina ( are puterea dorită ) şi poate să o cumpere
Call: (11) putere(ferrari, _L194) ? creep <- se apelează predicatul putere
Exit: (11) putere(ferrari, 500) ? creep <- puterea maşinii este 500
Call: (11) put_min(gicu, _L195) ? creep <- se apelează put_min
Exit: (11) put_min(gicu, 300) ? creep <- puterea minimă dorită de gicu este
300^Call: (11) 500>=300 ? creep <- se compară puterea maşinii cu puterea mi-
nimă dorită
^Exit: (11) 500>=300 ? creep <- relaţia putere maşină >= putere dorită este
adevărată
Exit: (10) place(gicu, ferrari) ? creep <- se iese cu succes din apelul
place(gicu,ferrari)
Call: (10) poate(gicu, ferrari) ? creep <- mai trebuie îndeplinită condiţia po-
147
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 148/183
sibilităţii financiare, se apelează poate(gicu,ferrari).
Call: (11) cont(gicu, _L194) ? creep
Exit: (11) cont(gicu, 13000) ? creep <- în contul lui gicu se găsesc 13000unităţi
Call: (11) car_cost(ferrari, _L195) ? creep
Exit: (11) car_cost(ferrari, 15000) ? creep <- maşina costă 15000 unităţi
^Call: (11) 13000>=15000 ? creep
^Fail: (11) 13000>=15000 ? creep <- predicatul aritmetic >= nu se îndepli-
neşte deoarece gicu nu are suficiente unităţi pentru a cumpăra maşina singur
Redo: (10) poate(gicu, ferrari) ? creep <- se încearcă resatisfacerea predica-tului poate(gicu,ferrari) pentru cea de-a doua clauză
Call: (11) sot(gicu, _L194) ? creep <- pentru a se îndeplini poate pentru a
doua clauză trebuie îndeplinite sot, place, putere, putere_min
Exit: (11) sot(gicu, ana) ? creep <- gicu are soţie pe ana
Call: (11) place(ana, ferrari) ? creep <- anei îi place ferrari ?
Call: (12) putere(ferrari, _L209) ? creep
Exit: (12) putere(ferrari, 500) ? creepCall: (12) put_min(ana, _L210) ? creep
Exit: (12) put_min(ana, 300) ? creep <- puterea minimă pe care şi-o doreşte
ana de la maşină este 300
^Call: (12) 500>=300 ? creep
^Exit: (12) 500>=300 ? creep
Exit: (11) place(ana, ferrari) ? creep <- anei îi place ferrari
148
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 149/183
Call: (11) cont(gicu, _L195) ? creep
Exit: (11) cont(gicu, 13000) ? creep <- gicu are în cont 13000 unităţi
Call: (11) cont(ana, _L196) ? creepExit: (11) cont(ana, 5000) ? creep <- ana are în cont 5000 unităţi
Call: (11) car_cost(ferrari, _L197) ? creep
Exit: (11) car_cost(ferrari, 15000) ? creep <- maşina costă 15000 unităţi
^Call: (11) _L198 is 13000+5000 ? creep
^Exit: (11) 18000 is 13000+5000 ? creep <- gicu şi ana au împreună 18000
unităţi
^Call: (11) 18000>=15000 ? creep^Exit: (11) 18000>=15000 ? creep <- preţul maşinii este mai mic decât suma
pe care o deţin cei doi
Exit: (10) poate(gicu, ferrari) ? creep <- se iese din clauza 2 a predicatului
poate , de data aceasta cu succes
Exit: (9) cumpara(gicu, ferrari) ? creep <- se iese din cumpara(gicu, ferrari).
Yes <- gicu poate cumpăra ferrari.
2.3 Unificarea. Operaţiile aritmetice
Rezolvarea 2.3.1.
Scrieţi un predicat care calculează media geometrică a două numere intro-
duse de la tastatură. Rezultatul va fi scris pe ecran.
149
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 150/183
2.3.1 Soluţie teoretică
Pentru a calcula media geometrică avem nevoie să calculăm radical din cele
două numere X şi Y. Folosim predicatul predefinit sqrt/1 care va fi evaluat
cu valoarea radicalului. Pentru a scrie pe ecran folosim predicatul write/1, iar
pentru citirile de la tastatură folosim read/1. Valoarea finală va fi obţinută prin
intermediul operatorului is în urma evaluării expresiei sqrt(X*Y). Clauzele vor
fi grupate în acelaşi predicat în ordinea în care ar fi şi în cadrul unui program
structurat.
2.3.2 Apel
?- start.
X=4.
Y=5.
media geometrica este: 4.47214
2.3.3 Cod sursă
start:-
write(’X=’),read(X),
write(’Y=’),read(Y),
M is sqrt(X*Y),
write(’media geometrica este: ’),
write(M).
150
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 151/183
2.4 Recursivitate. Predicatele !(cut) şi fail
Rezolvarea 2.4.1.
Scrieţi predicatul prolog puterea(N,K,R) care returnează în variabila R pe
N la puterea K, cu calculul puterii pe retur.
2.4.1 Soluţie teoretică
Programul trebuie să definească un fapt pentru N la puterea 0 rezultatul este
1, în continuare scădem din K până când K va fi 0 , facem cut în clauza în
care ştim cât este N la puterea 0 şi pe retur înmulţim rezultatul intermediar
cu N.
2.4.2 Apel
?- puterea(4,5,R).
R = 1024 Yes
?- puterea(3,3,R).
R = 27
Yes
151
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 152/183
2.4.3 Cod sursă
Codul sursă al programului de mai jos se găseşte în fişierul L4r1.pl
puterea(N,0,1):-!.
puterea(N,K,R):-
K1 is K-1,
puterea(N,K1,R1),
R is R1*N.
2.5 Turnurile din Hanoi. Funcţiile Fibonacci şi
Ackermann
2.5.1 Soluţie teoretică
N reprezintă termenul de rang N din şirul lui Fibonacci, vom scădea din N
câte o unitate atât timp cât N > 0. Pentru a ajunge la termenul de rang n,
calculăm X n = X n−1 + X n−2 şi reapelăm predicatul pentru termenii X n−1 şiX n şi N-1. Condiţia de oprire este dată de N=0, moment în care se va unifica
variabila liberă F cu valoarea calculată în N1.
2.5.2 Apel
?- fibo_tur(4,R).
R = 2
152
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 153/183
2.5.3 Cod Sursă
fibo_tur(N, F) :-
N1 is N - 2,
fibo_tur(0, 1, N1, F).
fibo_tur(_N0, N1, 0, N1).
fibo_tur(N0, N1, N, F) :-
N > 0,
N2 is N0 + N1,
M is N - 1,
fibo_tur(N1, N2, M, F).
2.6 Liste
Rezolvarea 2.6.1.
Scrieţi un program prolog care simulează pe liste reuniunea, intersecţia, dife-
renţa şi diferenţa simetrică pentru mulţimi.
2.6.1 Soluţie teoretică
Reuniune va fi un predicat recursiv structurat pe cazuri. Cazul în care un
element din prima listă este membru în a doua listă predicatul va face cut şi
se va reapela pentru coada primei liste şi lista a doua. Dacă elementul nu
153
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 154/183
este membru în a doua listă atunci el va fi introdus (la revenirea din apelurile
succesive) în lista rezultat. Oprirea apelurilor se va face atunci când în prima
listă nu mai sunt elemente, tot atunci se va unifica lista secundă cu lista rezul-tat, pe retur vor fi adăugate la lista rezultat elementele pentru care predicatul
member/2 a întors fail .
Intersecţia va funcţiona aproximativ pe acelaşi principiu cu diferenţa că ele-
mentele care sunt comune vor fi adăugate la lista rezultat, pe retur, în cadrul
primei clauze.
În cazul diferenţei la lista rezultat elementele se adaugă pe retur în cadrul
primei clauze dacă elementele din prima listă nu se găsesc şi în a doua listă.Diferenţa simetrică face uz de predicatele deja definite şi se bazează pe definiţia
matematică a acestei relaţii.
2.6.2 Apel
?- diferenta([1,5,3,8,6],[4,5,10,7,6],Rezultat).
Rezultat = [1, 3, 8]Yes
?- diferenta_simetrica([1,5,3,8,6],[4,5,10,7,6],Rezultat).
Rezultat = [1, 3, 8, 4, 10, 7]
Yes
?- reuniune([1,5,3,8,6],[4,5,10,7,6],Rezultat).
Rezultat = [1, 3, 8, 4, 5, 10, 7, 6]
Yes
154
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 155/183
?- intersectie([1,5,3,8,6],[4,5,10,7,6],Rezultat).
Rezultat = [5, 6]
Yes
2.6.3 Cod sursă
Codul sursă al programului de mai jos se găseşte în fişierul L6r1.pl
reuniune([],B,B).
reuniune([X|A],B,C):-
member(X,B),!,reuniune(A,B,C).
reuniune([X|A],B,[X|C]):- reuniune(A,B,C).
intersectie([X|Y],B,Z):-
member(X,B),!,
intersectie(Y,B,Z).
intersectie([_|A],B,C):- intersectie(A,B,C).
intersectie([],_,[]).diferenta(A,[],A):-!.
diferenta([X|A],B,[X|C]):-
not(member(X,B)),!,
dif(A,B,C).
diferenta([_|A],B,C):- diferenta(A,B,C).
diferenta([],_,[]).
diferenta_simetrica(A,B,C):-
155
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 156/183
diferenta(A,B,X),
diferenta(B,A,Y),
reuniune(X,Y,C).
2.7 Probleme speciale
Rezolvarea 2.7.1.
O firmă de cartografie urmăreşte să coloreze o hartă a N tări cu M culori
în aşa fel încât două ţări vecine să nu fie colorate cu aceeaşi culoare. Scrieţi
un program Prolog care să afişeze toate soluţiile posibile pentru N şi M date.
2.7.1 Soluţie teoretică
Predicatul coloreaza(-Lista) returnează o listă de termeni de forma
Tara/Culoare unde Tara este numele unei ţări şi Culoare este culoarea co-
respunzătoare pe hartă a acelei ţări. El apelează setof/3 pentru a construi o
listă de termeni de forma Tara/Var unde - Tara este numele ţării şi Var esteo variabilă, foloseşte apoi culori/2 pentru a lega fiecare variabilă Var de o cu-
loare.
Predicatul culori întoarce "Yes" atunci când , dându-i-se o listă de elemente
de forma Tara/Culoare, se poate găsi o valoare pentru Culoare în aşa fel încât
Tara careia îi este ataşată Culoare nu are ţări vecine de aceeaşi culoare. Pentru
o listă cu Tara/Culoare fiind capul listei şi coada Rest, colorează Rest şi apoi
selectează o valoare pentru Culoare din lista de culori apoi verifică daca există
156
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 157/183
o altă ţară în Rest care să fie colorată cu aceeaşi culoare cu cea selectată. Daca
nu mai sunt elemente în listă atunci întoarce "Yes".
Predicatul tari_vecine(Tara, Tara1) verifică dacă Tara1 este vecină cu Tara,iar lista_vecini/2 este un predicat folosit pentru a reţine în baza de fapte ceva
asemănător unei matrici de adiacenţă.
2.7.2 Apel
?- coloreaza(X).
X=[austria/rosu,belgia/verde,danemarca/albastru,franta/rosu,
italia/galben,olanda/albastru,portugalia/albastru,
spania/galben,elvetia/albastru,germania/galben]
2.7.3 Cod sursă
Codul sursă prezentat se găseşte în fişierul L11r1.pl
coloreaza(Culoare):-
setof(Tara_, X ^lista_vecini(Tara,X), Culoare),culori(Culoare).
culori([]).
culori([Tara/Culoare|Rest]):-
culori(Rest),
member(Culoare, [galben,albastru,rosu,verde]),
\+ (member(Tara1/Culoare, Rest), tari_vecine(Tara, Tara1)).
tari_vecine(Tara, Tara1):-
157
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 158/183
lista_vecini(Tara, Vecini),
member(Tara1, Vecini).
% Reprezentarea vecinilor fiecărei ţărilista_vecini(portugalia, [spania]).
lista_vecini(spania, [portugalia,franta]).
lista_vecini(franta, [spania,belgia,elvetia,germania,italia]).
lista_vecini(belgia, [franta,germania,olanda]).
lista_vecini(olanda, [belgia,germania]).
lista_vecini(germania, [olanda,belgia,franta,elvetia,austria,danemarca]).
lista_vecini(elvetia, [franta,germania,austria,italia]).lista_vecini(austria, [germania,elvetia,italia]).
lista_vecini(italia, [franta,elvetia,austria]).
lista_vecini(danemarca, [germania]).
2.8 Fişiere. Baze de date dinamice
Rezolvarea 2.8.1.
Scrieţi un program Prolog care citeşte de la tastatură informaţii de forma
persoana(nume(NumePrenume),telefon(NrTel)). le introduce în baza de date
dinamică şi le salvează într-un fişier specificat de utilizator, care mai apoi poate
fi citit şi încărcăt în baza de date dinamică.
158
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 159/183
2.8.1 Soluţia problemei 0.9.1
2.8.1.1 Soluţie teoretică
Citirea de la tastatură se face prin intermediul predicatului sistem read/1.
Citim informaţiile necesare şi folosim predicatul sistem assert/1 pentru a in-
troduce tuplul de forma dorită în baza de date dinamică. Pentru a salva datele
trebuie mai întâi să le recuperăm din baza de date dinamică, apelam predicatul
persoana(nume(NumePrenume),telefon(NrTel)). care se va apela pentru toate
persoanele introduse în baza de date dinamică, ne asigurăm de acest lucru
folosind predicatul sistem fail/0 pentru a cauza backtrackingul. Încărcareafişierului presupune citirea de la tastatură a numelui şi utilizarea predicatului
sistem consult/1 care va încărca toate clauzele predicatului persoana/2 salvate
în fişier. Afişarea foloseşte predicatul sistem listing/1 deoarece în urma unui
apel de forma listing. vom primi ca răspuns din partea sistemului o listă cu
toate predicatele compilate de sistem, listing(persoana). va lista numai predi-
catele persoana .
2.8.1.2 Apel
1 ?- adaug.
Nume: ionescu.
Telefon:123456.
mai adaugati?(y/n)y.
Nume: popescu.
Telefon:654321.
159
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 160/183
mai adaugati?(y/n)n.
Yes
2 ?- afisare.
:- dynamic persoana/2.
persoana(nume(ionescu), telefon(123456)).
persoana(nume(popescu), telefon(654321)).
Yes
3 ?- salvez_fisier.Fisier:agenda.
Yes
4 ?- deschid_fisier.
Fisier:agenda.
% agenda.dat compiled 0.00 sec, 676 bytes
Yes
5 ?- afisare.
persoana(nume(ionescu), telefon(123456)).
persoana(nume(popescu), telefon(654321)).
Yes
160
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 161/183
2.8.1.3 Cod sursă
sterg :-deschide_fisier,
prel,
st,
salvez_in_fisier.
deschid_fisier :-
write(’Fisier:’),
read(A),concat_atom([A, ’.dat’], B),
incarc(B).
prel :-
persoana(nume(A), telefon(B)),
fail.
prel.
incarc(A) :-exists_file(B),
consult(A).
incarc(A).
adaug :-
write(’Nume: ’),
read(A),
write(’Telefon:’),
161
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 162/183
read(B),
assert(persoana(nume(A), telefon(B))),
write(’mai adaugati?(y/n)’),read(C),
C=y,
adaug.
adaug.
salvez :-
persoana(nume(A), telefon(B)),
write(persoana(nume(A), telefon(B))),write_ln(’.’),
fail.
salvez.
salvez_fisier :-
write(’Fisier:’),
read(A),
concat_atom([A, ’.dat’], B),tell(B),
salvez,
told.
st :-
write(’Nume: ’),
read(A),
162
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 163/183
retract(persoana(nume(A), telefon(B))).
afisare :-
listing(persoana).
Rezolvarea 2.8.2.
Modificaţi programul de mai sus referitor la baze de date dinamice astfel
încât să nu se adauge de mai multe ori acelaşi fapt în baza de date.
2.8.2 Soluţia problemei 0.9.2
2.8.2.1 Soluţie teoretică
Ideea de rezolvare este simplă: înainte de a insera în baza de date verifi-
căm dacă există deja faptul respectiv , astfel adăugăm clauza adauga(X,Y):-
are(X,Y). care va întoarce yes dacă există deja un fapt în baza de date şi nu se
va mai încerca resatisfacerea celorlalte clauze. Pentru predicatul par/1 adop-
tăm aceeaşi metodă adauga(X,Y):- par(Y),par(X)., dacă există deja clauze în
baza de date nu se vor mai introduce altele pentru aceleaşi valori.
2.8.2.2 Apel
?- apel.
Continuati?(da/nu)d.
X=6.
Y=3.
Continuati?(da/nu)d.
163
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 164/183
X=6.
Y=2.
Continuati?(da/nu)d.X=6.
Y=2.
Continuati?(da/nu)n.
În urma unei comenzi listing. putem să observăm predicatele introduse în
baza de date dinamică:
:- dynamic par/1.par(2).
par(6).
:- dynamic are/2.
are(4, 2).
are(6, 3).
are(6, 2).
2.8.2.3 Cod sursă
start:-
write(’X=’),read(X),write(’Y=’),read(Y),
M is X mod Y,M=0,
adauga(X,Y),go.
164
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 165/183
adauga(X,Y):- are(X,Y).
adauga(X,Y):- par(Y),par(X).
adauga(X,Y):- assertz(are(X,Y)),fail.adauga(X,Y):- par(Y),assertz(par(X)).
adauga(_,_).
go:- write(’Continuati?(da/nu)’),read(R),R=’d’,start.
% go:- retract(are(_,_)),fail.
% go:- retract(par(_)),fail.
go.
apel:- asserta(par(2)),asserta(are(4,2)),go.% introducem faptele par(2) şi are(4,2) pentru a avea o definiţie pentru aceste
predicate în baza de date.
165
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 166/183
166
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 167/183
Capitolul 3
Anexa Predicate
167
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 168/183
3.1 Anexa predicate
3.1.1 Notaţiile predicatelorNumele predicatului este scris cu text îngroşat şi este urmat de paranteze, iar
între paranteze lista de argumente. Argumentele al căror nume este precedat
de "+" , "-" sau "?" denotă faptul că argumentul care începe cu "+" este
parametru de intrare , cel cu "-" este parametru de ieşire, cele cu "?" sunt
parametri care pot fi fie de intrare , fie de ieşire.
3.1.2 Încărcarea fişierelor sursă
Un fişier PROLOG conţine clauze şi directive, el este încărcat de obicei folosind
predicatele:
consult(+Fisier) Citeşte Fisier ca sursă PROLOG. Fisier poate fi o listă de
fişiere caz în care , fiecare va fi consultat pe rând.
?- consult(fisier). % încarcă fişier sau fisier.pl dacă se găseşte în directorul
curent.
ensure_loaded(+Fisier) Dacă fişierul nu este deja încărcat, acest predicat
este echivalent cu consult/1.
3.1.3 Compararea şi unificarea termenilor
Termenii sunt ordonaţi în ceea ce se cheama ordine standard , această ordine
este definită după cum urmează:
1. Variabile <Atomi <Şiruri de caractere <Numere <Termeni
168
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 169/183
2. Variabilă veche < Variabilă nouă
3. Atomii sunt comparaţi alfabetic.
4. Şirurile de caractere sunt comparate alfabetic.5. Numerele sunt comparate după valoare, numerele întregi şi cele în virgulă
mobilă sunt tratate identic.
6. Termenii compuşi sunt verificaţi mai întâi după aritatea lor, apoi după nu-
mele functorului şi la final după argumente, începând de la cel mai din stânga.
+Term1 == +Term2 Întoarce Yes dacă Term1 şi Term2 sunt echivalenţi.
+Term1 \ == +Term2 Echivalent cu \ +Term1 == Term2.
+Term1 = +Term2 Unifică pe Term1 cu Term2 şi întoarce Yes dacă unifi-carea reuşeşte.
3.1.4 Predicate de control
fail Întoarce fail în toate ocaziile.
true Întoarce Yes în toate ocaziile.
repeat Întoarce Yes pentru a oferi un număr infinit de puncte de alegere.! Cut. Renunţă la a mai căuta soluţii pentru alte valori are unor variabile.
+Scop1 , +Scop2 Conjuncţie. Întoarce Yes dacă Scop1 şi Scop2 pot fi
demonstrate.
+Scop1 ; +Scop2 Disjuncţie. Întoarce Yes dacă Scop1 sau Scop2 poate fi
demonstrat.
\+ +Scop Întoarce Yes dacă Scop nu poate fi demonstrat. + referă ceva
demonstrabil, iar \ este folosit pentru a indica negaţia în PROLOG.
169
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 170/183
3.1.5 Baze de date dinamice
assert(+Term) Adaugă un fapt la baza de date ca ultim fapt sau clauză a
predicatului corespunzător.
asserta(+Term) Echivalent cu predicatul de mai sus, dar Term este adăugat
ca primă clauză sau fapt al unui predicat.
assertz(+Clause) Echivalent cu assert/1 .
retract(+Term) Atunci când Term este atom sau termen el este unificat cu
primul fapt sau prima clauză din baza de date , iar faptul sau clauza este şters
din baza de date.
retractall(+Head) Toate faptele sau clauzele cu care Head se poate unifica
sunt şterse din baza de date.
abolish(+PredSpec) Şterge toate predicatele specificate de PredSpec, unde
PredSpec este de forma Predicat/Aritate. Tot ce are legătură cu predicatul
specificat este şters din sistem.
3.1.6 Intrări şi Ieşiri
3.1.6.1 Stilul ISO
open(+SrcDest, +Mode, -Stream, +Optiuni) SrcDest poate fi un fişier, ter-
minalul sau un termen, Mode poate fi read, write, append sau update, Stream
poate fi, fie o variabilă care la final va conţine identificatorul de stream, fie un
atom şi în cazul acesta atomul va fi identificatorul de stream. Optiuni pate fi :
- type(Type) se foloseşte pentru a putea scrie în mod text, compatibil cu sis-
170
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 171/183
temul de operare. Dacă se foloseşte tipul binar octeţii vor fi scrişi fără a fi
traduşi. De menţionat că pe sistemele Unix nu se face diferenţă între modul
text şi binar.- alias(Atom) dă unui stream un nume. Atenţie la această opţiune deoarece
numele de stream-uri sunt globale. Exemplu:
?- open(data, read, Fd, [alias(input)]). , ...,read(input, Term),...
- eof_action(Action) defineşte ce se întamplă în momentul în care se ajunge
la final de fişier
- buffer(Buffering) defineşte posibilitatea de a avea un buffer.
- close_on_abort(Bool) închide stream-ul dacă în timpul execuţiei programu-lui se apelează predicatul abort/0.
- lock(LockingMode) încearcă să blocheze fişierul pentru ca alte procese să nu
îl modifice în timpul execuţiei programului PROLOG. În mod implicit fişierul
nu va fi blocat , însă locking mode poate fi read sau shared, adica alte pro-
cese(programe) pot accesa fişierul numai pentru citire.
open(+SrcDest, +Mode, ?Stream) Este echivalent cu open/4 cu lista de op-
ţiuni vidă.open_null_stream(?Stream) Deschide un stream vid. Toate funcţiile sunt
active pentru un asemenea stream, dar o încercare de a citi de pe un astfel de
stream returnează end_of_file.
close(+Stream) Închide stream-ul specificat. Dacă acest stream este stream-
ul curent pentru intrare/ieşire atunci terminalul devine stream curent pentru
intrare/ieşire.
171
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 172/183
set_stream(+Stream, +Attribute) Setează stream-ului atributele prezentate
mai sus la predicatul open.
Alte predicate utile
character_count(+Stream, -Numar) Unifică Număr cu indexul curent al ca-
racterului. Pentru stream-urile de intrare acest index este numărul caracterelor
citite de când a fost deschis stream-ul, iar pentru cele de ieşire numărul carac-
terelor scrise. Primul caracter va avea indexul 0.
line_count(+Stream, -Numar) Unifică Numar cu numărul liniilor citite sau
scrise pe Stream.
line_position(+Stream, -Numar) Unifică Numar cu poziţia de pe linia cu-rentă. Se presupune că poziţia este 0 după deschiderea stream-ului , tab-urile
se presupun a exista după fiecare al 8-lea caracter, iar backspace reduce din
Numar o unitate, Numar fiind presupus a fi pozitiv.
3.1.6.2 Stilul Edinburgh
see(+SrcDest) Deschide SrcDest pentru citire şi îl face stream-ul curent deintrare.
tell(+SrcDest) Deschide SrcDest pentru scriere şi îl face să fie stream-ul curent
de ieşire.
append(+File) Similar cu tell/1, dar poziţionează pointerul de scriere la fina-
lul fişierului.
seeing(?SrcDest) şi telling(?SrcDest) Nu returnează numele fişierului deschis
pentru citire/scriere ci returnează indentificatorul de stream.
172
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 173/183
seen. Închide stream-ul curent de intrare.
told. Închide stream-ul curent de ieşire.
3.1.7 Predicate primitive pentru I/O
nl Trece pe linia următoare a stream-ului implicit.
nl(+Stream) Trece pe linia următoare a lui Stream.
put(+Char) Scrie un Char pe stream-ul curent. Char este un cod astfel încât
0=<Char=< 255
put(+Stream, +Char) Scrie Char pe Stream.put_byte(+Byte) Echivalent cu put/1.
put_byte(+Stream, +Byte) Echivalent cu put/2.
put_char(+Char) Echivalent cu put/1.
put_char(+Stream, +Char) Echivalent cu put/2.
put_code(+Code) Echivalent cu put/1.
put_code(+Stream, +Code) Echivalent cu put/2.
tab(+Numar) Scrie un Numar de tab-uri pe stream-ul implicit. Numar trebuiesă fie o expresie care se evaluează ca un întreg pozitiv.
tab(+Stream, +Numar) Scrie Numar de tab-uri pe Stream
flush_output Scrie output-ul pe stream-ul curent.
flush_output(+Stream) Scrie output-ul pe Stream.
get_byte(-Byte) Citeşte de pe stream-ul curent de intrare şi unifică următorul
octet cu Byte. Byte este un întreg între 1 şi 255 şi va fi unificat cu -1 când se
ajunge la final de fişier.
173
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 174/183
get_byte(+Stream, -Byte) Citeşte un octet de pe Stream
get_code(-Code) Asemănător cu get_byte/1.
get_code(+Stream, -Code) Asemănător cu get_byte/2.get_char(-Char) Asemănător cu get_byte/1.
get_char(+Stream, -Char) Asemănător cu get_byte/1.
get(-Char) Citeşte un caracter de pe stream-ul curent de intrare. Char va fi
diferit de caracterul vid şi va fi unificat cu -1 dacă se ajunge la final de fişier.
get(+Stream, -Char) Citeşte un Char de pe Stream.
3.1.8 Citirea şi scrierea termenilor
write(+Term) Scrie Term pe output-ul curent, se pot folosi paranteze şi ghi-
limele.
write(+Stream, +Term) Scrie Term pe Stream.
writeq(+Term) Scrie Term pe output-ul curent , atomii care au nevoie să fie
scrişi cu ghilimele vor fi scrişi în acest fel. Termenii scrişi cu acest predicat pot
fi citiţi cu read/1.writeq(+Stream, +Term) Scrie Term pe Stream şi inserează ghilimele.
print(+Term) Similar cu write/1 , însă acest predicat apelează portray/1
pentru fiecare sub-termen, iar dacă portray/1 întoarce Yes se presupune că
sub-termenul a fost scris. Este folosit pentru a scrie termeni definiţi de utili-
zator.
print(+Stream, +Term) Scrie Term pe Stream.
portray(+Term) Predicat dinamic care poate fi definit de utilizator pentru a
174
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 175/183
schimba felul în care se comportă print/1 .
read(-Term) Citeşte următorul termen PROLOG de pe stream-ul curent şi îl
unifică cu Term.read(+Stream, -Term) Citeşte Term de pe Stream.
3.1.9 Predicate pentru operaţii cu liste
is_list(+Term) Întoarce Yes dacă Term este lista vidă sau este legat de olistă.
memberchk(?Elem, +List) Echivalent cu member/2.
length(?Lista, ?Int) Întoarce în Int numărul elementelor din Lista. Poate fi
folosit pentru crearea unei liste ce conţine variabile neinstanţiate dacă variabila
Int este legată de o valoare întreagă mai mare sau egală cu 0. Dacă este 0 Lista
va fi o listă vidă.
sort(+Lista, -S) Întoarce Yes dacă S poate fi unificată cu o listă ce conţineelementele din Lista, sortate în mod standard. Dublurile vor fi eliminate.
msort(+List, -Sorted) Echivalent cu sort/2, dar nu elimină dublurile.
merge(+Lista1, +Lista2, -Lista3) Lista1 şi Lista2 sunt liste sortate în ordine
standard a termenilor. Lista3 va fi unificată cu o listă ordonată ce conţine
elementele din Lista1 şi Lista2.
merge_set(+Set1, +Set2, -Set3) Set3 va conţine elementele din Set1 şi Set2
cu dublurile eliminate.
175
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 176/183
3.1.10 Predicate aritmetice
between(+Min, +Max, ?Valoare) Min si Max si Valoare sunt numereîntregi. Dacă valoare este instanţiată predicatul întoarce Yes dacă
Min=<Valoare=<Max. Dacă Valoare este o variabiă liberă este legată succe-
siv de toate valorile întregi dinte Min şi Max.
succ(?Int1, ?Int2) Întoarce Yes dacă Int2 poate fi legat de o valoare egală cu
Int1+1 sau Int2 se evaluează ca fiind echivalent cu Int1+1.
plus(?Int1, ?Int2, ?Int3) Întoarce Yes dacă Int3= Int1+Int2 , cel puţin 2 ar-
gumente trebuie intstanţiate.+Expr1 > +Expr2 Întoarce Yes atunci când Expr1 se evaluează cu un nu-
măr mai mare decât Expr2.
+Expr1 < +Expr2 Întoarce Yes atunci când Expr1 se evaluează cu un nu-
măr mai mic decât Expr2.
+Expr1 =< +Expr2 Întoarce Yes atunci când Expr1 se evaluează cu un
număr mai mic sau egal cu Expr2.
+Expr1 >= +Expr2 Întoarce Yes atunci când Expr1 se evaluează cu unnumăr mai mare sau egal cu Expr2.
+Expr1 =\= +Expr2 Întoarce Yes atunci când Expr1 se evaluează cu un
număr care nu este egal cu Expr2.
+Expr1 =:= +Expr2 Întoarce Yes atunci când Expr1 se evaluează cu un
număr care este egal cu Expr2.
-Numar is +Expr Întoarce Yes când Numar a fost unificat cu numărul cu
care se evaluează Expr.
176
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 177/183
?- 1.0 is sin(pi/2). Întoarce No, deoarece sin(pi/2) întoarce 1.0 dat is va
reprezenta ca 1 valoare întreagă, iar după unificare va întoarce fail.
?- 1.0 is float(sin(pi/2)). Întoarce Yes deoarece predicatul float forţeazărezultatul să fie float.
?- 1.0 =:= sin(pi/2). Întoarce Yes deoarece predicatul =:= consideră ambii
termeni ca fiind expresii.
3.1.11 Funcţii aritmetice
+IntExpr1 mod +IntExpr2 Împărtire modulo.+IntExpr1 rem +IntExpr2 Restul împărţirii ca număr real.
abs(+Expr) Modulul expresiei Expr.
sign(+Expr) Semnul lui Expr, se evaluează ca fiind -1 dacă Expr<0 , 1 dacă
Expr>0 şi 0 daca Expr=0.
max(+Expr1, +Expr2) Evaluează cel mai mare număr din cele două.
min(+Expr1, +Expr2) Evaluează cel mai mic număr din cele două.
random(+Int) Se evaluează ca fiind un număr întreg i pentru care 0=<i<Int.round(+Expr) Evaluează Expr si rotunjeşte rezultatul.
integer(+Expr) Asemănător cu round/1.
float(+Expr) Se evaluează ca un număr în virgulă mobilă, în mod normal
PROLOG-ul utilizează pe cât posibil valori întregi. Dacă este folosită în
combinaţie cu predicatul is/2 ca al doilea argument returnează un număr în
virgulă mobilă. În alte contexte operaţia nu are efect.
float_fractional_part(+Expr) Se evaluează ca fiind partea fracţională
177
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 178/183
a unui număr în virgulă mobilă. Întoarce 0 dacă Expr este număr întreg,
negativ dacă Expr este negativ.
float_integer_part(+Expr) Se evaluează ca fiind partea întreagă a unuinumăr în virgulă mobilă. Întoarce Expr dacă Expr este număr întreg, negativ
dacă Expr este negativ.
truncate(+Expr) Trunchiază expresia Expr , asemănător cu
float_integer_part/1.
floor(+Expr) Evaluează Expr şi returnează cel mai mare întreg mai mic sau
egal cu rezultatul evaluării expresiei Expr.
ceiling(+Expr) Evaluează Expr şi returnează cel mai mic întreg mai maresau egal cu rezultatul evaluării expresiei Expr.
ceil(+Expr) Asemănător cu ceiling/1.
+IntExpr » +IntExpr Deplasare la dreapta pe biţi.
+IntExpr « +IntExpr Deplasare la stânga pe biţi.
+IntExpr \/ +IntExpr Operaţia "sau" pe biti.
+IntExpr /\ +IntExpr Operaţia "şi" pe biti.
+IntExpr xor +IntExpr Operaţia "sau exclusiv" pe biti.\ +IntExpr Negaţie pe biţi.
sqrt(+Expr) Radicalul expresiei Expr.
sin(+Expr) Sinusul expresiei Expr.
cos(+Expr) Cosinusul expresiei Expr.
tan(+Expr) Tangenta expresiei Expr.
asin(+Expr) Arcsinusul expresiei Expr.
178
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 179/183
acos(+Expr) Arccosinusul expresiei Expr.
atan(+Expr) Arctangenta expresiei Expr.
log(+Expr) Întoarce logaritmul natural al expresiei Expr.log10(+Expr) Întoarce logaritmul în baza 10 al expresiei Expr.
exp(+Expr) Întoarce e la puterea Expr.
+Expr1 ** +Expr2 Întoarce Expr1 la puterea Expr2.
+Expr1 ^+Expr2 Identic cu **/2.
pi Constanta matematică pi (3.141593).
e Constanta matematică e (2.718282).
3.1.12 Urmărirea execuţiei programului
trace Porneşte urmărirea programului.
tracing Întoarce Yes atunci când trace este activ.
notrace Opreşte trace-ul.
guitracer Instalează puncte cheie în program pentru a putea fi urmărit
trace-ul pe o interfaţă grafică.noguitracer Contrarul lui guitracer.
trace(+Pred) Echivalent cu trace(Pred, +all).
trace(+Pred, +Ports) Urmăreşte predicatul Pred pentru porturile specificate,
porturile valide sunt: call, redo, exit, fail.
notrace(+Scop) Apelează Scop dar suspendă debugger-ul cât timp se execută
Scop.
debug Porneşte debugger-ul.
179
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 180/183
nodebug Opreşte debugger-ul.
debugging Afişează informaţii despre starea debugger-ului.
180
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 181/183
Glosar
ţintă, 36
ţintă vidă, 36
abordare
descriptivă, 93
imperativă, 93
Ackermann, 147
algoritmi de unificare, 58
aritate, 24
backtracking, 115
baza Herbrand, 48
capul clauzei, 35cel mai general unificator, 59
clauză, 34
clauză definită, 36
clauză Horn, 36
clauză unitară, 36
clauză vidă, 34
clauza de bază, 127
clauza recursivă, 127
comentariu PROLOG, 114
comenzi SWI-Prolog, 98
conectori logici, 22
consecinţă logică, 39control, 92
corpul clauzei, 35
cuantificator existenţial, 23
cuantificator universal, 23
cut, 128
rectificată, 69
domeniu nevid, 31
echivalenţă logică, 40
fail, 128
familia formulelor, 26
fapt, 36
fapte PROLOG, 96
Fibonacci, 146
181
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 182/183
Forma Normală Prenex, 42
Forma Normală Skolem, 45
format relaţional, 71formulă, 25
formulă închisă, 26
formulă atomică, 25
formulă derivabilă, 41
formulă prenex, 42
graf de dependenţă, 71
guitracer, 112
inferenţă, 41
interogări PROLOG, 95
interpretare, 31
interpretare Herbrand, 48
Legea lui DeMorgan, 40
liste PROLOG, 151
literal, 34
Loewenheim-Skolem, 45
logică, 92
model, 76
model Herbrand, 49
model minimal, 76
predicat extensional, 72
predicat intensional, 72
predicatul cut, 128predicatul fail, 128
predicatul read, 113
predicatul write, 113
program DATALOG, 66
program definit, 37
program logic, 37
program rectificat, 69program recursiv, 72
rangul unei formule, 27
recursivitate, 127
regulă consistentă, 41
regulă PROLOG, 97
regulile de inferenţă, 41
rezolvent, 54
scop, 36
scopuri PROLOG, 95
simboluri, 22
simboluri funcţionale, 24
simboluri predicative, 22
SLD-arbore, 54
182
5/10/2018 Inteligenta Artificial A Curs - slidepdf.com
http://slidepdf.com/reader/full/inteligenta-artificial-a-curs 183/183
subformulă, 25
substituţie, 27
subtermen, 25
termen, 24
termen de bază, 26
termen ground, 26
termeni PROLOG, 106
trace, 111
transformare în forma prenex, 43
turnurile din Hanoi, 143
unificarea variabilelor, 119
unificatori, 58
univers Herbrand, 47
variabilă, 21
variabilă legată, 26
variabile anonime, 108
variabile limitate, 65
183