Snad každý, kdo kdy používal Windows, zná hru Minesweeper, tedy hledání min. Různé hry, včetně této, se staly předmětem seriózního teoretického výzkumu. Například bylo zjištěno, že Sokoban (skladník přesouvající bedny na určené místo) je NP-těžký problém. Stejně tak hledání min je NP-těžké. Zde jako malé myšlenkové cvičení ukázka, jak lze algoritmicky řešit hledání min převedením na problém splnitelnosti výrokových formulí (SAT).
Předpokládám, že čtenář zná pravidla hry. Nejprve je nutné rozhodnout se pro formální reprezentaci stavu hry. Každý element hrací plochy buď obsahuje minu, nebo ne. Již odhalená nezaminovaná pole mají číslo, jež udává počet min na sousedních polích (včetně diagonálních, tj. rohové pole má tři sousedy, pole na okraji mimo roh pět a pole někde uprostřed osm). Mějme tedy atomické predikáty numbered(x,y,z), mined(x,y) a safe(x,y). Predikát numbered říká, že na pozici [x,y] je číslo z, mined říká, že na dané pozici je určitě mina a safe, že tam určitě mina není.
V každém momentu hry můžeme její stav zakódovat pomocí uvedených predikátů. Zbývá určit vztahy mezi predikáty, tedy axiomy, které jsou vždy splněny. Platí, že pokud je v nějakém poli číslo, určitě tam není mina (a naopak):
∀x.[∃z.numbered(x,y,z)≡safe(x,y)]
Dále víme, že zaminovanost určité pozice a její bezpečnost se vylučují:
∀x.∀y.¬[mined(x,y) & safe(x,y)]
A nakonec dáme smysl číslu na určité pozici:
∀x.∀y.∀z.numbered(x,y,z)≡:neighbour(u,v,x,y) & mined(u,v)|=z & |[u,v]:neighbour(u,v,x,y) & safe(u,v)|=|[u,v]:neighbour(u,v,x,y)|-z]
Jinými slovy, počet určitě zaminovaných polí kolem [x,y] je z a počet určitě nezaminovaných je počet sousedů bez z (použili jsme pomocný predikát neighbour se zřejmým významem).
Umíme tedy formálně zakódovat stav hry. A jak ji řešit? Máme-li již výše popsanou logickou reprezentace, není nic snazšího než převést všechny relevantní formule na výrokovou logiku. Druhý axiom například bude ¬mined(x,y) ⋁ ¬safe(x,y) pro všechna x a y. A tak dále.
Získané výrokové formule dáme k řešení libovolnému SAT solveru. Moderní solvery umí efektivně řešit problémy se statisíci výrokových proměnných, my jich při hledání min (v závislosti na velikosti hrací plochy) budeme mít tisíce, takže řešení vždy dostaneme ve zlomku sekundy (a řádově rychleji by to vzhledem k NP-úplnosti problému hledání min ani nešlo).
Zbývá dekódovat řešení. Především je třeba si uvědomit, že řešení může být více (pokud je situace nejednoznačná). Pokud pro nějaké pole platí mined, určitě tam je mina. Pokud platí safe, mina tam určitě není. Zároveň díky axiomatizaci platit nemůžou a pokud neplatí ani jedno, za dané situace nevíme, nachází-li se tam mina nebo ne.
Kdo by si chtěl výše popsaný algoritmus vyzkoušet, může v C(++) použít například solver Minisat, v Javě třeba SAT4J.
Zkousel jsi to aplikovat pri hrani? Zrovna miny mi neprijdou jako idealni priklad pro demonstraci predikatove logiky. Snad behem kazde hry dojde nekolikrat k nerozhodnutelne situaci a ty rozhodnutelne situace by se(az na obcasnou vyjimku) snadno daly vyresit par if-y. Par situaci by jeste mozna pomohl rozhodnout celkovy pocet min(ten je myslim obvykle konstantni).
Hledání min podle mě není NP-hard. Jak by jste převedl SAT na hledání min?
Počet kroků hry je polynomiální k velikosti herního pole. Předpokládáme-li, že v každém tahu půjde vyplnit alespoň jedno políčko, tak průchod všemi políčky je také polinomiální. A vyřešitelnost případně řešení každého políčka závisí pouze na sousedech, takže to je konstantní složitost.
[8] Autor také netvrdí, že dokazuje NP-úplnost. Říká: "Zde jako malé myšlenkové cvičení ukázka, jak lze algoritmicky řešit hledání min převedením na problém splnitelnosti výrokových formulí (SAT)." Může se mu maximálně vytknout, že neupozornil na to, že plynule přešel k opačnému směru, což tady většinu lidí evidentně zmátlo - závěr, že by to měl být důkaz NP-úplnosti, tady někdo špatně vydedukoval až v diskuzi. Kromě toho, když by to dělal obráceně, tak by také ještě musel dokázat, že ta úloha je vůbec NP (to, že je NP-těžká, ještě neznamená, že je NP).
[7]: minesweeper ma specialni algoritmus jak udelat to aby prvni klik nebyl do miny, viz http://en.wikipedia.org/wiki/Microsoft_Minesweeper
Autor se zabývá vývojem kompilátorů a knihoven pro objektově-orientované programovací jazyky.
Přečteno 36 200×
Přečteno 25 361×
Přečteno 23 795×
Přečteno 20 177×
Přečteno 17 874×