Trädsökning och datorschack

Relevanta dokument
Schackprogrammet Amundsen

Kort Sammanfattning av Schack MAS

Tommy Färnqvist, IDA, Linköpings universitet. 1 ADT Map/Dictionary Definitioner Implementation... 2

MinMax Algoritmen Implementation och optimering. Joakim Östlund 15 juni 2004

Programmering II (ID1019) :00-11:00

Studium av Othellospelande program - Design, algoritmer och implementering. Andreas Ekbom

Innehåll. Föreläsning 12. Binärt sökträd. Binära sökträd. Flervägs sökträd. Balanserade binära sökträd. Sökträd Sökning. Sökning och Sökträd

Algoritmer, datastrukturer och komplexitet

Algoritmer, datastrukturer och komplexitet

Föreläsning 8 Datastrukturer (DAT037)

Dugga Datastrukturer (DAT036)

AI och schack. En överblick

Optimala koder. Övre gräns för optimala koder. Gränser. Övre gräns för optimala koder, forts.

Optimala koder. Det existerar förstås flera koder som har samma kodordsmedellängd. Enklaste fallet är att bara byta 0:or mot 1:or.

AI TILL BRÄDSPEL En jämförelse mellan två olika sökalgoritmer vid implementation av AI till brädspelet Pentago.

Tommy Färnqvist, IDA, Linköpings universitet

TDDI16 Datastrukturer och algoritmer. Algoritmanalys

Magnus Nielsen, IDA, Linköpings universitet

Källkodning. Egenskaper hos koder. Några exempel

Föreläsning Datastrukturer (DAT037)

Föreläsning 8 Datastrukturer (DAT037)

Föreläsning Datastrukturer (DAT036)

AI för Hive. Kungliga Tekniska Högskolan. Examensarbete inom datalogi, grundnivå (DD143X) Författare: Urban Pettersson

Antag att följande träd genereras i ett spelförande program om vi applicerar evalueringsfunktionen

Föreläsning 7 Datastrukturer (DAT037)

Föreläsning 5 Datastrukturer (DAT037)

Krafts olikhet. En momentant avkodbar kod (prefixkod) med kodordslängderna l 1,...,l N existerar om och endast om. 2 l i. 1 i=1

Datastrukturer. föreläsning 10. Maps 1

Schackspelande datorer Hur fungerar de? Joakim Östlund Patrik Lindegrén 19 oktober 2004

DD1320 Tillämpad datalogi. Lösning (skiss) till tenta 20 okt 2011

UPPGIFT 1 V75 FIGUR 1.

Tentamen Datastrukturer D DAT 035/INN960

Tentamen'('Datastrukturer,'algoritmer'och'programkonstruktion.'

DAI2 (TIDAL) + I2 (TKIEK)

Helgrapport från Örebro-SM

Nätverksprogrammering, EDA095

Föreläsning Datastrukturer (DAT036)

3. Toppkvinnor på hög Låt lådan och de två kvinnornas famnar utgöra stackarna L, K1 respektive K2. Från början finns alla kort i L.

Lösningsförslag till tentamen Datastrukturer, DAT037,

Sagaforms spelregler SCHACK, FIA MED KNUFF, BACKGAMMON, DOMINO

Föreläsning 8 SLUMPTAL, SIMULERING + INTRODUKTION TILL VEKTORER

Schackledarens blad Lektion 1

Föreläsning 4 Datastrukturer (DAT037)

Sökning och sortering

Lektion 2: Sökagenter. Robin Keskisärkkä

Upplägg. Binära träd. Träd. Binära träd. Binära träd. Antal löv på ett träd. Binära träd (9) Binära sökträd (10.1)

F11 - Rekursion. ID1004 Objektorienterad programmering Fredrik Kilander

Sökning. Sökning. Köoperationer. Generell sökalgoritm

Lösningar Datastrukturer TDA

Föreläsning Datastrukturer (DAT037)

Speciell användning av heltalsvariabler. Heltalsprogrammering. Antingen-eller-villkor: Exempel. Speciell användning av heltalsvariabler

Informationsteknologi Tom Smedsaas 19 augusti 2016

TENTAMEN I DATASTRUKTURER OCH ALGORITMER DVG B kl. 14:00-19:00

