Preskočiť na obsah
coden

Hry a protivník: minimax, alfa-beta orezávanie a Monte Carlo tree search

Hra ako úloha prehľadávania, herný strom, minimax, alfa-beta orezávanie, hodnotiaca funkcia a MCTS — na piškvorkách, kde sa dá spočítať všetko, a s cestou od Deep Blue k AlphaZero.

14 minút Matěj Žalmánek 2026-10-15

Séria Základy AI Diel 22 z 52
  1. Mapa umelej inteligencie: čo je čo a ako to do seba zapadá
  2. Stručná história umelej inteligencie: od Turinga po jazykové modely
  3. Dáta, model, tréning, inferencia: základné pojmy na jednom príklade
  4. Ako čítať matematický zápis: symboly, indexy, sumy a kvantifikátory
  5. Množiny a relácie: stavebnica, z ktorej sa skladajú definície v AI
  6. Funkcie a zobrazenia: prečo je každý model v AI funkcia
  7. Logika a dôkazy: pravidlá, podľa ktorých sa v AI uvažuje
  8. Grafy a stromy: štruktúra, na ktorej stojí hľadanie aj neurónové siete
  9. Lineárna algebra pre strojové učenie: vektory, matice a prečo AI hlavne násobí
  10. Derivácie, gradient a reťazové pravidlo: ako model zistí, ktorým smerom sa učiť
  11. Gradientný zostup: ako sa model učí
  12. Čo je pravdepodobnosť: od hodu kockou ku Kolmogorovovým axiómam
  13. Podmienená pravdepodobnosť a Bayesova veta: ako zmeniť odhad, keď sa dozviete niečo nové
  14. Náhodná premenná a distribučná funkcia: jedna funkcia, ktorá o rozdelení povie všetko
  15. Funkcia hustoty a pravdepodobnostná funkcia: prečo má spojitá premenná v bode pravdepodobnosť nula
  16. Stredná hodnota, rozptyl a kovariancia: kde rozdelenie leží, aké je široké a čo s čím súvisí
  17. Prehľad pravdepodobnostných rozdelení: Bernoulliho, binomické, Poissonovo, rovnomerné, normálne a exponenciálne
  18. Zákon veľkých čísel a centrálna limitná veta: prečo sa priemery správajú tak predvídateľne
  19. Štatistika a odhady parametrov: maximálna vierohodnosť, MAP a intervaly spoľahlivosti
  20. Teória informácie: entropia, krížová entropia a KL divergencia — odkiaľ sa berú stratové funkcie
  21. Prehľadávanie stavového priestoru: BFS, DFS, UCS a A* s animáciami
  22. Hry a protivník: minimax, alfa-beta orezávanie a Monte Carlo tree search
  23. Splňovanie obmedzujúcich podmienok: backtracking, propagácia obmedzení a AC-3 na sudoku a mape krajov
  24. Logika a znalostné systémy: dopredné a spätné reťazenie, rezolúcia a expertné systémy
  25. Plánovanie: STRIPS, svet kociek, heuristiky z relaxácie a plánovanie v AI agentoch
  26. Lokálne hľadanie a simulované žíhanie: obchodný cestujúci cez krajské mestá
  27. Genetické algoritmy: populácia, kríženie, mutácia a výber na batohu na výlet
  28. Evolučné stratégie a genetické programovanie: od pravidla jednej pätiny po Keplerov zákon
  29. Optimalizácia mravčou kolóniou: ako feromónová stopa nájde krátku cestu
  30. Optimalizácia rojom častíc: zotrvačnosť, vlastná skúsenosť a skúsenosť roja
  31. Neuroevolúcia: evolúcia váh aj tvaru neurónových sietí a algoritmus NEAT
  32. Fuzzy množiny a funkcie príslušnosti: ako zapísať „trochu teplo“
  33. Fuzzy logika a pravdepodobnosť: prečo „trochu teplo“ neznamená „pravdepodobne teplo“
  34. Fuzzy logika: t-normy, implikácie a pravidlá AK–TAK
  35. Fuzzy riadenie: Mamdani a Sugeno od ventilátora po kyvadlo na vozíku
  36. Fuzzy zhlukovanie: algoritmus fuzzy c-means a body medzi zhlukmi
  37. Neuro-fuzzy systémy (ANFIS): fuzzy pravidlá, ktoré sa učia z dát
  38. Markovove reťazce: prechodová matica, stacionárne rozdelenie a PageRank
  39. Skryté Markovove modely: Viterbiho algoritmus a nepoctivé kasíno
  40. Bayesovské siete: prečo je tráva mokrá a čo z toho vyplýva pre postrekovač
  41. Kalmanov filter: ako z nepresných meraní odhadnúť, kde auto je a ako rýchlo ide
  42. Druhy strojového učenia: s učiteľom, bez učiteľa, s čiastočným učiteľom a ďalšie
  43. Prompty, kontext a RAG: ako modelu dať správne informácie
  44. Variačné autoenkodéry (VAE): nové obrázky zo spojitého latentného priestoru
  45. Generatívne adversariálne siete (GAN): falšovateľ proti detektívovi
  46. Difúzne modely: ako sa z čistého šumu stane obrázok
  47. Markovove rozhodovacie procesy: stavy, akcie, odmeny a Bellmanove rovnice
  48. Q-learning a DQN: učenie hodnoty akcií od tabuľky po neurónovú sieť
  49. Policy gradient a PPO: učenie priamo stratégie
  50. Ako funguje AI agent: jazykový model v slučke s nástrojmi
  51. Programovanie s AI agentmi: zadanie, testy a kontrola
  52. Vyhodnocovanie a bezpečnosť AI systémov: ako merať a ako strážiť

