Upload
phamdat
View
240
Download
8
Embed Size (px)
Citation preview
FUNDAMENTELE
PROGRAMĂRII
Laura Dioşan
Metode de rezolvare a problemelor
Programare dinamică
Greedy
UNIVERSITATEA BABEŞ-BOLYAI
Facultatea de Matematică şi Informatică
Conținut curs Introducere în procesul de dezvoltare software Programare procedurală Programare modulară Tipuri definite de utilizator Principii de dezvoltare a aplicațiilor soft Testarea și inspectarea programelor Recursivitate Complexitatea algoritmilor Metode de rezolvare a problemelor
Backtracking Divide et impera Programare dinamică Greedy
Algoritmi de căutare Algoritmi de sortare Recapitulare
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 2
Sumar
Metode de rezolvare a problemelor
Programare dinamică
Greedy
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 3
Paşi în rezolvarea problemelor
Definirea problemei
Analiza problemei
Alegerea unei tehnici de rezolvare
căutare
reprezentarea cunoştinţelor
abstractizare
Decembrie, 2013 4 Fundamentele programării - tehnici de rezolvare a problemelor
Paşi în rezolvarea problemelor prin căutare –
Alegerea unei tehnici de rezolvare
Rezolvarea problemelor prin metode clasice
Metode exacte
Metoda generării și testării
backtracking
Metoda divizării -> Divide et Impera
Metoda programării dinamice
Metode euristice
Metoda greedy
Decembrie, 2013 5 Fundamentele programării - tehnici de rezolvare a problemelor
Programare dinamică Ideea de bază
Descompunerea problemei în sub-probleme imbricate (suprapuse) și similare problemei inițiale, dar de dimensiuni mai mici, rezolvarea sub-problemelor și stabilirea soluției finale prin combinarea sub-soluțiilor
Mecanism
împărțirea problemei în sub-probleme imbricate P(P1(P2(P3(...(Pn))...)
Rezolvarea celei mai interne sub-probleme (Pn) și stocarea rezultatelor parțiale
Rezolvarea sub-problemei Pn-1 pe baza soluției găsite pentru sub-problema Pn și stocarea rezultatelor parțiale
Rezolvarea sub-problemei Pn-2 pe baza soluției găsite pentru sub-problema Pn-1 și stocarea rezultatelor parțiale
...
Rezolvarea sub-problemei P1 pe baza soluției găsite pentru sub-problema P2 și stocarea rezultatelor parțiale
Rezolvarea problemei P pe baza soluției găsite pentru sub-problema P1 și stocarea rezultatelor finale
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 6
Programare dinamică
Când se poate folosi
Problema P (de optimizare) având datele de intrare D poate fi rezolvată prin rezolvarea aceleiași probleme P, dar cu datele de intrare d, unde d < D
Soluția este rezultatul unei succesiuni de decizii dec1, dec2, ...
Se verifică principiul optimalității
Problema se poate descompune în sub-probleme suprapuse
Care pot fi utlizate de mai multe ori
Se pot memora soluțiile sub-problemelor pentru re-utilizări viitoare
Caracteristici
Furnizează soluția optimă întotdeauna
Timp de lucru polinomial
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 7
Programare dinamică Principiul optimalității
Optimul general implică optimul (optimele) local(e)/parțiale
Într-o secvență optimă de decizii, fiecare decizie este optimă
Nu se verifică pentru orice problemă
Formal
O secvență de decizii dec1, dec2, ..., decn transformă optim starea s0 în starea sn dacă cel puțin una din condițiile următoare este îndeplinită:
deck, deck+1, ..., decn este o secvență de decizii care transformă optim starea sk-1 în starea sn, pentru orice k, 1 ≤ k ≤ n
Metoda înainte (decizia deck depinde de decizia deck+1, deck+2, ...,decn)
dec1, dec2, ..., deck este o secvență de decizii care transformă optim starea s0 în starea sk, pentru orice k, 1 ≤ k ≤ n
Metoda înapoi (decizia deck depinde de decizia deck+1, deck+2, ...,decn)
deck+1, ..., decn și dec1, dec2,...,deck sunt 2 secvențe de decizii care transformă optim starea sk-1 în starea sn, respectiv starea s0 în starea sk pentru orice k, 1 ≤ k ≤ n
Metoda mixtă
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 8
Programare dinamică Algoritm
Verificarea principiului optimalității
Înainte
Înapoi
Mixt
Stabilirea structurii soluției optime
Descompunerea problemei în sub-probleme
Stabilirea relațiilor de recurență pentru obținerea optimului global din optimele parțiale
Soluția optimă se determină într-o manieră bottom-up, plecând de la cazurile minimale (sub-problemele interne) pentru care se cunoaște soluția
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 9
Programare dinamică Exemple
Să se găsească cel mai lung sub-șir crescător al unui șir de elemente întregi.
Soluție Pentru fiecare si se calculează lungimea celui mai lung sub-șir crescător care se
poate forma cu el
la final, se selectează elementul cu care se poate forma cel mai lung sub-șir crescător.
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 10
i 1 2 3 4 5
s 2 1 9 6 12
L 3 2,9,12 sau
2, 6,12
3 1,9,12
sau 1,6,12
2 9,12
2 6,12
1 12
i 1 2 3 4 5
s 2 1 9 6 12
Programare dinamică Exemple
Să se găsească cel mai lung sub-șir crescător al unui șir de elemente întregi.
Etape Verificarea principiului optimalității
Pp – cel mai lung sub-șir care începe pe poziția i1 (are k
elemente)
Trebuie să arătăm că este un sub-șir crescător de lungime
maximă pentru orice j=2,3,4,...,k-1
Pp (prin reducere la absurd) că sjk nu este de lungime maximală
=>există un sub-șir cu lungimea mai mică de k-j+1 (lungimea lui sjk),
, m+1≤k-j.
Deci sub-șirul este crescător si are lungimea
m+j<j+k-j=k, ceea ce contrazice presupunera inițială
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 11
i 1 2 3 4 5
s 2 1 9 6 12
s..., ,s ,s sk21
iii
1k
s...,,s,ssk1jj iii
jk
m21j jjji
jm s ...ss s s
m21j21 jjjiii s ,..,.s,s ,s ,...,s,s
Programare dinamică Exemple
Să se găsească cel mai lung sub-șir crescător al unui șir de elemente întregi.
Etape Stabilirea structurii soluției optime
Descompunerea problemei în sub-probleme
Problemă: determinarea celui mai lung sub-șir crescător
Sub-problemă: determinarea celui mai lung sub-șir crescător care începe cu si, pentru i=n, n-1, n-2,...,1. Aceste sub-șiruri au lungimea cel mult 1,2,...,n
Soluția
Cel mai lung sub-șir din cele n sub-șiruri
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 12
i 1 2 3 4 5
s 2 1 9 6 12
Programare dinamică Exemple
Să se găsească cel mai lung sub-șir crescător al unui șir de elemente întregi.
Etape Stabilirea relațiilor de recurență pentru obținerea optimului global din optimele
parțiale
Fie Li lungimea celui mai lung sub-șir care începe pe poziția i (cu si)
Sub-șirurile crescătoare care încep cu si se obțin adăugând elementul si în fața unui sub-șir crescător care începe cu sj, dacă si ≤ sj
Ln = 1
Soluția optimă
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 13
i 1 2 3 4 5
s 2 1 9 6 12
1,...,1pentru ,,max1,1
nissLL jijnij
i
ini
LL,1
max max
Programare dinamică Exemple
Să se găsească cel mai lung sub-șir crescător al unui șir de elemente întregi.
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 14
def long_seq(s): L = [0] * len(s) ind = [0] * len(s) #index of the succesor of si in the long seq Lmax = 0 imax = -1 #compute vector L L[len(s) - 1] = 1 ind[len(s) - 1] = -1 for i in range(len(s) - 2, -1, -1): ind[i] = -1; L[i] = 1 for j in range(i+1, len(s)): if (s[i] <= s[j]): if (L[i] <= L[j] + 1): L[i] = L[j] + 1; ind[i] = j #determine position max elem from L max_pos = 0 for i in range(1, len(s)): if (L[i] > L[max_pos]): max_pos = i #construct the solution sol = []; i = max_pos while (i != -1): sol.append(s[i]) i = ind[i] return sol
def test_long_seq(): assert long_seq([2,1,9,6,12]) == [2, 6, 12] assert long_seq([0,-2,3,1,0,-1,2,5,-5,5,-8.10,7,-3,1]) == [0,0,2,5,5,7] test_long_seq()
Greedy
Ideea de bază
Descompunerea problemei în sub-probleme succesive și similare problemei inițiale, dar de dimensiuni mai mici, rezolvarea sub-problemelor și stabilirea soluției finale prin alegerea succesivă a celor mai bune sub-soluții
Optimul global = o succesiune de optime locale
Mecanism
împărțirea problemei în sub-probleme succesive P1, P2, ...Pn
Construirea treptată a soluției prin alegerea, la fiecare pas, a celei mai bune decizii
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 15
Greedy
Când se poate folosi
Problema P (de optimizare)
Soluția este rezultatul unei succesiuni de optime locale
Pentru probleme a căror soluție este reprezentată prin
submulțimi sau produse carteziene pentru care se atinge un
anumit optim (minim sau maxim) al unei funcții obiectiv
Caracteristici
Poate furniza soluția optimă
Construiește treptat soluția
Furnizează o singură soluție
Timp de lucru polinomial
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 16
Greedy
Algoritm
Fie S o soluție a problemei, iar C mulțimea optimelor locale pentru fiecare sub-problemă (mulțime de elemente candidate la soluție)
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 17
def greedy(C): S = Φ while (not isSolution(S)) and (C≠Φ): el = selectMostPromissing(C) C.remove(el) if acceptable(el, S): S.append(el) if isSolution(S) return S else: return None
Greedy Exemple
Să se găsească o modalitate de a plăti o sumă de bani folosind cât mai puține monezi de diferite valori.
Date: Suma = 80, Monezi = [1, 5, 10, 25, 50]
Rezultate: 80 = 50 + 25 + 5
Date: Suma = 10, Monezi = [1, 2, 3, 4]
Rezultate: 10 = 4 + 3 + 2 + 1
Date: Suma = 10, Monezi = [2, 3, 4, 5]
Rezultate: 10 = 5 + 3 + 2
Soluție
C – lista de monezi disponibilă isSolution(sol)
Dacă suma monezilor din sol este egală cu suma cerută
selectMostPromissing(C)
Alegerea celei mai mari monezi din C
acceptable(el,sol)
Dacă suma monezilor din sol + el nu depășește suma cerută de problemă
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 18
Greedy Exemple
Să se găsească o modalitate de a plăti o sumă de bani folosind cât mai puține monezi de diferite valori.
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 19
def sum(l): s = 0 for el in l: s = s + el return s def isSolution(solution, limit): return sum(solution) == limit def selectMostPromissing(candidates): return max(candidates) def acceptable(element, solution, limit): return sum(solution) + element <= limit def greedy_coins(coins, sumOfMoney): sol = [] while (not isSolution(sol, sumOfMoney)) and (coins != []): el = selectMostPromissing(coins) coins.remove(el) if acceptable(el, sol, sumOfMoney): sol.append(el) if isSolution(sol, sumOfMoney): return sol else: return None
def test_greedy_coins(): assert greedy_coins([1, 5, 10, 25, 50], 80) == [50, 25, 5] assert greedy_coins([1, 2, 3, 4], 10) == [4, 3, 2, 1] #assert greedy_coins([1, 2, 3, 4, 5], 10) == [5, 3, 2] assert greedy_coins([2, 3, 4, 5], 10) == None test_greedy_coins()
Recapitulare
Metode de rezolvare a problemelor
Programare dinamică
Greedy
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 20
Cursul următor
Rezolvarea problemelor prin metode clasice
Metode exacte
Metoda generării și testării
Metoda divizării -> Divide et Impera
Metoda programării dinamice
Metode euristice
Metoda greedy
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 21
Materiale de citit şi legături utile
1. Limbajul Python http://docs.python.org/3/reference/index.html
2. Biblioteca standard Python http://docs.python.org/3/library/index.html
3. Tutorial Python http://docs.python.org/3/tutorial/index.html
4. Frentiu, M., H.F. Pop, Fundamentals of Programming, Cluj University Press, 2006, 220 pagini
5. Kent Beck.Test Driven Development: By Example. Addison-Wesley Longman, 2002 http://en.wikipedia.org/wiki/Test-driven_development
6. Martin Fowler. Refactoring. Improving the Design of Existing Code. Addison-Wesley, 1999 http://refactoring.com/catalog/index.html
Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 22
Informaţiile prezentate au fost colectate din diferite surse de pe internet, precum şi din cursurile de Fundamentele Programării ţinute în anii anteriori de către:
Lect. Dr. Adriana Guran – www.cs.ubbcluj.ro/~adriana
Lect. Dr. Istvan Czibula - www.cs.ubbcluj.ro/~istvanc
Lect. Dr. Andreea Vescan -www.cs.ubbcluj.ro/~avescan
Lect. Dr. Ioan Lazăr -www.cs.ubbcluj.ro/~ilazar
Decembrie, 2013 23 Fundamentele programării - tehnici de rezolvare a problemelor