Documente Academic
Documente Profesional
Documente Cultură
ia2-CĂUTARE ÎN SPAŢIUL DE STĂRI
ia2-CĂUTARE ÎN SPAŢIUL DE STĂRI
Spaţiul de stări
Spaţiul de căutare a
Stare curentă
c
Operatori b
Stări noi d e f g
h i j k
Fig.4. Elementele spaţiului de căutare
NivelStăriTotal
stari011123247381541631
1
n 2n 2(n+1)-1
2 4 7
4 16 31
6 64 127
10 1024 2047
15 32768 65536
20 1048576 2097151
30 1073741824 2147483647
Căutarea “oarbă”
Căutarea în adâncime
a
c
b
d e f g
h i j k
2
succesor(N,N1), /*dacă N1 e un nod succesor al lui N şi*/
drum_1(N1,S). /*S e soluţia din N1 spre nodul final*/
succesor(a,b).
succesor(b,d).
succesor(d,h).
succesor(b,e).
succesor(e,i).
succesor(e,j).
succesor(a,c).
succesor(c,f).
succesor(c,g).
succesor(f,k).
atunci la întrebarea cu starea iniţială în calitate de primul argument se obţine următoarea soluţie
?-drum_1(a,S)
S=[a,b,e,j]
S=[a,c,f]
Dacă, însă, spaţiul de stări este un graf ciclic cum ar fi, spre exemplu, graful obţinut prin
adăugarea la precedentul a arcului
succesor(h,d).
atunci pentru a evita buclele care, de exemplu, apar pentru a răspunde la aceeaşi întrebare, se cere
introducerea unui control. Controlul poate fi făcut prin adăugarea unui al treilea argument ce ar
reprezenta lista nodurilor deja explorate cu care se va confrunta orice nod nou înainte de a fi introdus
în listă.
drum_2(N,[N|C],C):-stare_finala(N).
drum_2(N,S,C):-
succesor(N,N1),
not(apartine(N1,C)),
drum_2(N1,S,[N|C]).
apartine(Elem,[Elem|_]).
apartine(Elem,[_|Rest]):-apartine(Elem,Rest).
3
Căutarea limitată în adâncime
drum_3(N,[N],_):-stare_finala(N).
drum_3(N,[N|S],Max):-
Max>0,
succesor(N,N1),
Max1 is Max-1,
drum_3(N1,S,Max1).
Predicatul drum_3/3 este apelat cu argumentul trei instanţiat de valoarea adâncimii maxime.
Adresându-ne din nou la graful nostru, obţinem
?-drum_3(a,S,2)
S=[a,c,f]
?-drum_3(a,S,3)
S=[a,b,e,j]
S=[a,c,f]
?-drum_4(a,S,[],2)
S=[f,c,a]
?-drum_4(a,S,[],3)
S=[j,e,b,a]
S=[f,c,a]
Lumea blocurilor
C A
A B
B C
Fig.12. Lumea blocurilor
4
Spaţiul de stări Lumea blocurilor
stare_finala(l).
succesor(a,c). succesor(c,a).
succesor(c,e). succesor(e,c).
succesor(b,d). succesor(d,b).
succesor(d,e). succesor(e,d).
succesor(c,d). succesor(d,c).
succesor(e,h). succesor(h,e).
succesor(h,i). succesor(i,h).
succesor(e,g). succesor(g,e).
succesor(g,f). succesor(f,g).
succesor(g,j). succesor(j,g).
succesor(h.k). succesor(k,h).
succesor(e,j). succesor(j,e).
succesor(e,k). succesor(k,e).
succesor(j,l). succesor(l,j).
succesor(k,m). succesor(m,k).
succesor(1,6).
succesor(1,8).
succesor(2,7).
succesor(2,9).
succesor(3,4).
succesor(3,8).
succesor(4,3).
succesor(4,9).
succesor(6,7).
succesor(6,1).
succesor(7,6).
succesor(7,2).
succesor(8,3).
succesor(8,1).
succesor(9,4).
succesor(9,2).
?-drum_2(1,S,[])
S=[8,3,4,9,2,7,6,1]
S=[8,1]
5
1 1234567812345678Fig.15. Un drum al
2 3 calului de şah
4 5 6
4a 3a
a
8 7a
a
6 5a
a
2 1a
stare_finala(patrat(1,5)).
succesor(patrat(R1,C1),patrat(R2,C2)):-
R1<=6,C1<=7,R2 is R1+2,C2 is C1+1.
succesor(patrat(R1,C1),patrat(R2,C2)):-
R1<=6,C1=2,R2 is R1+2,C2 is C1-1.
succesor(patrat(R1,C1),patrat(R2,C2)):-
R1>=3,C1<=7,R2 is R1-2,C2 is C1+1.
succesor(patrat(R1,C1),patrat(R2,C2)):-
R1>=3,C1>=2,R2 is R1-2,C2 is C1-1.
succesor(patrat(R1,C1),patrat(R2,C2)):-
R1<=7,C1<=6,R2 is R1+1,C2 is C1+2.
succesor(patrat(R1,C1),patrat(R2,C2)):-
R1<=7,C1>=3,R2 is R1+1,C2 is C1-2.
succesor(patrat(R1,C1),patrat(R2,C2)):-
R1>=2,C1<=6,R2 is R1-1,C2 is C1+2.
succesor(patrat(R1,C1),patrat(R2,C2)):-
R1>=2,C1>=3,R2 is R1-1,C2 is C1-2.
?-drum_2(patrat(4,2),S,[])
6
S=[patrat(1,5),patrat(3,4),patrat(1,3),patrat(3,2),
patrat(5,1),patrat(7,2),patrat(5,3),patrat(7,4),
patrat(5,5),patrat(3,6),patrat(2,8),patrat(4,7),
patrat(6,8),patrat(8,7),patrat(6,6),patrat(7,8),
patrat(5,7),patrat(7,6),patrat(8,8),patrat(6,7),
patrat(8,6),patrat(6,5),patrat(8,4),patrat(6,3),
patrat(4,2)]
Problema fermierului
VestEstFLCVFLCV
Fig.17. Soluţiile problemei fermierului
stare_finala(stare(e,e,e,e)).
7
opus(e,v).
opus(v,e).
periculos(stare(X,Y,Y,_)):-opus(X,Y).
periculos(stare(X,_,Y,Y)):-opus(X,Y).
?-drum_2(stare(v,v,v,v),S,[])
S=[stare(e,e,e,e),stare(v,e,v,e),stare(e,e,v,e),
stare(v,e,v,v),stare(e,e,e,v),stare(v,v,e,v),
stare(e,v,e,v),stare(v,v,v,v)]
S=[stare(e,e,e,e),stare(v,e,v,e),stare(e,e,v,e),
stare(v,v,v,e),stare(e,v,e,e),stare(v,v,e,v),
stare(e,v,e,v),stare(v,v,v,v)]
Căutarea în lărgime
c
b
d e f g
h i j k
alegere_urmator_nod([Nod|Drum],[Nod1,Nod|Drum]):-
succesor(Nod,Nod1),
not(apartine(Nod1,[Nod|Drum])).
8
Aici apartine/2 şi concatenare/3 sunt predicate cunoscute asupra listelor, iar findall/3 este un
predicat predefinit în unele implementări Prolog.
predicatele write vor afişa consecutivitatea de mai jos. În această consecutivitate, la fiece nod curent
sunt găsiţi toţi succesorii adiacenţi ce extind drumul în lista Drumuri_cand. Aici “lista” este lista
Drumuri_cand modificată: se elimină drumul din capul listei şi se adaugă la coadă extinderile acestui
drum.
ista: [[b,a],[c,a]]
lista: [[c,a],[d,b,a],[e,b,a]]
lista: [[d,b,a],[e,b,a],[f,c,a],[g,c,a]]
lista: [[e,b,a],[f,c,a],[g,c,a],[h,d,b,a]]
lista: [[f,c,a],[g,c,a],[h,d,b,a],[i,e,b,a],[j,e,b,a]]
S=[f,c,a]
lista: [[g,c,a],[h,d,b,a],[i,e,b,a],[j,e,b,a],[k,f,c,a]]
lista: [[h,d,b,a],[i,e,b,a],[j,e,b,a],[k,f,c,a]]
lista: [[i,e,b,a],[j,e,b,a],[k,f,c,a]]
lista: [[j,e,b,a],[k,f,c,a]]
S=[j,e,b,a]
lista: [[k,f,c,a]]
lista: []
cautare_succesori(St,OS,NS):-
succesor(St,NS),St<>NS,
not(agenda(NS,S)),not(agenda_veche(NS,S)),
assertz(agenda(NS,[NS|OS])).
cautare_succesori(St,OS,NS):-
retract(agenda(St,OS)),
asserta(agenda_veche(St,OS)),
write(“Agenda:”),nl,
vizualizare(agenda(X,Y)),
vizualizare(agenda_veche(X,Y)),
fail.
repetare.
repetare:-agenda(_,_),repetare.
9
vizualizare(X):-X,write(X),nl,fail.
vizualizare(_).
Formulând întrebarea
?-largime_2(a,S)
Să considerăm spaţiul necesar pentru derularea acestei strategii. Până a se trece la adâncimea
k+1 se examinează toate nodurile de la nivelul k. Adică până a parcurge nodurile de la adâncimea p
sunt memorate datele despre f p-1 noduri de la nivelul p-1. Deci dacă soluţia se află la nivelul p, atunci
spaţiul necesar pentru păstrarea nodurilor, în cel mai rău caz, este
1+f+f2+…+f p.
Să calculăm timpul mediu necesar pentru parcurgerea spaţiului de stări. Numărul de noduri
examinate până la nivelul p este
10
p 1 (f p 1)
1 f f 2 ... f
(f 1)
Fiecare din nodurile nivelului p poate fi stare finală. Deci pot fi examinate 1 nod, în cel mai
bun caz şi f p noduri, în cel mai rău caz. Presupunând că nodul final poate fi repartizat uniform la
nivelul p, atunci timpul mediu necesar căutării în lărgime este
Astfel pentru f şi p mari această expresie converge spre f p/2, adică timpul consumat este O(f p).
p 1
(f p 1 ) (1 f p ) (f f p f 3)
(f - 1) 2 2(f 1)
Fie că factorul de ramificare este 10, memoria necesară pentru păstrarea unui nod este 100
octeţi, iar viteza de parcurgere este 1000 noduri/secundă. Atunci tabelul din fig.19 ilustrează necesităţile de
memorie şi timp pentru căutarea în lărgime.
În ce priveşte spaţiul consumat, căutarea în adâncime e cu mult mai avantajoasă decât căutarea
în lărgime graţie păstrării numai drumului curent care conţine p noduri. Deci complexitatea spaţiului
este O(p), adică e o funcţie liniară în raport cu adâncimea.
Presupunem că graful de căutare este finit şi are adâncimea p. Dacă soluţia se află în primul
nod al nivelului p, atunci sunt explorate p+1 noduri. Dar dacă soluţia se găseşte în ultimul nod al
nivelului p, atunci numărul de noduri vizitate este
(f p 1 1)
1 f f 2 ... f p
(f 1)
Atunci numărul mediu de noduri vizitate va fi
p 1 p 1
(f 1 ) (p 1 ) (f fp f p 2 )
2(f - 1) 2 2(f 1)
adică pentru valori mari ale lui f şi p este aproximativ f p/2. Prin urmare, căutarea în adâncime are de
a
asemenea complexitatea O(f p).
32 1
1 c
Căutarea iterativă în adâncime
213
1 32
b
32
drum_5(N,S,C,Max_dem,Max):- 2 32 2
2 3 23 2 3
d 3 e f 3 g
3
3 3 3
3 33 3 11
h i j k
drum(N,[N|C],C,_,_):-stare_finala(N).
drum(N,S,C,Max_dem,Max):-
Max_dem>0,
succesor(N,N1),
not(apartine(N1,C)),
Max_dem1=Max_dem-1,
drum(N1,S,[N|C],Max_dem1,Max).
Spaţiul utilizat de căutarea iterativă în adâncime este O(p), deoarece la fiece iteraţie are loc
căutarea în adâncime. Mai mult ca atât, contrar aparenţei, complexitatea timpului nu e mai mare decât
complexitatea timpului pentru la căutările în adâncime sau în lărgime.
Într-adevăr, numărul total de noduri explorate de căutările sterile până la nivelul p este
p 1
( f i 1 1 ) 1 p 1 p 1
i 0 ( f 1 )
( f 1)
[ f (
i 0
f i
)
i 0
1]
1 f p 1 f p 1 fp f p
[ f( ) p]
Adăugând
( f 1 ) la acest
f 1număr numărul ( f mediu
1 ) 2 de noduri examinate la ultimul nivel, obţinem
p 1 p 1
f fp f p f fp f p 2
( f 1 )2 2( f 1 )
Deoarece numărul de noduri creşte exponenţial la fiecare nivel, cel mai mult timp efectiv este
consumat la ultimul nivel. Astfel timpul e dominat de
( f 1 ) f p 1
2( f 1 ) 2
f p 1
2( f 1 )
Deci raportul dintre timpul consumat de căutarea iterativă în adâncime şi timpul consumat de căutarea
în adâncime este
( f 1)
adică căutarea iterativă în
( f adâncime
1) are aceeaşi complexitate ca şi căutarea în adâncime.
12
Tabelul din fig.21 este o totalizare comparativă a tehnicilor de căutare oarbă, unde simbolurile
reprezintă
f – factorul de ramificare
p – adâncimea soluţiei
m – adâncimea maximală a arborelui de căutare
l – limita de adâncime
Căutare
Evaluare Adâncime Iterativă
Lărgime Adâncime
Limitată Adâncime
Timp fp fm fl fp
p
Spaţiu f m l p
Admisibilă? Da Nu Nu Da
Completă? Da Nu Da, dacă l>=p Da
13