Celá osnova série Hotovo: 52 z 83 tém

Čo si odnesiete
  • Ako sa hra dvoch hráčov zapíše ako úloha prehľadávania a prečo je riešením stratégia, nie cesta.
  • Ako minimax vypočíta zaručenú hodnotu pozície a prečo alfa-beta dospeje k rovnakému výsledku oveľa rýchlejšie.
  • Ako Monte Carlo tree search nájde dobrý ťah bez hodnotiacej funkcie a čo z neho urobil AlphaGo.

Čo sa hodí vedieť vopred: Prehľadávanie stavového priestoru: BFS, DFS, UCS a A* s animáciami, Grafy a stromy: štruktúra, na ktorej stojí hľadanie aj neurónové siete

V bludisku z minulého dielu stál panáčik sám. Svet sa nehýbal a každý ťah viedol tam, kam mal. V hre však sedí oproti vám niekto, kto chce presný opak — a na každý váš ťah odpovie tým, ktorý vás bolí najviac. Hľadať cestu k cieľu už nestačí: musíte hľadať stratégiu, ktorá obstojí proti každej odpovedi. Šach, dáma aj go boli desiatky rokov meradlom umelej inteligencie a algoritmy z tohto dielu stoja za Deep Blue aj za AlphaGo.

Nadväzuje na diely Prehľadávanie stavového priestoru a Grafy a stromy.

1. Hra ako úloha prehľadávania

Definícia — hra dvoch hráčov

Hra dvoch hráčov (deterministická, s úplnou informáciou a nulovým súčtom) je sedmica

Γ = (S, s0, hráč, A, T, K, U),

ktorá spĺňa:

  1. S je neprázdna množina stavov (pozícií) a s0 ∈ S je počiatočný stav;
  2. K ⊆ S je množina koncových stavov — v nich sa hra skončí;
  3. hráč : S ∖ K → {MAX, MIN} určuje, kto je v stave na ťahu;
  4. A priraďuje každému stavu s ∈ S ∖ K konečnú neprázdnu množinu A(s) ťahov (akcií) a v koncových stavoch A(s) = ∅;
  5. T je prechodová funkcia: pre s ∈ S ∖ K a a ∈ A(s) je T(s, a) ∈ S stav po ťahu a (ťahy sú deterministické);
  6. hráči sa striedajú: ak je s ∈ S ∖ K, a ∈ A(s) a T(s, a) ∉ K, potom hráč(T(s, a)) ≠ hráč(s);
  7. U : K → ℝ je úžitok koncového stavu z pohľadu hráča MAX; úžitok hráča MIN je −U (nulový súčet: U(s) + (−U(s)) = 0 pre každé s ∈ K).

Obaja hráči poznajú celú sedmicu a v každom okamihu vidia aktuálny stav (úplná informácia). Hra je konečná práve vtedy, keď neexistuje nekonečná postupnosť s0, s1, s2, … s si = T(si−1, ai) pre nejaké ai ∈ A(si−1) — každá partia teda po konečne mnohých ťahoch skončí v K. Všetky hry v tomto diele sú konečné.

Stratégia hráča MAX je funkcia σ, ktorá každému stavu s ∈ S ∖ K s hráč(s) = MAX priradí ťah σ(s) ∈ A(s); stratégia τ hráča MIN je definovaná rovnako pre stavy s hráč(s) = MIN. Dvojica stratégií (σ, τ) jednoznačne určí partiu zo stavu s0 a tým aj jej úžitok.

Laicky povedané

Hra je bludisko, v ktorom sa o ťahy delíte so súperom. Na konci sa spočíta skóre — v piškvorkách +1, keď vyhrá MAX, −1, keď vyhrá MIN, a 0 za remízu. MAX chce skóre čo najvyššie, MIN čo najnižšie. „Nulový súčet“ znamená, že sa nedá vyhrať spoločne: čo jeden získa, druhý stratí.

Rozdiel oproti prehľadávaniu je zásadný. Riešením už nie je cesta — tú si nevyberiete, pretože každý druhý ťah robí súper. Riešením je stratégia: predpis, ako odpovedať na každý ťah, ktorý súper môže zahrať.

2. Herný strom

Definícia — herný strom

Nech Γ = (S, s0, hráč, A, T, K, U) je konečná hra dvoch hráčov. Herný strom hry Γ je koreňový strom (pozri diel Grafy a stromy), pre ktorý platí:

  1. uzly sú všetky postupnosti ťahov (a1, …, ak), k ≥ 0, ktoré sa dajú zo s0 zahrať, t. j. si−1 ∉ K, ai ∈ A(si−1) a si = T(si−1, ai) pre i = 1, …, k; uzlu prislúcha stav sk;
  2. koreň je prázdna postupnosť () so stavom s0;
  3. deti uzla (a1, …, ak) so stavom sk ∉ K sú uzly (a1, …, ak, a) pre všetky a ∈ A(sk) so stavmi T(sk, a);
  4. listy sú práve uzly, ktorých stav je koncový (sk ∈ K).

Uzol teda nie je pozícia, ale história, ktorá k nej viedla — do rovnakého stavu sa dá dostať rôznymi postupnosťami ťahov a v strome sa potom objaví viackrát. Uzly, kde je na ťahu MAX, kreslíme ako trojuholník špičkou nahor, uzly MIN špičkou nadol.

Nech b = maxs ∈ S ∖ K |A(s)| je faktor vetvenia a m najväčšia dĺžka partie (počet ťahov). Potom má strom najviac bm listov.

Laicky povedané

