Wstęp do Programowania potok funkcyjny

Podobne dokumenty
Wstęp do Programowania potok funkcyjny

Programowanie dynamiczne (optymalizacja dynamiczna).

Programowanie dynamiczne cz. 2

Wstęp do Programowania potok funkcyjny

Programowanie Funkcyjne. Marcin Kubica Świder,

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

FUNKCJA REKURENCYJNA. function s(n:integer):integer; begin if (n>1) then s:=n*s(n-1); else s:=1; end;

Wstęp do Programowania potok funkcyjny

Sortowanie przez scalanie

Programowanie dynamiczne

Wstęp do programowania

Wstęp do Programowania potok funkcyjny

Wstęp do Programowania potok funkcyjny

Wstęp do Programowania potok funkcyjny

Wstęp do programowania

Algorytmy i Struktury Danych.

Schemat programowania dynamicznego (ang. dynamic programming)

Wstęp do Programowania potok funkcyjny

Programowanie dynamiczne

Wstęp do programowania

Wstęp do Programowania potok funkcyjny

Wstęp do Programowania potok funkcyjny

Algorytmy i struktury danych.

Rekurencja. Przygotowała: Agnieszka Reiter

Zadanie 1 Przygotuj algorytm programu - sortowanie przez wstawianie.

Algorytmy i struktury danych

Wstęp do Programowania potok funkcyjny

Projektowanie i analiza algorytmów

Wstęp do Programowania potok funkcyjny

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

Obiektowy Caml. Paweł Boguszewski

Algorytmy i Struktury Danych, 2. ćwiczenia

Analiza algorytmów zadania podstawowe

Wstęp do informatyki Ćwiczenia. Piotr Fulmański

ALGORYTMY I STRUKTURY DANYCH

Strategia "dziel i zwyciężaj"

WYKŁAD 8. Funkcje i algorytmy rekurencyjne Proste przykłady. Programy: c3_1.c..., c3_6.c. Tomasz Zieliński

Algorytmy i Struktury Danych

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

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

TEORETYCZNE PODSTAWY INFORMATYKI

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

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 )

Rekurencja. Rekurencja zwana także rekursją jest jedną z najważniejszych metod konstruowania rozwiązań i algorytmów.

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

Wstęp do programowania. Procedury i funkcje. Piotr Chrząstowski-Wachtel

Technologie informacyjne Wykład VII-IX

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

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

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

Podstawy programowania 2. Temat: Drzewa binarne. Przygotował: mgr inż. Tomasz Michno

Wstęp do programowania. Dziel i rządź. Piotr Chrząstowski-Wachtel

Technologia informacyjna Algorytm Janusz Uriasz

Wykład 7 Porównanie programowania funkcyjnego i imperatywnego

Teoretyczne podstawy informatyki

Znajdowanie największego i najmniejszego elementu w zbiorze n liczb całkowitych

Wstęp do informatyki

Wstęp do Programowania potok funkcyjny

Obliczenia na stosie. Wykład 9. Obliczenia na stosie. J. Cichoń, P. Kobylański Wstęp do Informatyki i Programowania 266 / 303

Składnia funkcji i Rekurencja w języku Haskell

Podstawowe algorytmy i ich implementacje w C. Wykład 9

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

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

Metody Kompilacji Wykład 7 Analiza Syntaktyczna

PoniŜej znajdują się pytania z egzaminów zawodowych teoretycznych. Jest to materiał poglądowy.

Zaawansowane algorytmy i struktury danych

Wstęp do programowania. Listy. Piotr Chrząstowski-Wachtel

Algorytmy i struktury danych. wykład 2

Podstawy algorytmiki i programowania - wykład 6 Sortowanie- algorytmy

Paradygmaty programowania

Podstawy Programowania semestr drugi. Wykład dziewiąty

Rekurencja. Rekurencja zwana także rekursją jest jedną z najważniejszych metod konstruowania rozwiązań i algorytmów.

