23
FUNDAMENTELE PROGRAMĂRII Laura Dioşan Metode de rezolvare a problemelor Programare dinamică Greedy UNIVERSITATEA BABEŞ-BOLYAI Facultatea de Matematică şi Informatică

Greedy si Programare dinamica

  • Upload
    phamdat

  • View
    240

  • Download
    8

Embed Size (px)

Citation preview

Page 1: Greedy si Programare dinamica

FUNDAMENTELE

PROGRAMĂRII

Laura Dioşan

Metode de rezolvare a problemelor

Programare dinamică

Greedy

UNIVERSITATEA BABEŞ-BOLYAI

Facultatea de Matematică şi Informatică

Page 2: Greedy si Programare dinamica

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

Page 3: Greedy si Programare dinamica

Sumar

Metode de rezolvare a problemelor

Programare dinamică

Greedy

Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 3

Page 4: Greedy si Programare dinamica

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

Page 5: Greedy si Programare dinamica

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

Page 6: Greedy si Programare dinamica

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

Page 7: Greedy si Programare dinamica

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

Page 8: Greedy si Programare dinamica

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

Page 9: Greedy si Programare dinamica

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

Page 10: Greedy si Programare dinamica

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

Page 11: Greedy si Programare dinamica

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

Page 12: Greedy si Programare dinamica

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

Page 13: Greedy si Programare dinamica

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

Page 14: Greedy si Programare dinamica

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()

Page 15: Greedy si Programare dinamica

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

Page 16: Greedy si Programare dinamica

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

Page 17: Greedy si Programare dinamica

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

Page 18: Greedy si Programare dinamica

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

Page 19: Greedy si Programare dinamica

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()

Page 20: Greedy si Programare dinamica

Recapitulare

Metode de rezolvare a problemelor

Programare dinamică

Greedy

Decembrie, 2013 Fundamentele programării - tehnici de rezolvare a problemelor 20

Page 21: Greedy si Programare dinamica

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

Page 22: Greedy si Programare dinamica

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

Page 23: Greedy si Programare dinamica

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