Symmetrireducering av slutspelsdatabas i Schack

Lär datorn att spela luffarschack

Föreläsning 9 Innehåll. Söndra och härska. Fibonaccitalen. Söndra och härska. Divide and conquer teknik för att konstruera rekursiva algoritmer.

Prov i DAT 312: Algoritmer och datastrukturer för systemvetare

Algoritmer, datastrukturer och komplexitet

Tentamen kl Uppgift 4. Uppgift 5

Föreläsning 6 Datastrukturer (DAT037)

Magnus Nielsen, IDA, Linköpings universitet

Föreläsning Datastrukturer (DAT037)

Föreläsning 4: Giriga algoritmer. Giriga algoritmer

BINÄRA TRÄD. (X = pekarvärdet NULL): struct int_bt_node *pivot, *ny; X X X 12 X X 12 X X -3 X X

Grundläggande datalogi - Övning 4

[][] Arrayer med två index

Föreläsning 7 Innehåll. Rekursion. Rekursiv problemlösning. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursion. Rekursivt tänkande:

Handbok Knights. Översättare: Stefan Asserhäll

Tildatenta Lösningsskiss

Tentamen, Algoritmer och datastrukturer

public static void mystery(int n) { if (n > 0){ mystery(n-1); System.out.print(n * 4); mystery(n-1); } }

Föreläsning 5: Giriga algoritmer. Kruskals och Prims algoritmer

Föreläsning 6 Datastrukturer (DAT037)

Binära sökträd. Seminarium 9 Binära sökträd Innehåll. Traversering av binära sökträd. Binära sökträd Definition. Exempel på vad du ska kunna

Föreläsning 4: Kombinatorisk sökning

Självbalanserande träd AVL-träd. Koffman & Wolfgang kapitel 9, avsnitt 1 2

Handbok Othello. Clay Pradarits Utvecklare: Mario Weilguni Granskare: Lauri Watts Översättare: Stefan Asserhäll

KTH, NADA, Vahid Mosavat. 1. Flervalsfrågor (5p)

Att utveckla den sociala samvaron genom schack Författare: Jonas Nilsson

Objektorienterad programmering. Telefonboken igen, en bättre version. En jämförelse. Föreläsning 4

Programkonstruktion och Datastrukturer

Föreläsningsanteckningar F6

Föreläsning 9 Datastrukturer (DAT037)

Algoritmer, datastrukturer och komplexitet

Föreläsning 5: Giriga algoritmer. Kruskals och Prims algoritmer

Föreläsning 9 Innehåll

Lösningsförslag DD1320/DD

OMTENTAMEN I DATASTRUKTURER OCH ALGORITMER DVG B kl. 14:15 19:15

Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten Nu till dagens ämne: Vi rekapitulerar det första problemet ur ProblemI:

Översikt. Stegvis förfining. Stegvis förfining. Dekomposition. Algoritmer. Metod för att skapa ett program från ett analyserat problem

Bakgrund och motivation. Definition av algoritmer Beskrivningssätt Algoritmanalys. Algoritmer. Lars Larsson VT Lars Larsson Algoritmer 1

Datastrukturer. föreläsning 9. Maps 1

Lösningsförslag till tentamen Datastrukturer, DAT037,

Gör ditt nästa drag så som beskrivits ovan. Tryck STOP när Du vill för att stänga av datorn. Lycka till med partiet!

Sökning. Översikt. Binärt sökträd. Linjär sökning. Binär sökning. Sorterad array. Linjär sökning. Binär sökning Hashtabeller

Föreläsning 10 Datastrukturer (DAT037)

C++ Slumptalsfunktioner + switch-satsen

Algoritmer och datastrukturer H I HÅKAN S T R Ö M B E R G N I C K L A S B R A N D E F E L T

Transkript:

Trädsökning och datorschack Johnny Bigert Nada, KTH johnny@kth.se

Datorschack Hobby: schackdatorn Rainman http://www.nada.kth.se/~johnny/chess_comp.html Påbörjad i oktober 2002 Spelar på free internet chess server (FICS, www.freechess.org) under namnet RainmanC Har spelat 2500 matcher (030228) FICS-rating version 060: ca 1875

