Iti0210lab6: erinevus redaktsioonide vahel

Allikas: Lambda
Mine navigeerimisribale Mine otsikasti
PriitJ (arutelu | kaastöö)
Resümee puudub
PriitJ (arutelu | kaastöö)
55. rida: 55. rida:
== Hästi mängimine ==
== Hästi mängimine ==


Siin osas kirjeldatavaid tehnikaid võib katsetada vastavalt huvile ja motivatsioonile, kohustuslikud nad ei ole. Enamus tehnikaid on suhteliselt tüüpilised paljude lauamängude (ja sarnaste asjade) alpha-beta otsinguga tehtud lahenduste juures.
[[Iti0120lab6lisa|Siin kirjeldatavaid tehnikaid]] võib katsetada vastavalt huvile ja motivatsioonile, kohustuslikud nad ei ole. Enamus tehnikaid on suhteliselt tüüpilised paljude lauamängude (ja sarnaste asjade) alpha-beta otsinguga tehtud lahenduste juures.
 
=== Korduvate seisude elimineerimine ===
 
Alpha-beta on sügavutiotsing ning tsüklid mängupuus genereerivad sinna lõputus koguses tippe. Karujahi puhul teame ka, et ükskõik milline kordus on alati karu jaoks kasulik. Seda võib ''minimax'' hinnangut arvutades isegi karu võiduks lugeda, kuna see on parim võimalik tulemus karu jaoks - kahe korduva seisu vahel pole jahimehed mitte midagi saavutanud.
 
* jäta meelde kõik mängus reaalselt esinenud seisud ja seisude jada otsingupuu juurest käesoleva tipuni (s.t. kuidas otsing hetkel arvab, et mäng edasi läheks)
* katkesta otsing (s.t. tagasta seisu väärtus, mis on karu jaoks positiivne ja jahimeeste jaoks negatiivne), kohe, kui otsingu käigus esinev seis kordab mingit eelnevat seisu
* pane tähele, et sama nuppude konfiguratsioon on sama seis ainult siis, kui käigul on ka sama pool
 
=== Käikude järjestamine ===
 
Alpha-beta algoritm eeldab, et paremad käigud tehakse enne, kui halvemad. Üks lihtsamaid viise seda teha oleks otsida enne käike, mis viivad mänguvälja keskele. Karu eelistaks jääda keskele ning jahimehed peavad ka sinna liikuma, et karu äärele tõrjuda. Seega võime väga umbkaudu hinnata, et käigud keskmistele väljadele on paremad.
 
=== Transpositsioonitabel ===
 
Eelnevad muudatused teevad meie otsingu teoreetilisest seisukohast väga palju efektiivsemaks. Praktikas peab ta aga ikkagi palju tühja tööd tegema, kuna meie karujahi mängus, nagu ka paljudes teistes mängudes, viivad sageli erinevad käikude järjestused samade seisudeni, seda nii samal kui ka teistel otsingusügavustel.
 
Väga lihtsustatult on transpositsioonitabel (TT) koht, kus on kirjas, mis mingi seisu otsinguga leitud väärtus on. Selle seisu uuesti kohtamisel pole enam vaja otsingut korrata, väärtus võetakse tabelist.
 
Praktikas on asi natuke keerulisem. Alpha-beta efektiivsus põhineb sellel, et paljude seisude jaoks ei arvutata selle täpset väärtust vaid see, palju ta maksimaalselt või minimaalselt väärt on. Neid ei saa omavahel segamini ajada ega ka käsitleda täpse ''minimax'' väärtusena.
 
