Programowanie dynamiczne (optymalizacja dynamiczna).

Podobne dokumenty
Programowanie dynamiczne cz. 2

Wstęp do Programowania potok funkcyjny

Techniki konstruowania algorytmów. Metoda dziel i zwyciężaj

Schemat programowania dynamicznego (ang. dynamic programming)

Projektowanie i analiza algorytmów

Programowanie dynamiczne

Algorytmy i Struktury Danych

Algorytmy i struktury danych.

Sortowanie przez scalanie

Strategia "dziel i zwyciężaj"

Programowanie dynamiczne

Struktury danych i złożoność obliczeniowa Wykład 2. Prof. dr hab. inż. Jan Magott

Zadanie 1 Przygotuj algorytm programu - sortowanie przez wstawianie.

Programowanie dynamiczne i algorytmy zachłanne

Struktury danych i złozoność obliczeniowa. Prof. dr hab. inż. Jan Magott

Zaawansowane algorytmy i struktury danych

Programowanie dynamiczne

Wstęp do programowania

Analiza algorytmów zadania podstawowe

Algorytmy w teorii liczb

Algorytmy i struktury danych. Co dziś? Tytułem przypomnienia metoda dziel i zwyciężaj. Wykład VIII Elementarne techniki algorytmiczne

Definicja. Ciąg wejściowy: Funkcja uporządkowująca: Sortowanie polega na: a 1, a 2,, a n-1, a n. f(a 1 ) f(a 2 ) f(a n )

TEORETYCZNE PODSTAWY INFORMATYKI

Wykład 3. Metoda dziel i zwyciężaj

Wstęp do programowania

Wykład 10 Grafy, algorytmy grafowe

Wstęp do programowania

Rekurencja/rekursja. Iluzja istnienia wielu kopii tego samego algorytmu (aktywacji) Tylko jedna aktywacja jest aktywna w danej chwili

Wieczorowe Studia Licencjackie Wrocław, Wykład nr 6 (w oparciu o notatki K. Lorysia, z modyfikacjami) Sito Eratostenesa

TEORETYCZNE PODSTAWY INFORMATYKI

Modele i narzędzia optymalizacji w systemach informatycznych zarządzania

//warunki początkowe m=500; T=30; c=0.4; t=linspace(0,t,m); y0=[-2.5;2.5];

Wstęp do programowania

Algorytmy i Struktury Danych.

Złożoność obliczeniowa algorytmu ilość zasobów komputera jakiej potrzebuje dany algorytm. Pojęcie to

Temat: Algorytmy zachłanne

Teoretyczne podstawy informatyki

Efektywna metoda sortowania sortowanie przez scalanie

Technologia informacyjna Algorytm Janusz Uriasz

Porównanie czasów działania algorytmów sortowania przez wstawianie i scalanie

Algorytmy i struktury danych IS/IO, WIMiIP

EGZAMIN - Wersja A. ALGORYTMY I STRUKTURY DANYCH Lisek89 opracowanie kartki od Pani dr E. Koszelew

Wykład 2. Poprawność algorytmów

Wykład 4: Iteracja, indukcja i rekurencja

Wykład 5: Iteracja, indukcja i rekurencja Sortowanie

Wykład 4. Określimy teraz pewną ważną klasę pierścieni.

Złożoność obliczeniowa zadania, zestaw 2

Algorytmy i Struktury Danych, 2. ćwiczenia

Maciej Piotr Jankowski

Sortowanie danych. Jolanta Bachan. Podstawy programowania

Struktury danych i złożoność obliczeniowa Wykład 5. Prof. dr hab. inż. Jan Magott

Algorytmy i str ruktury danych. Metody algorytmiczne. Bartman Jacek

Ę Ą Ł Ę Ł ć

Ż Ć Ź Ź Ż Ą Ą ć Ź Ź Ć Ę

Ę Ą Ż ć Ę Ż Ł ź

Ą Ą Ł

ć Ę Ę ć Ę ć Ę Ę Ę

ć Ę ć ć ć ć ą

Ą Ą

ż

Algorytmy i złożoność obliczeniowa. Wojciech Horzelski

Algorytm simplex i dualność

Transformata Fouriera. Sylwia Kołoda Magdalena Pacek Krzysztof Kolago