Datorschack Lite kuriosa: 5000 rader C++ Kommande version 073 innehåller Bitbräden, alfa-betasökning, transpositionstabell, MTD(f)-sökning, enkel quiescencesökning, enhanced transposition cutoff, SEE-algoritm, hashtabell för bondestruktur, öppningsbok, slutspelsdatabas, dragupprepningsbehandling, Winboardinterface, tidskontroll m.m. Internmöte v073 mot v060: +26 =2-2

Allmänt Minimax-sökning Alfa-beta-sökning Översikt Transpositioner Dragsortering Killer move Historik Intern iterat. fördj. Quiescence search Öppningsbok, slutspelstabeller Söktekniker Iterativ fördjupning Aspirationssökning NegaScout MTD(f) Utökad transp.besk Heuristiker Nulldrag Futility Selective extensions

Minimaxsökning (eng: minimaxing, negamaxing) Schack: det som är bra för dig är dåligt för din moståndare Du vill maximera din poäng, din moståndare vill minimera din poäng Varannat drag ditt, varannat din moståndares Maximera varannat, minimera varannat

Minimaxing Trädsökning: Varje nod är ett bräde Varje kant är ett drag Utvärdering sker i löven Maximera varannat djup, minimera varannat djup

Minimaxsökning -10-15 -20-2 3 0-5 3-6 -7 5 2-15 4-10 4-1 0 1 0-1 7 10 8 5 3 8 12 11 14 25 23 23 10 7 8 10 13 7-3 7-2 12 17 14 20 21 10 8 14 9 12 9 13 4 10 2 10 7 6 5 5 6-1 4-3 0 0 3 5 8 6 13 12 15 10 14 11 14 9 9 max min max min

Minimaxsökning max 10 10 min -3 10 5 max -3-1 7 23 12 10 6 5 12 min -20-3 -6-7 -15-1 -1 7 3 11 23 7 7-3 12 10 8 9 2 6 5-3 0 5 12 10 9-10 -2-5 -20 0-6 -15-3 3-7 2-15 4-10 0 5 4-1 1 7 5-1 8 8 0 10 3 12 25 10 14 23 8 11 23 10-3 12 20 8 12 7-2 14 10 9 13 7 13 7 17 21 14 9 4 10 2 6 10 5 6 7 5-1 0-3 3 4 5 6 0 8 13 10 14 15 11 9 12 14 9

Minimaxsökning Antag 50000 positioner/sekund Förgreningsfaktor i schack: ca 30 Djup (halvdrag) 2 3 4 5 6 7 Positioner 900 27,000 810,000 24,300,000 729,000,000 21,870,000,000 Tid 0.018 s 0.54 s 16.2 s 8 min 4 h 5 dagar

Minimaxsökning Snabbschack: ca 5 min per person och parti dvs 5-10 s per drag Vi hinner inte ens söka klart djup 4! Slutsats: Brute force ogörligt, träden växer för snabbt

Alfa-beta-sökning Observationer: När vi maximerar har vi en undre gräns för det rätta värdet När vi minimerar får vi övre gränser Om inget överlapp, omöjligt att hitta bättre värde

Alfa-beta-sökning max -3 min > -20? -20-3 <-5 > -3? -10-20 -15-2 0-3 -5-6 3

Alfa-beta-sökning Vi kallar den undre gränsen för alfa Vi kallar den övre gränsen för beta Algoritmen heter alfa-beta-sökning (eng: alpha-beta-pruning) De grenar vi inte besökar kallas beskurna (eng: pruned)

Alfa-beta-sökning min -3-1 max < -3? -3-3 < -3? -1 7 min < -3? >-7? -20-3 -6-7 -7 <-3? -15-1 -1 7 3-10 -2-20 0-15 -5-6 -3 3-7 2 5-15 -10 4 4 0-1 1 7 5-1 8 8 0 10 3

Alfa-beta-sökning max 10 min -3 10 5 max -3-1 7 23 12 10 6 min -20-3 -6-7 -15-1 -1 11 23 7 7-3 12 10 8 9 2 6 5-10 -2-5 -20 0-6 -15-3 3-7 2-15 4 0 5-1 1-1 0 12 25 10 10-3 12 20 8 12 14 23 7 14 10 9 13 11 23 13 17 21 14 9 4 10 5 Besökta: 45, beskurna: 36

