310 likes | 566 Views
Grafov é algoritmy: minimálna kostra, najkratšie cesty. Čo máme v pláne ?. 2 problémy a algoritmy na ich riešenie: boli motivované potrebami praxe formulácia v „reči“ ohodnotených grafov jednoduché riešenia zložitejšie dôkazy , že algoritmy naozaj fungujú Problém minimálnej kostry
E N D
Čo máme v pláne ? • 2 problémy a algoritmy na ich riešenie: • boli motivované potrebami praxe • formulácia v „reči“ ohodnotených grafov • jednoduché riešenia • zložitejšie dôkazy, že algoritmy naozaj fungujú • Problém minimálnej kostry • Nájdenie najkratších ciest v grafe
S čím budeme pracovať ? • Neorientovaný graf bez násobných hrán a slučiek • Ku každej hrane egrafu bude priradené kladné číslow(e): váha hrany(cena hrany, ohodnotenie hrany) • Graf je súvislý • “Alternatívny pohľad”: • “guličky a čiary”, nad čiarami budú napísané čísla • neorientovaný = budeme používať čiary a nie šípky (tak ako na minulej prednáške)
Interpretácie v reálnom svete • Príklad 1: • Vrcholy = mestá • Hrany = priame cesty medzi mestami • Váha hrany = dĺžka priamej cesty • Príklad 2: • Vrcholy = elektrické rozvodne • Hrany = elektrické vedenie medzi rozvodňami • Váha hrany = cena za rekonštrukciu vedenia
Ako reprezentovať ohodnotený graf ? • Zoznam hrán+ ku každej hrane pridáme váhu: • [A, B, 7], [B, C, 8], …. • Matica susednosti: • 2-rozmerné pole intov(resp. doublov): mapa • n x n, kde n je počet vrcholov grafu (“miest”) • políčko mapa[X][Y] obsahuje • váhu hrany medzi vrcholmi X a Y • -1 ak hrana neexistuje • mapa[A][B] = 7, mapa[B][A] = 7, mapa[B][C] = 8, … • A veľa iných spôsobov ...
Graf v poli(matica susednosti) … V reálnom programe vrcholy nebude označovať písmenami, ale číslami, aby sme označenie vrcholu použili ako indexy do poľa
Graf ako objekt • Ako znalý objektového programovania v Jave a kolekcií, si môžeme vytvoriť triedu Graph, ktorá by reprezentovala graf (množina vrcholov + množina hrán) • Vrchol reprezentovaný ako objekt triedy Vertex • Hrana reprezentovaná ako objekt triedy Edge • Očakávané metódy triedy Graph: • public Set<Vertex> getVertices() • vráti množinu vrcholov, ktoré tvoria graf • public Set<Edge> getEdges() • vráti množinu hrán, ktoré tvoria graf
Problém minimálnej kostry – motivácia • Uvažujme dopravnú sieť • Máme nejaké peniaze z EÚ na výstavbu diaľníc • Ktoré cesty máme prerobiť na diaľnice, aby existovalo (nie nutne priame) spojenie medzi každými 2 mestami výhradne po diaľniciach a pritom aby sme minuli, čo najmenej • Vstup: pre každý úsek spájajúci 2 mestá náklady na jeho prestavbu na diaľnicu
Iné praktické motivácie • Telefónna sieť: ktoré linky prebudovať na optické, aby bolo možné presmerovať všetky hovory po optických linkách a chceme pritom minúť čo najmenej ? • Algoritmus na riešenie ako prvý navrhol v roku 1926 Otakar Borůvka, keď riešil problémefektívnej konštrukcie elektrickej siete na Morave
Čo je kostra grafu ? • Kostra grafu je taká podmnožina T hrán grafu G, že platí: • Medzi každými 2 vrcholmi grafu existuje cesta využívajúca len hrany kostry T • Odobratím ľubovoľnej hrany kostry už vlastnosť 1 nebude platiť • „Kostra“ sú hrany, ktoré graf „držia po kope“
Vlastnosti kostier (bez dôkazu) • Graf môže mať veľa kostier • Každá kostra grafu s n vrcholmi má práve n-1 hrán • Hrany kostry nevytvárajú cyklus • Pridanie ľubovoľnej nekostrovej hrany ku kostre vytvorí cyklus • Medzi každými 2 vrcholmi grafu existuje jediná cesta využívajúca len kostrové hrany • Minimálna kostra: taká kostra, v ktorej súčet ohodnotení (váh) hrán je minimálny spomedzi všetkých možných kostier grafu
Algoritmus na nájdenie minimálnej kostry: Kruskalov algoritmus • Utriedime vzostupne hrany grafu podľa váhy: e1, e2, e3, …, em tak, že w(e1) <= w(e2) <= w(e3) <= …, <= w(em) • Množina hrán kostry T = {} • Postupne skúšame hranu ei pre i = 1..m • Ak T + eineobsahuje cyklus, tak do množiny hrán kostry T pridáme hranuei
A C 7 8 B 5 5 7 9 15 E 8 D 9 6 F 11 G Červené sú hrany vybrané do vytváranej kostry.
Ako to naprogramovať ? • Problémy: • Utriediť hrany podľa váh (QuickSort, HeapSort) • Zistiť, či po pridaní hrany ei k aktuálne vybraným hranám kostry T vznikne cyklus • Pozorovanie: • Cyklus po pridaní hrany ei= {X, Y} vznikne práve vtedy, keď medzi vrcholmi X a Y už existuje cesta po vybraných kostrových hranách • Počas algoritmu vznikajú skupiny vrcholov, ktoré sú prepojené kostrovými hranami: „ostrovčeky súvislosti” (komponenty) vzhľadom na hrany vytváranej kostry T
“Komponenty súvislosti” • Pozorovanie vlastností komponentov: • Medzi vrcholmi X a Y existuje cesta po aktuálnych kostrových hranách, ak patria rovnakým komponentom • Pridaním hrany ei= {X, Y}, kde X a Y sú v rôznych komponentoch, sa tieto komponenty „zlúčia“ • Ako efektívne zistiť, že vrcholy sú v rovnakom komponente ?
“Komponenty súvislosti” 2 • Pre každý vrchol budeme udržiavať “identifikátor“ komponentu, do ktorého patrí • Porovnaním „identifikátorov“ vieme rýchlo zistiť, či sú v rovnakom alebo rôznom komponente • Na začiatku je vrchol i v komponente s identifikátorom i • Ak sa 2 komponenty (pridaním hrany) zlúčia, tak všetkým vrcholom jedného z komponentom nastavíme identifikátor druhého komponentu
Prečo to funguje ? (Dôkaz sporom) • Nech T je kostra vypočítaná algoritmom a Y je nejaká minimálna kostra, ktorá má s kostrou Tnajviac spoločných hrán • Keďže T je rôzne od Y existuje taká hrana z T, ktorá nepatrí do Y a naopak (pretože T aj Y majú presne n-1 hrán) • Nech e je prvá hrana vybraná algoritmom do kostry T, ktorá nie je v Y • Y+e vytvára cyklus (viď tvrdenia o kostrách), ktorý musí obsahovať nejakú hranu f, ktorá nie je z T(inak by cyklus už existoval v T, čo nie je možné) • Y+e–f je opäť kostra, ale keďže Y je najlacnejšia, musí platiť, že w(e) > w(f) • w(e) = w(f)nemôže platiť, lebo potom Y+e-f by bola kostra s minimálnou cenou, ktorá má viac spoločných hrán s T ako Y
Prečo to funguje ? (Pokračovanie) • Keďže w(e) > w(f) v algoritme sme spracovali hranu f pred hranou e • Pripomenutie: • e je prvá hrana zaradená do T, ktorá nie je v Y • f je hrana okrem iného hrana z Y, ktorá nie je v T • Keďže sme f nezaradili do T musela vytvárať cyklus s hranami, ktoré boli dovtedy vybrané do T, čo sú zároveňhrany z Y (viď pripomenutie) • Teda už časť hrán z Y spolu s f vytvára cyklus, čo je spor s tým, že Y je kostra (t.j. neobsahuje žiaden cyklus)
Zložité otázky o zložitosti ... • m hrán, n vrcholov • Utriedenie hrán: O(m log m) • Nájdenie kostry: O(m) + O(n2) • Spracovanie jednej z m hrán stojí čas O(1) • Zlúčenie komponentov stojí čas O(n), ale to vykonávame iba n-1 krát • Celková časová zložitosť O(n2 + m log m) • Chytrejšie implementácie: O(m log n)
Najkratšie cesty v grafe – motivácia • Mapa s informáciami o priamych cestách (spojniciach) medzi mestami • Hľadáme najkratšiu(najrýchlejšiu, najlacnejšiu) cestu medzi 2 mestami • Aplikácie: GoogleMaps, GPS + navigátor, ...
Mať orientáciu sa oplatí • Orientované grafy sú niekedy lepšie na modelovanie reálnej situácie: • Cesta z A do B (do kopca) trvá 1 hodiny • Cesta z B do A (z kopca) trvá 45 minút • Orientovaný ohodnotený graf: • Hrany majú svoj smer • Medzi 2 vrcholmi najviac 2 hrany: každá má iný smer • „guličky + šípky, nad ktorými sú čísla“ • Reprezentácia: Matica susednostinemusí byť symetrická (mapa[A][B] = 60, mapa[B][A] = 45)
Dijkstrov algoritmus • 1959, Edsger Dijkstra (Holandsko) • Vstup: • ohodnotený orientovaný/neorientovaný graf G s kladnými ohodnoteniami hrán • vrchol v grafu G • Výstup: • pre každý vrchol wdĺžka najkratšej cesty z vrcholu v do vrcholu w • informácia na zrekonštruovanie najkratších ciest
Princíp algoritmu • Počas výpočtu si udržiavame: • Množinu vrcholov S, do ktorých sa podarilo definitívnevypočítať dĺžku najkratšej cesty zo štartovacieho vrcholuv • Pre každý vrchol w dĺžku najkratšej cesty d[w]z vrcholu v do vrcholuw, ktorá vedie len cez vrcholy z množiny S • Iniciálne: • S= prázdna množina • d[w] = nekonečno (budeme reprezentovať ako zápornú hodnotu), pre všetkyw z V-{v} • d[v] = 0
Dijkstrov algoritmus Kým existuje vrchol x z V-S taký, že d[x] nie je nekonečno: • Vyber vrchol u z V-S taký, že d[u] je minimálne • Pridaj u do množinyS • Pre každý vrchol w z V-Sskúsime zlepšiťd[w] pomocou cesty prichádzajúcej z u: Ak d[w] > d[u] + w((u, w)), tak d[w] = d[u] + w((u, w))
Simulácie a vizualizácie algoritmu • http://cam.zcu.cz/~rkuzel/aplety/Dijkstra/Dijkstra.html • http://www.cs.auckland.ac.nz/software/AlgAnim/dijkstra.html • http://www.unf.edu/~wkloster/foundations/DijkstraApplet/DijkstraApplet.htm
Prečo to funguje ? (Náznak/Bonus) • Kľúčové pozorovanie: • Ak (v, v1, v2, v3, …, x, …, w) je najkratšia cesta z v do w, potom (v, v1, v2, v3, …, x) je najkratšia cesta z v do x • Pre formálny dôkaz treba ukázať: • Ak zaradíme nejaký vrchol udo S, tak naozaj hodnota d[u] obsahuje dĺžku najkratšej cesty z vrcholu v do vrcholu u • Platnosť invariantov(tvrdenia platiace vždy keď prechádzame istým miestom programu)
Zložitosť algoritmu • Každý vrchol (z n vrcholov) je zaradený do Snajviac raz: • Výber prvku uz minimálnym d[u] : O(n) • Zlepšenie d[w] cez vrchol u: O(n) • Celková časová zložitosť: O(n2) • Úloha na cvičenia: Algoritmus nájde dĺžku najkratšej cesty z vrcholu v do ostatných vrcholov. Ako zistíme, ako najkratšia cesta vyzerá?
Ďakujem za pozornosť Otázky???