Šachové myšlení (2) - minimax
Většina programátorských úloh má jednoduché, správné a velmi pomalé řešení typu projdi všechny možnosti. V šachách se jmenuje minimax.
15.3.2006 06:00 |
Jan Němec
| Články autora
| přečteno 26325×
Minimax
V minulém dílu jsem ukázal program, který porovnává pozice po jediném zahraném
tahu. Zkoušeli jsme z výchozího postavení postupně zahrát všechny přípustné
tahy a vzniklé pozice ohodnocovali jednoduchou statickou ohodnocovací funkcí.
Zahráli jsme tah, který vedl k nejlepší pozici.
Uvedený program nepočítá odpovědi soupeře na náš tah a to je jeho největší
slabina. Sebere klidně dámou krytého pěšce, nebrání se jednotahovému matu a
podobně. Naštěstí je velmi jednoduché program zlepšit. Místo statické
ohodnocovací funkce po každém zahraném půltahu zavoláme kód, který vyzkouší
všechny odpovědi soupeře na náš tah. Jednu po druhé zahraje, ohodnotí je
statickou ohodnocovací funkcí a zahraje zpět a zapamatuje si hodnotu nejlepšího
tahu, tentokrát z hlediska soupeře. Za cenu konkrétního našeho tahu z úvodní
pozice je tak prohlášena cena nejlepší soupeřovy odpovědi. Algoritmus z prvního
dílu se nazývá propočet do hloubky jedna, naše vylepšení pak analogicky
propočet do hloubky dva.
Jistě není problém program dále upravovat, aby počítal do hloubky 3 nebo 4
nebo lépe do nějaké obecné hloubky n určené parametrem. Takto
zobecněný algoritmus se jmenuje minimax, neboť když se za jednoho hráče
snažíme v propočtu maximalizovat cenu pozice, za druhého ji tím minimalizujeme
a o půltah dále zase naopak. Implementuje se obvykle pomocí jedné rekurzivní
funkce minimax, která má jako parametry pozici a hloubku propočtu, návratovou
hodnotou je cena pozice po propočtu do dané hloubky. Místo statické
ohodnocovací funkce hodnotaPozice volá minimax sám sebe do hloubky o jedničku menší.
Pouze při hloubce
nula zavolá hodnotaPozice a v koncových pozicí vrací konstanty pro mat a
remízu a v propočtu příslušné varianty nepokračuje.
int minimax(Pozice p, int hloubka) {
Tahy t;
int i, indexNejlepsiho;
int cena;
/* V případě koncové pozice nebo nulové hloubky propočet ukončíme. */
if (jsemVMatu(p)) return -MAT;
if (remiza(p)) return 0;
/* Dávat mat nemůžu, protože pozice je po tahu soupeře. */
if (hloubka <= 0) return hodnotaPozice(p);
/* Cyklus přes tahy je podobný jako u předchozího algoritmu. */
t = generujTahy(p);
nejlepsi = -NEKONECNO;
for (i = 0; i < tahy.pocet; i++) {
zahrajTah(p, t[i]);
cena = -minimax(p, hloubka - 1);
zahrajTahZpet(p, t[i]);
/* Nejlepší tah nás nezajímá, důležitá je jen jeho hodnota. */
if (cena > nejlepsi) nejlepsi = cena;
}
/* Pokud je výsledná hodnota velmi velká nebo velmi malá, znamená,
že dávám nebo dostávám mat. V tom případě je třeba cenu upravit,
aby se např. z "bílý dává 3. půltahem mat" stalo "černý dostává
4. půltahem mat", neboť se návratem do volající funkce posunu
o jeden půltah. Toto je nezbytné, jinak by program nepreferoval
např. mat 1. tahem před matem 2. tahem. */
if (nejlepsi > MNOHO) nejlepsi--;
if (nejlepsi < -MNOHO) nejlepsi++;
return nejlepsi;
}
/* Hlavní funkce se téměř nezměnila. Pouze přibyl parametr hloubka
a místo hodnotaPozice voláme minimax. */
V kořeni stromu propočtu je postup nepatrně jiný, především nás zajímá nejlepší
tah samotný a nikoliv pouze jeho cena.
Tah nejlepsiTah(Pozice p, int hloubka) {
Tahy t;
int i, indexNejlepsiho;
int cena, nejlepsi;
t = generujTahy(p);
nejlepsi = -NEKONECNO;
for (i = 0; i < tahy.pocet; i++) {
zahrajTah(p, t[i]);
cena = -minimax(p, hloubka);
zahrajTahZpet(p, t[i]);
if (cena > nejlepsi) {
nejlepsi = cena;
indexNejlepsiho = i;
}
}
return t[indexNejlepsiho];
}
Na šachovnici je v základním postavení jen 16 pěšců, každý z nich může táhnout
nejvýše šestkrát, potom se promění v nějakou figuru. Když nepočítám krále,
které není možné sebrat,
kamenů je celkem 30, každý z nich může být sebrán nejvýše jednou. Pokud se
během 50 tahů, tedy 100 půltahů, netáhne pěšcem ani nesebere žádný kámen, je
partie dána za remízu. Díky tomu můžeme shora odhadnout délku partie na
(16 * 6 + 30 + 1) * 100 = 12700 půltahů.
Algoritmus minimax, s parametrem hloubky propočtu 12700, bude
teoreticky hrát šachy naprosto dokonale. Alespoň v tom smyslu, že žádnou
remízovou pozici neprohraje, každou vyhranou pozici nejen vyhraje, ale dokonce
(vůči dokonalému soupeři) tím nejrychlejším způsobem. V prohrané pozici pak bude
porážku alespoň maximálně oddalovat.
Z lidského pohledu má algoritmus určité nedostatky
pouze v pozicích remízových. Například v pozici s pěšcem navíc, kde se soupeř
může jen tak tak ubránit program klidně odevzdá úplně zadarmo třeba dva pěšce,
pokud se tak dostane do pozice, kde sice horko těžko, ale přeci jen udrží
remízu. Tento drobný problém lze snadno vyřešit kombinací s propočtem do
malé hloubky, který bude jen vybírat mezi jednotlivými remízovými tahy
z hlavního propočtu do hloubky 12700.
Po uvedení algoritmu je dobrým zvykem zamyslet se nad jeho časovou a paměťovou
složitostí. Z hlediska paměti je všechno v pořádku, neboť na zásobníku
rekurzivního propočtu je v jednom okamžiku vždy jen jedna varianta. Kdyby se programu opravdu
podařilo najít variantu dlouhou 12700 půltahů a jedna instance
funkce minimax zabrala 1 kB, vejdeme se i s volajícím kódem do 13 MB.
To je pozoruhodné zjištění, na propočet stromu tak bohaté hry, jakou jsou
šachy, nám stačí pár MB. Proč tedy není programování šachů dětskou hrou?
Pokračování příště
V příštím dílu se zaměříme na časovou složitost a ukážeme si, proč lze minimax
použít pouze proti slabým soupeřům a jak je možné jej překvapivě jednoduše a účinně vylepšit.
Verze pro tisk
|
Příspívat do diskuze mohou pouze registrovaní uživatelé.
|
|

Vyhledávání software

Vyhledávání článků
28.11.2018 23:56 /František Kučera Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.
Komentářů: 1
12.11.2018 21:28 /Redakce Linuxsoft.cz 22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář
6.11.2018 2:04 /František Kučera Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
4.10.2018 21:30 /Ondřej Čečák LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář
18.9.2018 23:30 /František Kučera Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
9.9.2018 14:15 /Redakce Linuxsoft.cz 20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business.
Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář
12.8.2018 16:58 /František Kučera Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář
16.7.2018 1:05 /František Kučera Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář
Více ...
Přidat zprávičku
 Poslední diskuze
31.7.2023 14:13 /
Linda Graham iPhone Services
30.11.2022 9:32 /
Kyle McDermott Hosting download unavailable
13.12.2018 10:57 /
Jan Mareš Re: zavináč
2.12.2018 23:56 /
František Kučera Sraz
5.10.2018 17:12 /
Jakub Kuljovsky Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?
Více ...
|