Sökning Sökning! Datastrukturer och operationer! Värdering av sökstrategier! Blind sökning! Heuristisk sökning! Constraint satisfaction! Spelförande program Datastruktur: nod = [tillstånd, förälder, operator, djup, vägkostnad] Expandera varje nod Applicera operatorer på ett tillstånd och generera alla nya tillstånd Ex: Initialtillståndet (0, 0) expanderas till (4, 0) och (0, 3) (4, 0) expanderas till (0, 0) (4, 3) (1, 3) (0, 3) expanderas till (0, 0) (4, 3) (3, 0) etc. Sökstrategi avgör vilken nod som skall expanderas Köoperationer Generell sökalgoritm Sökalgoritmer sparar noder som skall expanderas i en kö Typiska köoperationer:! empty?(queue)! pop(queue)! insert(element, queue) def treesearch(problem): frontier = insert(initialstate(problem), frontier) while true: if empty?(frontier): return failure node = pop(frontier) if goaltest(problem, state(node)): return solution(node) frontier = insert(expand(node, problem), frontier)
Nodexpansion Värdering av sökstrategi Expand(node, problem) Skapa en lista av noder, s, som är efterföljare till en nod, n, där: state[s] = tillståndet efter uförd legal handling i n parent-node[s] = n action[s] = handlingen som utfördes vägkostnad[s] = vägkostnad[n] + kostnad från n till s djup[s] = djup[n] + 1! Komplett! hittar lösning om den finns! Optimal! hittar bästa lösningen! Tidsåtgång! Minnesåtgång Blind sökning Bredden först Ingen information om hur långt det är kvar till målet! Bredden först! Uniform cost! Djupet först! Djupbegränsad sökning! Iterativ fördjupning! Dubbelriktad sökning! Expandera alla noder på en nivå innan nästa nivå 1 2 3 4 6 7 8 9 10 11 12 13 14 1! Implementeras med insert som en FIFO-kö
Bredden först Bredden först! Komplett! Optimal! Komplexitet ett problem! Förgreningsfaktor b! Sökdjup d Antag lösning på djupet d, då har vi expanderat: 1+b+b 2 +b 3 +b 4 +b +..b d noder Vid komplexitetsanalys säger vi att vi har O(b d ), dvs exponentiell tillväxt Ex b=2 1 d=0, en nod, b 0 T 2 3 4 6 7 d=1, b 1 noder d=2, b 2 noder d 8 9 10 11 12 13 14 1 d=3, b 3 noder Bredden först, tids- och minneskomplexitet Djup Noder Tid Minne 2 110 0,11 ms 0,1 MB 4 11110 11 ms 10,6 MB 6 10 6 1.1 s 1 GB 8 10 8 2 min 103 GB 10 10 10 3 timmar 10 TB 12 10 12 13 dagar 1 PetaByte 14 10 14 3, år 99 PetaByte 16 10 16 30 år 10 ExaByte Förgreningsfaktor = 10, 1 miljon noder/sekund, 1000 bytes/nod Uniform Cost! Om inte alla operatorer har samma kostnad! Expandera billigaste vägen längs frontier S S A B C 1 1 S A B C 1 M 11 S A B C 1! Optimal och komplett om det inte finns negativa kostnader M 11! I princip O(b d ) för tids- och minneskomplexitet M 10 A 1 10 B M 1 C
Djupet först Djupet först! Följer alltid en väg till slutet, om inte en lösning backa upp 1 1 1 1 2 3 2 3 3 3 4 6 7! Kräver mindre minne, m*b där m=maxdjup.! Jämför b=10,m=12, djupet först = 10*12=120, bredden först = 10 12! Samma tidskomplexitet O(b m )! Inte optimal! Inte komplett, kan dyka ner i en oändligt lång sökväg 8 9 10 11 12 13 14 1! Implementeras med insert som en LIFO-kö, STACK Djupbegränsad sökning Iterativ fördjupning! Lägg in ett maxdjup, l, för djupet först! Tidskomplexitet fortfarande exponentiell, O(b l )! Minneskomplexitet O(b*l)! Inte komplett om man inte kan skatta ett sökdjup som garanterar en lösning, jfr, rumäniengrafen, max 20 städer, dvs l=20 ger komplett! Inte optimal! Låt sökdjupet, h, öka från 0 till det djup, d, där en lösning finns h=0 h=1 h=2 h=3
Iterativ fördjupning Dubbelriktad sökning! Optimal och komplett! Minneskomplexitet, O(b*d)! Tidskomplexitet, O(b d )! Expanderar dock noderna flera gånger! Bredden-först 1+b+b 2 +b 3 +b 4 +b +..b d! Iterativ fördjupning db+(d-1)b 2 +(d-2)b 3 + +3b d-2 +2b d-1 +b d! Men antal noder på nivå d många fler än resten! Ex b=10, d=! Bredden först: 1+10+100+1000+10000+100000=111111! Iterativ födjupning: 0+400+3000+20000+100000=12340! Sök bredden-först från start och mål samtidigt! Inte alltid möjligt! Komplett och optimal! Tids- och minneskomplexitet, lösning djup d! 2b d/2, dvs O(b d/2 )! Ex b=10, d=6! Bredden först, O(b d ) = 10 6 = 1000000! Dubbelriktad sökning = 10 6/2 = 10 3 = 1000 Egenskaper hos sökstrategier Undvika loopar Kriterium Bredden först Uniform Cost Djupet först Djupbegränsad Komplett? Ja Ja Nej Nej Ja Ja Iterativ fördjupning Dubbelriktad sökning Ex vattenhinksproblemet (0,0) (4,0) (0,3) Optimal? Ja Ja Nej Nej Ja Ja (0,0) (4,3) (1,3) (0,0) (4,3) (3,0) Tid O(b d ) O(b C*/ε ) O(b m ) O(b l ) O(b d ) O(b d/2 ) Minne O(b d ) O(b C*/ε ) O(bm) O(bl) O(bd) O(b d/2 )! Generera inte tillstånd som är lika med fadertillståndet! Generera inte vägar med cykler! Behöver bara leta från noden som genererats upp till startnoden! Generera inte ett tillstånd som genererats förut! Varje tillstånd måste lagras i minnet, O(b d )
Heuristisk sökning Greedy Search! Antar att vi har någon information om vilken nod som är bäst att expandera! Greedy search! A*! IDA* och SMA*! Heuristik! Hill Climbing! Minimera uppskattad kostnad till målet, dvs expandra den nod som verkar vara närmast målet! Inför h(n)= heuristisk funktion som uppskattar kostnaden från nod n till målet! h(n) = 0 betyder att n är målnod! Ex Rumänienkartan! Fågelavståndet ett exempel på heuristik h(n)= Arad 366 Bukarest 0 Craiova 160 Dobreta 242 Eforie 161 Fagaras 178 Giurgiu 77 Hirsova 11 Iasi 226 Lugoj 244 Mehadia 241 Neamt 234 Oradea 380 Pitesi 98 Rimnicu V. 193 Sibiu 23 Tisioara 329 Urziceni 80 Vasliu 199 Zerind 374 Oradea Neamt Zerind Iasi Greedy Search, Arad Bukarest Arad Zerind (374) Sibiu (23) Timisoara (329) Arad Sibiu Fagaras Vaslui Oradera (380) Fagaras (178) Rimnicu Vilcea (193) Timisoara Rimnicu Vilcea Lugoj Pitesi Urziceni Bukarest (0) Mehadia Bukarest Dobreta Craiova Giurgiu Eforie
Greedy Search A*! Liknar djupet först och kan råka ut för samma problem! Inte optimal! Inte komplett! Tids- och minneskomplexitet O(b d ) men kan ofta bli bättre med god heuristik! Jämför Uniform Cost! Komplett och optimal men ineffektiv! Inför g(n) för kostnad från start för nod n! Inför f(n) = g(n) + h(n), dvs tillryggalagd kostnad + uppskattad återstående kostnad! Kräv också att h(n) aldrig överskattar den verkliga kostnaden! h(n) kallas då tillåten (admissible), ex fågelavståndet h(n)= Arad 366 Bukarest 0 Craiova 160 Dobreta 242 Eforie 161 Fagaras 178 Giurgiu 77 Hirsova 11 Iasi 226 Lugoj 244 Mehadia 241 Neamt 234 Oradea 380 Pitesi 98 Rimnicu V. 193 Sibiu 23 Tisioara 329 Urziceni 80 Vasliu 199 Zerind 374 Oradea 71 Neamt Zerind 11 87 Iasi 7 Arad 140 Sibiu 92 99 Fagaras Vaslui 118 Timisoara 80 Rimnicu Vilcea 211 142 97 Pitesi 98 111 Lugoj 8 70 146 Urziceni 86 138 101 Mehadia Bukarest 7 90 120 Dobreta Craiova Giurgiu Eforie A*, Arad Bukarest Zerind f(zerind) = 7+374 = 449 Oradera (140+11+380=671) Bukarest (140+99+211+0=40) Arad Sibiu f(sibiu) = 140+23=393 Timisoara f(timisoara) = 118+329=447 Fagaras (140+99+178=417) Rimnicu Vilcea (140+80+193=413) Pitesi(140+80+97+98=41) Bukarest (140+80+97+101+0=418) Craiova (140+80+146+160=26) Craiova (140+80+138+160=18)
A* är optimal Evalueringsfunktionen i A*! Antag: lösningsnoden G optimum med kostnad f* och G 2 lösning men med kostnad g(g 2 ) > f*! För att A* skall välja G 2 måste det finnas en nod, n, på vägen till G som inte expanderats! f* f(n) eftersom h aldrig överskattar (tillåten)! f(n) f(g 2 ) eftersom A* expanderat till G 2! dvs f* f(g 2 ) n G 2! Eftersom G 2 målnod så h(g 2 ) = 0 f(g 2 ) = g(g 2 ) dvs f* g(g 2 ) vilket motsäger antagandet G f(n) = g(n) + h(n) där f(n) = totalkostnad g(n) = kostnad hittills h(n) = uppskattad återstående kostnad (måste underskatta) g(n) = 0 Greedy search h(n) = 0 Uniform Cost g(n) = 1 och h(n) = 0 f(n) = 1, dvs Bredden först Heuristik! Heuristiska sökmetoder bättre med bättre heuristik, dvs bättre skattning av kostnaden Heuristik, 1! Antal brickor som ligger fel Ex. 1-spel 1 2 3 4 2 3 4 6 7 8 6 9 8 1 1 2 3 4 3 2 4 6 7 8 6 9 13 1 9 10 11 12 7 11 10 12 9 10 11 12 7 11 10 12 13 14 1 14 1 8 13 14 1 14 1 13 12: (1,3,4,,6,7,8,9,10,11,12,13,14,1)=14 8: (1,3,4,,6,7,8,9,10,11,13,14,1)=13
Heuristik, 2 Hill Climbing! Mahattanavståndet 1 2 3 4 3 2 4! Om varje nytt tillstånd innehåller all nödvändiginformation för att gå vidare, dvs vi kan utvärdera en nod utan hänsyn till varifrån vi kom och vägen mindre viktig 6 7 8 6 9 13 1 S 9 10 11 12 7 11 10 12 3 2 13 14 1 14 1 8 10 13 12 12: 4+0+2+1+4+1+3+3+2+1+1+1+4+1+1=29 8: 4+0+2+1+4+1+3+2+2+1+1+0+4+1+1=27 30 23 1 Hill Climbing Problem för hill climbing def hillclimbing (problem): current = makenode(initialstate(problem)) while True: next = highestvaluedsuccessor(current) if (value next) <= (value current): return current current = next Lokal metod, hittar lokalt optimum Lokalt maximum Platå Globalt maximum Ås
Constraint satisfaction Ex. trefärgsproblemet Givet:! En mängd variabler 1, 2,. n! Med värden v i till i ur domänen D i! En mängd begränsningar C 1,C 2, C n! Som talar om vilka värden som är tillåtna Mål:! En tilldelning { i =v i, j =v j } som är konsistent med begränsningarna Färga varje stat: Tre färger Grannstater olika färg Ex. {(WA=grön),(NT=blå), (Q=grön),(NSW=blå), (SA=röd),(V=grön),(T=blå)} Constraint satisfaction sökning Algoritm! Bredden först skulle tilldela varje variabel ett värde generera ett stort sökträd! Eftersom ordningen saknar betydelse kan man istället tilldela en variabel ett värde och sen backa tillbaka om det inte blev bra start NT=Röd NT=Blå NT=Grön Q=Röd Q=Blå Q=Grön SA=Röd SA=Blå SA=Grön def backtrackingsearch(csp): return recursivebacktracking([ ], csp) def recursivebacktracking(assignment, csp): if complete(assignment): return assignment var = selectunassignedvariable(variables(csp),assignment,csp) for value in orderdomainvalues(var,assignment,csp): if consistent(value,assignment,constraint(csp)): add {var=value} to assignment result = recursivebacktracking(assignment,csp) if result!= failure: return result remove {var=value} from assignment return failure
Algoritm Algoritm, forts! Variabler = [NT, Q, NSW, SA, V, T, WA]! Värden = [Röd, Blå, Grön]! Initialt assignment = { }! selectunassignedvariable väljer variabel! Ex var = NT! orderdomainvalues väljer värden enligt någon heuristik! Ex assignment = {NT = röd}! Nytt anrop recursivebacktracking({nt=röd}, csp})! selectunassignedvariable väljer var = Q! orderdomainvalues väljer röd. Inte konsistent! väljer nytt värde i for-loopen assignment = {Q=blå}! recursivebacktracking({nt=röd, Q=blå}, csp}! etc! {NT=röd, Q=blå, NSW=grön}! var=sa går inte utan det rekursiva anropet ger ett failure! remove {var=value} from assignment tar bort något värde, t.ex. det sista NSW=grön och sen fortsätter algoritmen med ny variabel Heuristik Spelförande program! Val av variabel och värde! selectunassignedvariable bör välja den variabel som är mest begränsad och först väljs den som har flest begränsningar, SA! orderdomainvalues välj det minst begränsande värdet! Constraint propagation! Propagera effekten av en variabels begränsningar till de andra variablerna! Backtrackingstrategier! Ta bort det värde, eller den variabel, som orsakade konflikten! Minimax! Evalueringsfunktioner! alfa-beta cutoff
Minimax Ett sökträd Max 84 O O O O O O Min 84 3 O O O e(x,,,x,o,,,, )=4-4=0 e(,x,,x,o,,,,, )=0 e(,,,x,o,,,,x)=4-3=1 Max 8 9 4 9 6 3 9 9 Applicera evaluaeringsfunktion, t.ex.: e(p)=n(vinstdrag för mig) n(vinstdrag för motståndaren) 8 7 2 9 1 6 2 4 1 1 3 3 9 2 6 2 1 2 3 9 7 2 9 6 4 Evalueringsfunktion alfa-beta cutoff, 1! Linjär! Ex: e(p)=1*n(vinst för mig)-1*n(motståndarvinst) e(p)=π*n(vinst för mig)-2,18*n(motståndarvinst)+1*n(diagonaler)! Icke-linjär n e(p) = w i f i i=0 n e(p) = f i 2 i=1 Två tröskelvärden α och β:! α representerar det lägsta värdet en maxnod kan få, dvs en undre gräns för MA! β representerar det högsta värdet en minnod kan få, dvs en övre gräns för MIN! Inlärning! Vikter och funktioner lärs in automatiskt utifrån gamla spel! Credit assignmentproblemet
alfa-beta cutoff, 2 Ett sökträd! Initiering:! α = sämsta värdet; β = bästa värdet! Tilldelning: Max 84! α = bästa efterföljare hitills, på MA-nivå! β = sämsta efterföljare hitills, på MIN-nivå! Regler: Min 84 3! Avbryt MIN-sökning vid nod med värde mindre än α! Avbryt MA-sökning vid nod med värde större än β Max 8 9 4 9 6 3 8 7 2 9 2 4 1 1 3 3 9 6 1 2 3