
Sld 9. ZaawanTech. 2013.ppt
- Количество слайдов: 45
Rozdział 9 Zaawansowane techniki programowania
Sld 9. 1. Zaawansowane techniki programowania 1. Algorytmy typu „dziel-i-rządź”(“conquer and divide”) 2. Algorytmy „zachłanne“ (“żarłoczne”, “greedy”) 3. Algorytmy dynamiczne
Sld 9. 2. Algorytmy typu „dziel-i-rządź“ 1. 2. 3. Programowanie typu „dziel-i-rządź" polega na wykorzystaniu podstawowej cechy rekurencji: dekompozycji problemu na pewną skończoną ilość podproblemów tego samego typu, rozwiązania podproblemów, połączeniu częściowych rozwiązań w celu odnalezienia rozwiązania globalnego. Jeśli oznaczymy problem do rozwiązania przez Pb, a rozmiar danych przez N, to zabieg wyżej opisany da się przedstawić za pomocą zapisu: • 1. Pb(N) → Pb(N 1) + Pb(N 2) +. . . + Pb(Nk) + KOMB(N). Problem „rzędu" N został podzielony na k podproblemów. Funkcja KOMB(N) nie jest rekurencyjna. Technika „dziel-i-rządź" pozwala w wielu przypadkach na zmianę klasy algorytmu (np. z O(n) do O(log 2 N) ). Istnieje grupa zadań, dla których zastosowanie metody „dziel-i-rządź" nie spowoduje przyspieszenia.
Sld 9. 3. Algorytmy typu „dziel-i-rządź“ - 2 Pb 0 Pb 1 Pbn Pbi °°° Pb 1, 1 Pb 1, k °°° Pbi, 1 °°° ° ° ° ° ° Pbi, l, Pb i, 1, t Pbi, 1, 1. °°° Pbn, 1 Pbn, s °°° ° ° ° ° °
Sld 9. 4. Quicksort Złożoność O(n log 2 n)
Sld 9. 5. Przeszukiwanie binarne Złożoność O(log 2 n)
Sld 9. 6. Znajdowanie zera funkcji metodą połowienia przedziału Ilość iteracji i = log 2((b – a)/ Δ; Δ – dokładność obliczeń y a x 2 x 4 x 3 x 1 b x x 1= a+½(b - a); y > 0; x 2= a+½(x 1 - a); y < 0; x 3= x 2+½(x 1 - x 2); y > 0; x 4= x 2+½(x 3 - x 2); y > 0; . .
Sld 8. 7. Algorytmy „zachłanne“ (“żarłoczne“, ”greedy”) • Cechą szczególną algorytmu „zachlannego" jest to, że w każdym etapie poszukiwania rozwiązania wybiera on opcję lokalnie optymalną. W zależności od tego doboru, rozwiązanie globalne może być również optymalne, ale nie jest to gwarantowane. y ymin, loc ymin x Δ = 1, 2, 3, 4, 5, 6 xopt
8. 8. Algorytm zachłanny (ang. greedy algorithm) – algorytm, który w celu wyznaczenia rozwiązania w każdym kroku dokonuje zachłannego, tj. najlepiej rokującego w danym momencie wyboru rozwiązania częściowego. Algorytm zachłanny nie patrzy czy w kolejnych krokach jest sens wykonywać dane działanie, dokonuje decyzji lokalnie optymalnej, dokonuje on wyboru wydającego się w danej chwili najlepszym, kontynuując rozwiązanie podproblemu wynikającego z podjętej decyzji. Typowe zadanie rozwiązywane metodą zachłanną ma charakter optymalizacyjny. W dziedzinie sztucznej inteligencji zachłanna odmiana przeszukiwania lokalnego jest nazywana "podchodzeniem pod wzgórze.
8. 9. Przykład Dany jest problem znalezienia trasy podróży z Madrytu do Rzeszowa. Można na niego spojrzeć jako problem z dziedziny teorii grafów – jeżeli z wierzchołkami grafu utożsami się punkty podróży (miasta, lotniska, stacje kolejowe, skrzyżowania dróg itp. ) a z krawędziami możliwe trasy przebiegu (autostrady, trasy przelotu samolotów, przejazdu pociągów itp. ), z wagami odpowiadającymi kosztom podróży (odległości, ceny biletów itp. ) to zadanie sprowadza się do odnalezienia minimalnej ścieżki łączącej wierzchołki opowiadające Madrytowi i Moskwie, a zbiór wszystkich rozwiązań C składa się z rozwiązań zarówno optymalnych jak i propozycji tras typu Madryt–Paryż –Berlin – Warszawa - Rzeszow czy nawet tak nieoptymalnych jak Madryt–Rzym–Hongkong–Pekin – Moskwa – Kijów – Lwów - Rzeszow.
9. 10. Poprawność rozwiązania zachłannego Nie istnieje ogólna metoda dowodzenia, czy dla danego problemu rozwiązanie zachłanne zawsze odnajduje poprawny i optymalny wynik. Istnieją jednak stosujące się do samego problemu kryteria, pozwalające sądzić, iż dla owego problemu istnieje rozwiązanie zachłanne.
9. 11. Własność zachłannego wyboru Za pomocą lokalnie optymalnych (zachłannych) wyborów można uzyskać optymalne rozwiązanie całego zadania. Własność optymalnej podstruktury – jest własnością problemów, które można rozwiązywać za pomocą algorytmów. Mówi się, że dany problem ma własność optymalnej podstruktury, jeżeli jego optymalne rozwiązanie jest funkcją optymalnych rozwiązań podproblemów. • Jeżeli problem wykazuje własność optymalnej podstruktury, to można znaleźć rozwiązujący go algorytm dynamiczny, a także zachłanny.
9. 12. Przeszukiwanie grafu • Przeszukiwanie grafu lub inaczej przechodzenie grafu to czynność polegająca na odwiedzeniu w jakiś usystematyzowany sposób wszystkich wierzchołków grafu w celu zebrania potrzebnych informacji. • Często podczas przejścia grafu rozwiązujemy już jakiś problem, ale przeważnie jest to tylko wstęp do wykonania właściwego algorytmu. • Powszechnie stosuje się dwie podstawowe metody przeszukiwania grafów: – przeszukiwanie wszerz (BFS), – przeszukiwanie w głąb (DFS).
9. 13. Przeszukiwanie wszerz • Przeszukiwanie wszerz (ang. Kolejność odwiedzania węzłów Breadth-first search, w skrócie BFS) – jeden z najprostszych algorytmów przeszukiwania grafu. • Przechodzenie grafu rozpoczyna się od zadanego wierzchołka s i polega na odwiedzeniu wszystkich osiągalnych z niego wierzchołków. • Wykorzystywany jest do odnajdywania najkrótszej drogi w grafie. • Wynikiem działania algorytmu jest także drzewo przeszukiwania wszerz o korzeniu w s, zawierające wszystkie wierzchołki Złożoność czasowa: O(|V|+|E|) do których prowadzi droga z s.
9. 14. Przeszukiwanie wszerz
9. 15. Przeszukiwanie w głąb polega na badaniu wszystkich krawędzi wychodzących z podanego wierzchołka. Po zbadaniu wszystkich krawędzi wychodzących z danego wierzchołka algorytm powraca do wierzchołka, z którego dany wierzchołek został odwiedzony. Kolejność odwiedzania węzłów Złożoność czasowa: O(|V|+|E|)
9. 16. Przechodzenie drzewa Istnieje 6 sposobów przejścia drzewa binarnego: VLR, LVR, LRV, VRL, RVL, RLV, gdzie: Visit - "odwiedź" węzeł, Left - idź w lewo, Right - idź w prawo. Wyróżnia się 3 pierwsze: • VLR - pre-order, przejście wzdłużne • LVR - in-order, przejście poprzeczne • LRV - post-order, przejście wsteczne • • W przypadku gdy dane drzewo jest binarnym drzewem AST przejścia określa się również: pre-order - prefiksowym, gdyż wynik odwiedzania poszczególnych węzłów jest trawestacją wyrażenia zawartego w strukturze AST do postaci przedrostkowej (notacji Łukasiewicza) in-order - infiksowym, gdyż trawestuje wyrażenie do postaci wrostkowej post-order - postfiksowym, gdyż trawestuje wyrażenie do postaci przyrostkowej (odwrotnej notacji polskiej)
9. 17. Podstawowe algorytmy odwiedzają węzły w następującej kolejności: • pre-order: F, B, A, D, C, E, G, I, H • post-order: A, C, E, D, B, H, I, G, F • in-order: A, B, C, D, E, F, G, H, I
9. 18. Algorytm Prima • Algorytm Prima – algorytm zachłanny wyznaczający tzw. minimalne drzewo rozpinające (MDR). • Mając do dyspozycji graf G = (V, E) nieskierowany i spójny, tzn. taki w którym krawędzie grafu nie mają ustalonego kierunku oraz dla każdych dwóch wierzchołków grafu istnieje droga pomiędzy nimi, algorytm oblicza podzbiór E' zbioru krawędzi E, dla którego graf nadal pozostaje spójny, ale suma kosztów wszystkich krawędzi zbioru E' jest najmniejsza możliwa. • Algorytm został wynaleziony w 1930 przez czeskiego matematyka Vojtěcha Jarníka, a następnie odkryty na nowo przez informatyka Roberta C. Prima w 1957 oraz niezależnie przez Edsgera Dijkstrę w 1959. Z tego powodu algorytm nazywany jest również czasami algorytmem Dijkstry–Prima, algorytmem DJP, algorytmem Jarníka, albo algorytmem Prima–Jarníka.
9. 19. Przekroj grafu Przekrojem w grafie G, oznaczanym przez (S 1, S 2) nazywamy zbior krawędzi, ktorych jeden koniec nalezy do S 1 a drugi do S 2: {S 1, S 2} = {{i, j}: i S 1, j S 2}. S 1 S 2
9. 20. Drzewo rozpinające (MDR). Niech T bedzie drzewem rozpinajacym grafu. Wtedy 1. Dla kazdej krawędzi {k, l} T istnieje w T jedyna droga od k do l. Krawedz {k, l} łacznie z ta droga tworza cykl. 2. Jesli z drzewa T usunie sie dowolna krawedz {i, j} to drzewo T rozpada sie na dwa rozłaczne podgrafy. Krawędzie grafu G, ktorych konce znajduja sie w roznych podgrafach tworza przekroj. S 1 i k j l S 2
9. 21. Przekroj drzewa S 1 S 2
9. 22. Twierdzenie Drzewo rozpinajace T* jest minimalne wtedy i tylkowtedy, gdy spełniony jest nastepujcy warunek: • Dla kazdej krawedzi {i, j} T* jest spełniona nierowność: cij ckl, gdzie {k, l} jest dowolna krawedzia nalezaca do przekroju otrzymanego z drzewa T*przez usuniecie z niego krawedzi {i, j}.
9. 23. Twierdzenie Drzewo rozpinajace T* jest minimalnym drzewem rozpinajacym wtedy i tylko wtedy, gdy jest spełniony nastepujacy warunek: • Dla kazdej krawedzi {k, l} grafu G nie nalezacej do T* ({k, l} T*) prawdziwa jest nierowność cij ckl, gdzie {i, j} jest dowolna krawedzia drogi łaczacej wezły k oraz l w T*.
9. 24. Schemat działania Algorytmu Prima 1. Utwórz drzewo zawierające jeden wierzchołek, dowolnie wybrany z grafu. 2. Powtarzaj, dopóki drzewo nie obejmuje wszystkich wierzchołków grafu: - wśród nieprzetworzonych wierzchołków (spoza obecnego MDR) wybierz ten, dla którego koszt dojścia z obecnego MDR jest najmniejszy, - dodaj do obecnego MDR wybrany wierzchołek i krawędź realizującą najmniejszy koszt. Uwaga: dodawana krawędz nie tworze cyklu z już utworzoną częścą MDR.
9. 25. Minimalne drzewo rozpinające (MDR) ψ(T*) = 1+2+2+3+1+1+2+1= 16 2 2 4 6 2 535 7 2 14 3 6 5 16 3 1 8 8 6 5 4 1 1 5 2 4 1 3 2 2 1 3 1 2 1 1
9. 26. Złożoność obliczeniowa Algorytmu Prima O(|E| log(|V|))
9. 27. Dowód poprawności Poprawność algorytmu polega na tym, iż w każdym kroku algorytm konstruuje MDR (za każdym razem wybierane są krawędzie o najmniejszej wadze) dla coraz większego zbioru wierzchołków. To indukuje stwierdzenie, iż w końcu uzyskiwane jest drzewo rozpinające dla całego grafu G.
9. 28. Algorytm Dijkstry. Znajdowania najkrótszej ścieżki Algorytm Dijkstry, opracowany przez holenderskiego informatyka E. Dijkstrę, służy do znajdowania najkrótszej ścieżki z pojedynczego źródła w grafie o nieujemnych wagach krawędzi. Działanie • Mając dany graf z wyróżnionym wierzchołkiem (źródłem) algorytm znajduje odległości od źródła do wszystkich pozostałych wierzchołków. • Łatwo zmodyfikować go tak, aby szukał wyłącznie (najkrótszej) ścieżki do jednego ustalonego wierzchołka, po prostu przerywając działanie w momencie dojścia do wierzchołka docelowego, bądź transponując tablicę incydencji grafu. • Algorytm Dijkstry znajduje w grafie wszystkie najkrótsze ścieżki pomiędzy wybranym wierzchołkiem a wszystkimi pozostałymi, wyliczając również koszt przejścia każdej z tych ścieżek. • Algorytm Dijkstry jest przykładem algorytmu zachłannego.
9. 29. Algorytm Dijkstry • • Przez S oznaczamy wierzchołek źródłowy, (i, j) - to waga krawędzi (i, j) w grafie. 1. 2. 3. 4. Stwórz tablicę d odległości od źródła dla wszystkich wierzchołków grafu. Na początku d[S] = 0. Dla wszystkich pozostałych wierzchołków d[v] = . Utwórz kolejkę priorytetową wszystkich wierzchołków grafu. Priorytetem kolejki jest aktualnie wyliczona odległość od wierzchołka źródłowego. 5. Dopóki kolejka nie jest pusta: - Usuń z kolejki wierzchołek u o najniższym priorytecie (wierzchołek najbliższy źródła, który nie został jeszcze rozważony), - Dla każdego sąsiada v wierzchołka u dokonaj relaksacji poprzez u : jeśli d[u] + (u, v) d(v), (poprzez u da się dojść do v szybciej niż dotychczasową ścieżką), to d(v): = d[u] + (u, v). Na końcu tablica d zawiera najkrótsze odległości do wszystkich wierzchołków.
9. 30. Algorytm Dijkstry
9. 31. Algorytm Dijkstry Ilustracja algorytmu Dijkstry dla znalezienia drogi od węzła początkowego do węzła celu. Otwarte węzły stanowią "wstępny" zestaw. Wypełnione są węzły odwiedzane. Węzły w wszystkich kierunkach różnych są badane w sposób jednolity, pojawiający się jako wavefront.
9. 32. Problem komiwojażera • Problem komiwojażera (TSP - ang. travelling salesman problem) jest to zagadnienie optymalizacyjne, polegające na znalezieniu minimalnego cyklu Hamiltona w pełnym grafie ważonym. • Nazwa pochodzi od typowej ilustracji problemu, przedstawiającej go z punktu widzenia wędrownego sprzedawcy (komiwojażera): dane jest n miast, które komiwojażer ma odwiedzić, oraz odległość/cena podróży/czas podróży pomiędzy każdą parą miast. Celem jest znalezienie najkrótszej/najtańszej/najszybszej drogi łączącej wszystkie miasta zaczynającej się i kończącej się w określonym punkcie. • Symetryczny problem komiwojażera (STSP) polega na tym, że dla dowolnych miast A i B odległość z A do B jest taka sama jak z B do A. W asymetrycznym problemie komiwojażera (ATSP) odległości te mogą być różne. • Rozwinięciem problemu komiwojażera jest problem marszrutyzacji.
9. 33. Przykład • Miasta: Kutno, Warszawa, Poznań, Kraków • • • Odległości: Kutno 0 Warszawa 130 Poznań 180 Kraków 300 Wars Poznań 130 180 0 320 0 350 360 Kraków 300 350 360 0 • Należy znaleźć najkrótszą trasę zaczynającą się np. z Kutna, przechodzącą jednokrotnie przez wszystkie pozostałe miasta i wracającą do Kutna.
Sld 9. 34. Ogólny problem plecakowy • Polega on na zapakowaniu do plecaka o ograniczonej pojemności możliwie najbardziej wartościowych rzeczy. W innych zastosowaniach, może to dotyczyć pakowania walizek, paczek, samochodu, samolotu itp. • Dane: – · n rzeczy R 1 R 2, . . . , Rn, każda w nieograniczonej ilości; · rzecz Ri waży wi i ma wartość pi. – · maksymalna pojemność plecaka, wynosząca Wmax. • Wyniki: Ilości ni, n 2, . . . , nn, poszczególnych rzeczy (mogą być zerowe),
Sld 9. 35. Algorytm zachłanny dla ogólnego problemu plecakowego W decyzjach ścierają się ze sobą trzy kryteria wyboru kolejnych rzeczy do zapakowania: 1. wybierać najcenniejsze rzeczy, czyli w kolejności nierosnących wartości pt; 2. wybierać rzeczy zajmujące najmniej miejsca, czyli w kolejności niemalejących wag wi 3. wybierać rzeczy najcenniejsze w stosunku do swojej wagi, czyli w kolejności nierosnących wartości ilorazu pi/wi.
Sld 9. 36. Przyklad problemu plecakowego Wmax = ∑ niwi ≤ 23
9. 37. Programowanie dynamiczne • Programowanie dynamiczne jest techniką lub strategią projektowania algorytmów, stosowaną przeważnie do rozwiązywania zagadnień optymalizacyjnych. Jest alternatywą dla niektórych zagadnień rozwiązywanych za pomocą algorytmów zachłannych. Wynalazcą techniki jest amerykański matematyk Richard Bellman, uhonorowany za to odkrycie medalem IEEE (ang. medal of honour) w 1979 roku. • Programowanie dynamiczne opiera się na podziale rozwiązywanego problemu na podproblemy względem kilku parametrów. W odróżnieniu od techniki dziel i zwyciężaj podproblemy w programowaniu dynamicznym nie są na ogół rozłączne, ale musi je cechować własność optymalnej podstruktury. Zagadnienia odpowiednie dla programowania dynamicznego cechuje również to, że zastosowanie do nich metody siłowej (ang. brute force) prowadzi do ponadwielomianowej liczby rozwiązań podproblemów, podczas gdy sama liczba różnych podproblemów jest wielomianowa.
9. 38. Programowanie dynamiczne • Zazwyczaj jednym z parametrów definiujących podproblemy jest liczba elementów znajdujących się w rozpatrywanym problemie, drugim jest pewna wartość liczbowa, zmieniająca się w zakresie od 0 do największej stałej występującej w problemie. Możliwe są jednak bardziej skomplikowane dobory parametrów, a także większa ich liczba. Ponieważ jednak uzyskiwany algorytm zazwyczaj wymaga pamięci (i czasu) proporcjonalnego do iloczynu maksymalnych wartości wszystkich parametrów, stosowanie większej ilości parametrów niż 3 -4 rzadko bywa praktyczne. • Klucz do zaprojektowania algorytmu tą techniką leży w znalezieniu równania rekurencyjnego opisującego optymalną wartość funkcji celu dla danego problemu jako funkcji optymalnych wartości funkcji celu dla podproblemów o mniejszych rozmiarach. • Programowanie dynamiczne znajduje optymalną wartość funkcji celu dla całego zagadnienia rozwiązując podproblemy od najmniejszego do największego i zapisując optymalne wartości w tablicy. Pozwala to zastąpić wywołania rekurencyjne odwołaniami do odpowiednich komórek wspomnianej tablicy i gwarantuje, że każdy podproblem jest rozwiązywany tylko raz. Rozwiązanie ostatniego z rozpatrywanych podproblemów jest na ogół wartością rozwiązania zadanego zagadnienia.
9. 39. Programowanie dynamiczne • Niejednokrotnie stosowanie techniki programowania dynamicznego daje w rezultacie algorytm pseudowielomianowy. Programowanie dynamiczne jest jedną z bardziej skutecznych technik rozwiązywania problemów NP-trudnych. Niejednokrotnie może być z sukcesem stosowana do względnie dużych przypadków problemów wejściowych, o ile stałe występujące w problemie są stosunkowo nieduże. • Programowanie dynamiczne może być również wykorzystywane jako alternatywna metoda rozwiązywania problemów zaliczanych do klasy P, o ile złożoność algorytmu wielomianowego nie jest satysfakcjonująca, a w praktyce, nawet dla dużych instancji problemu, wartości liczbowe występujące w problemie są niewielkie.
Sld 9. 40. Programowanie dynamiczne 1. koncepcja: • dla danego problemu P stwórz rekurencyjny model jego rozwiązania (wraz z jednoznacznym określeniem przypadków elementarnych); • stwórz tablicę, w której będzie można zapamiętywać rozwiązania przypadków elementarnych i rozwiązania podproblemów, które zostaną obliczone na ich podstawie; 2. inicjacja: • wpisz do tablicy wartości numeryczne, odpowiadające przypadkom elementarnym; 3. progresja: • na podstawie wartości numerycznych wpisanych do tablicy używając formuły rekurencyjnej, oblicz rozwiązanie problemu wyższego rzędu i wpisz je do tablicy; • postępuj w ten sposób do osiągnięcia pożądanej wartości.
Sld 9. 41. Ciąg Fibonacciego fib(0) = 1, fib(1) = 1, fib(n) = f(n - I) + fib(n - 2) gdzie n ≥ 2; Nf = 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, . . . Tablica dla zapamiętywania rozwiązania podproblemów: fib(5)=8 fib(4)=5 fib(3)=3 fib(2)=2 fib(0)=1 fib(1)=1 fib(3)=3 fib(2) = 2 fib(1)=1 fib(2)=2 fib(1)=1 fib(0)=1 fib(1)=1
Sld 9. 42. Dwuwymiarowy wzór rekurencyjny. Do obliczenia wartości P(i, j) potrzebna jest znajomość dwóch sąsiednich komórek: dolnej - P(ij-l) oraz tej znajdującej się z lewej strony - P(i-l, j). Naturalnym sposobem obliczania wartości P(i, j) będzie posuwanie się „zygzakiem" zaznaczonym na rysunku.
Sld 9. 43. Znajdowanie najkrótszej drogi do wyjścia z labiryntu 1. Rozpowszechnianie fali od pola S. 2. Zwinięcie fali od pola wyjścia C 1.
Sld 9. 53. Literatura 1. P. Wróblewski. Algorytmy. Struktury danych i techniki programowania. Helion. 2001. 2. K. A. Lambert, D. W. Nance, T. L. Naps. Introduction to Computer Science with C++. Books/Cole, 2000. 3. M. M. Syslo. Algorytmy. Warszawa, WSP, 1997. 4. Wikipedia.