function AlphaBeta(node, alpha, beta, depth) if depth == 0 then g = evaluate(node); else if node == MAXNODE then g = -INFINITY; a = alpha; c = firstchild(node); while (g < beta) and (c!= NOCHILD) do g = max(g, AlphaBeta(c, a, beta, depth - 1)); a = max(a, g); c = nextbrother(c); else /* node is a MINNODE */ g = +INFINITY; b = beta; c = firstchild(node); while (g > alpha) and (c!= NOCHILD) do g = min(g, AlphaBeta(c, alpha, b, depth - 1)); b = min(b, g); c = nextbrother(c); return g;

Dragordning (eng: move ordering) Den mest kritiska delen av alfa-betaalgoritmen är ordningen på dragen Bäst drag först ger tidiga beskärningar Ditt bästa drag maximerar din poäng Motståndarens drag minimerar din poäng

Dragordning Förgreningsfaktor w Träddjup d Besökta noder: värsta fallet: w d perfekt dragordning: w ceil(d/2) + w floor(d/2) Vi kan alltså söka dubbelt så djupt!

Perfekt dragordning max 10 min 10 5-3 max 10 12 23 5 6 12-3 -1 7 min 10 9 8 12 7-3 23 11 7 5 0-3 6 5 2 12 10 9-3 -6-20 -1-7 -15 7 3-1 10 9 8 12 7-3 20 12 9 14 10-2 21 13 14 17 13 7 23 11 7 23 12 8 25 14 10 5 6 0 0 8-3 -1 3 4 6 5 7 5 10 2 12 10 9 4 13 11 9 6 10 15 14 14-3 -6-20 -1-2 -5-15 0 0 3-10 -7 2 4-15 -10 5 4 7 3 8 5 10-1 0 8 1

Perfekt dragordning max 10 min 10 5-3 max 10 12 23 5-3 min 10 9 8 12 23 5 0-3 -3-6 -20 10 9 8 12 20 14 21 17 23 23 25 5 0-3 -3-6 -20 Besökta: 17, beskurna: 64

Omvänt perfekt dragordning max 10 (Vi besöker från höger till vänster) min 10 5-3 max 10 12 23 5 6 12-3 -1 7 min 10 9 8 12 7-3 23 11 7 5 0-3 6 5 2 12 10 9-3 -6-20 -1-7 -15 7 3-1 10 9 8 12 7-3 20 12 9 14 10-2 21 13 14 17 13 7 23 11 7 23 12 8 25 14 10 5 6 0 0 8-3 -1 3 4 6 5 7 5 10 2 12 10 9 4 13 11 9 6 10 15 14 14-3 -6-20 -1-2 -5-15 0 0 3-10 -7 2 4-15 -10 5 4 7 3 8 5 10-1 0 8 1

Omvänt perfekt dragordning max 10 (Vi besöker från höger till vänster) min 10 5-3 max 10 12 23 5 6 12-3 -1 7 min 10 9 8 12 7-3 23 11 7 5 0-3 6 5 2 12 10 9-3 -6-20 -1-7 -15 7 3-1 10 9 8 12 7-3 23 11 7 20 12 9 14 10 23 12 8 21 13 14 17 13 25 14 10 5 6 0 0 8-3 6 5 7 5 3 10 2 12 10 9 4 13 11 9 6 10 15 14 14-3 -6-20 -1-2 -5-15 0 0 3-10 -7 2 4-15 -10 5 4 7 3 8 5 10-1 0 8 1 Besökta: 77, beskurna: 4

Dragordning Med perfekt dragsortering behöver vi inte söka! Det bästa draget är ju det första. Man vet inte det bästa draget Heuristiker: Grundläggande schackunskap Killer move Historik

Dragordning Intressanta drag: De som kan förändra poängen drastiskt Slå den pjäs som flyttades sist Övriga drag som slår en pjäs Bonde som blir till dam Schackar (problematiskt)

Killer move Observation: ett drag som är bra på djup d i en gren är nog bra i en annan gren Ex: flytta damen om den är hotad Drag som orsakar avskärningar är bra Vi sparar ett eller flera drag per nivå Minskning av trädet: ca 30%