Všetky partie, ktoré sa dajú odohrať, nakreslené ako rozvetvený strom: z koreňa vedie jedna vetva pre každý prvý ťah, z každej z nich vetva pre každú odpoveď a tak ďalej, až po koniec hry. Jeden list = jedna dohraná partia.

Piškvorky na hracom poli 3 × 3 sú malá hra, a predsa má ich strom 549 946 uzlov a 255 168 listov — toľko rôznych partií sa dá odohrať. Rôznych pozícií je pritom len 5 478: do rovnakej pozície sa dostanete mnohými poradiami ťahov. Šach má faktor vetvenia okolo 35 a partia trvá desiatky ťahov; Claude Shannon v roku 1950 odhadol jeho strom na 10120 partií. Go s faktorom vetvenia okolo 250 je ešte o mnoho rádov ďalej. Celý strom teda prejdeme len pri malých hrách — pri veľkých sa musíme naučiť, ktoré vetvy vynechať.

Príklad — horný odhad stromu piškvoriek a Shannonovo číslo

Keby sa piškvorky hrali vždy až do zaplnenia poľa, mal by strom v hĺbke k práve 9 · 8 · … · (9 − k + 1) = 9!/(9 − k)! uzlov (k = 0, …, 9). Spolu

∑k=09 9!/(9 − k)! = 1 + 9 + 72 + 504 + 3 024 + 15 120 + 60 480 + 181 440 + 362 880 + 362 880 = 986 410 uzlov a 9! = 362 880 listov.

Skutočný strom má 549 946 uzlov a 255 168 listov, pretože partia, v ktorej niekto zloží tri v rade, končí skôr a jej vetva sa ďalej nevetví. Odhad bm je teda horná hranica; tu s b klesajúcim od 9 k 1.

Shannon (Programming a Computer for Playing Chess, 1950) počítal pre šach s asi 103 možnosťami na jednu dvojicu ťahov (biely a čierny) a typickou partiou so 40 dvojicami ťahov: (103)40 = 10120. Je to hrubý rádový odhad, nie presné číslo.

3. Minimax

Definícia — minimaxová hodnota

Nech Γ = (S, s0, hráč, A, T, K, U) je konečná hra dvoch hráčov. Minimaxová hodnota je funkcia MM : S → ℝ definovaná rekurzívne pre každé s ∈ S:

  1. MM(s) = U(s), ak s ∈ K;
  2. MM(s) = maxa ∈ A(s) MM(T(s, a)), ak s ∉ K a hráč(s) = MAX;
  3. MM(s) = mina ∈ A(s) MM(T(s, a)), ak s ∉ K a hráč(s) = MIN.

Rekurzia je dobre definovaná: hra je konečná, takže každý reťazec rekurzívnych volaní skončí v koncovom stave, a A(s) je konečná neprázdna, takže maximum aj minimum existujú.

Ťah a* ∈ A(s) je optimálny ťah hráča MAX v stave s s hráč(s) = MAX práve vtedy, keď

a* ∈ argmaxa ∈ A(s) MM(T(s, a)), t. j. MM(T(s, a*)) = MM(s);

optimálny ťah hráča MIN je obdobne prvok argmin. Stratégia, ktorá v každom stave volí optimálny ťah, je minimaxová stratégia.

Laicky povedané

Hodnotu pozície vypočítate odzadu. Na konci hry ju poznáte — je to skóre. O ťah skôr: keď hrá MAX, vyberie si to najlepšie z toho, čo ho čaká; keď hrá MIN, vyberie to najhoršie pre MAX. Takto sa hodnoty prelievajú poschodie po poschodí nahor až ku koreňu. Je to presne úvaha „keď pôjdem sem, on pôjde tam, a potom ja…“, len dotiahnutá do konca.

1 4 2 4 6 2 10 3 3 4 4 6 5 9 7 2 8 7 9 8 11 5 12 3 13 9 MAX MIN
Minimax: hodnoty prebublávajú od listov ku koreňu

Uzol MIN vľavo si z listov 4, 6 a 9 vyberie 4, prostredný z 2, 7 a 8 vyberie 2, pravý z 5, 3 a 9 vyberie 3. MAX v koreni potom volí medzi 4, 2 a 3 a zahrá ľavý ťah s hodnotou 4. Všimnite si, že pravá vetva skrýva deviatku — lenže na ňu MAX nikdy nedosiahne, pretože MIN by namiesto nej zahral trojku.

Veta — čo minimax zaručuje

Nech Γ je konečná hra dvoch hráčov a σ* minimaxová stratégia hráča MAX. Potom

  1. pre každú stratégiu τ hráča MIN má partia hraná dvojicou (σ*, τ) úžitok ≥ MM(s0);
  2. ak je aj τ* minimaxová stratégia hráča MIN, má partia hraná dvojicou (σ*, τ*) úžitok práve MM(s0).

Dôkaz (náčrt), indukciou podľa výšky uzla: v liste MAX získa presne U(s) = MM(s). V uzle MAX zahrá ťah do dieťaťa s najväčšou hodnotou a podľa indukčného predpokladu si v ňom ubráni aspoň túto hodnotu, teda aspoň MM(s). V uzle MIN si súper vyberie ľubovoľné dieťa, ale každé má hodnotu ≥ min = MM(s), a v každom si MAX podľa predpokladu ubráni aspoň jeho hodnotu. Pre s = s0 je to bod 1. Rovnakou úvahou s vymenenými rolami si MIN minimaxovou stratégiou τ* zaistí úžitok najviac MM(s0) proti každej stratégii MAX; obe nerovnosti spolu dávajú bod 2. ∎

Minimax prechádza strom do hĺbky: čas O(bm), pamäť O(b · m).

Laicky povedané