Vaata [http://people.csail.mit.edu/plaat/mtdf.html#abmem siit] ühte viisi, kuidas TT väärtuseid käsitleda. Näiteks ''beta''-lõike puhul otsing katkestatakse ning teada on vaid, et väärtus on ''vähemalt'' see mis leiti. Nii pannaksegi see alampiirina kirja ja seda tohib ka järgmisel korral samas seisus ''beta''-lõike tekitamiseks kasutada.
 
Sageli kontrollitakse ka, kui sügava otsinguga TT väärtus on leitud ning kasutatakse ainult neid, mille sügavus on sama suur või suurem, kui praeguse otsingu sügavus oleks ilma TT-ta.
 
Koos eelnevate muudatustega peaks saavutatav otsingusügavus radikaalselt suurenema ning ulatuma vähemalt 20-40 käiguni.
 
=== Hinnangufunktsioon ===
 
Nüüd on otsing efektiivne, aga suudab eristada ainult võiduseise ja kordusi. See tähendab, et vahepealsed seisud tunduvad kõik ühesugustena, mida nad kindlasti tegelikult ei ole. Täpsem hinnangufunktsioon (''utility'', ''eval'') aitab mängu juhtida soodsas suunas.
 
Strateegiamängudes on tihti oluline tsentraalsus ja mobiilsus. See kehtib ka siin, vähemalt karu kohta. Lihtsa, aga suhteliselt hea hinnangufunktsiooni saame, kui anname jahimeestele plusspunkte, kui karu asub serval. Lisaks anname jahimeestele punkte, kui mõni jahimees paikneb karu kõrval - see piirab karu mobiilsust. Karu poolt mängides annavad samad asjad miinuspunkte.
 
=== Peavariant ja iteratiivne sügavnemine ===
 
Iteratiivset sügavnemist (''iterative deepening'') kasutatakse mängudes paljudeks eesmärkideks, nagu aja haldamine, transpositsioonitabelite efektiivne kasutus jne. Meie puhul on temast aga kasu peavariandi (''principal variation'', PV) arvestamisel.
 
Nimelt on tavaline fikseeritud (näiteks 20 käiguni) sügavusega otsing strateegiliselt väga rumal. Kui sama eesmärgi võib saavutada kolme või 20 käiguga, et tee ta neil vahet ning võib juhuslikult eelistada pikemat varianti - kõik sõltub sellest, mis käik otsingus ettepoole satub. Selline "edasi lükkamine" võib ebasoodsal juhusel kesta lõpmatuseni. Sama efektiga tegelesime juba võiduseisu väärtuse arvutamise juures.
 
* alustame otsingut sügavusega 1
* jätame meelde, mis käik leiti ning liidame sügavusele 1
* järgmisel sügavusel paigutame leitud käigu otsingujärjekorras esimeseks
 
Sellisel viisil otsides eelistab programm käiku, mis saavutab sama tulemuse varem: kui käik A ja B viivad mõlemad karu nurka surumiseni, aga A teeb seda 3 käigu ja B 20 käiguga, siis järjestades A ettepoole, jääb ta meie valitud käiguks, isegi kui maksimumsügavusel B sama väärtuse saavutab.
 
=== Teoreetiline keerukus ===
 
Arvuta välja, kui palju on meie ülesandes toodud mänguväljal erinevaid võimalikke seise. Kas on mõeldav, et teha tabel, kus iga seisu jaoks on kirjas, mis käik kõige soodsam on?
 
Kuna harjutuse eesmärk on alpha-beta otsinguga tutvumine, siis selliste tabelite genereerimise tehnikaid juhendis pole kirjeldatud :-)


== Ideed lahenduse jaoks ==
== Ideed lahenduse jaoks ==

Redaktsioon: 7. oktoober 2018, kell 16:11

Alpha-beta otsing

Sissejuhatus

"Karujaht" on arvatavasti Vana-Roomast pärit mäng, kus kolm jahimeest peavad karu "kinni püüdma" - suruma ta sellisesse seisu, kus karul enam ühtegi käiku ei ole. Nupud paiknevad mängulaua joonte ristumiskohtades, näiteks nagu pildil olevas algseisus. Käike teevad pooled kordamööda ja käiguks on ühe nupu liigutamine mööda joont järgmisesse ristumiskohta.

Mängus ei ole karul võimalik võita, mängitakse selle peale, kas ja kui kiiresti ta kinni püütakse. Võimalik, et Vana-Roomas mängiti mängu raha peale, kihla veeti selle peale, kas karu suudab näiteks 40 käiku vastu pidada.