Historik (eng: history heuristic) Skapa tabell med 64 x 64 heltal (från, till) Varje gång ett drag ger avskärning, räkna upp mosvarande räknare i tabellen Ger inbördes ordning mellan alla drag

Transpositioner Observation: samma bräde kan uppkomma på olika sätt Ex: jag flyttar kungen och sen tornet eller jag flyttar tornet och sen kungen Om en position redan är besökt behöver den inte behandlas igen Vi skapar en tabell över besökta noder

Transpositionstabell Istället för att spara besökta noder i trädform, spara den i en hashtabell Snabb uppslagning Varje bräde får ett hashvärde som beror på hur pjäserna står, vems tur det är etc.

Transpositionstabell Kollisioner: Efter ett tag blir tabellen full Många bräden hashas till samma element Probabilistiskt lås - ytterligare ett hashvärde per bräde

Transpositionstabell Sparad information: Hashlås (normalt 32 bitar) Sökdjup Undre gräns för värdet Övre gräns för värdet Bästa draget!

Transpositionstabell Om bräde finns i hash vid uppslagning Om djup = sparat djup, använd hashat värde: Om upper < alpha, sluta sök Om lower > beta, sluta sök Annars Prova sparat drag först!

Transpositionstabell Bräden i hashen: ca 1/4 av trädets storlek Hashade drag ger väldigt bra gissning på vilket drag som är bäst

Utökad transpositionsbeskärning (eng: enhanced transposition cutoff) Vänta med att utföra dragen (söka djupt i trädet) Slå istället upp alla drag i hashtabellen Hittar vi ett som ger beskärning så kan vi sluta söka!

Iterativ fördjupning Dragen i hashen är ofta bra gissning Vi vet inte hur mycket tid sökning på djup n kommer att ta När tiden är slut måste vi ha ett drag Vi söker djup 1, 2,..., n!

Iterativ fördjupning Onödigt arbete? Djup n kan ta 30 ggr längre tid än djup n-1 Det går oftast snabbare att söka 1, 2,..., n än att söka n-1, n! Hashen är fylld med användbar information

Iterativ fördjupning Finns inget drag i hashen har vi ingen gissning Vi kan då tillämpa intern iterativ fördjupning Vi söker ett par nivåer för att fylla hashen med nyttig information Försumbart arbete om vi får en tidig beskärning

Aspirationssökning Poängen i ett parti ändras oftast inte så mycket Med snävare ingångsvärden i alfa-betasökningen går sökningen snabbare Vi gissar på föregående värde och lägger på en bråkdel av en bonde Alfa-beta med fönster (a, ß) = (v-30, v+30)

Aspirationssökning Alfa-beta med fönster (a, ß) = (v-30, v+30) Får vi ett värde w = v-30 så vet vi att det rätta värdet x är = w Får vi ett värde w = v+30 så vet vi att det rätta värdet x är = w Vi måste göra en omsökning för att hitta det rätta värdet, a < x < ß

Nollfönster En ambitiös gissning är ett s.k. nollfönster (a, ß) = (v-1, v) Vi kan aldrig träffa det rätta värdet, men med flera sökningar kan vi ta reda på värdet Vi får bara information om huruvida värdet är < v eller = v

NegaScout Idé: Vi söker bara noggrant i det första barnet i varje nod De övriga får frågan: Är ditt värde < v eller = v? Är värdet mindre än v är allt bra Är värdet större måste vi söka om

NegaScout Algoritmen kallas NegaScout Den är en förbättring av huvudvariantssökning (principal variation search, PVS) PVS söker noggrant på den mest troliga dragutvecklingen och mindre noggrant på andra NegaScout dominerar Alfa-beta-algoritmen, dvs Alfa-beta beskär inget som NegaScout besöker