Minimax počíta s najhorším: predpokladá, že súper nikdy neurobí chybu. Keď ju urobí, dopadnete len lepšie. Preto je minimaxová hodnota zaručená — to, čo si ubránite, nech súper hrá akokoľvek.

4. Minimax na piškvorkách

Piškvorky 3 × 3 sú dosť malé na to, aby minimax prešiel celý strom. Výsledok pozná každý, kto ich hral dlhšie než pár minút: minimaxová hodnota prázdneho poľa je 0 — keď obaja hrajú bez chyby, je to vždy remíza. Zaujímavejšie je, čo minimax povie o konkrétnej pozícii. Na ťahu je X (MAX) a v každom voľnom políčku je hodnota ťahu naň:

X O −1 X +1 −1 O 0 −1
Hodnota každého ťahu X podľa minimaxu +1 výhra0 remíza−1 prehra

Vyhráva jediný ťah — stred. X tým postaví vidličku: hrozí dokončiť prostredný riadok aj uhlopriečku a O nemôže zablokovať oboje. Ťah dole do stredu drží remízu. Zvyšné tri ťahy vyzerajú nevinne, ale prehrávajú: O na ne odpovie vlastnou vidličkou. Človek by to musel premyslieť; minimax to jednoducho vypočíta.

def minimax(deska):
    konec = vitez(deska)                 # "X", "O", "remiza" alebo None
    if konec:
        return {"X": 1, "O": -1, "remiza": 0}[konec]
    hodnoty = [minimax(zahraj(deska, tah)) for tah in volna_pole(deska)]
    return max(hodnoty) if na_tahu(deska) == "X" else min(hodnoty)

5. Alfa-beta orezávanie

Minimax prejde celý strom, aj keď je z polovice zbytočný. Pozrite sa znova na prostrednú vetvu: prvý list ukázal 2. MIN teda v tej vetve dosiahne 2 alebo menej — a MAX už má ľavú vetvu s hodnotou 4 istú. Nech sú zvyšné dva listy akékoľvek, MAX do prostrednej vetvy nepôjde. Nemusí sa na ne ani pozerať.

Definícia — alfa-beta

Nech Γ je konečná hra dvoch hráčov. Alfa-beta je prehľadávanie do hĺbky, ktoré si so sebou nesie dve hranice α, β ∈ ℝ ∪ {−∞, +∞}:

  1. α — najvyššia hodnota, ktorú si MAX už zaistil niekde na ceste od koreňa (na začiatku −∞);
  2. β — najnižšia hodnota, ktorú si už zaistil MIN (na začiatku +∞).

Funkcia AB(s, α, β) pre stav s ∈ S:

  1. Ak je s ∈ K, vráť U(s).
  2. Ak je hráč(s) = MAX, polož v ← −∞; inak v ← +∞.
  3. Pre ťahy a ∈ A(s) postupne (v pevnom poradí) vypočítaj h ← AB(T(s, a), α, β) a
    • v uzle MAX polož v ← max(v, h) a α ← max(α, v),
    • v uzle MIN polož v ← min(v, h) a β ← min(β, v);
    hneď ako α ≥ β, zvyšné ťahy sa orežú — neprehľadávajú sa — a pokračuje sa krokom 4.
  4. Vráť v.

Alfa-beta v koreni je volanie AB(s0, −∞, +∞).

Veta. Nech Γ je konečná hra dvoch hráčov. Potom AB(s0, −∞, +∞) = MM(s0) — alfa-beta vráti v koreni rovnakú hodnotu ako minimax (vo vnútorných uzloch, kde došlo k orezu, vracia len hranicu, nie presnú hodnotu). Ak má strom faktor vetvenia b a hĺbku m a ak sú ťahy zoradené v najlepšom možnom poradí, preskúma alfa-beta len O(bm/2) uzlov.

Laicky povedané

α je „toto už mám vo vrecku“, β je „viac mi súper aj tak nedovolí“. Keď v nejakej vetve zistíte, že súper vás v nej môže zraziť pod to, čo už máte isté inde, nemá zmysel ju skúmať ďalej — stačí jediný vyvracajúci ťah. Hodnota v koreni zostane rovnaká, len ju nájdete rýchlejšie.

orež, keď α ≥ β

α
to najlepšie, čo si MAX už zaistil inde na ceste od koreňa. Do vetvy, ktorá dá menej, nikdy nepôjde — má lepšiu voľbu
β
to najhoršie pre MAX, čo mu MIN v tejto vetve už môže vnútiť. Viac než β odtiaľto MAX nedostane, nech zvyšné deti vyjdú akokoľvek
≥
okno [α, β] je prázdne: hodnota, o ktorú by sa tu ešte dalo hrať, by musela byť zároveň aspoň α a najviac β. Taká neexistuje (pri rovnosti by nebola lepšia, než čo MAX už má), takže zvyšok vetvy koreň nemôže ovplyvniť
V prostrednej vetve stromu: α = 4 (ľavá vetva), po prvom liste β = 2. Keďže 4 ≥ 2, listy 7 a 8 sa neskúmajú.
1 4 2 4 6 ≤2 8 ≤3 α=−∞ β=∞ α=−∞ β=∞ α=−∞ β=4 α=−∞ β=4 α=−∞ β=4 α=4 β=∞ α=4 β=∞ α=4 β=2 α=4 β=∞ α=4 β=∞ α=4 β=5 α=4 β=3 α=4 β=∞ 3 4 4 6 5 9 7 2 7 8 9 5 10 3 9 MAX MIN
Alfa-beta na rovnakom strome: čísla sú poradie návštev pri uzloch okno α, β; oranžovo, keď α ≥ β a zvyšok vetvy sa orežeorezaných listov: 3 / 9

