Sunteți pe pagina 1din 10

Inteligenţă Artificială – PROLOG Lucrarea de laborator nr.

Aritmetica, comparaţii

Expresii aritmetice

Expresiile aritmetice constau din operanzi (constante numerice şi variabile), operatori (+, -, *, /, div şi
mod) şi paranteze. Simbolurile din partea dreaptă a semnului = ( care este predicatul = ) de mai jos
formează o expresie aritmetică:

A = 1 + 6 / (11 + 3) * Z

Valoarea unei expresii poate fi calculată dacă toate variabilele sunt legate la momentul evaluării.

Calculele se fac într-o anumită ordine determinată de prioritatea operatorilor aritmetici: operatorii cu
cea mai mare prioritate sunt evaluaţi primii.

Operaţii aritmetice

Tipul rezultatului unei operaţii aritmetice este dat de urmatorul tabel:

Operand1 Operator Operand2 Rezultat


întreg +,-,* întreg întreg
real +,-,* întreg real
întreg +,-,* real real
real +,-,* real real
întreg,real / întreg,real real
întreg div întreg întreg
întreg mod întreg întreg

Ordinea evaluării
1. Subexpresiile din paranteze se evaluează primele.
2. Apoi, se execută înmulţirile (*) sau împărţirile (/, div, mod), lucrând de la stânga la dreapta.
3. Apoi se execută adunările (+) şi scăderile (-), lucrând de la stânga la dreapta.

Funcţii şi predicate

Funcţii Explicaţie
X mod Y restul împărţirii lui X la Y
X div Y câtul împărţirii lui X la Y
abs(X) valoarea absolută a lui X

cos(X), sin(X) , tan(X) funcţiile trigonometrice cer ca X să fie legat de o valoare


reprezentând unghiul în radiani

arctan(X) arctangenta valorii reale de care e legata X