Struktury danych i złożoność obliczeniowa Wykład 7. Prof. dr hab. inż. Jan Magott

Rekurencja. Dla rozwiązania danego problemu, algorytm wywołuje sam siebie przy rozwiązywaniu podobnych podproblemów. Przykład: silnia: n! = n(n-1)!

Podstawy programowania. Podstawy C# Przykłady algorytmów

12. Rekurencja. UWAGA Trzeba bardzo dokładnie ustalić <warunek>, żeby mieć pewność, że ciąg wywołań się zakończy.

Matematyczne Podstawy Informatyki

Algorytm i złożoność obliczeniowa algorytmu

Teoretyczne podstawy informatyki

Jeśli czas działania algorytmu zależy nie tylko od rozmiaru danych wejściowych i przyjmuje różne wartości dla różnych danych o tym samym rozmiarze,

Rekurencja. Przygotowała: Agnieszka Reiter

Technologie informacyjne Wykład VII-IX

Podstawy Informatyki. Sprawność algorytmów

Teoria obliczeń i złożoność obliczeniowa

Poprawność semantyczna

Wykład 8. Rekurencja. Iterować jest rzeczą ludzką, wykonywać rekursywnie boską. L. Peter Deutsch

Zaprojektować i zaimplementować algorytm realizujący następujące zadanie.

Zaawansowane algorytmy i struktury danych

INFORMATYKA WYBRANE ALGORYTMY OPTYMALIZACYJNE KRYPTOLOGIA.

Ćwiczenie 3 Programowanie dynamiczne

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 9. Karol Tarnowski A-1 p.

Język ludzki kod maszynowy

Efektywność algorytmów

Wstęp do programowania INP001213Wcl rok akademicki 2017/18 semestr zimowy. Wykład 13. Karol Tarnowski A-1 p.

Programowanie w VB Proste algorytmy sortowania

Wstęp do programowania INP001213Wcl rok akademicki 2018/19 semestr zimowy. Wykład 13. Karol Tarnowski A-1 p.

Za pierwszy niebanalny algorytm uważa się algorytm Euklidesa wyszukiwanie NWD dwóch liczb (400 a 300 rok przed narodzeniem Chrystusa).

ZŁOŻONOŚĆ OBLICZENIOWA ALGORYTMÓW

Klasyczne zagadnienie przydziału

Programowanie równoległe