Alfa-beta dospela k rovnakému výsledku — MAX hrá vľavo a získa 4 — ale ohodnotila len 6 listov z 9. V prostrednej vetve orezala dva listy hneď po dvojke, v pravej jeden po trojke. Pri orezanom uzle MIN je preto len hranica „≤ 2“ a „≤ 3“: presnú hodnotu nepoznáme, a nepotrebujeme ju.

To isté, čo animácia ukazuje pri uzloch, krok po kroku v tabuľke. Riadok zachytáva okno uzla pri vstupe doň a potom po každom dieťati, ktoré vrátilo hodnotu:

krokuzolčo sa staloαβpoznámka
1A (MAX)vstup−∞+∞
2B (MIN)vstup−∞+∞
3B (MIN)b1 vrátil 4−∞4
4B (MIN)b2 vrátil 6−∞4
5B (MIN)b3 vrátil 9−∞4B vracia 4
6A (MAX)B vrátil 44+∞
7C (MIN)vstup4+∞
8C (MIN)c1 vrátil 242α ≥ β: orez c2, c3; C vracia len hranicu ≤ 2
9A (MAX)C vrátil 24+∞
10D (MIN)vstup4+∞
11D (MIN)d1 vrátil 545
12D (MIN)d2 vrátil 343α ≥ β: orez d3; D vracia len hranicu ≤ 3
13A (MAX)D vrátil 34+∞A vracia 4

Uzol MIN dostane od rodiča α = 4 a mení len svoje β; uzol MAX naopak mení len α. Okno každého uzla sa tak len zužuje. V pravej vetve prvý list (5) orez nevyvolá — 5 je viac než 4, MIN by tu MAXovi mohol dať viac než vľavo —, až druhý list (3) stiahne β pod α.

Na piškvorkách je rozdiel dramatickejší. Úplný minimax z prázdneho poľa navštívi 549 946 pozícií, alfa-beta s rovnakým poradím ťahov len 18 297 — asi tridsaťkrát menej — a vráti rovnakú nulu. Exponent m/2 vo vete znamená, že za rovnaký čas dovidíte dvakrát hlbšie. Preto na poradí ťahov toľko záleží: šachové programy skúšajú ako prvé brania a ťahy, ktoré boli dobré minule.

Príklad — koľko listov ušetrí alfa-beta pri najlepšom poradí

Presnú hranicu dokázali D. E. Knuth a R. W. Moore (An Analysis of Alpha-Beta Pruning, 1975): v strome s faktorom vetvenia b a hĺbkou d ohodnotí alfa-beta pri najlepšom poradí ťahov

b⌈d/2⌉ + b⌊d/2⌋ − 1 listov namiesto bd.

Šach, b = 35, hĺbka d = 6 polťahov: minimax 356 = 1 838 265 625 listov, alfa-beta 353 + 353 − 1 = 42 875 + 42 875 − 1 = 85 749 listov — asi 21 000-krát menej. A naopak: 12 polťahov prejde alfa-beta s 356 + 356 − 1 ≈ 3,7 · 109 listami, teda len za dvojnásobok práce, ktorú minimax potrebuje na 6 polťahov.

Malý strom z obrázka (b = 3, d = 2): hranica je 3 + 3 − 1 = 5 listov. Alfa-beta ich ohodnotila 6, pretože poradie listov nie je najlepšie možné — v pravej vetve stojí trojka až na druhom mieste.

def alfabeta(deska, alfa=-inf, beta=inf):
    konec = vitez(deska)
    if konec:
        return {"X": 1, "O": -1, "remiza": 0}[konec]
    maximalizuje = na_tahu(deska) == "X"
    v = -inf if maximalizuje else inf
    for tah in volna_pole(deska):
        h = alfabeta(zahraj(deska, tah), alfa, beta)
        if maximalizuje:
            v = max(v, h); alfa = max(alfa, v)
        else:
            v = min(v, h); beta = min(beta, v)
        if alfa >= beta:
            break                          # orez: zvyšok vetvy nič nezmení
    return v

6. Obmedzená hĺbka a hodnotiaca funkcia

Ani alfa-beta neprejde šachový strom do konca partie. Skutočné programy preto hľadajú len do pevnej hĺbky a pozíciu, v ktorej skončia, odhadnú.

Definícia — minimax s obmedzenou hĺbkou

Nech Γ = (S, s0, hráč, A, T, K, U) je hra dvoch hráčov. Hodnotiaca funkcia je funkcia E : S → ℝ taká, že E(s) = U(s) pre všetky s ∈ K; pre s ∉ K je E(s) odhad MM(s). Zvyčajne je to vážený súčet n ≥ 1 príznakov pozície f1, …, fn : S → ℝ s váhami w1, …, wn ∈ ℝ:

E(s) = w1f1(s) + … + wnfn(s).

Minimax s obmedzenou hĺbkou je pre každé d ∈ ℕ0 funkcia MMd : S → ℝ definovaná rekurzívne podľa d:

  1. MMd(s) = E(s), ak s ∈ K alebo d = 0;
  2. MMd(s) = maxa ∈ A(s) MMd−1(T(s, a)), ak s ∉ K, d ≥ 1 a hráč(s) = MAX;
  3. MMd(s) = mina ∈ A(s) MMd−1(T(s, a)), ak s ∉ K, d ≥ 1 a hráč(s) = MIN.

Hodnota MMd(s) teda počíta minimax len d polťahov dopredu a pozície, v ktorých skončí, nahradí odhadom E. Ak je d aspoň dĺžka najdlhšej partie zo s, je MMd(s) = MM(s).

Laicky povedané