exp(X e la puterea X
ln(X) logaritm din X, în baza e
log(X) logaritm din X, în baza 10

1
Inteligenţă Artificială – PROLOG Lucrarea de laborator nr. 3

sqrt(X) rădăcina pătrată a lui X


random(X) leagă X de o valoare reală aleatoare, 0 <= X < 1
random(X, Y) leagă Y de o valoare întreagă aleatoare, 0 <= Y < X
round(X) întoarce valoarea rotunjită a lui X
trunc(X) întoarce valoarea trunchiată a lui X

Întrebare: Ce returnează scopul t(X) ?

predicates
t(real)
clauses
t(X):- X = 9.0 / 3.0.

Operaţii pe biţi:

Operaţii pe biţi Explicaţie


bitand(X,Y,Z) "si bit cu bit" intre bitii cuvintelor X si Y
bitor(X,Y,Z) "sau bit cu bit" " "

bitnot(X,Z) "negarea lui X"

bitxor(X,Y,Z) "sau exclusiv" intre X si Y


bitleft(X,N,Z) deplasare cu N pozitii la stanga
bitright(X,N,Z)= deplasare cu N pozitii la dreapta

Observaţii
- rezultatul este întotdeauna depus în Z care este un întreg;
- în momentul executării unei operaţii pe biţi, variabilele X şi Y trebuie să fie legate.

Comparaţii

T.Pro. poate compara expresii aritmetice, caractere, string-uri şi simboluri.

În T.Pro. se foloseşte notaţia înfix, ceea ce înseamnă că operatorii sunt plasaţi între operanzi (ex: X < 4)
şi nu înaintea lor (ex: <(X, 4)).

Iată operatorii relaţionali permişi în T.Pro.:

< mai mic


<= mai mic sau egal
> mai mare
<= mai mare sau egal
= egal
<>, ><diferit (neegal)

2
Inteligenţă Artificială – PROLOG Lucrarea de laborator nr. 3

Egalitate şi predicatul egal ( = )

În T.Pro. propoziţii precum N = N1 - 2 indică fie o relaţie între trei obiecte (N, N1, 2) fie o relaţie între
două obiecte (N şi valoarea N1 - 2).

Dacă N este variabila liberă, propoziţia este satisfăcută legând pe N de rezultatul evaluării N1 - 2.
Aceasta corespunde unei instrucţiuni de atribuire din limbajele de programare.

Dacă N este o variabilă legată, atunci propoziţia este satisfacută dacă relaţia de egalitate are loc.

De remarcat că în ambele situaţii variabila N1 trebuie să fie legată.

Să considerăm exemplele următoare:

1. predicates
plus(integer,integer,integer)
minus(integer,integer,integer)
less_than(integer,integer)
clauses
plus(X,7,Z):-Z=X+7.
minus(9,Y,W):-W=9-Y.
less_than(X,Y):-plus(X,7,Z),minus(9,Y,W),Z<W.

Verifcaţi cazurile: - less_than(10,4) Răspuns: No


- less_than(1,0) Răspuns: Yes

2. Un exemplu clasic de utilizare a "aritmeticii" este rezolvarea ecuaţiei de gradul II:

predicates
soluţie(real,real,real)
unu(real,real,real)
doi(real,real,real)
radical(real,real)
clauses
soluţie(A,B,C):-A<>0,
D=B*B-4*A*C,doi(A,B,D),nl,!.
soluţie(A,B,C):-unu(A,B,C),nl,!.
doi(A,B,D):-D>=0,
radical(D,Rad),
X1=(-B+Rad)/(2*A),
X2=(-B-Rad)/(2*A),
write("X1=",X1," X2=",X2).
doi(A,B,D):- D1=-D,
radical(D1,Rad),
X1=-B/(2*A), X2=Rad/(2*A),
write("Soluţii complex conjugate, Partea Reală=", X1,"\n"," Coeficienţii Părţii
Imaginare=",X2),nl,!.
unu(_,B,C):-B<>0, X=-C/B,
write("Ecuaţia este de gradul I. X=",X),nl,!.
unu(_,_,C):-C=0,
write("Ecuaţie nedeterminată!"),nl,!.
3
Inteligenţă Artificială – PROLOG Lucrarea de laborator nr. 3

unu(_,_,_):- write("Ecuaţie imposibilă!"),nl.


radical(D,Rad):-Rad=sqrt(D).

Compararea caracterelor, string-urilor şi symbol-urilor

Caractere

Când T.Pro. compară

'a' < 'b'

el converteşte această expresie la expresia artimetică echivalentă 97 < 98, folosind codurile ASCII ale
caracterelor de comparat.

String-uri

Comparaţia

"antony" > "antonia"

se evaluează la adevărat, deoarece cele două string-uri diferă prima oară la poziţia unde primul conţine
litera y (79 ASCII) iar al doilea conţine litera i (69 ASCII).

În aceeasi logică,

"aa" > "a"

este adevărat.

Simboluri

Simbolurile nu pot fi comparate direct, din motive de sintaxă. Ele trebuie să fie mai întâi legate de
variabile:

P1 = peter, P2 = sally, P1 > P2

Tema

Utilizând operaţiile şi funcţiile aritmetice să se construiască o problemă care simulează un joc cu zaruri.

4
Inteligenţă Artificială – PROLOG Lucrarea de laborator nr. 3

Backtracking, Predicatele CUT şi FAIL

Backtracking

Fie programul următor:

domains
child = symbol
age = integer
predicates
player(child, age)
clauses
player(peter, 9).
player(paul, 10).
player(chris, 9).
player(susan, 9).

Dorim să aflăm toate perechile de copii în vârstă de 9 ani. Adresăm următoarea întrebare T.Pro.:

player(P1, 9),
player(P2, 9),
P1 <> P2.

Iată mecanismul prin care T.Pro. găseşte soluţiile:

1. T.Pro. găseşte soluţie la primul sub-goal, mergând de sus în jos: P1 va fi legat de peter
2. T.Pro. găseşte soluţie la al doilea subgoal: P2 va fi legat de peter.
3. T.Pro. încearcă să verifice al treilea subgoal: P1 si P2 sunt ambele legate de peter, deci eşec.
4. T.Pro. revine la al doilea subgoal. Următoarea soluţie: P2 e legat de chris.
5. T.Pro. verifică condiţia a treia: P1 si P2 sunt diferite, rezultă o soluţie:

P1=peter, P2=chris

6. T.Pro. revine la al doilea subgoal. Următoarea soluţie: P2 e legat de susan.


7. T.Pro. verifică condiţia a treia: P1 si P2 sunt diferite, rezultă o soluţie:

P1=peter, P2=susan

8. T.Pro. revine la al doilea subgoal, dar nu mai găseşte alte soluţii.


9. T.Pro. revine la primul subgoal. Următoarea soluţie: P1 e legat de chris.
10. T.Pro. trece la al doilea subgoal: P2 va fi legat de peter.
11. T.Pro. verifică condiţia a treia: P1 si P2 sunt diferite, rezultă o soluţie:

P1=chris, P2=peter

Ş.a.m.d. În final, T.Pro. găseşte şase soluţii:

P1=peter, P2=chris
P1=peter, P2=susan
P1=chris, P2=peter
P1=chris, P2=susan
P1=susan, P2=peter
5
Inteligenţă Artificială – PROLOG Lucrarea de laborator nr. 3

P1=susan, P2=chris
6 Solutions

Notă
T.Pro. a găsit soluţii redundante. Mecanismul backtracking face de data aceasta cautare nenecesară.

Pentru alterarea mecanismului backtracking, T.Pro. oferă doua predicate:

- fail, care forţează backtracking-ul;


- ! (cut, taietura), care împiedică backtracking-ul.

Utilizarea predicatului fail

Valoarea lui fail este eşec. Prin aceasta el încurajează backtracking-ul. Efectul lui este acelaşi cu al unui
predicat imposibil, de genul 2 = 3.

Exemplu:

domains
nume = symbol
predicates
tatăl(nume, nume)
oricine
oricine1
clauses
tatăl(gheorghe,maria).
tatăl(vasile,ion).
tatăl(vasile,elena).
oricine :-
tatăl(X, Y),
write(X, " este tatăl lui ", Y, "\n"),
fail.
oricine1 :-
tatăl(X, Y),
write(X, " este tatăl lui ", Y, "\n").

Răspunsul la întrebarea

oricine1.

va fi
gheorghe este tatăl lui maria
Yes

iar răspunsul la întrebarea

oricine

va fi

gheorghe este tatăl lui maria


vasile este tatăl lui ion

6
Inteligenţă Artificială – PROLOG Lucrarea de laborator nr. 3

vasile este tatăl lui elena


No

Faptul că apelul lui oricine se termină cu fail (care eşuează întotdeauna) obligă T.Pro. să înceapă
backtrackingul prin corpul regulii oricine. Prolog va reveni până la ultimul apel care poate oferi mai
multe soluţii. Un astfel de apel se numeşte apel nedeterminist. Predicatul write nu poate da alte soluţii,
deci revine la apelul lui tatăl.

Observatii:
1. Acel No semnifică faptul că predicatul oricine nu a fost satisfăcut.

2. După fail nu are rost să puneţi nici un predicat, deoarece Prolog nu va ajunge să-l execute
niciodată.

Notă
Secvenţa Pseudocod echivalentă cu predicatul oricine este:

cât timp tatăl(X, Y) are soluţii execută


write(...)

Deci, secvenţele următoare sunt echivalente

cat timp conditie predicat :-


executa conditie,
corp corp,
fail.

Utilizarea predicatului ! (cut)

T.Pro. conţine predicatul cut (!) folosit pentru a preveni backtracking-ul.

Când se procesează predicatul !, apelul reuşeşte imediat şi se trece la subgoalul următor. Odată ce s-a
trecut peste o tăietură, nu este posibilă revenirea la subgoal-urile plasate înaintea ei şi nu este posibil
backtrack-ul la alte reguli ce definesc predicatul în execuţie.

Există două utilizări importante ale tăieturii:


1. Când ştiţi dinainte că anumite posibilităţi nu vor duce la soluţii semnificative, este o pierdere
de timp să lăsaţi Prolog-ul să lucreze. În acest caz, tăietura se numeşte tăietură verde.

2. Când logica programului cere o tăietură, pentru prevenirea luării în consideraţie a subgoal-
urilor alternative. În acest caz, tăietura se numeşte tăietură roşie.

Prevenirea backtrack-ului la un subgoal anterior

Utilizare:
r1 :- a, b, !, c.

Aceasta este o modalitate de a spune că sunteţi mulţumiţi cu primele soluţii descoperite cu subgoal-
urile a şi b. Deşi T.Pro. ar putea găsi mai multe soluţii prin apelul la c, nu este autorizat să revină la a şi
b. Deasemenea,nu este autorizat să revină la altă clauză care defineşte predicatul r1.

7
Inteligenţă Artificială – PROLOG Lucrarea de laborator nr. 3

Prevenirea backtrack-ului la următoarea clauză

Tăietura poate fi utilizată pentru a-i spune T.Pro. că a ales corect clauza pentru un predicat particular.

De exemplu, fie codul următor:

r(1) :- !, a, b, c.
r(2) :- !, d.
r(3) :- !, e.
r(_) :- write(“Aici intră restul apelurilor”).

Folosirea “tăieturii” face predicatul r determinist. Aici, T.Pro. apelează predicatul r cu un argument
întreg. Să presupunem că apelul este r(1). T.Pro. caută o potrivire a apelului. O găseşte la prima clauză.
Faptul că imediat după intrarea în clauză urmează o tăietură, împiedică T.Pro. să mai caute şi alte
potriviri ale apelului r(1) (cu alte clauze).

Observaţie
Acest tip de structură este echivalent cu un case unde condiţia de test a fost inclusă în capul clauzei. La
fel de bine s-ar fi putut spune şi:

r(X) :- X = 1, !, a, b, c.
r(X) :- X = 2, !, d.
r(X) :- X = 3, !, e.
r(_) :- write(“Aici intră restul apelurilor”).

Note
1. Deci, următoarele secvenţe sunt echivalente:

case X of
v1: corp1; predicat(X) :- X = v1, !, corp1.
v2: corp2; predicat(X) :- X = v2, !, corp2.
... ...
else corp_else. predicat(X) :- corp_else.

2. De-asemenea, următoarele secvenţe sunt echivalente:

if cond1 then predicat(...) :-


corp1 cond1, !, corp1.
else if cond2 then predicat(...) :-
corp2 cond2, !, corp2.
... ...
else predicat(...) :-
corp_else. corp_else.

Tema

Rulaţi următorul program aşa cum este scris mai jos, iar apoi scoateţi “tăietura” (!) şi analizaţi
rezultatele obţinute.

domains
nume=symbol
predicates

8
Inteligenţă Artificială – PROLOG Lucrarea de laborator nr. 3

tatăl(nume,nume)
şef(nume,nume)
citeşte(nume)
oricine(nume,nume,nume,nume,nume)
clauses
tatăl(gheorghe,maria).
tatăl(vasile,ion).
citeşte(carte).
citeşte(ziar).
şef(ana,viorica).
şef(nae,nicu).
oricine(X,Y,Z,V,W):-tatăl(X,Y),citeşte(Z),!,şef(V,W).

Predicatul not

Sintaxa:
not(subgoal(Arg1, ..., ArgN))

Predicatul not reuşeşte atunci când subgoal-ul care este argument al lui not nu poate fi dovedit adevărat.

Dacă subgoal-ul este apelat cu variabile libere,T.Pro. va emite eroare: Variabilele libere nu sunt
autorizate în NOT.

De exemplu, fie secvenţa:

place(bill, Cineva) :-
place(sue, Cineva),
not(uraste(bill, Cineva)).

Acest enunţ este echivalent cu: lui Bill îi place de cineva dacă şi lui Sue îi place, şi dacă Bill nu îl
urăşte.

De observat că, la intrare, Cineva este liberă, dar la ieşirea din primul subgoal, Cineva este legat. Astfel,
la intrarea în not, Cineva este legat, şi totul va funcţiona bine.

Dacă se inversează ordinea clauzelor, rezultatul nu va mai fi corect, deoarece la intrarea în not Cineva
va fi variabilă liberă. Folosirea variabilei anonime (_) în not în locul lui Cineva tot nu va rezolva
problema.

Direcţii de flux

În Prolog, legările de variabile se fac în două moduri: la intrarea în clauză sau la ieşirea din clauză.
Direcţia în care este trecută o valoare se numeşte 'direcţia de flux'. Când o variabilă este dată la intrarea
într-o clauză este un parametru de intrare (i), iar când o variabilă este dată la ieşirea dintr-o clauză este
un parametru de ieşire (o). O anumită clauză poate să aibă mai multe modele de flux.

Să analizăm aceste direcţii de flux pe exemplul cu factorial.

factorial(N,F)

9
Inteligenţă Artificială – PROLOG Lucrarea de laborator nr. 3

este predicatul care va calcula factorialul lui N poate avea următoarele direcţii de flux:

(i,i) - verifică dacă N!=F : factorial(3,6) --> Yes;


(i,o) - atribuie F:= N! : factorial(4,F) --> F=24;
(o,i) - găseşte acel N pt. care N! = F : pentru acest caz trebuie construit alt program;
(o,o) - ? situaţia este absurdă factorial(N,R), se obţine eroare de compilare.

Să regândim problema pentru cazul (o,i):

Varianta “clasică” pentru limbajele procedurale este:

i=2;
while(m mod i=0) do
begin
m:=m div i;
i:=i+1;
end;
if (m=1) then n:=i-1;

Varianta PROLOG este:

domains
n = real
f = integer
predicates
fact(f,f)
fact1(f,f,f)
clauses
fact(0,1).
fact(N,M) :- I=2, fact1(N,M,I).
fact1(N,M,I) :- M mod I = 0,
M1=M div I, I1=I+1,
fact1(N,M1,I1).
fact1(N,1,I):-N=I-1.

Temă

Scrieţi un predicat care rezolvă problema ridicării la putere:


power(X,Y,Z) unde Z = X la puterea Y.

10