Algorytmy zachłanne dr inż. Urszula Gałązka
Algorytm zachłanny O Dokonuje wyboru, który w danej chwili wydaje się najkorzystniejszy. O Mówimy, że jest to wybór lokalnie optymalny O W rzeczywistości nie zawsze jest to optymalne rozwiązanie, chociaż dla wielu problemów jest ono wystarczające O Podejmowane wybory mogą zależeć od wcześniej podjętych decyzji ale nie mogą zależeć od przyszłych wyborów czy rozwiązań podproblemów
W jakich algorytmach stosuje się algorytmy zachłanne O Algorytm wyznaczania minimalnego drzewa rozpinającego O Algorytm Dijkstry do znajdowania najkrótszej ścieżki w grafie startujący od wybranego wierzchołka O Problem wyboru zajęć O Kodowanie Huffmana
Własności Wyboru zachłannego Dokonując lokalnie optymalnych (zachłannych) wyborów możemy uzyskać rozwiązanie globalnie optymalne Optymalna podstruktura optymalne rozwiązanie problemu zawiera w sobie optymalne rozwiązania prodproblemów
Algorytm Zachłanny Schemat działania Oznaczenia: W zbiór danych wejściowych, rozwiązania zbiór, który posłuży do konstrukcji rozwiązania, X- element zbioru wybierz(d) funkcja wybierająca optymalnie element ze zbioru D i usuwająca go z niego, pasuje(x) Czy wybierając X uda się skompletować rozwiązanie cząstkowe, aby odnaleźć, co najmniej jedno rozwiązanie globalne? znalazlem(s) Czy S jest rozwiązaniem zadania?
Algorytm Zachłanny Schemat działania
Programowanie dynamiczne a zachłanne
Problem plecakowy Dyskretny (ang. 0-1 knapsack problem) Mamy do dyspozycji n przedmiotów. Każdy przedmiot i jest wart v i złotych i waży w i kilogramów. Zarówno v i jak i w i są nieujemne i całkowite. Zadanie mamy spakować do plecaka jak najwięcej najbardziej wartościowych przedmiotów ale tak by nie przekroczyć W kilogramów. Uwaga przedmioty pakujemy w całości, więc musimy zdecydować czy dany przedmiot bierzemy (tak 1) do plecaka czy nie bierzemy (nie 0). Ponadto możemy użyć każdy przedmiot tylko jeden raz. Ciągły Ponownie mamy do dyspozycji n przedmiotów o odpowiednich wartościach i wadze. I tak samo jak poprzednio ładujemy plecak. Jednak tym razem możemy zabierać części ułamkowe przedmiotów (np. gdy mamy czekoladę to zamiast całej tabliczki bierzemy kilka jej kostek).
Przedmiot 1 Przedmiot 2 Przedmiot 3 Plecak Problem plecakowy v i 60 100 120 n.d. w i 10 20 30 50 v i /w i 6 5 4 n.d.
Problem plecakowy algorytm zachłanny O Obliczamy stosunek wartości do masy v i /w i O Najpierw wybieramy największą możliwą ilość najbardziej wartościowego przedmiotu O Jeśli mamy miejsce w plecaku wybieramy następny przedmiot i tak dalej aż wyczerpie się miejsce w plecaku O Strategia zadziała dla problemu ciągłego dla dyskretnego będzie niewłaściwa.
Dyskretny problem plecakowy możliwe przypadki
Przedmiot 1 Przedmiot 2 Przedmiot 3 Plecak Ciągły problem plecakowy v i 60 100 2/3*120 240 w i 10 20 2/3*30 50 ilość 1 1 2/3
Kodowanie Huffmana
Kod Huffmana O Służą do kompresji danych i dają oszczędności rzędu od 20% do 90%. O Do kodowania wykorzystuje się częstotliwość występowania znaków. O Częstotliwość zapisuje się w postaci liczby całkowitej lub w postaci ułamka oznaczającego O prawdopodobieństwo wystąpienia liczby. Można też wykorzystać tabelę z obliczoną częstotliwością występowania liter dla danego języka np. polskiego lub angielskiego. O To kod prefiksowym. Oznacza to, że żadne słowo kodowe nie może być prefiksem innego słowa kodowego.
Tablica częstotliwości występowania liter w alfabecie polskim a 8.91% w 4.65% p 3.13% g 1.42% ć 0.40% i 8.21% s 4.32% m 2.80% ę 1.11% f 0.30% o 7.75% t 3.98% u 2.50% h 1.08% ń 0.20% e 7.66% c 3.96% j 2.28% ą 0.99% q 0.14% z 5.64% y 3.76% l 2.10% ó 0.85% ź 0.06% n 5.52% k 3.51% ł 1.82% ż 0.83% v 0.04% r 4.69% d 3.25% b 1.47% ś 0.66% x 0.02% Źródło: Przepiórkowski Adam, odpowiedź na pytanie Frekwencja liter polskich w tekście, 20.03.2006 https://sjp.pwn.pl/poradnia/haslo/;7072 Dostęp: 14.11.2017
Tablica częstotliwości występowania liter w alfabecie angielskim e 12,70% h 6,09% w 2,36% k 0,77% t 9,06% r 5,99% f 2,23% j 0,15% a 8,17% d 4,25% g 2,02% x 0,15% o 7,51% l 4,03% y 1,97% q 0,10% i 6,97% c 2,78% p 1,93% z 0,07% n 6,75% u 2,76% b 1,49% s 6,33% m 2,41% v 0,98% Źródło: Opracowano na podstawie artykułu Letter Frequency, Wikipedia, https://en.wikipedia.org/wiki/letter_frequency, dostęp: 14.11.2017
Inne zastosowania znajomości częstotliwości liter Łamanie szyfrów podstawieniowych Rozwiązywanie szyfrówek Odczytywanie prac studentów ;-) Każdej literze jest jednoznacznie przyporządkowany inny znak Każdej literze odpowiada cyfra Dane są 2, 3 lub więcej liter Zamiana kroju czcionki na symboliczny problem można rozwiązać wybierając czcionkę np. Arial
Kod Huffmana O Przyjmijmy, że mamy dany plik z 100 znakami i danymi częstotliwościami występowania poszczególnych liter jak w tabeli poniżej. O Każdy znak możemy zakodować za pomocą kodu binarnego (w skrócie kodu) w postaci ciągu bitów zwanego słowem kodowym. znak a b c d e f częstość 46 11 12 17 8 6 słowo 000 001 010 011 100 101 kodowe o stałej długości słowo kodowe o zmiennej długości 0 100 101 110 1110 1111
Reprezentacja Kod Huffmana Drzewo binarne Liście zawierają zakodowane znaki, Kod binarny dla znaku będzie odczytujemy jako prostą ścieżkę od korzenia do danego znaku. Przyjmiemy, że 0 będzie oznaczać, przejście do lewego syna a 1 przejście do prawego syna w drzewie. Optymalny kod Reprezentuje go regularne drzewo binarne, w którym każdy węzeł wewnętrzny ma dwóch synów. Jeśli nasz alfabet oznaczymy przez C to drzewo optymalnego kodu prefiksowego ma dokładnie C liści, po jednym dla każdej litery alfabetu oraz dokładnie C -1 węzłów wewnętrznych.
Wzór na liczbę bitów potrzebnych do zakodowanie pliku: B T = z c d T (c) gdzie: c C O z c częstotliwość wystąpienia znaku c, O d T (c) oznacza głębokość liścia znaku c w drzewie T, jest to także długość słowa kodowego dla znaku c. O c znak z alfabetu C
Obliczanie kodu Huffmana O O O O Przyjmijmy, że C jest zbiorem n znaków i że każdy znak c C jest obiektem o znanej częstotliwości (liczbie wystąpień) z c. Algorytm buduje drzewo T, odpowiadające optymalnemu kodowi metodą wstępującą od liści do korzenia. Rozpoczynamy od zbioru C liści i wykonujemy C -1 scaleń aż otrzymamy końcowe drzewo. W algorytmie korzystamy z kolejki priorytetowej Q typu min, z atrybutami z w roli kluczy, do wyznaczania dwóch obiektów o najmniejszej liczbie wystąpień, które należy scalić. W wyniku tego działania otrzymujemy nowy obiekt, którego liczba wystąpień to suma liczby wystąpień jego składowych
Kod Huffmana Algorytm opisowy O Powtarzamy czynności: O W każdym kroku wybieramy dwa węzły o najmniejszych wartościach i łączymy je w jeden węzeł O Kiedy wyczerpią nam się elementy w zbiorze mamy gotowe drzewo. O Wówczas na każdą gałąź wpisujemy etykietę: Wpisujemy etykiety: 0 na lewą gałąź a 1 na prawą. O Odczytujemy ciągi zer i jedynek idąc od korzenia do każdego liścia. Powstały ciąg to kod dla litery
Dekodowanie Przykładowy tekst: 00111110010000 0 0 1111 100 100 0 0 a a f b b b a a
Kod Huffmana - Pseudokod
Bibliografia Literatura: Cormen Thomas; Leiserson Charles; Rivest Ronald; Stein Clifford, Wprowadzenie do Algorytmów, Wydawnictwo Naukowe PWN, Warszawa 2012 Sedgewick Robert, Algorytmy w C++, Wydawnictwo RM, Warszawa 1999, Drozdek Adam, C++. Algorytmy i Struktury Danych, Wydawnictwo Helion, Gliwice 2004, Przepiórkowski Adam, odpowiedź na pytanie Frekwencja liter polskich w tekście, 20.03.2006, https://sjp.pwn.pl/poradnia/haslo/;7072 dostęp: 14.11.2017 Wikipedia, https://en.wikipedia.org/wiki/letter_frequency dostęp: 14.11.2017 Wróblewski Piotr, Algorytmy, Struktury Danych i Techniki Programowania, Wydawnictwo Helion, Gliwice 2010, Rysunki: opracowanie własne