function NegaScout(node, alpha, beta, depth) a = alpha; b = beta; if depth == 0 then g = evaluate(node); else if node == MAXNODE then c = firstchild(node); while (a < beta) and (c!= NOCHILD) do t = NegaScout(c, a, b, depth - 1); if (t > a) and (t < beta) and (c!= FIRST) and (depth > 1) a = NegaScout(c, t, beta); a = max(a, t); b = a + 1; c = nextbrother(c); return a; else /* node is a MINNODE */ c = firstchild(node); while (b < alpha) and (c!= NOCHILD) do t = NegaScout(c, a, b, depth - 1); if (t > alfa) and (t < b) and (c!= FIRST) and (depth > 1) b = NegaScout(c, alfa, t); b = min(b, t); a = b - 1; c = nextbrother(c); return b;

MTD(f) MTD(f) är en sökalgoritm som bara använder nollfönster Den anropar Alfa-beta-sökning upprepat Beroende på om returvärdet slår i alfa eller beta så stegar vi ett steg nedåt resp. uppåt Resultatet kan bli hundratals små men väldigt snabba sökningar

MTD(f) Varför tar man då inte större steg? Jag har gjort lite experiment med steglängder och binärsökning Med nollfönster som ligger intill tidigare sökta nollfönster blir varje ny sökning liten Längre steg ger stor ökning i tid Intressant, men osäkert om det lönar sig

function MTDf(root, f, depth) g := f; upper := +INFINITY; lower := -INFINITY; repeat if (g == lower) beta = g + 1; else beta = g; g := AlphaBeta(root, beta - 1, beta, depth); if (g < beta) upper = g; else lower = g; until (lower >= upper) return g;

Horizonteffekten (eng: horizon effect) Om man söker till djup n kan man ha otur och sluta mitt i en slagväxling Det kan då se ut som om man ligger en pjäs under, fast detta åtgärdas i nästa drag Man kan även få för sig att ens hopplöst förlorade dam går att rädda, det är bara att offra tornet och sen löparen och sen en bonde På så sätt så slipper man se att damen går förlorad Detta kallas för horizonteffekten

Stabil sökning och horizonteffekten (eng: quiescense search) Man bör därför bara utvärdera stabila positioner (eng: quiet) Exempel på instabila positioner: Slagväxlingar Kungen i schack Bonde till sista raden Man fortsätter söka tills positionen är stabil och utvärderar först då

Selektiv utvidgning (eng: selective extensions) En människa spelar inte schack på samma sätt som en dator En människa söker djupt på lovande positioner En dator provar alla drag till djup n För att förbättra datorns spel kan man utvidga lovande stigar

Kostnad och bråkdelsdjup (eng: fractional depth) Ett sätt att utvidga en stig är att tilldela en kostnad/belöning till egenskaper som uppkommer utmed stigen Ex: Drag med bara ett motdrag, sök +0.5 djupare Hot mot tung pjäs, sök +0.25 djupare Bonde på sjunde raden, sök +0.5 djupare Summan kan ge ytterligare djup

Nolldrag (eng: null move heuristic) För att minska sökträdets storlek kan man ta till potentiellt farliga heuristiker Idé: Om motståndaren får göra tre drag på rad och ändå inte leder, sluta sök (eller sök -2.0 mindre djup etc.) Farligt: man kan missa djupa kombinationer Farligt: det finns situationer där det är bra att inte vara vid draget (Zugzwang)

Hopplöshet (eng: futility pruning) Om följande kriterier är uppfyllda: Situationen är stabil och nästa drag slår inte en pjäs Motståndaren ligger minst en lätt pjäs efter Isåfall, utvärdera inte nästa drag Man spar stora delar av sökdjup n Razoring - ungefär: om motståndaren ligger en dam efter och bara två drag till horizonten, sluta sök Mycket farligt, många besparingar

Öppningsbok (eng: opening book) Datorn har dålig positionell känsla Svårt att starta spelet på ett vettigt sätt Lösning: öppningsbok med acceptabla drag Att ladda ned: ECO - vanligaste öppningarna

Slutspelstabeller (eng: end game table bases, EGTB) Slutspelet har få pjäser och mycket positionell karaktär Man har spelat samtliga spel med upp till fem pjäser (några med sex) och sparat till disk! Begränsad användbarhet (6 pjäser = många terabyte)

Slut Moderna schackdatorer innehåller det mesta av det vi berört och mycket därtill Ladda ner och prova Rainman: http://www.nada.kth.se/~johnny/chess_comp.html