Generowanie liczb o zadanym rozkładzie. ln(1 F (y) λ

TEORETYCZNE PODSTAWY INFORMATYKI

Rekurencje. Jeśli algorytm zawiera wywołanie samego siebie, jego czas działania moŝe być określony rekurencją. Przykład: sortowanie przez scalanie:

Uwaga: Funkcja zamień(a[j],a[j+s]) zamienia miejscami wartości A[j] oraz A[j+s].

9. Schematy aproksymacyjne

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Problemy porządkowe zadania

[12] Metody projektowania algorytmów (dziel i rządź, programowanie dynamiczne i algorytmy zachłanne).

Transkrypt:

Programowanie dynamiczne (optymalizacja dynamiczna). W wielu przypadkach zadania, których złożoność wynikająca z pełnego przeglądu jest duża (zwykle wyk ładnicza) można rozwiązać w czasie wielomianowym stosując metodę optymalizacji dynamicznej. Programowanie dynamiczne - metoda znajdowania rozwiązań problemów optymalizacyjnych podobna do metody dziel i zwyciężaj - w metodzie tej zadany problem dzielimy na podproblemy, rozwiązujemy je, a następnie łączymy rozwiązania podproblemów. metoda dziel i zwyciężaj - wielokrotnie rozwiązuje ten sam problem, wykonuje więc dużo więcej pracy programowanie dynamiczne - algorytm oparty na tej metodzie rozwiązuje każdy podproblem tylko jeden raz zapamiętując wynik, unika się w ten sposób wielokrotnych obliczeń dla tego samego podproblemu

Rozpatrzmy rekurencyjny algorytm obliczający ciąg Fibonacciego: Fib(0)= 0 Fib(1)=1 Fib(n)= Fib(n-1)+Fib(n-2) dla n 2 int Fib( int n ) { if( n < 1 ) return 0; if( n == 1 ) return 1; return Fib(n-1) + Fib(n-2); [Fib(5)] = Fib(4) + Fib(3) [Fib(4)] = Fib(3) + Fib(2) [Fib(3)] = Fib(2) + Fib(1) [Fib(3)] = Fib(2) + Fib(1) [Fib(2)] = Fib(1) + Fib(0) [Fib(2)] = Fib(1) + Fib(0) [Fib(2)] = Fib(1) + Fib(0)

Algorytm rekurencyjny mo ż na poprawi ć wykorzystuj ą c tak zwane "zapamiętywanie". Wykorzystujemy w tym celu tablicę zawierającą już obliczone wartości: int fib[max]; // inicjujemy ją, aby oznaczyć wszystkie wartości jako "nieznane" for( i= 0; i < MAX; i++ ) fib[i]= -1; int Fib( int n { if ( n < 1 ) return 0; if ( n == 1 ) return 1; if ( fib[n] == -1 ) fib[n]= Fib(n-1) + Fib(n-2); return fib[n];

Etapy programowania dynamicznego Scharakteryzowanie struktury optymalnego rozwiązania Rekurencyjne zdefiniowanie kosztu optymalnego rozwiązania. Obliczenie optymalnego kosztu metodą wstępującą. Konstruowanie optymalnego rozwiązania na podstawie wcześniejszych obliczeń. Problem: Dla danego ciągu n macierzy <A 1, A 2,..., A n >, gdzie dla i=1, 2,..., n macierz A i ma wymiar p i-1 x p i, wyznaczyć taką kolejność mnożenia macierzy A 1 A 2... A n aby koszt obliczeń był jak najmniejszy.

Pseudokod standardowego algorytmu mnożenia dwóch macierzy MNOŻENIE_MACIERZY(A,B) { if ile_kolumn[a] ile_wierszy[b] then error else { for i=1 to ile_wierszy[a] for j=1 to ile_kolumn[b] do { C[i,j]:=0 for k=1 to ile_kolumn[a] do C[i,j]:=C[i,j]+A[i,k] B[k,j] return C

Obserwacja: Czas obliczeń jest zdeterminowany przez ilość mnożeń skalarnych. Jeśli A i B są macierzami o rozmiarze odpowiednio p x q i q x r, to ilość mnożeń wynosi pqr. Przykład: A1 o rozmiarze 10 x 100 A2 o rozmiarze 100 x 5 A3 o rozmiarze 5 x 50 Ile mnożeń skalarnych? ((A1A2)A3) 10 x 100 x 5 + 10 x 5 x 50 = 5000 + 2500 = 7500 (A1(A2A3) 100 x 5 x 50 + 10 x 100 x 50 = 25000 + 50000=75000

Struktura optymalnego rozwiązania Oznaczenie: A i..j =Ai A i+1 A j Obserwacja: Umieszczenie nawiasów w podci ą gu A 1 A 2 A k w optymalnym nawiasowaniu A 1 A 2 A n jest optymalnym nawiasowaniem A 1 A 2 A k. Dowód: Gdyby istniało nawiasowanie A 1 A 2 A k o niższym koszcie, to w połączeniu z optymalnym nawiasowaniem A 1 A 2 A n otrzymalibyśmy nawiasowanie A 1 A 2 A k o koszcie niższym czyli sprzeczność.

Zdefiniowanie rekurencyjne kosztu optymalnego. Podproblemy: wyznaczenie optymalnego nawiasowania iloczynów Ai A i+1 A j gdzie 1 i j n Oznaczenie: m[i, j] minimalna liczba mnożeń skalarnych niezbędnych do obliczenia macierzy A i..j Oznaczenie: s[i, j] wartość k, która realizuje minimalną wartość m[i, j] Niech dane wejściowe stanowi ciąg <p 0, p 1,...,p n > rozmiarów macierzy, gdzie d ł ugość [p]=n+1, uż ywamy macierzy m[1..n,1..n] oraz s[1..n,1..n] do zapamiętywania kosztów oraz indeksów k dających optymalny podział

MACIERZE_KOSZT(p) n:=długość[p]-1 for i=1 to n do m[i, i]:=0 for w=2 to n do { for i=1 to n-w+1 do { j=i+w-1 m[i,j]:= for k=i to j-1 do { q:=m[i,k]+m[k+1,j]+p i-1 p k p j if q<m[i,j] then { m[i,j]:=q, s[i,j]:=k return (m, s)

Konstruowanie optymalnego rozwiązania MNOŻENIE_ŁAŃCUCHA_MACIERZY(A, s, i, j) if j>i then X:= MNOŻENIE_ŁAŃCUCHA_MACIERZY(A, s, i, s[i, j]) Y:= MNOŻENIE_ŁAŃCUCHA_MACIERZY(A, s, s[i, j]+1, j) return MNOŻENIE_MACIERZY(X, Y) else return Ai

Charakterystyczne elementy metody programowania 1.Problem wykazuje optymalną podstrukturę, jeśli jego optymalne rozwiązanie jest funkcją optymalnych rozwiązań podproblemów; metoda dowodzenia jest następująca: zakładamy, że jest lepsze rozwiązanie podproblemu, po czym pokazujemy, iż to założenie zaprzecza optymalności rozwiązania całego problemu 2. Rozsądnie mała przestrzeń istotnie różnych podproblemów. Mówimy, że problem ma w ł asno ść wspólnych podproblemów, jeś li algorytm rekurencyjny wielokrotnie oblicza rozwiązanie tego samego podproblemu bo algorytmy oparte na programowaniu dynamicznym rozwiązują dany podproblem tylko jeden raz i zapamiętują gotowe rozwiązania, które potem wystarczy odczytać w stałym czasie. Jeśli problem wykazuje te własności warto spróbować, czy daje się stosować metoda programowania dynamicznego.

PROBLEM NAJDŁUŻSZEGO WSPÓLNEGO PODCIĄGU (Problem LCS) Problem znalezienia Najdłuższego Wspólnego Podciągu (LCS Longest Common Subsequences) pojawia się w kilku praktycznych zastosowaniach : 1.Poszukiwanie podobieństwa dwóch pary nici DNA jako jednej z miar stopnia pokrewieństwa odpowiadających im organizmów 2.Wył apywanie plagiatów muzycznych poprzez analiz ę ich linii melodycznych 3.Porównywanie zawartości plików 4.Kryptografii Najefektywniejsza metoda jego rozwiązania opiera się na programowaniu dynamicznym.

Dane są ciągi: X = <x 1, x 2,..., x m > i Y = <y 1, y 2,..., y n >. Problem: Znaleźć najdłuższy wspólny podciąg ciągów X i Y. Jak działa algorytm wyczerpujący? Bierzemy krótszy z ciągów (załóżmy, że jest to X), generujemy wszystkie podciągi ciągu X, sprawdzamy, który podciąg jest też podciągiem Y, zapamiętujemy najdłuższy podciąg. Ile jest podciągów ciągu X? Każdy podciąg ciągu X jest jednoznacznie wyznaczony przez pewien podzbiór zbioru {1, 2,..., m, zatem ilość podciągów jest równa ilości podzbiorów zbioru {1, 2,.., m, czyli 2 m. Czyli razem ze sprawdzeniem O(2 m n). Wniosek: algorytm wyczerpujący ma złożoność wykładniczą!.

Struktura optymalnego rozwiązania Na szczęście ten problem ma własność optymalnej podstruktury i naturalna przestrzeń podproblemów odpowiada w tym przypadku parom prefiksów ciągów wejściowych. Oznaczenie: Niech X = <x 1, x 2,..., x m > i Xi = <x 1, x 2,..., x i > dla i=0,1,2,...,m będzie i-tym prefiksem ciągu X, przy czym Xo jest ciągiem pustym. Twierdzenie (o optymalnej podstrukturze NWP) Niech X = <x1, x2,..., xm> i Y= <y1, y2,..., yn> oraz niech Z = <z1, z2,..., zk> będzie NWP ciągów X i Y. Wtedy: jeśli xm = yn, to zk= xm=yn oraz Zk-1 jest NWP(Xm-1, Yn-1) jeśli x m yn i zk xm, to Z jest NWP(Xm-1,Y), jeśli x m yn i zk yn, to Z jest NWP(X, Yn-1).

Rekurencyjne zdefiniowanie kosztu optymalnego rozwiązania Obserwacja: Z twierdzenia wynika, że aby obliczyć NWP(X, Y) trzeba rozwiązać jeden lub dwa podproblemy: jeżeli xm = yn, to znajdujemy NWP(Xm-1, Yn-1), a następnie dołączając xm=yn otrzymujemy NWP(X, Y) jeżeli xm yn, to znajdujemy NWP(Xm-1, Y) oraz NWP(X, Yn-1), a następnie wybierając dłuższy z nich otrzymujemy NWP(X, Y)

Oznaczenie: c[i, j] długość NWP(Xi, Yj) Uwaga: jeśli i=0 lub j=0, to c[i, j]=0 Wniosek:

Obliczanie długości NWP Obserwacja 1: Jest O(mn) rożnych podproblemów problemu NWP. Dowód: X ma długość m, Y ma długość n Obserwacja 2: Problem NWP ma własność wspólnych podproblemów. Dowód: Aby znaleźć NWP(X, Y) możemy potrzebować NWP(Xm-1, Y) oraz NWP(X, Yn-1). Oba te podproblemy mogą zawierać wspólny podproblem znalezienia NWP(Xm-1, Yn-1). Wniosek: Można stosować programowanie dynamiczne. dane wejściowe: ciągi X i Y c[1.. m, 1.. n ] - przechowuje wartości c[i, j] b[1.. m, 1.. n] - b[i, j] wskazuje na pole w tablicy c odpowiadające wybranemu podczas obliczeń c[i, j] optymalnemu rozwiązaniu podproblemu

NWP_Długość(X,Y){ m:=długość(x) n:=długość(y) for i:=1 to m do c[i,0]:=0 for j:=1 to n do c[0,j]:=0 for i:=1 to m for j:=1 to n if xi=yjthen { c[i, j]:=c[i-1, j-1]+1; b[i, j]:= else if c[i-1, j] c[i, j-1] then { c[i, j]:=c[i-1, j]; b[i, j]:= else { c[i, j]:=c[i, j-1]; b[i, j]:= return c i b

Przykład: X = <A, B, C, B, D, A, B> Y = <B, D, C, A, B, A> Rozwiązanie: <B, C, B, A>

Konstrukcja NWP na podstawie wcześniejszych obliczeń Procedura Drukuj_NWP - wypisuje NWP(X, Y) korzystając z tablicy b, każda strzałka typu w polu b[i, j] oznacza, że x i =y j należy do NWP Drukuj_NWP(b, X, Y, i, j) if i=0 lub j=0 then return; if b[i, j]= then { Drukuj_NWP(b, X, Y, i-1, j-1); wypisz xi else if b[i, j]= then Drukuj_NWP(b, X, Y, i-1, j) else Drukuj_NWP(b, X, Y, i, j-1); Obserwacja: Czas działania wynosi O(m*n)

Inne rozwiązania algorytmiczne tego samego problemu. Wagner i Fisher 1974 zaproponowa ł rozwią zanie problemu LCS z wykorzystaniem programowania dynamicznego przedstawiony wcześniej o rozwiązaniu O(mn). Hirschberg 1975 zaproponował metodę dziel i zwyciężaj w oparciu o programowanie dynamiczne o złożoności czasowej O(n 2 ) ale o pamięciowej tylko O(n). Hirschberg 1977 O(pn) gdzie p to długość LCS Hunt i Szymański 1977 O(rlogn) gdzie r liczba wszystkich dopasowań. Należy zwrócić uwagę, że te dwa algorytmy są efektywne dla p i r małych. Niestety w najgorszym przypadku gdy p=n a r=n 2 algorytmy osiągają wartości O(n 2 ) i O(n 2 logn) gorsze od standardowej metody opartej na programowaniu dynamicznym. Masek i Paterson 1980 zaproponowali algorytm O(n 2 /logn).

Allison i Dix 1986 (lub Crochemore 2001) zaproponowali algorytm oparty na bitowej równoległości o złożoności obliczeniowej gdzie w to rozmiar słowa maszynowego. Np. na 32-bitowej maszynie uzyskano szybszy o ok. 30 razy, na 64- bitowej maszynie uzyskano szybszy o ok. 55 razy.