Neviete domyslieť partiu do konca, tak sa pozriete pár ťahov dopredu a spýtate sa: „Ako dobre to tu vyzerá?“ V šachu je najjednoduchšia odpoveď spočítať materiál — pešiak 1, jazdec a strelec 3, veža 5, dáma 9 — a odčítať súperov. Lepšie funkcie pridajú aktivitu figúr, bezpečnosť kráľa alebo štruktúru pešiakov.

E(s) = ∑i wi · (pi(s) − p′i(s))

E(s)
odhad hodnoty pozície z pohľadu MAX (bieleho) — dosadí sa tam, kde hľadanie skončí, namiesto skutočnej minimaxovej hodnoty
∑i
cez druhy figúr: pešiak, jazdec, strelec, veža, dáma. Súčet, pretože materiál rôznych figúr sa v najjednoduchšom modeli jednoducho sčíta
wi
cena figúry: 1, 3, 3, 5, 9. Váha prevádza „kusy“ na spoločnú menu, aby sa dala porovnať veža s dvoma jazdcami
pi − p′i
koľko figúr daného druhu má biely viac než čierny. Rozdiel, nie počet, pretože hra má nulový súčet: čo má súper navyše, je strata
Biely má o jazdca viac, čierny o dvoch pešiakov viac: E = 3 · (+1) + 1 · (−2) = +1, teda mierna výhoda bieleho. Ceny figúr sú tradičná šachová konvencia, nie výsledok výpočtu.
def minimax_d(s, d):
    if je_konec(s) or d == 0:
        return E(s)                        # ďalej nevidíme: odhad namiesto skutočnej hodnoty
    hodnoty = [minimax_d(T(s, a), d - 1) for a in akce(s)]
    return max(hodnoty) if hrac(s) == "MAX" else min(hodnoty)

def iterativni_prohlubovani(s, cas):      # v s je na ťahu MAX
    d, nejlepsi = 1, None
    while zbyva(cas):
        nejlepsi = max(akce(s), key=lambda a: minimax_d(T(s, a), d - 1))
        d += 1                             # ďalšie kolo o polťah hlbšie
    return nejlepsi

Obmedzená hĺbka má svoju pascu: efekt horizontu. Keď hľadanie skončí uprostred výmeny figúr — vy ste práve vzali dámu, súper ju o ťah vezme späť —, hodnotiaca funkcia vidí len prvú polovicu a pozíciu precení. Programy sa bránia tým, že „nepokojné“ pozície prehľadávajú ďalej, kým sa neupokoja. A pretože nikdy nevedia, koľko majú času, hľadajú iteratívnym prehlbovaním z minulého dielu: hĺbka 1, 2, 3, … kým nedôjde čas. Výsledky plytkých prechodov navyše poslúžia ako poradie ťahov pre hlbšie — a alfa-beta potom orezáva oveľa viac.

7. Monte Carlo tree search

Hodnotiacu funkciu pre šach ľudia ladili desiatky rokov. Pre go sa ju napísať nedarilo — pozícia, ktorá vyzerá pokojne, môže byť o dvadsať ťahov neskôr prehraná. Monte Carlo tree search (MCTS) na hodnotiacu funkciu úplne rezignuje. Namiesto odhadu pozíciu dohrá: náhodne, mnohokrát, a pozrie sa, ako často to dopadlo dobre.

Definícia — jedna iterácia MCTS

Nech Γ = (S, s0, hráč, A, T, K, U) je konečná hra dvoch hráčov, v ktorej má každá partia výsledok výhra, remíza, alebo prehra. Vstup: stav s0 ∉ K (koreň) a počet iterácií (alebo časový limit). Výstup: ťah a ∈ A(s0).

MCTS buduje prehľadávací strom — časť herného stromu, ktorá začína len koreňom a v každej iterácii sa o jeden uzol rozrastie. Každý uzol i stromu si pamätá:

  1. počet návštev ni ∈ ℕ0 — koľko simulácií prešlo uzlom;
  2. súčet výsledkov wi ∈ [0, ni] z pohľadu hráča, ktorý do uzla ťahal, pričom výsledok jednej partie je 1 za výhru, ½ za remízu a 0 za prehru.

Uzol je plne rozšírený práve vtedy, keď má v strome dieťa pre každý ťah a ∈ A(s) svojho stavu s. Jedna iterácia MCTS má štyri kroky:

  1. Výber — začni v koreni; kým je aktuálny uzol plne rozšírený a jeho stav nie je koncový, prejdi do dieťaťa s najvyššou hodnotou UCT (definícia nižšie).
  2. Rozšírenie — ak stav aktuálneho uzla nie je koncový, vyber doteraz neskúšaný ťah a, pridaj dieťa so stavom T(s, a) a n = w = 0 a prejdi doň.
  3. Simulácia — zo stavu aktuálneho uzla dohraj partiu náhodnými ťahmi (každý z A(s) s rovnakou pravdepodobnosťou) až do koncového stavu sK ∈ K.
  4. Spätné šírenie — každému uzlu i na ceste od aktuálneho uzla späť ku koreňu (vrátane oboch) polož ni ← ni + 1 a wi ← wi + výsledok partie sK z pohľadu hráča, ktorý do uzla i ťahal.

Iterácie sa opakujú, kým nevyprší počet iterácií alebo čas. Potom sa zahrá ťah z koreňa do dieťaťa s najväčším ni.

Laicky povedané

Ako keď sa rozhodujete medzi reštauráciami: chodíte tam, kde vám zatiaľ chutilo najviac, ale občas skúsite aj inú. Každý ťah dostane šancu, sľubné ťahy dostanú viac pokusov a strom rastie práve tam, kde sa hrá o veľa. Náhodné dohrávky sú hlúpe, lenže keď ich je tisíc, priemer už niečo hovorí.