Informatyka A. Algorytmy

Wprowadzenie do programowania

Wykład 9 Funktory (moduły sparametryzowane)

Instrukcje pętli przykłady. Odgadywanie hasła. 1) Program pyta o hasło i podaje adres, gdy hasło poprawne lub komunikat o błędnym haśle.

Programowanie funkcyjne wprowadzenie Specyfikacje formalne i programy funkcyjne

Programowanie funkcyjne. Wykªad 13

Testy jednostkowe Wybrane problemy testowania metod rekurencyjnych

Algorytmy i język C++

Procedury i funkcje składowane

Programowanie w VB Proste algorytmy sortowania

Wykład 5 Dopasowywanie lokalne

Funkcje. Piotr Zierhoffer. 7 października Institute of Computer Science Poznań University of Technology

INFORMATYKA POZIOM ROZSZERZONY

Algorytmy i Struktury Danych, 2. ćwiczenia

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

INFORMATYKA WYBRANE ALGORYTMY OPTYMALIZACYJNE KRYPTOLOGIA.

Wstęp do programowania. Drzewa. Piotr Chrząstowski-Wachtel

Wykład 5: Iteracja, indukcja i rekurencja Sortowanie

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Obrazy rekurencyjne. Zastosowanie rekurencji w algorytmice. AUTOR: Martin Śniegoń

Wykład 4: Iteracja, indukcja i rekurencja

Wstęp do Programowania potok funkcyjny

Kolejka priorytetowa. Często rozważa się kolejki priorytetowe, w których poszukuje się elementu minimalnego zamiast maksymalnego.

Wstęp do programowania. Drzewa podstawowe techniki. Piotr Chrząstowski-Wachtel

Sortowanie. Kolejki priorytetowe i algorytm Heapsort Dynamiczny problem sortowania:

Matematyka Dyskretna. Andrzej Szepietowski. 25 czerwca 2002 roku

TEORETYCZNE PODSTAWY INFORMATYKI

1. Nagłówek funkcji: int funkcja(void); wskazuje na to, że ta funkcja. 2. Schemat blokowy przedstawia algorytm obliczania

Transkrypt:

i programowanie dynamiczne Wstęp do Programowania potok funkcyjny Marcin Kubica 2010/2011

i programowanie dynamiczne Outline 1 i programowanie dynamiczne

i programowanie dynamiczne Rekurencyjny zapis rozwiązania + Mapy. Unikamy wielokrotnych wywołań dla tych samych argumentów. Spamiętujemy wszystkie obliczone wcześniej wyniki wywołań. Skrzyżowanie rekurencji i programowania dynamicznego

i programowanie dynamiczne Przykład spamiętywania (Liczby Fibonacciego i spamiętywanie) let tab = ref empty;; let rec fib n = if dom!tab n then apply!tab n else let wynik = if n < 2 then n else fib (n-1) + fib (n-2) in begin tab := update!tab n wynik; wynik end;;

i programowanie dynamiczne Schemat spamiętywania Schemat spamiętywania jest dosyć uniwersalny: Implementacja rekurencyjna. Założenie: dla tych samych argumentów zawsze dostajemy takie same wyniki. Tabela do spamiętywania wyników. Przed wywołaniem rekurencyjnym sprawdzamy, czy już dla takiego wywołania nie obliczono wyniku. Jeśli tak, wykorzystujemy obliczony wcześniej wynik. Jeśli nie, wywołujemy rekurencyjnie procedurę i zapamiętujemy wynik.

i programowanie dynamiczne Uniwersalny spamiętywacz Uniwersalna otoczka spamiętująca: let memoize tab f x = if dom!tab x then apply!tab x else let wynik = f x in begin tab := update!tab x wynik; wynik end;;

