This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
GRAFOVSKI ALGORITMIBFS za grafove sa razliitim duinama grana
Posmatrali smo BFS algoritam za grafove ije grane nemaju teinu
(imaju iste duine).
To je prilino redak sluaj u primenama gde se trae najkrai
putevi
eši su sluajevi kada grane imaju razliite teine (duine), kao u
donjem primeru to ne mora da budu fizike duine, to moe biti vreme
(potrebno da bi se prešao put), novac (cena autobuske karte ili
goriva), ili bilo koja druga vrednost
Adaptacija BFS algoritma
Neka je dat graf = , kod koga je svakoj grani = (, ) ∈ pridruena
duina koju oznaavamo sa (, ), ili
Neka su duine pozitivni celi brojevi
Adaptiraemo BFS za potrebe ovakvog algoritma:
svaku granu = (, ) ∈ zamenimo sa grana duine 1, dodajui − „lanih“
vorova izmeu i
Na ovaj nain dobijamo novi graf ′ koji sadri sve vorove iz i
rastojanja izmeu njih su ista kao u , i moemo ih izraunati
pokretanjem BFS na ′
Budilnik
Ako nam efikasnost algoritma nije vana, moemo se zaustaviti
ovde.
Meutim, ako graf ima duge grane, graf ′ e imati veliki broj lanih
vorova, i BFS e najvei deo svog radnog vremena potrošiti na
izraunavanje rastojanja do nebitnih vorova, kao što je sluaj u
sledeem primeru:
Šta nam je initi? Da li postoji li neki nain da dremamo dok
prelazimo zamorni deo puta preko lanih vorova i da navijemo alarm
koji e da nas probudi kada se desi nešto zanimljivo, kada stignemo
do pravog vora?
Budilnik
Na primer, mogli bi da podesimo dva alarma na poetku, jedan za vor
, podešen da se ukljui u vremenu = 100, a drugi za vor , podešen za
vreme = 200.
To su procenjena vremena dolaska.
Kada nas alarm probudi u = 100 i otkrijemo , procenjeno vreme
dolaska za prepodešavamo na = 150, jer smo tu u ustanovili da je
vreme dolaska u prethodno bilo precenjeno.
Budilnik
Sledei „alarm clock algoritam“ verno simulira izvršavanje BFS na
grafu ′ :
podešavamo alarm za vor na vreme 0
ponavljamo sledee sve dok više ne bude alarma:
recimo da se sledei alarm ukljuuje u vreme , za vor . Tada
rastojanje od do je
za svakog suseda od radimo sledee: ako još uvek nije bilo alarma za
, podesimo ga na + (, )
ako je alarm za podešen za vreme kasnije od + (, ), prepodesimo ga
na to ranije vreme
Dijkstrin algoritam
Da bi nam algoritam bio gotov, treba samo da vidimo kako da
implementiramo sistem alarma.
Struktura podataka pogodna za to je kju prioriteta (priority
queue)
Kju prioriteta je skup elemenata (u ovom sluaju vorovi) sa
pridruenim numerikim kljunim vrednostima (u ovom sluaju vremena
alarma)
Kju prioriteta dozvoljava sledee operacije:
Insert dodaje novi element u skup
Decrease-key smanjuje kljunu vrednost posebnog elementa
Delete-min izdvaja element sa najmanjom kljunom vrednošu i uklanja
ga iz skupa
Make-queue izgrauje kju prioriteta iz datih elemenata, sa datim
kljunim vrednostima (u mnogim primenama to je znatno bre nego
unošenje elemenata jedan po jedan)
Dijkstrin algoritam najkraeg puta (Dijkstra's shortest-path
algorithm)
predstavlja trenutnu vrednost vremena alarma, a ∞ znai da alarm još
uvek nije podešen
pokaziva koji ukazuje na prvi vor ispred na naj- kraem putu od do ,
pomou koga rekonstrui- šemo najkrai put
Primer
Primer
Primer
Primer
Evo plana kako da izraunamo najkrae puteve:
Kreemo od startnog vora i stalno uveavamo region grafa u kome su
rastojanja i najkrai putevi poznati.
To uveanje mora da bude prema odreenom redosledu – prvo ukljuujemo
najblie vorove, a onda prelazimo na one koji su malo dalje.
Preciznije, kada je „poznati region“ neki podskup skupa vorova koji
uklju-uje , onda naredni dodati vor mora biti onaj vor van koji je
najblii do ; neka to bude vor ;
Kako ga identifikovati?
Neka je vor neposredno ispred na najkraem putu od do
pošto su duine grana pozitivne, mora biti blie do od
Što znai da je u , u suprotnom bi to bilo u kontradikciji sa
izborom kao vora iz najblieg do vora .
Alternativno izvoenje
Prema tome, najkrai put od do je poznati najkrai put proširen
jednom granom (single-edge proširenje)
Moe da postoji više single-edge proširenja trenutno poznatih
najkraih puteva; koji od njih identifikuje ?
odgovor je: najkrai od tih single-edge proširenih puteva!
(poslednji vor najkraeg proširenog puta je vor van najblii do , pa
to mora biti baš )
Alternativno izvoenje
Sada je lako pronai – to je vor van kod koga je postignuta najmanja
vrednost + (, ), gde prolazi kroz skup .
Treba proveriti sva single-edge proširenja trenutno poznatih
najkraih puteva, nai najkrae, i njegov završni vor e biti sledei
koji dodajemo u
D
odatna efikasnost potie iz injenice da u svakoj novoj iteraciji,
jedina nova proširenja su ona koja ukljuuju poslednji vor koji smo
dodali u , jer su sva ostala proširenja prethodno razmatrana i nema
potrebe ponovo ih raunati
Vreme realizacije
Dijkstrin algoritam je strukturno slian BFS-u, ali je sporiji, jer
je kju prioriteta zahtevniji od obinog kjua.
Kako makequeue traje kao || insert operacija, to dobijamo ukupno ||
deletemin i + || insert/decreasekey operacija
Pri tome, vreme potrebno za realizaciju ovih operacija zavisi od
toga za koju implementaciju kjua prioriteta smo se odluili:
Pohlepni algoritmi
Pohlepni algoritmi predstavljaju algoritamsku strategiju kod koje
se problem rešava deo po deo, pri emu se uvek bira naredni deo koji
nudi najoigledniju neposrednu korist.
Ovakva strategija u mnogim sluajevima ne daje dobre
rezultate:
Na primer, u šahu ne bi dala rezultate, jer moramo dobro
isplanirati više poteza unapred i planiranje samo narednog poteza
vrlo brzo dovodi do poraza.
Meutim, postoje i sluajevi gde ovakva pohlepna strategija daje
rezultate i razmotriemo takve sluajeve.
Minimalna razapinjua stabla
Pretpostavimo da nam je dat zadatak da umreimo kolekciju raunara
pove- zujui izabrane parove tih raunara.
Ovaj zadatak moe se prevesti u problem teorije grafova, gde su
vorovi rau- nari, neusmerene grane su potencijalne veze izmeu njih,
i cilj je da izabere- mo dovoljno tih grana da vorovi budu
povezani.
Meutim, to nije sve. Svaka veza takoe ima svoje troškove odravanja,
koje predstavljamo kao teine grana (naš graf je neusmeren i
teinski).
Pitanje je: Koja je najjeftinija mogua mrea?
Ono što odmah moemo uoiti je da optimalan skup grana ne moe sadrati
ciklus, jer uklanjanjem grane sa tog ciklusa moemo redukovati cenu
bez da poremetimo povezanost.
Minimalna razapinjua stabla
Svojstvo 1 Uklanjanje grane sa ciklusa ne moe poremetiti povezanost
grafa.
Prema tome, rešenje koje traimo mora biti povezan i aciklian
graf.
Neusmereni grafovi tog tipa nazivaju se stabla.
Stablo koje mi traimo je ono sa minimalnom ukupnom teinom, i
poznato je kao minimalno razapinjue stablo.
Input: Neusmeren graf = (, ); teine grana
Output: Stablo = (, ′), sa ′ ⊆ , i minimalnim
weight =
∈′
U prethodnom primeru, minimalno razapinjue stablo ima cenu (teinu)
16:
Pohlepni pristup
Uzastopno dodavati po jednu najlakšu granu koja ne proizvodi
ciklus.
Drugim reima, konstruišemo stablo granu po granu i, pored toga što
pazimo da izbegnemo cikluse, jednostavno biramo onu granu koja je
najjeftinija u da-tom trenutku.
Jasno, to je pohlepni algoritam: svaka odluka koju donosimo je ona
koja u istom trenutku donosi najoigledniju prednost.
Da li je ovo jedino
optimalno rešenje?
Minimalno razapinjue stablo dobijeno Kruskalovim algoritmom:
Najpre poreajmo grane po teinama, od najlakše do najtee, pri emu
grane iste teine moemo poreati bilo kojim redosledom:
Krenimo sada sa praznim grafom i dodajmo jednu po jednu granu, po
tom redosledu, tako da ne dobnijemo ciklus. Sa prve dve grane nam
to uspeva, ali sa treom, granom − , to ne uspeva, jer bi inae
dobili ciklus.
U tom sluaju, tu granu ignorišemo i idemo dalje. Konaan rezultat je
stablo sa najmanjom moguom cenom 14.
Svojstvo seenja– Cut property
Korektnost Kruskalovog metoda sledi direktno iz tzv. svojstva
seenja.
Recimo da smo u procesu izgradnje minimalnog razapunjueg stabla
(MST) ve izabrali neke grane i da smo za sada na pravom putu.
Koju granu treba sledeu da dodamo?
Svojstvo seenja: Pretpostavimo da je skup grana deo nekog
minimalnog razapinjueg stabla grafa = (, ). Izaberimo bilo koji
skup grana tako da ne prelazi izmeu i \, i neka je najlakša grana
koja povezuje i \.
Tada je ∪ {} takoe deo nekog minimalnog razapinjueg stabla.
Seenje (cut) je bilo koja particija skupa vorova sa dva bloka, i
\.
Svojstvo seenja kae da je uvek bezbedno dodati najlakšu granu preko
bilo kog seenja (tj. izmeu jednog vora u i jednog u \), pod uslovom
da nema granu preko tog seenja.
Svojstvo seenja– Cut property
Da vidimo zašto to vai. Prema pretpostavci, grane iz su deo nekog
MST .
Ako je nova grana takoe deo od , tada nema šta da se
dokazuje.
Dakle, uzmimo da nije u . Konstruisaemo drugo MST ′ koje sadri ∪ {}
neznatno modifikujui stablo , zamenom samo jedne od njegovih
grana.
Dodajmo granu u . Kako je povezano, ve postoji put izmeu krajnjih
taa- ka grane , pa se dodavanje grane kreira ciklus.
Taj ciklus mora takoe da ima neku drugu granu ′ preko seenja (, \)
(vidi sliku).
Ako sada uklonimo tu granu ′, ostaje nam ′ = ( ∪ )\{′} , za koje
emo pokazati da je stablo. Zaista, ′ je povezano na osnovu Svojstva
1, jer je ′ grana na ciklusu.
Takoe, ′ ima isti broj grana kao , pa je ′ takoe stablo.
Svojstvo seenja– Cut property
Osim toga, ′ je minimalno razapinjue stablo. Uporedimo njegovu
teinu sa teinom od :
weight ′ = weight + − (′)
I i ′ prelaze izmeu i \, i je po pretpostavci najlakša grana tog
tipa.
Prema tome, () ≤ (′) , pa je weight(′) ≤ weight().
Kako jeste MST, onda mora da bude weight ′ = weight() pa ′ takoe
jeste MST.
Primer
Sada emo potvrditi korektnost Kruskalovog algoritma.
U svakom trenutku, grane koje su ve izabrane ine parcijalno
rešenje, kolekciju povezanih komponenti od kojih svaka ima
strukturu stabla.
Sledea grana koja treba da bude dodata povezuje dve od tih
komponenti, recimo da su to 1 i 2.
Kako je najlakša grana koja ne proizvodi ciklus, sigurno je da je
najlakša grana izmeu 1 i \1, pa, prema tome, zadovoljava svojstvo
seenja.
Objasnimo sada detalje implementacije algoritma.
U svakom stadijumu, algoritam bira granu koju e dodati trenutnom
parcijalnom rešenju.
Da bi se to uinilo, potrebno je proveriti svaku granu kandidata −
da bi videli da li krajnje take i lee u razliitim komponentama, u
suprotnom ta grana proizvodi ciklus.
Kada je grana izabrana, odgovarajue komponente treba da se
spoje.
Koja struktura podataka podrava takve operacije?
Kruskalov algoritam
Inicijalno, svaki vor je sam za sebe komponenta:
(): kreira jednoelementni skup koji sadri samo .
Mi uvek iznova proveravamo parove vorova da bi videli da li
pripadaju istom skupu.
(): kom skupu pripada ?
I kad god dodamo granu, mi spajamo dve komponente:
(, ): spaja skupove koji sadre i .
Kruskal's minimum spanning tree algorithm
Ovo je konana verzija algoritma.
Algoritam koristi || makeset, 2|| find, i − 1 union
operacija.
Struktura podataka za disjunktne skupove
Predstavljanje usmerenog stabla od dva skupa {B, E} i {A, C, D, F,
G, H}
Jedan od naina da se predstavi skup je usmereno stablo.
vorovi stabla su elementi skupa, aranirani bez nekog posebnog
redosleda, i svaki od njih ima roditeljski pokaziva koji nas vodi
prema korenu stabla.
Element u korenu je zgodan za predstavnika skupa.
On se razlikuje od ostalih elemenata po tome što mu roditeljski
pokaziva predstavlja petlju.
Unija po rangu
Pored roditeljskog pokazivaa , svaki vor takoe ima rang koji se moe
interpretirati kao visina podstabla koje izlazi iz tog vora.
Kao što se moe oekivati, makeset je operacija koja troši konstantno
vreme.
Sa druge strane, find sledi roditeljski pokaziva do korena stabla,
pa, prema tome, zahteva vreme proporcionalno visini stabla.
Stablo se zapravo gradi treom operacijom, union, pa treba da budemo
sigurni da procedura ostavlja stablo plitkim.
Unija po rangu
Stapanje (merging) dva skupa je jednostavno: spojimo koren stabla
jednog od tih skupova sa korenom stabla drugog skupa.
Meutim, ovde treba da napravimo izbor. Ako predstavnici (koreni)
dva skupa jesu i , da li vezujemo za ili obratno?
Kako je za efikasnost algoritma najvanija visina stabla, dobra
strategija je da se postavi grana iz korena nieg stabla u koren
višeg stabla.
Na taj nain se stapanjem dobija više stablo samo ako su oba stabla
koja se stapaju iste visine, pri emu se visina uveava samo za
1.
Umesto da eksplicitno raunamo visinu stabala, mi emo koristiti rang
brojeve njihovih korena, zbog ega se i ovaj metod naziva unija po
rangu.
Procedura union
Unija po rangu
Oigledno, rang vora je upravo visina podstabla iji koren je taj
vor.
To znai, na primer, kako se kreemo naviše prema korenu stabla,
vrednosti ranga se du tog puta uveavaju.
Property 1 Za svaki , rank < rank( ).
Property 2 Svaki vor ranga ima najviše 2 vorova u svom
podstablu.
Property 3 Ako ukupno ima elemenata, tada moe biti najviše /2 vo-
rova ranga .
Iz poslednjeg svojstva sledi da rang moe biti maksimalno log
.
Prema tome, sva stabla imaju visinu ≤ log, i to je gornja granica
vremena rada za find i union.
Primer – Kruskalov algoritam
Primer – Kruskalov algoritam
Primer – Kruskalov algoritam
Primer – Kruskalov algoritam
Primer – Kruskalov algoritam
Kompresija puteva
Sa strukturom podataka o kojoj smo do sada govorili, ukupno vreme
rada Kruskalovog algoritma je (|| ||) za sortiranje grana (imajmo u
vidu da je || ≈ ||) plus još jedno (||||) za operacije union i find
koje dominiraju u ostatku algoritma.
Dakle, ini se da nema mnogo prostora da se naša struktura podataka
uini još
efikasnijom.
Meutim, šta ako su grane ve sortirane? Ili ako su teine male
(recimo,
(||)), pa se sortiranje moe izvršiti u linearnom vremenu?
U takvim sluajevima razmatrana struktura podataka postaje usko
grlo, i
korisno je razmišljati o tome da njene performanse poboljšaju ispod
po
operaciji.
Moemo razmišljati o izvesnoj operaciji odravanja za union-find
strukturu,
koja bi odravala stabla kratkim tokom svake find operacije, kada se
sledi niz
roditeljskih pokazivaa do korena stabla, gde moemo izmeniti sve
te
pokazivae tako da ukazuju direktno na koren stabla.
Primer – kompresija puteva
Takva kompresija puteva (path compression) samo malice uveava vreme
potrebno za find operaciju i lako se kodira.
Dobit od ove jednostavne izmene više dolazi do izraaja dugorono
nego trenutno, i stoga zahteva posebnu analizu.
Treba posmatrati nizove find i union operacija, koje kreu od prazne
struk- ture podataka, i odrediti proseno vreme po operaciji.
U tom sluaju e potrebno vreme po operaciji biti jedva nešto više od
(1), što je nie od ranijeg (log ).
Primov algoritam
Vratimo se na našu diskusiju o algoritmima za konstrukciju
minimalnog razapinjueg stabla.
Ono što nam svojstvo seenja kae u najopštijim crtama glasi da e
svaki algoritam koji prati sledeu pohlepnu strategiju gatarnovano
raditi.
Popularna alternativa Kruskalovom algoritmu je Primov algoritam,
gde u svakom meukoraku skup grana uvek ini podstablo, a se bira kao
skup vorova tih stabala.
Primov algoritam
U svakoj iteraciji, podstablo odreeno sa se uveava za po jednu
granu, i to za onu najlakšu izmeu vora iz i vora van (Figure
5.8).
Ekvivalentno, moemo zamisliti da raste tako što ukljuuje vor ∉ sa
najmanjom cenom:
Primov algoritam
Primov algoritam jako lii na Dijkstrin algoritam, pseudokodovi su
im skoro identini (Figure 5.9).
Jedina razlika je u kljunim vrednostima pomou kojih je kju
prioriteta ureen.
Kod Primovog algoritma, vrednost vora je teina najlakše ulazne
grane iz skupa , dok je kod Dijkstrinog algoritma to duina celog
puta do tog vora iz startnog vora.
U svakom sluaju, dva algoritma su dovoljno slina da imaju isto
vreme rada, koje zavisi od konkretne implementacije kjua
prioriteta.
Fig. 5.9 pokazuje kako radi Primov algoritam na malom grafu sa 6
vorova.
Primetimo da je završno MST potpuno odreen nizom prev.
Primov algoritam