Programowanie silników szachowych jest bardzo skomplikowanym terytorium, więc od razu skieruję cię do Wiki Programowania Szachowego , które zawiera wiele świetnych informacji na ten temat.
tło
Obliczenia szachowe (i wiele podobnych rzeczy) są na ogół modelowane i uważane za „drzewa gry” lub „ drzewa decyzji ”. Zasadniczo to drzewo jest ukierunkowanym wykresem, z jednym węzłem u góry (bieżąca pozycja), prowadzącym do węzła dla każdego możliwego ruchu, z których każdy prowadzi do większej liczby węzłów dla każdego możliwego następnego ruchu i tak dalej.
W swojej najbardziej uproszczonej, brutalnej sile, silniki szachowe generują wszystkie pozycje na tym drzewie do pewnego poziomu głębokości („warstwa”), oceniając każdą uzyskaną pozycję na podstawie złożonych kryteriów 1 . Następnie odtwarza ruch, który wydaje się prowadzić do najlepszego wyniku. Obecnie opracowano wiele naprawdę skomplikowanych technik ograniczających liczbę pozycji, na które musi patrzeć silnik, ale zignoruję je dla celów tej odpowiedzi, ponieważ nie zmieniają prawdziwego problemu w dłoń.
Styczna matematyczna
Podstawowym powodem, dla którego silniki zazwyczaj zajmują tyle samo czasu na rozważenie każdego ruchu, jest to, że wielkość drzewa decyzyjnego rośnie wykładniczo wraz z głębokością ( k
).
Rozważ pozycję początkową. Wierzchołek drzewa ( k=0
) to jeden węzeł. Istnieje 20 możliwych pierwszych ruchów dla Białych, więc głębokość ma dwadzieścia węzłów k=1
. Następnie Czarne mają również dwadzieścia dostępnych ruchów dla każdej z opcji Białych: więc przy k=2
są 20 * 20 = 400
możliwe pozycje! I tylko gorzej, gdy gracze rozwijają swoje pionki!
Na przykład, udawajmy, że dla każdego gracza w danym momencie istnieje zawsze dwadzieścia możliwych ruchów 2 . Poinstruujesz komputer, aby spojrzał w przyszłość o pięć ruchów dla każdego gracza (dziesięć warstw). Spójrzmy na rozmiar drzewa brutalnej siły na każdym poziomie. Dla zabawy przyjrzymy się również całkowitej liczbie pozycji w drzewie (od góry do podanego poziomu).
Ply | Positions | Total Tree Size
----------------------------------------
0 | 1 | 1
1 | 20 | 21
2 | 400 | 421
3 | 8000 | 8421
4 | 160000 | 168421
5 | 3200000 | 3368421
6 | 64000000 | 67368421
7 | 1280000000 | 1347368421
8 | 25600000000 | 26947368421
9 | 512000000000 | 538947368421
10 | 10240000000000 | 10778947368421
Skutkiem tego, że każdy poziom jest wykładniczo większy niż poziom poprzedni, wielkość całego drzewa jest zdominowana przez poziom dolny . Rozważ powyższy przykład: sam ostatni poziom zawiera dziesięć bilionów węzłów. Cała reszta drzewa zawiera tylko pięćset miliardów. Dziesiąta warstwa zawiera około 95% węzłów w całym drzewie (jest to prawdą na każdym poziomie). W praktyce oznacza to, że cały czas poszukiwań jest poświęcony na ocenę „ostatniego” ruchu.
Odpowiedź
Jak to się ma do twojego pytania? Powiedzmy, że komputer jest ustawiony na dziesięć warstw, jak wyżej, i dalej „zapamiętuje” wyniki swoich ocen. Oblicza ruch, odtwarza go, a następnie wykonujesz ruch. Teraz wykonano dwa ruchy, więc przycina wszystkie pozycje z pamięci związane z ruchami, które się nie wydarzyły, i zostaje z drzewem, które schodzi z pozostałych ośmiu ruchów, które już obliczyło: 26 947 368 421 pozycji!
W porządku! Musimy więc obliczyć tylko dwie ostatnie warstwy! Korzystając z naszego oszacowania 20 ruchów na każdej głębokości, łączna liczba ruchów, które musimy tutaj obliczyć, wciąż przekracza dziesięć bilionów. Pozycje, które obliczyliśmy, stanowią jedynie 2,5% możliwości! Nawet buforując wyniki ostatniego ruchu, możemy mieć nadzieję na 2,5% wzrost prędkości! Zasadniczo dlatego nawet jeśli twój program buforuje poprzednie wyniki, zwykle nie widzisz znacznego przyspieszenia między ruchami (z wyjątkiem przypadków, gdy komputer znajdzie przymusowego partnera lub coś takiego!).
Uproszczenie Zastrzeżenie
To pytanie wiąże się z dużą złożonością, dlatego połączyłem się z wiki programowania na samym szczycie i próbowałem wyjaśnić odpowiedź w szerokich kategoriach matematycznych. W rzeczywistości programy zrobić ogólnie części cache na drzewie z ruchu, aby przenieść, i istnieją inne powody, dla których to niewystarczające na własną rękę - kilka prostych powodów (np pewna linia może wyglądać dobrze na zewnątrz do ośmiu ruchów, ale kończy z tyłu -rankuj partnera w ruchu dziewiątym!) i wiele bardzo skomplikowanych (ogólnie związanych z różnymi sprytnymi metodami przycinania). Komputer musi więc patrzeć w przyszłość, próbując uniknąć złych założeń na podstawie głębokości odcięcia poprzedniego ruchu.
1 Nie będę tutaj wchodził w funkcje heurystyczne, ponieważ jest to jego niezwykle złożony obszar, ale często istnieją pewne korzyści, które można osiągnąć również tutaj poprzez schematy buforowania pozycji.
2 Średni współczynnik rozgałęzień wynoszący 20 jest prawdopodobnie o wiele za niski .