Teeme lihtsa programmi, mis seda mängu inimese vastu mängib. Seejuures on oluline, et programm kasutataks alpha-beta puuotsingut või mingit selle edasiarendust.

Nõuded

  1. Kasutajaliides on tekstipõhine
  2. Kasutame piltidel toodud algseisu ja mängulaua tähistust ("A1"..."E5"). Käiku tähistame näiteks B1-A1, mis tähendab et väljal B1 asuv nupp, olgu see siis jahimees või karu, liigub väljale A1.
  3. Algseisus on karu käik
  4. Programm kasutab alpha-beta algoritmi ja peaks oskama ükskõik kumba poolt mängida

Mängu mängimine võiks välja näha umbes nii:

...

current state:
To move: bear
Bear position: C3
Hunters are at: B1 C1 D1
available moves: [('C3', 'B3'), ('C3', 'D3'), ('C3', 'C2'), ('C3', 'C4')]


Your move? ('C3', 'B3')
current state:
To move: bear
Bear position: B3
Hunters are at: B1 C2 D1
available moves: [('B3', 'C3'), ('B3', 'B2'), ('B3', 'B4'), ('B3', 'A3')]


Your move? 

Programm näitab mänguseisu, küsib käiku, seejärel teeb oma käigu (või käigud) ja näitab jälle mänguseisu. See tsükkel kordub, kuni mäng läbi saab. Näites ei ole mänguseisu visualiseeritud ja see ei ole ka kohustuslik.

Lahenduse võimalikud variandid (vali üks):

  • aima-python paketi games moodul ja games.Game klass. See töötab üsna sarnaselt search.Problem klassiga ning samas moodulis on üsna palju vajalikku juba ära implementeeritud. Juhendi lõpus on mõned näited selle paketi kasutamisest.
  • Implementeeri ise [AIMA] õpiku Figure 5.7 toodud algoritm
  • Leia sobivad kooditükid või pseudokood Internetist.

Ükskõik millise variandi valid, pööra tähelepanu, et ülalpool toodud nõuded oleks täidetud. Ühelt poolt need lihtsustavad ülesannet, aga teiselt poolt kitsendavad - kusagilt üle võetud lahendus vajab ikkagi tõenäoliselt ümber tegemist ja kohandamist.

Elementaarsed asjad

Elementaarse osa tegemisest ülesande kaitsmise juures piisab.

Hästi mängimine

Siin kirjeldatavaid tehnikaid võib katsetada vastavalt huvile ja motivatsioonile, kohustuslikud nad ei ole. Enamus tehnikaid on suhteliselt tüüpilised paljude lauamängude (ja sarnaste asjade) alpha-beta otsinguga tehtud lahenduste juures.

Ideed lahenduse jaoks

  • kui esitad olekut tegemata käikude kaudu, siis muutub käikude genereerimine actions() meetodis lihtsamaks
  • mängu saab mängida ka nii, kui pole märgitud, kes millise kriipsu tegi, seega visualiseerimist saab lihtsustada kui näitad mõlema mängija kriipse ühtemoodi
  • Kui kasutad games.Game klassi, siis seal leiduv play_game() meetod sunnib mängijaid käike tegema kordamööda ja meie mängus see ei ole nii. Aga sellest saab teha oma versiooni, mis kontrolliks näiteks mängu olekust, kelle käik parajasti on.
  • kui su otsing on mingil põhjusel liiga aeglane, siis piira rekursiooni sügavus ära ning tagasta lõppseisu asemel mingi vahepealne hinnang seisule (vt [AIMA] 5.4). Sel juhul on oluline ka järgmine punkt.
  • utility() funktsioon peaks vahet tegema, kas tegu on lõppseisuga või mitte. Lõppseisus võitmine on palju olulisem kui mingis vahepealses olekus hea skoori omamine.

games.Game klassi kasutamise näited ja vihjed

Trips-traps-trull on games moodulis juba valmis tehtud ja kasutab ka Game klassi. Käima tõmmatakse mäng nii:

import games

ttt = games.TicTacToe()
ttt.play_game(games.query_player,
              games.alphabeta_player)