1 výber 2 rozšírenie výhra 3 simulácia +1+1+1+1 4 spätné šírenie
Štyri kroky jednej iterácie MCTS
def mcts(koren, iteraci):
    for _ in range(iteraci):
        u = koren
        while u.vsechny_deti() and u.deti:         # 1. výber
            u = max(u.deti, key=uct)
        if u.nezkusene and not je_konec(u.stav):   # 2. rozšírenie
            u = u.pridej_dite(nahodny(u.nezkusene))
        s = u.stav
        while not je_konec(s):                     # 3. simulácia
            s = T(s, nahodny(akce(s)))
        while u is not None:                       # 4. spätné šírenie
            u.n += 1
            u.w += vysledek(s, pro=u.kdo_tahl)     # 1, ½ alebo 0
            u = u.rodic
    return max(koren.deti, key=lambda d: d.n).tah
Definícia — UCT

Nech uzol prehľadávacieho stromu MCTS má N ≥ 1 návštev a deti i = 1, …, k, každé s ni ≥ 1 návštevami a súčtom výsledkov wi ∈ [0, ni] (značenie z definície MCTS vyššie). Nech c > 0 je pevná konštanta prieskumu, zvyčajne c = √2. Hodnota UCT (Upper Confidence bounds applied to Trees) dieťaťa i je

UCT(i) = wi/ni + c · √ln N/ni.

V kroku výberu sa volí dieťa i* ∈ argmaxi ∈ {1, …, k} UCT(i). Kocsis a Szepesvári (2006) dokázali, že s rastúcim počtom iterácií pravdepodobnosť, že MCTS s UCT odporučí iný než minimaxovo optimálny ťah, klesá k nule.

Laicky povedané

Prvý člen je „ako dobre to zatiaľ dopadalo“, druhý „ako málo to poznám“. Ťah, ktorý ste dlho neskúsili, dostáva bonus, ktorý s každou návštevou iného ťahu pomaly rastie. Je to rovnaká dilema ako pri učení posilňovaním: využívať to, čo funguje, alebo preskúmavať, čo by mohlo fungovať lepšie?

UCT(i) = wi/ni + c · √ln N/ni

UCT(i)
skóre dieťaťa i vo výbere; vyhrá najväčšie. Nie je to odhad hodnoty ťahu, ale „ako veľmi sa oplatí ho skúsiť znova“
wi/ni
priemerný výsledok ťahu (0 až 1) — využívanie: ťahy, ktoré zatiaľ vychádzali dobre, dostanú prednosť
c
konštanta prieskumu — koľko váži zvedavosť oproti doterajším výsledkom. Hodnota √2 pochádza z pravidla UCB1 pre mnohorukých banditov (Auer, Cesa-Bianchi a Fischer, 2002) pre výsledky v ⟨0, 1⟩; na stromy ho preniesli Kocsis a Szepesvári (2006). V praxi sa ladí
ln N
rastie s počtom návštev rodiča, ale len pomaly. Vďaka nemu bonus málo skúšaných ťahov pomaly rastie: každý ťah sa skôr či neskôr skúsi znova
ni
koľkokrát už bol ťah skúšaný — v menovateli, takže čím menej ho poznáme, tým väčší bonus. Odmocnina zodpovedá (zjednodušene) tomu, ako rýchlo sa spresňuje priemer: jeho neistota klesá ako 1/√n
Druhý člen dohromady je preskúmavanie. Jeho vplyv slabne, ako ťah zbiera návštevy, ale pretože ln N rastie, nespadne nikdy na nulu.

Pustime MCTS na pozíciu, ktorú minimax rozlúštil vyššie. Čísla v políčkach sú návštevy po 100, 300 a 1000 iteráciách, pod nimi priemerný výsledok pre X:

X O X O 12 0,42 47 0,86 7 0,14 19 0,61 15 0,50 100 iterácií 20 0,38 197 0,89 24 0,44 33 0,55 26 0,44 300 iterácií 27 0,33 856 0,94 30 0,38 52 0,55 35 0,43 1000 iterácií
MCTS v tej istej pozícii: koľkokrát ktorý ťah navštívil hore návštevy, dole priemerný výsledok pre X

Po 100 iteráciách má stred 47 návštev a ostatné ťahy dohromady viac. Po tisícke ich má 856 a priemerný výsledok 0,94; remízový ťah dole v strede dostal 52 návštev, prehrávajúce ťahy ešte menej. MCTS pritom nepozná ani pojem vidlička, ani žiadnu hodnotiacu funkciu — len pravidlá a náhodu. A predsa našiel rovnaký ťah ako minimax, ktorý musel prejsť celý zvyšok stromu.

Prečo práve také rozloženie návštev? Vypočítajme UCT ťahov z koreňa po 1000 iteráciách (N = 1000, ln N ≈ 6,908, c = √2; farby podľa vzorca vyššie):

ťahniwi/nibonus c · √ln N/niUCT
vpravo hore (2)270,3330,7151,049
stred (4)8560,9410,1271,068
vpravo v strede (5)300,3830,6791,062
dole v strede (7)520,5480,5151,064
vpravo dole (8)350,4290,6281,057

Hodnoty UCT sú skoro rovnaké — v rozmedzí 1,049 až 1,068. Nie je to náhoda: výber zakaždým navštívi ťah s najvyšším UCT, a tým mu zníži bonus (priemer sa pritom zmení len málo), takže sa hodnoty postupne vyrovnajú. Stred má najlepší priemer, a preto mu na vyrovnanie stačí malý bonus — teda veľa návštev. Ostatné ťahy majú horší priemer a dorovnávajú ho veľkým bonusom, na ktorý stačí málo návštev. (Súčty v tabuľke počítame z nezaokrúhlených hodnôt, na poslednom mieste sa preto môžu líšiť o 1.)