i programowanie dynamiczne Przykład zastosowania spamiętywacza Procedura obliczająca liczby Fibonacciego zapisana przy użyciu uniwersalnego spamiętywacza: let fib = let tab = ref empty in let rec f n = memoize tab (function n -> if n < 2 then n else f (n-1) + f (n-2)) n in f;;

i programowanie dynamiczne Problem NWP Problem najdłuższego wspólnego podciągu: Dane: dwa ciągi x = [x 1 ; x 2 ;... ; x m ] i y = [y 1 ; y 2 ;... ; y n ]. Szukamy najdłuższego ciągu, który jest podciągiem x i y. Oznaczenie: NWP(x, y).

i programowanie dynamiczne Idea rozwiązania problemu NWP Idea rozwiązania: Uogólnienie problemu na prefiksy: nwp(i, j) = NWP([x 1 ;... ; x i ], [y 1 ;... ; y j ]) Własność podproblemu: Jeśli x i = y j, to nwp(i, j) = nwp(i 1, j 1)@[x i ]. Jeśli ostatni wyraz nwp jest różny od x i, to nwp(i, j) = nwp(i 1, j). Jeśli ostatni wyraz nwp jest różny od y j, to nwp(i, j) = nwp(i, j 1). Funkcja nwp jest monotoniczna względem obydwu współrzędnych. Jeśli x i y j, to nwp(i, j) jest dłuższym z podciągów nwp(i 1, j) i nwp(i, j 1)). Warunki brzegowe: nwp(i, 0) = nwp(0, j) = [].

i programowanie dynamiczne Algorytm rozwiązania problemu NWP Algorytm: tabela rozwiązań dla podproblemów i jej wypełnianie. A B C B D A B 0 0 0 0 B D C A B A 0 0 1 1 1 0 0 1 1 1 2 0 0 1 2 2 2 1 1 2 2 2 3 3 3 4 4 4 Najdłuższe wspólne podciągi: BCBA, BCAB, BDAB, ostatni z nich występuje w pierwszym ciągu na dwa sposoby.

i programowanie dynamiczne NWP implementacja ze spamiętywaniem Wynikiem procedury pom jest para: (odwrócony) najdłuższy wspólny podciąg i jego długość. let nwp ciag_x ciag_y = let x = Array.of_list ciag_x and y = Array.of_list ciag_y and tab = ref empty in let rec pom (i, j) =... in rev (fst (pom (length ciag_x, length ciag_y)));; nwp [ A ; B ; C ; B ; D ; A ; B ] [ B ; D ; C ; A ; B ; A ];; - : char list = [ B ; D ; A ; B ]

i programowanie dynamiczne NWP implementacja ze spamiętywaniem let rec pom (i, j) = memoize tab (fun (i, j) -> if i = 0 j = 0 then ([], 0) else if x.(i-1) = y.(j-1) then let (c, l) = pom (i-1, j-1) in (x.(i-1)::c, l+1) else let (c1, l1) = pom (i-1, j) and (c2, l2) = pom (i, j-1) in if l1 > l2 then (c1, l1) else (c2, l2) ) (i, j)

i programowanie dynamiczne NWP Implementacja z wykorzystaniem tablic Dane: dwa ciągi x = [x 1 ; x 2 ;... ; x m ] i y = [y 1 ; y 2 ;... ; y n ]. Szukamy najdłuższego ciągu, który jest podciągiem x i y. Oznaczenie: NWP(x, y). Spamiętywanie możemy zaimplementować wprost, tworząc tablicę: a.(i).(j) = NWP([x 1 ;... ; x i ], [y 1 ;... ; y j ]) Dwie fazy: obliczenie tablicy a, rekonstrukcja wyniku.

