Documente Academic
Documente Profesional
Documente Cultură
Utilizând structura de control a limbajului Prolog, se poate realiza foarte simplu sortarea unei
secvente de elemente utilizând metoda generare şi testare. Aceasta metodă de rezolvare a
problemelor, utilizata în inteligenta artificiala dar puţin potrivită pentru o sortare, are la baza
urmatoarea idee: o componenta generatoare construieste solutii candidate şi o a doua componenta,
componenta de testare, verifica fiecare solutie candidata pentru a vedea dacă este sau nu o solutie a
problemei. În acest fel se pot obtine fie toate solutiile problemei, fie una singura. Aceasta metoda
poate fi exprimata succint în Prolog astfel:
gaseste(Solutie) :-
genereaza(Solutie),
testeaza(Solutie).
Metoda este în general ineficienta chiar în cazul problemelor tipice de inteligenta artificiala
care necesita un proces de cautare a solutiei. Metoda este extrem de ineficienta în cazul rezolvarii
problemelor de sortare, pentru care exista algoritmi eficienti de rezolvare. Cu toate acestea, se
prezinta în continuare solutia de sortare în ordine crescatoare a unei liste de întregi prin metoda
generare şi testare ca exerciţiu Prolog.
% permut(+Lista, -PermutareLista)
permut([], []).
permut(Lista, [Prim | Rest]) :- elim(Prim, Lista, L), permut(L, Rest).
Se observa ca sortarea se face prin generarea permutarilor elementelor din lista şi verificarea
dacă o permutare generata este o secventa sortata. Componenta generatoare este predicatul
permut(Lista, ListaSortata) şi componenta de testare este predicatul ordonata(Lista). Desi
implementarea este simpla, exploatând facilitatile nedeterministe ale limbajului Prolog, ea este
foarte ineficienta.
Metoda de sortare prin insertie
Sortarea prin insertie a unei liste de elemente L = [H | T] se poate exprima recursiv astfel: se
sorteaza mai întâi lista T în TS si apoi se insereaza elementul H în lista TS acolo unde îi este locul
conform relatiei de ordine rel(X, Y).
Predicatul cut folosit în definirea predicatului insereaza este un cut verde. Se poate rescrie
predicatul insereaza folosind un cut rosu astfel:
A doua varianta de sortare prin insertie este urmatoarea: Lista poate fi privita la un moment
dat ca L' = PS::PN, unde PS este partea sortata si PN = [X | T] este partea nesortata. Se ia primul
element X din PN si se insereaza în PS. Algoritmul porneste cu PS = [] si PN = L, si se opreste
când PN = [], în acel moment PS fiind chiar lista sortata. Se observa ca PS are rol de acumulator,
rezultatul final fiind întors în al treilea parametru (constructia rezultatului se face pe apelul
recursiv).
Arbori binari
Traversarea unui arbore binar, cu afisarea cheilor din noduri, se implementeaza în Prolog
foarte usor folosind facilitatile recursive ale limbajului. Predicatul rsd(Arbore) realizeaza afisarea
cheilor din Arbore în ordinea radacina-stânga-dreapta.
% rsd(+Arbore) - parcurge arborele binar Arbore
% în ordinea radacina-stânga-dreapta, afisând cheile arborelui
rsd(nil).
rsd(arb(Radacina, SubarboreStang, SubarboreDrept)) :-
write(Radacina), write(' '),
rsd(SubarboreStang),
rsd(SubarboreDrept).
Dacă se considera cazul arborilor binari de cautare (cu chei întregi), se pot defini trei
predicate: caut(Cheie, Arbore), de cautare a unei chei în arbore, care reuşeşte dacă cheia este în
arbore şi eşuează în caz contrar; inser(Cheie, Arbore, ArboreRez), de inserare a unei chei în
arbore, cu argumentele Cheie şi Arbore instantiate şi argumentul ArboreRez sintetizat de
program; si elim(Cheie, Arbore, ArboreRez), care sterge o cheie dintr-un arbore.
Prima clauza a predicatului caut reuşeşte dacă cheia este în arbore. Pentru a impiedica o
posibila resatisfacere, deci gasirea unei alte aparitii a cheii de cautare în arbore, s-a introdus în acest
caz predicatul cut. Dacă se doreste, de exemplu, afisarea tuturor aparitiilor cheii de cautare în
arbore, se va elimina acest cut şi predicatul caut va avea atâtea solutii câte aparitii ale cheii de
cautare exista în arbore.
Predicatul de inserare a unei chei într-un arbore de cautare, inser, utilizeaza în definitie un cut
verde pentru cresterea eficientei. Se poate elimina conditia Cheie Radacina, din cea de a treia
regula a predicatului inser, caz în care predicatul cut se transforma într-un cut rosu. Programul
Prolog care urmeaza foloseste definitiile predicatelor caut şi inser pentru a implementa mai multe
operatii de prelucrare a arborilor binari de cautare.
Eliminarea unei chei dintr-un arbore binar de cautare se face dupa algoritmul standard:
% elim(+Cheie,+Arb,-ArbNou) elimina Cheie din Arb cu rezultat in ArbNou
elim(Cheie, nil, nil).
elim(Cheie, arb(Cheie, nil, nil), nil).
elim(Cheie, arb(Cheie, ArbStg, nil), ArbStg).
elim(Cheie, arb(Cheie, nil, ArbDr), ArbDr).
elim(Cheie, arb(Cheie, ArbStg, ArbDr), arb(Cheie1, Stg1, ArbDr)) :-
drept(ArbStg, Cheie1, Stg1).
elim(Cheie, arb(Cheie1, ArbStg, ArbDr), arb(Cheie1, ArbStg1, ArbDr1)) :-
(Cheie < Cheie1, !, elim(Cheie, ArbStg, ArbStg1), ArbDr1=ArbDr) ;
elim(Cheie, ArbDr, ArbDr1), ArbStg1=ArbStg.
% drept(+Arb,+Cheie,-SuccDr) - intoarce cel mai din dreapta succesor din
% subarborele stâng al nodului cu cheia Cheie in arborele Arb.
drept(arb(Cheie, ArbStg, nil), Cheie, ArbStg).
drept(arb(Cheie, ArbStg, ArbDr), Cheie1, arb(Cheie, ArbStg, ArbDr1)) :-
drept(ArbDr, Cheie1, ArbDr1).
Se poate defini un meniu de prelucrare arborilor binari de căutare care să permită execuţia
operaţiilor definite anterior, la cerere.
meniu(Arb):- nl,
write('1. Sfarsit'), nl,
write('2. Creeaza arbore'), nl,
write('3. Insereaza o cheie'), nl,
write('4. Cauta o cheie'), nl,
write('5. Sterge o cheie'), nl,
write('6. Afiseaza arbore'), nl,
read(Opt), Opt \= 1, !, actiune(Opt, Arb, ArbNou),
meniu(ArbNou).
meniu( _ ) :- write('Sfarsit'), nl.
creare(Arb, ArbNou) :-
write('Introduceti o cheie, 0 pentru terminare: '), read(Cheie), Cheie \= 0, !,
inser(Cheie, Arb, A), creare(A, ArbNou).
creare(Arb, Arb).
Probleme propuse
1. Scrieti un program Prolog care sa sorteze o lista prin metoda de sortare rapida (quicksort).
2. Scrieti un predicat de sortare a listelor care utilizeaza arbori binari de cautare. Predicatul
binsort(Lista, ListaSortata) sorteaza lista Lista în lista ListaSortata. El construieste un
arbore binar de cautare prin inserarea succesiva a elementelor din Lista cu ajutorul
predicatului inser prezentat anterior. ListaSortata se obtine prin parcurgerea în inordine a
arborelui obtinut.