Programowanie dynamiczne
Programowanie dynamiczne – technika lub strategia projektowania algorytmów, stosowana 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 (ang. IEEE Medal of Honor) przez IEEE 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ą 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.
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.
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. Na przykład w przypadku dyskretnego zagadnienia plecakowego jako parametry dynamiczne w metodzie programowania dynamicznego należy przyjąć rozmiar kolejno rozpatrywanych podzbiorów elementów oraz rozmiar plecaka, zmieniający się od 0 do wartości B danej w problemie.
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.
Przykłady zastosowań
[edytuj | edytuj kod]Algorytmy programowania dynamicznego są stosowane między innymi w informatyce, matematyce, bioinformatyce, ekonomii, i logistyce. Oto niektóre przykłady zastosowań programowania dynamicznego:
- algorytm Bellmana-Forda
- algorytm CYK
- algorytm Earleya
- algorytm Floyda-Warshalla
- algorytm Needlemana-Wunscha (dopasowywanie ciągów)
- algorytm Viterbiego
- algorytmy znajdujące najdłuższy wspólny podciąg
- algorytmy rozwiązujące zagadnienie plecakowe
- znajdowanie rozwiązania problemu optymalnego nawiasowania macierzy
- obliczanie odległości Levenshteina
- wybór instrukcji niskiego poziomu w kompilatorach (ang. instruction selection)
- algorytm znajdujący cykl Hamiltona (problem komiwojażera)
- estymatory wielopunktowe funkcji skojarzonych Buchalskiego (dyskretyzacja wielomianowa)
Bibliografia
[edytuj | edytuj kod]- Richard Bellman. On the Theory of Dynamic Programming. Proceeding of the National Academy of Sciences (USA). 1952.
- Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein, 2001. Introduction to Algorithms, 2nd ed. MIT Press & McGraw-Hill. ISBN 0-262-03293-7. Zwłaszcza rozdział 15: 323–69. (klasyczny wykład podręcznikowy na poziomie podstawowym)
- Juraj Hromkovič. Algorithmics for Hard Problems. Introduction to Combinatorial Optimization, Randomization, Approximation, and Heuristics. 2nd ed. Springer Verlag 2004. ISBN 3-540-44134-4. Rozdział 3.2: 152–7 (zwięzła prezentacja teoretyczna)