i programowanie dynamiczne NWP Implementacja z wykorzystaniem tablic let nwp ciag_x ciag_y = if (ciag_x = []) (ciag_y = []) then [] else let n = length ciag_x and m = length ciag_y and x = Array.of_list ((hd ciag_x)::ciag_x) and y = Array.of_list ((hd ciag_y)::ciag_y) in let a = Array.make_matrix (n+1) (m+1) 0 in let rec rekonstrukcja acc i j =... in begin for i = 1 to n do for j = 1 to m do if x.(i) = y.(j) then a.(i).(j) <- a.(i-1).(j-1) + 1 else a.(i).(j) <- max a.(i-1).(j) a.(i).(j-1) done done; rekonstrukcja [] n m end;;

i programowanie dynamiczne NWP Implementacja z wykorzystaniem tablic Rekonstrukcja podciągu na podstawie tablicy a: let rec rekonstrukcja acc i j = if i = 0 j = 0 then acc else if x.(i) = y.(j) then rekonstrukcja (x.(i)::acc) (i-1) (j-1) else if a.(i).(j) = a.(i-1).(j) then rekonstrukcja acc (i-1) j else rekonstrukcja acc i (j-1)

i programowanie dynamiczne NWP Implementacja z wykorzystaniem map Zamiast tablicy możemy użyć mapy. Złożoność czasowa gorsza o czynnik O(log n). Główna procedura: let nwp ciag_x ciag_y = let a = zbuduj_tablice1 ciag_x ciag_y in odtworz_podciag1 a ciag_x ciag_y;; Zależność między sąsiednimy elementami tablicy: let dlugosc u v w x y = if x = y then v + 1 else max u w;;

i programowanie dynamiczne NWP Implementacja z wykorzystaniem map let zbuduj_tablice ciag_x ciag_y = let dodaj_wiersz tablica y j =... in let pierwszy =... and buduj a yl =... in buduj pierwszy ciag_y;;

i programowanie dynamiczne NWP Implementacja z wykorzystaniem map let pierwszy = let (a, _) = fold_left (fun (a, i) _ -> (update a (0, i) 0, i+1)) (update empty (0, 0) 0, 1) ciag_x in a and buduj a yl = let (w, _) = fold_left (fun (a, j) y -> (dodaj_wiersz a y j, j+1)) (a, 1) yl in w

i programowanie dynamiczne NWP Implementacja z wykorzystaniem map let dodaj_wiersz tablica y j = let (t, _) = fold_left (fun (tab, i) x -> let u = apply tab (j, i-1) and v = apply tab (j-1, i-1) and w = apply tab (j-1, i) in (update tab (j, i) (dlugosc u v w x y), i+1)) (update tablica (j, 0) 0, 1) ciag_x in t

i programowanie dynamiczne NWP Implementacja z wykorzystaniem map Rekonstrukcja podciągu: let odtworz_podciag tablica ciag_x ciag_y = let rec odtworz akumulator tab ciag_x ciag_y i j =... in odtworz [] tablica (rev ciag_x) (rev ciag_y) (length ciag_x) (length ciag_y);;

i programowanie dynamiczne NWP Implementacja z wykorzystaniem map let rec odtworz akumulator tab ciag_x ciag_y i j = match ciag_x with [] -> akumulator (x::tx) -> match ciag_y with [] -> akumulator (y::ty) -> if x = y then odtworz (x::akumulator) tab tx ty (i-1) (j-1) else let u = apply tab (j, i-1) and w = apply tab (j-1, i) in if u > w then odtworz akumulator tab tx ciag_y (i-1) j else odtworz akumulator tab ciag_x ty i (j-1)

i programowanie dynamiczne Ogólny schemat programowania dynamicznego Sparametryzowanie problemu. Zależności między rozwiązaniami podproblemów. Rodzaj użytej struktury danych. Kolejność rozwiązywania podproblemów. Czy można lepiej sformułować podproblemy? Ewentualne wyznaczenie pomocniczych problemów. Ewentualna rekonstrukcja wyniku. Polepszenie złożoności pamięciowej. Czy lepiej zastosować spamiętywanie, czy programowanie dynamiczne?