Dynamické programování

Dynamické programování v teorii řízení a teorii počítačových systémů  je způsob řešení složitých problémů jejich rozdělením na jednodušší dílčí úkoly. Je použitelný pro problémy s optimální podstrukturou, které vypadají jako soubor překrývajících se dílčích problémů, jejichž složitost je o něco menší než u původního. V tomto případě může být doba výpočtu ve srovnání s "naivními" metodami výrazně zkrácena.

Klíčová myšlenka dynamického programování je poměrně jednoduchá. K vyřešení problému je zpravidla nutné vyřešit jednotlivé části problému (podproblém) a následně sloučit řešení dílčích úkolů do jednoho společného řešení. Mnoho z těchto dílčích úkolů je často stejných. Přístup dynamického programování spočívá v řešení každého dílčího problému pouze jednou, čímž se sníží počet výpočtů. To je užitečné zejména v případech, kdy je počet opakujících se dílčích úkolů exponenciálně velký.

Metoda dynamického programování shora  je jednoduchým zapamatováním výsledků řešení těch dílčích problémů, se kterými se může v budoucnu znovu setkat. Dynamické programování zdola zahrnuje přeformulování složitého problému jako rekurzivní sekvence jednodušších dílčích problémů.

Historie

Fráze „dynamické programování“ byla poprvé použita ve 40. letech 20. století Richardem Bellmanem k popisu procesu hledání řešení problému, kdy odpověď na jeden problém lze získat až po vyřešení problému, který mu „předcházel“. V roce 1953 tuto definici zdokonalil na moderní. Obor byl původně založen jako systémová analýza a inženýrství, což bylo uznáno IEEE . Bellmanův příspěvek k dynamickému programování byl zvěčněn ve jménu Bellmanovy rovnice , ústředního výsledku teorie dynamického programování, která přeformuluje optimalizační problém v rekurzivní formě.

Slovo „programování“ ve spojení „dynamické programování“ ve skutečnosti nemá téměř nic společného s „tradičním“ programováním (psáním kódu) a dává smysl jako ve spojení „ matematické programování “, které je synonymem slova „optimalizace“. Proto slovo „program“ v tomto kontextu spíše znamená optimální sled akcí k získání řešení problému. Například konkrétní plán akcí na výstavě je někdy označován jako program. Program je v tomto případě chápán jako platný sled událostí.

Myšlenka dynamického programování

Optimální podstruktura v dynamickém programování znamená, že k vyřešení původního problému lze použít optimální řešení menších dílčích problémů. Například nejkratší cestu v grafu z jednoho vrcholu (označeného s) do druhého (označeného t) lze nalézt následovně: nejprve vezmeme v úvahu nejkratší cestu ze všech vrcholů sousedících s s do t a poté vezmeme s ohledem na váhy hran, které spojují s se sousedními vrcholy, zvolíme nejlepší cestu k t (kterým vrcholem je nejlepší projít). V obecném případě můžeme problém, který má optimální podstrukturu, vyřešit provedením následujících tří kroků.

  1. Rozdělení úkolu na menší dílčí úkoly.
  2. Nalezení optimálního řešení dílčích problémů rekurzivně pomocí stejného tříkrokového algoritmu .
  3. Využití získaného řešení dílčích úloh ke konstrukci řešení původního problému.

Podproblémy se řeší tak, že se rozdělují na ještě menší podproblémy a tak dále, dokud nedojdou k triviálnímu případu problému, který lze vyřešit v konstantním čase (odpověď lze říci okamžitě). Pokud například potřebujeme najít n!, pak 1! = 1 (nebo 0! = 1).

Překrývající se podproblémy v dynamickém programování znamenají podproblémy, které se používají k řešení řady problémů (nejen jednoho) větší velikosti (to znamená, že totéž děláme několikrát). Pozoruhodným příkladem je výpočet Fibonacciho posloupnosti a - i  v takovém triviálním případě jsme již dvakrát počítali výpočty pouze dvou Fibonacciho čísel. Pokud budete pokračovat dále a počítat , pak se to započítá ještě dvakrát, protože znovu a bude potřeba pro výpočet . Ukazuje se následující: jednoduchý rekurzivní přístup stráví čas výpočtem řešení problémů, které již vyřešil.

Abychom se takovému průběhu událostí vyhnuli, uložíme si řešení podproblémů, které jsme již vyřešili, a až budeme znovu potřebovat řešení podproblému, místo přepočítávání jej jednoduše získáme z paměti. Tento přístup se nazývá memoizace . Můžete také provádět další optimalizace - například pokud jsme si jisti, že již nepotřebujeme řešit dílčí úlohu, můžeme ji vyhodit z paměti a uvolnit ji pro jiné potřeby, nebo pokud je procesor nečinný a víme, že řešení některých dílčích úkolů, které ještě nebyly spočítány, potřebujeme v budoucnu, můžeme je vyřešit předem.

Shrneme-li výše uvedené, můžeme říci, že dynamické programování využívá následující vlastnosti problému:

Dynamické programování obecně sleduje dva přístupy k řešení problémů:

Programovací jazyky si mohou zapamatovat výsledek volání funkce s určitou sadou argumentů ( memoization ), aby se urychlil „výpočet podle jména“. Některé jazyky mají tuto schopnost zabudovanou (např . Scheme , Common Lisp , Clojure , Perl , D ), zatímco jiné vyžadují další rozšíření ( C++ ).

Známé jsou sériové dynamické programování, které je obsaženo ve všech učebnicích operačního výzkumu , a nesériové dynamické programování (NSDP), které je v současnosti málo známé, ačkoli bylo objeveno v 60. letech 20. století.

Konvenční dynamické programování je speciálním případem nesériového dynamického programování, kde je graf vztahu proměnných pouze cestou. NSDP, která je přirozenou a obecnou metodou pro zohlednění struktury optimalizačního problému, považuje množinu omezení a/nebo účelovou funkci za rekurzivně vypočítatelnou funkci. To umožňuje najít řešení krok za krokem, v každé fázi pomocí informací získaných v předchozích fázích, a účinnost tohoto algoritmu přímo závisí na struktuře grafu proměnných vztahů. Pokud je tento graf dostatečně řídký, pak lze množství výpočtů v každé fázi udržet v rozumných mezích.

Jednou z hlavních vlastností problémů řešených pomocí dynamického programování je aditivnost . Neaditivní problémy se řeší jinými metodami. Například mnoho úkolů optimalizace investic společnosti není aditivní a řeší se porovnáním hodnoty společnosti s investicemi a bez nich.

Klasické problémy dynamického programování

Literatura

Odkazy