2016 / 2017 1
Waarom dit vak? Omdat Mensen ongeduldig zijn Het belangrijk is dat antwoorden (van berekeningen door computers) snel / op tijd komen (en juist zijn) Dus leren we Algoritmische technieken kennen, toepassen, analyseren Belangrijke algoritmen voor centrale problemen kennen en begrijpen 2
Docenten Hans Bodlaender Buys Ballotgebouw 503 030-2534409 h.l.bodlaender@uu.nl Maandags afwezig Erik Jan van Leeuwen Werkt bij UU vanaf midden maart 3
Team werkcollege en practicum Werkcollegeleider: Tom van der Zanden Studentassistenten (werkcollege, clarifications domjudge): Gerben Aalvanger Casper Hagenaars Max Hessey Jan Posthoorn 4
Onderdelen College Werkcollege Practicum Tentamens 5
Onderdelen College Twee keer per week, belangrijke aanvulling op stof uit boek Powerpoints op website Werkcollege Practicum Tentamens 6
Onderdelen College Werkcollege Twee keer per week: let op de tijden Belangrijk: oefenen van stof is belangrijker dan er naar luisteren Twee keer een autodiagnostische toets (proeftentamen Vragen over: opgaven, practicum (maar zonder naar code te kijken) Practicum Tentamens 7
Onderdelen College Werkcollege Practicum 6 opgaven met Domjudge (straks meer) Tentamens 8
Onderdelen College Werkcollege Practicum Tentamens Twee deeltentamens, elk over ongeveer helft van de stof Je mag meenemen: 4 kantjes A4 (2 vel A4 aan beide zijden beschreven, 4 vel A4 aan 1 kant beschreven, normaal lettertype, zelfgemaakt) 9
Cijfer Beide deeltentamens tellen even zwaar Eindcijfer: Hooguit 3 practicumopgaven goed: onvoldoende 4 practicumopgaven goed: gemiddeld tentamencijfer afgerond 5 practicumopgaven goed: gemiddeld tentamencijfer afgerond + 0.5 6 practicumopgaven goed: gemiddeld tentamencijfer afgerond + 1 Afronding: 5.5 gaat naar 6, 5.49 naar 5. Boven de 6 op halve punten afgerond. 10
Herkansingsregeling Je kan of: 1 practicumopgave inhalen 2 practicumopgaven inhalen Hertentamen doen 1 practicumopgave inhalen en hertentamen doen Hertentamen vervangt laagste deeltentamencijfer en gaat over de hele stof 11
Practicum 6 opgaven, inleveren via Domjudge 1e opgave niet triviaal, maar veel makkelijker dan de rest Latere opgaven veel moeilijker. Opgave 6 is het moeilijkst Je moet er minstens 4 halen. Let op de deadlines! Te laat is te laat Dus: begin op tijd! 12
Alleen werken Je moet de opgaven alleen maken Er wordt gecontroleerd op fraude, en bij een vermoeden van fraude wordt de regeling van de Universiteit Utrecht gevolgd en is het eindcijfer van dit vak een 1 Je mag wel kort (1.5 minuut) met elkaar praten over het practicum, maar niet: Code of pseudocode van elkaar bekijken (of inkijken, uitwisselen, geven, in ontvangst nemen, debuggen, inleveren, etc.) 13
Domjudge Je kan een opgave tot de deadline zo vaak inleveren als je wilt Tot in het redelijke Je ingeleverde code wordt: Gecompileerd en gedraaid met een aantal geheime testinvoeren Je krijgt te horen: Code compileert niet goed Code geeft runerror Code geeft fout antwoord op testinvoer Code gebruikt te veel tijd Correct programma In het algemeen geldt: bij correct programma heb je de opgave gehaald; anders kan je je programma verbeteren en opnieuw inleveren 14
Tips en hulp Test je programma ook met eigen testinvoeren en die van de website Clarifications: Vragen over je programma kan je stellen via clarificationssysteem in domjudge aan studentassistenten Verwacht niet altijd en niet direct antwoord Zorg voor leesbare code Hulp door clarifications heeft grenzen Geen clarifications dag voor de deadline Programma te langzaam: Gebruik je het goede algoritme? Gebruik je de goede constructies uit C#? (Bijvoorbeeld: ingebouwde functies kunnen grote complexiteit hebben) 15
Allerlei vragen Over organisatie van vak, cijfers van tentamens, etc: docent Hans Bodlaender Over practicum (cijfers, inloggen, ): Tom van der Zanden Over inhoud: werkcollege, of docent in de pauze 16
Inhoud Algoritmische technieken: Dynamisch programmeren Divide and Conquer Greedy Algorithms Randomized algorithms Analyse van algoritmen Geamortiseerde analyse (o.a. Union-Find datastructuur) NP-volledigheid Grafen en netwerken Kortste paden Opspannende bomen Stroming en snedes 17
Dynamisch Programmeren I
Dynamisch programmeren Een algoritmische techniek Werkt voor veel verschillende problemen Soms snel, soms langzaam Soms makkelijk, soms moeilijk Algoritme wordt gemaakt door volgen van een `stappenplan 19
Inhoud Voorbeelden De techniek Het stappenplan Nog meer voorbeelden, en ingewikkelder toepassingen van Dynamisch Programmeren Implementatie details 20
Eerste voorbeeld Fibonaccigetallen F(0) = 0; F(1) = 1 Als i > 1, dan is F(i) = F(i 1) + F(i 2) Hoe reken je F(6) uit? 21
Recursief Method Fibonacci (integer i) if i == 0 then return 0; if i == 1 then return 1; Return Fibonacci(i 1) + Fibonacci(i 2) 22
Beter: een dynamisch programma Method FibonacciDP (integer i) if i == 0 then return 0 if i == 1 then return 1 Maak een integer array F[0 i] aan F[0]=0; F[1]=1; for j == 2 to i do F[j]=F[j 1]+F[j 2] enddo. Return F[j] 23
De driehoek van Pascal Function C(n,k) if (k == 0) or (k == n) then return 1 else return C(n 1, k 1) + C(n 1, k) 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 n n! n 1 n 1 = = + k k!( n k)! k 1 k 24
Recursief of met Memorisatie? In functionele taal als bijv. Haskell (hangt af van compiler): Iedere term C(i,j) wordt maar 1 keer uitgerekend. Kost O((n+1)(k+1)) tijd, zeg O(nk). In imperatieve taal: Verschillende termen worden vaker dan 1 keer uitgerekend Kost veel tijd: berekenen van C(n,k) kost Θ(C(n,k)) tijd!! Function C(n,k) if (k == 0) or (k == n) then return 1 else return C(n 1, k 1) + C(n 1, k) 25
Driehoek van Pascal Imperatief Function C(n,k) Neem 2-dimensionaal array A(0 n, 0 k) for i=0 to n do for j=0 to min(i,k) do if (j == 0) or (j == i) then A(i,j) = 1 else A(i,j) = A(i 1, j 1) + A(i 1, j) Return A(n,k) Zelfde stappen als in recursief algoritme, maar 26
Equivalent Function C(n,k) Neem 2-dimensionaal array A(0 n, 0 k) for i=0 to n do A(i,0) = 1; for i=0 to k do A(i,i) = 1; for i=0 to n do for j=0 to min(i,k) do A(i,j) = A(i 1, j 1) + A(i 1, j) Return A(n,k) Initialisatie buiten de hoofdloop gehaald: dit is net iets efficienter 27
Analyse dynamisch programmeer algoritme O(nk) tijd Kan in O(k) geheugenruimte door maar twee regels van array te gebruiken Function C1(n,k) Neem arrays A(0 k) en B(0 k) for i=0 to n do for j=0 to min(i,k) do if (j == 0) or (j == i) then A(j) = 1 else A(j) = B( j 1) + B(j) for j=0 to k do B(j) = A(j) Return A(n,k) 28
1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1 1 7 21 35 35 21 7 1 29
Voorbeeld 2: Simplified Risk Deel van spel: Twee `legers : i rode steentjes en j blauwe steentjes. Beide spelers gooien een dobbelsteen. Als de rode speler meer dan de blauwe speler gooit, dan gaat er 1 blauw steentje weg, anders 1 rood steentje. Een speler wint als de tegenstander geen steentjes meer heeft P(i,j) is kans dat rode speler wint. P(i,j) = 15/36 * P(i,j 1) + 21/36 * P(i 1, j) Function P(i,j) if (i == 0) then return 0 else if (j == 0) then return 1 else return 15/36 * P(i,j 1) + 21/36 * P(i 1, j) 30
Simplified Risk (2) Met Memorisatie (functioneel): snel Recursief imperatief: Te veel tijd Function P(i,j) if (i == 0) then return 0 else if (j == 0) then return 1 else return 15/36 * P(i,j 1) + 21/36 * P(i 1, j) 31
0 j: aantal steentjes blauwe speler 0 1 2 3 4 * 0 0 0 0 1 i: aantal van rode 2 speler 3 4 1 1 1 1 15/36 85/144 32
Berekeningsvolgorde Function SRP(i,j) Maak 2 dim array P(0 i,0 j) for r = 0 to i do for b = 0 to j do Bereken P(r,b) Return P(i,j) 33
DP algoritme voor Simplified Risk Function SRP(i,j) Maak 2 dim array P(0 i,0 j) for r = 0 to i do for b = 0 to j do if (r == 0) then P(r,b) = 0 else if (b == 0) then P(r,b) = 1 else P(r,b) = 15/36 * P(r,b 1) + 21/36 * P(r 1, b) Return P(i,j) 34
Basisidee Dynamisch Programmeren Reken iets niet voor de tweede keer uit iets : deelprobleem Twee mogelijkheden: `Klassiek DP: vul datastructuur met antwoorden voor deelproblemen, zodat nodige gegevens al eerder zijn berekend Memorisatie: kijk of we t al eerder hebben uitgerekend zo ja, geef dat antwoord; zo nee: reken uit en sla antwoord op in datastructuur (bijvoorbeeld array of hashtabel) 35
De ontwerpmethode (1) 1. Identificeer `deelproblemen, waarbij helpt a) Wat is de `rij van keuzes die leidt tot een oplossing? b) Wat is de `top choice (laatste keuze)? 2. Ontwerp een recurrente betrekking voor het probleem: druk het probleem uit in termen van (andere) deelproblemen. Geef ook basisgevallen Top choice helpt (vaak: gevalsonderscheid) 3. Wat is de berekeningsvolgorde? (Mag geen cycle hebben ) 4. Bereken in volgorde de waardes voor de deelproblemen. 5. Eventueel: geheugenbesparing of constructieve versie. 36
37 Voorbeeld 3 Gepast betalen Stel, we hebben munten van waardes a 1, a r en we willen b betalen. Hoe kunnen we dit doen met zo min mogelijk munten? Euro s kunnen greedy (komt later deze collegeserie), maar andere sets munten niet altijd. Greedy: geef steeds grootst mogelijke munt terug, bijv: 84: 50 (34), 20 (14), 10 (4), 2 (2), 2. Met munten van 1, 10, 25 geeft greedy niet altijd goede antwoord: Greedy geeft voor 30 cent: 25, 1, 1, 1, 1, 1 (6 munten), maar optimaal is: 10, 10, 10 (3 munten) Hier: DP algoritme voor `wisselgeld probleem.
Gepast betalen: probleemstelling Gegeven: positieve gehele getallen a 1,, a r, niet negatief geheel getal b Gevraagd: op welke manier kan b verkregen worden door zo min mogelijk munten van waardes a 1,, a r? 38 Munten mogen ieder niet-negatief aantal keren gebruikt worden. Totale som moet b zijn. We zoeken dus x 1,, x r in N= {0,1, } met r i= 1 x i a i = b en r i= 1 x i zo klein mogelijk
Rij van keuzes Hoeveel nemen we van de eerste munt? Hoeveel nemen we van de tweede munt? Hoeveel nemen we van de laatste munt? Oftwel: x 1,, x r Top choice: x r 39
Hoe ziet de situatie eruit als we al een aantal keuzes gemaakt hebben? Stel we hebben al van de eerste q munten besloten hoeveel te nemen. Situatie kan je karakteriseren met: q Aantal munten tot nu toe gebruikt Totaalbedrag van de tot nu toe gebruikte munten Dus: (q, q, q ) 40 i= 1 x i i= 1 x i a i
Deelproblemen Gegeven a 1,, a r, b, schijf W(i,c) als het minimum aantal munten Nodig om bedrag c te krijgen Als we alleen munten a 1,, a i mogen gebruiken Vb: Munten van waarden 1, 5, 8, 20 W(1,7) = 7 (we mogen alleen munt 1 gebruiken) W(2,7) = 3 (beste oplossing is 5, 1, 1) W(3,7) = W(4,7) = 3 (nog steeds) W(1,23) = 23; W(2,23) = 7; W(3,24) = 5 (met: 8,8,5,1,1); W(4,23) = 4 (met: 20,1,1,1) 41
Speciale gevallen Munten met waardes 3, 5, 10, 30 W(*,0) = 0: geen munten nodig om 0 te betalen. W(4,7) = + (kan niet gemaakt worden) W(0,5) = + (geen munten dus kan niet gemaakt worden) 42
Recurrente betrekkingen W(i, 0) = 0 voor alle i 0. Basisgevallen W(0, y) = + voor alle y > 0. Als i > 0 en y > 0 en a i > y, dan W(i, y) = W( i 1, y) Munt a i kan niet gebruikt worden om y te betalen. Als i > 0 en y > 0 en a i y, dan W(i, y) = min ( W( i 1, y), W(i, y a i ) + 1) Munt a i kan wel gebruikt worden. Als je de munt niet gebruikt moet je y maken met de eerste i 1 munten; anders moet je y a i maken en nog een munt a i erbij. Bekijk beide en neem de beste (minimum). 43 Gevalsonderscheid met de top-choice
Recursief programma Wissel( Array A, integers i, y) If (y == 0) then return 0; If (i == 0) then return maxint; If (a i > y) then return Wissel(A, i 1, y); Return min (Wissel(A, i 1, y), Wissel(A,i, y a i ) + 1) 44
i: munten Voor berekeningen nodig: Element met i-1 en element met y-a i y: bedrag 45
Uitrekenen in volgorde Function Wissel(A[1 r], b) Maak 2-dim array W[0 r, 0 b]. W[0,0]=0. for j=1 to b do W[0,j] = +. for i=1 to r do for j=0 to b do Bereken W[i,j]. Return W[r,b] Straks preciezer 46
Algoritme Function WisselDP(A[1 r], b) Maak 2-dim array W[0 r, 0 b]. W[0,0]=0. for j=1 to b do W[0,j] = +. for i=1 to r do for j=0 to b do if (A[i] > j) then W[i,j] = W[i-1,j] else W[i,j] = min (W[i-1,j],W[i,j-A[i]]+1) Return W[r,c] 47
Analyse WisselDP gebruikt O(rb) tijd. Als b niet te groot is, is dit snel. 48
Niet altijd integer functies Wisselbaar Gegeven munten met waardes a 1,, a r, kan hiermee een bedrag b betaald worden? Wisselbaar({3,5,11},6) = true Wisselbaar({3,5,11},16) = true Wisselbaar({3,5,11},7) = false Zelfde soort algoritme als voor Wissel: nu met Booleans. 49
DP algoritme voor Wisselbaar probleem Function Wisselbaar(A[1 r], b) Maak 2-dim array van Booleans W[0 r, 0 b]. W[0,0]=true. for j=1 to b do W[0,j] = false. for i=1 to r do for j=0 to b do if (A[i] > j) then W[i,j] = W[i-1,j] else W[i,j] = W[i-1,j] or W[i,j-A[i]] Return W[x,y] 50
Het optimaliteitsprincipe Dynamisch programmeren lukt vaak als: Het niet uitmaakt hoe je er gekomen bent, maar alleen waar je bent Preciezer: Als een oplossing optimaal is, dan zijn diens deeloplossingen ook optimaal. 51
Uitwisselargumenten 52
Wat is een goede keuze van Vaak werkt dit: deelproblemen 1. Hoe ziet een oplossing voor de hele input eruit? 2. Als we naar een deel (bijv. beginstuk) van de input kijken, wat zien we dan van zo n oplossing (definieer een notie deeloplossing) 3. Wat is essentieel om te weten van een deeloplossing voor mogelijke uitbreiding tot een hele oplossing? 53
Eerlijke Boedelverdeling Twee broers moeten een stel voorwerpen verdelen van waarde a 1, a 2,, a n. Hoe doen ze dat zo eerlijk mogelijk? (D.w.z., verdeel a 1, a 2,, a n in twee verzamelingen waarvan de som zo weinig mogelijk verschilt.) 1, 5, 8, 10, 11 {8, 10} en {1, 5, 11} is eerlijkste verdeling (verschil 1.) 54
Stappenplan voor DP Stap 1: wat is de rij van keuzes? Voor de hand liggend: Welke broer krijgt voorwerp 1? Welke broer krijgt voorwerp 2? Welke broer krijgt voorwerp n? Top choice: welke broer krijgt voorwerp n? 55
Stappenplan voor DP Stap 3: Identificeer deelproblemen Vaak werkt volgende strategie: Deelprobleem is: Beginstuk van gebeurtenissen of beslissingen + Situatie na een stel gebeurtenissen en beslissingen 56
Boedelprobleem Stap 1 1 e poging Beslissingen: welke broer krijgt voorwerp 1; welke broer krijgt voorwerp 2; etc. Idee voor deelproblemen: Wat is de eerlijkste verdeling van de eerste i voorwerpen? Hiermee is geen DP algoritme te maken: optimaliteitsprincipe geldt niet. mislukt Voorwerpen 1, 5, 6: eerlijkste verdeling 1 e twee voorwerpen zegt niets over eerlijkste verdeling alle drie voorwerpen 57
Waarom werkt dit niet? Er zijn mogelijke begin-keuzes die tot een optimale oplossing leiden die niet in een deelprobleem `gevangen worden Voorwerpen 1, 5, 6, 10 Begin: (1 en 5, 6) is geen deel van de optimale oplossing (1 en 10, 5 en 6) 58
Boedelprobleem Stap 1 Verdeel(i, c): is er een verdeling van de eerste i voorwerpen met verschil in waarde precies c? 1,5,8,10,11: Verdeel(2,4) = true Verdeel(2,5) = false Verdeel(2,6) = true (1,5 vs niets) Verdeel(3,2) = true (1,5 vs 8) 59
Welke deelproblemen zijn relevant? n n i= 1 a i c i= 1 a i 60
Stap 3 Ontwerp recurrente betrekking die oplossing van deelprobleem uitdrukt in oplossingen van andere deelproblemen. Verdeel(0,0) = true Voor c 0: Verdeel(0,c) = false Voor i>0: Verdeel(i,c) = Verdeel(i-1,c-a i ) or Verdeel(i-1,c+a i ) i de voorwerp naar 1e of 2e broer: gevalsonderscheid op de top-choice 61
Stap 4 i: voorwerpen Wat is de berekeningsvolgorde? Hier: kolomsgewijs, d.w.z, stijgend aantal voorwerpen c: verschil 62
Stap 5 Bereken de deelproblemen met behulp van de recurrente betrekking in de gevonden volgorde. Eigenlijk fout: neem een false voor elt die niet in de array zitten n a i Bereken T = i= 1 Maak array V[0 n, T T] for i = 0 to n do for c = -T to T do if i=0 and c=0, then V[i,c]= true else if i=0 and c 0 then V[i,c]=false else V[i,c] = V[i-1,c-a i ] or V[i-1,c+a i ] Nu nog het antwoord vinden 63
Vervolg stap 5: Antwoord vinden: poging 1 for c = 0 to T do if V[n,c] == true then return c Dit vindt het kleinst mogelijke verschil in de waarde van de verdeling tussen de broers. Maar nog niet de eerlijkste verdeling zelf? Hoe dat te doen is Stap 6. To be continued 64
Practicumsom 1: een variant Aantal rijtjes van A naar B A en B getallen, en een rijtje is een rij met D s en I s: D: twee keer t vorige getal; I: plus 1 Bijvoorbeeld: 5 met IIDI geeft 15 (6, 7, 14, 15) Practicumsom: gegeven A en B, wat is het aantal (A,B)-rijtjes. Hier: wat is het kortste (A,B)-rijtje? 65
Lengte van kortste rijtje Kortste rijtje Het kortste (A,B)-rijtje 1. Wat is de rij keuzes? Wat is de laatste keuze? 2. Wat zijn de deelproblemen? 3. Recurrente betrekking a) Uitdrukking in kleinere deelproblemen b) Basisgeval(len) 4. Berekeningsvolgorde 5. Programma voor lengte van kortste rijtje 6. Versie voor constructie van het kortste rijtje 66
Wordt vervolgd Vinden van oplossingen in plaats van waardes van oplossingen Memorisatie Besparen van geheugenruimte Andere toepassingen van dynamisch programmeren Ingewikkelder structuren 67