8. Od Deep Blue k AlphaZero

  • Deep Blue (1997) porazil majstra sveta Garriho Kasparova. Vnútri bola alfa-beta s ručne písanou hodnotiacou funkciou a špecializovaný hardvér, ktorý zvládol okolo 200 miliónov pozícií za sekundu.
  • Chinook hral dámu proti majstrom sveta už v 90. rokoch a v roku 2007 jeho autori hru vyriešili: prešli toľko pozícií, že dokázali, že bezchybná partia končí remízou — rovnako ako piškvorky 3 × 3.
  • AlphaGo (2016) porazil Lee Se-dola 4 : 1. Spojil MCTS s neurónovými sieťami: jedna sieť navrhovala sľubné ťahy (namiesto náhodného výberu), druhá odhadovala hodnotu pozície (namiesto celej náhodnej dohrávky).
  • AlphaZero (2017) zahodil aj ľudské partie. Naučil sa šach, šogi a go len hraním sám proti sebe — učením posilňovaním — a v každej z hier porazil najlepší dovtedajší program.
  • Hry s náhodou a skrytou informáciou potrebujú viac. V backgammone rozhoduje kocka, takže sa do stromu pridávajú uzly náhody so strednou hodnotou (expectiminimax). V pokri nevidíte súperove karty; program Libratus (2017) napriek tomu porazil profesionálov v pokri dvoch hráčov.
Definícia — expectiminimax

Nech Γ = (S, s0, hráč, A, T, K, U) je konečná hra ako v definícii hry dvoch hráčov, len k hráčom MAX a MIN pribudne „hráč“ NÁHODA: hráč : S ∖ K → {MAX, MIN, NÁHODA} a podmienka striedania sa nevyžaduje. Pre každý stav s s hráč(s) = NÁHODA je A(s) konečná neprázdna množina možných výsledkov náhody r (napríklad čísel na kocke) a je dané rozdelenie pravdepodobnosti Ps : A(s) → [0, 1] s ∑r ∈ A(s) Ps(r) = 1 (pozri diel o pravdepodobnosti); výsledok r nastane s pravdepodobnosťou Ps(r) a vedie do stavu T(s, r).

Expectiminimaxová hodnota je funkcia EMM : S → ℝ definovaná rekurzívne:

  1. EMM(s) = U(s), ak s ∈ K;
  2. EMM(s) = maxa ∈ A(s) EMM(T(s, a)), ak hráč(s) = MAX;
  3. EMM(s) = mina ∈ A(s) EMM(T(s, a)), ak hráč(s) = MIN;
  4. ak hráč(s) = NÁHODA, je EMM(s) stredná hodnota hodnôt nasledovníkov: EMM(s) = ∑r ∈ A(s) Ps(r) · EMM(T(s, r)).

V uzloch MAX a MIN sa teda hodnota počíta ako pri minimaxe a v uzloch náhody ako priemer vážený pravdepodobnosťami výsledkov. Rozbor posledného vzorca (Ps skrátene ako P):

EMM(s) = ∑r P(r) · EMM(T(s, r))

EMM(s)
hodnota uzla náhody — čo môže MAX od pozície čakať v priemere, pretože výsledok hodu neovplyvní ani on, ani súper
∑r
cez všetky možné výsledky náhody; namiesto výberu najlepšieho (max) alebo najhoršieho (min) sa tu nevyberá nič — započíta sa každý
P(r)
pravdepodobnosť výsledku ako váha: častý výsledok ovplyvní hodnotu viac než zriedkavý
EMM(T(s, r))
hodnota pozície po danom výsledku, vypočítaná rekurzívne rovnakým pravidlom
Hod mincou: hlava (s pravdepodobnosťou 1/2) vedie do pozície s hodnotou 4, znak (1/2) do pozície s hodnotou −2. EMM = 1/2 · 4 + 1/2 · (−2) = 2 − 1 = 1. Ťah do istej pozície s hodnotou 0,5 je teda horší, aj keď nehrozí strata.

Myšlienka „pozri sa dopredu, než niečo urobíš“ zo šachovníc nezmizla. Plánujúci jazykoví agenti skúšajú niekoľko variantov postupu, ohodnotia ich a pokračujú tým najsľubnejším — len namiesto ťahov figúr volia kroky riešenia.

9. Zhrnutie

  • Hra dvoch hráčov s nulovým súčtom je úloha prehľadávania, v ktorej sa o ťahy delíte so súperom; riešením je stratégia, nie cesta.
  • Minimax počíta hodnotu odzadu: MAX berie maximum, MIN minimum. Výsledok je zaručený proti akémukoľvek súperovi.
  • Alfa-beta vráti rovnakú hodnotu, ale oreže vetvy, ktoré výsledok nemôžu zmeniť; s dobrým poradím ťahov dovidí dvakrát hlbšie.
  • Veľké hry sa prehľadávajú do obmedzenej hĺbky s hodnotiacou funkciou — a pozor na efekt horizontu.
  • MCTS namiesto ohodnotenia pozíciu mnohokrát náhodne dohrá a strom rozvíja tam, kde je to sľubné; s neurónovými sieťami z neho vznikol AlphaGo.

Chcete si to vyskúšať? Nechajte AI agenta napísať piškvorky s minimaxom a potom spočítajte, koľko pozícií ušetrí alfa-beta, keď ťahy zoradíte od stredu k okrajom.

Máte na to iný názor? Napíšte na support@coden-app.com.

Agent na vašom počítači, ovládaný z telefónu