-
X-Received: by 10.157.42.231 with SMTP id e94mr358273otb.5.1459806686845; Mon, 04 Apr
2016 14:51:26 -0700 (PDT)
X-Received: by 10.157.42.231 with SMTP id e94mr358273otb.5.1459806686845; Mon, 04 Apr
2016 14:51:26 -0700 (PDT)
Path: news-archive.icm.edu.pl!agh.edu.pl!news.agh.edu.pl!newsfeed2.atman.pl!newsfeed.
atman.pl!goblin3!goblin1!goblin.stu.neva.ru!10no426024qgg.1!news-out.google.com
!ha2ni35igb.0!nntp.google.com!nt3no7783507igb.0!postnews.google.com!glegroupsg2
000goo.googlegroups.com!not-for-mail
Newsgroups: pl.comp.programming
Date: Mon, 4 Apr 2016 14:51:26 -0700 (PDT)
In-Reply-To: <5702c5ae$0$656$65785112@news.neostrada.pl>
Complaints-To: g...@g...com
Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=77.254.35.242;
posting-account=xjvq9QoAAAATMPC2X3btlHd_LkaJo_rj
NNTP-Posting-Host: 77.254.35.242
References: <57025882$0$639$65785112@news.neostrada.pl>
<0...@g...com>
<5702c5ae$0$656$65785112@news.neostrada.pl>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <a...@g...com>
Subject: Re: Negamax with alpha beta pruning and transposition tables
From: "M.M." <m...@g...com>
Injection-Date: Mon, 04 Apr 2016 21:51:26 +0000
Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
Xref: news-archive.icm.edu.pl pl.comp.programming:209261
[ ukryj nagłówki ]On Monday, April 4, 2016 at 9:51:13 PM UTC+2, mk wrote:
> W dniu 2016-04-04 14:50, M.M. pisze:
> > On Monday, April 4, 2016 at 2:05:24 PM UTC+2, mk wrote:
> >> Próbuję zaimplementować możliwie efektywnie algorytm rozwiązujący pewien
> >> problem sprowadzający się do gry o sumie stałej pomiędzy dwoma
> >> przeciwnikami.
> >>
> >> W pierwszym kroku zaimplementowałem algorytm min-max (w postaci negamax).
> >>
> >> W moim problemie do danego stanu gry (transpozycji) można dojść czasami
> >> na wiele różnych sposobów więc by przyśpieszyć działanie algorytmu
> >> zastosowałem "memoryzację" czyli zapamiętuję już przeanalizowane stany
> >> gry (transpozycje) i wykorzystuję taki wpis jeśli ponownie natrafię na
> >> wcześniej przeanalizowaną transpozycję. Obliczenia znacząco
> >> przyśpieszyły, wyniki zgodne, jak dotąd dobrze...
> >>
> >> Obok, wzbogaciłem też algorytm negamax (bez memoryzacji) o alpha-beta
> >> prunning. No i też OK: obliczenia przyśpieszyły, wyniki zgodne, jak
> >> dotąd dobrze...
> >>
> >> Dalej, chcę połączyć alpha-beta prunning z memoryzacją... Zaświtało mi w
> >> głowie, że to będzie bardziej skomplikowane niż na początku by się mogło
> >> wydawać... ale od czego Internet, poszukajmy jak zrobili to inni i
> >> natrafiłem na artykuł Wikipedii:
> >> https://en.wikipedia.org/wiki/Negamax#Negamax_with_a
lpha_beta_pruning_and_transposition_tables
> >>
> >> Zaimplementowałem u siebie algorytm przedstawiony w Wikipedii i niestety
> >> zacząłem otrzymywać wyniki niezgodne z trzema uprzednio przedstawionymi
> >> metodami.
> >
> > Też z tym miałem problemy. Nie pamiętam już czy dla wszystkich pozycji
> > otrzymałem ten sam wynik. U mnie czasami wersja z błędem grała lepiej, więc
> > się aż tak bardzo nie przejmowałem.
>
> Zacznę od podziękowania za zainteresowanie moim tematem i poświęcony czas.
Mnie też jest miło że poruszyłeś ten ciekawy temat, jednocześnie
przepraszam że odpisuję tylko z pamięci.
> W moim problemie chciałbym uzyskiwać wartości dokładne, a nie
> heurystyczne. Przeszukuję pełne drzewo gry (tj. aż nastąpi koniec gry).
Rozumiem, nie wiem czemu pomyślałem, że to gra w szachy :D
>
> > Najpierw zwróć uwagę na to co jest niezgodne: najlepszy ruch, wartość dla
najlepszego ruchu, czy jeszcze coś innego?
>
> W ogólności niezgodne są najlepszy ruch oraz wartość najlepszego ruchu.
> Nie są to wartości odległe, czasami się nawet zgadzają, ale to raczej
> kwestia przypadku.
W szachach to zależało od innych zastosowanych heurystyk. Jeśli
nie stosuje się heurystyk wpływających na wartość evala, to zastosowanie
tablicy transpozycji nie powinno wpływać na rezultat. Ale przypominam sobie,
że w szachach miałem z tym problem. Czy ostatecznie uzyskałem takie same
wartości i ruchy z tablicą transpozycji - nie pamiętam, ale chyba tak.
>
> >
> > Jak odzyskujesz układy z tablicy transpozycji? Czy wtedy gdy depth>=curr_depth,
> > czy wtedy gdy depgh==curr_depth ? Wartość zgodna z poprzednimi testami
> > może być tylko dla drugiej wersji.
>
> Akurat w moim problemie takie same transpozycje mogą wystąpić tylko na
> tej samej głębokości, więc nie sprawdzam wcale warunku głębokości.
> Sytuacja podobna jak w grze "kółko i krzyżyk".
Rozumiem.
> Swoją drogą jednak nie rozumiem dlaczego *nie* można skorzystać z
> tablicy transpozycji na płytszych poziomach...
Nie można tylko wtedy, gdy chce się uzyskać takie same wyniki jak w
testach bez TT, no i gdy transpozycje mogą występować między
poziomami. Gdy w szachach odzyskuje się gdy
if( curr_depth <= transposition_depth )
to uzyskuje się znacznie silniejszy program.
> muszę też to przemyśleć
> (mam pewne intuicje dlaczego), chętnie zapoznałbym się z wyjaśnieniem,
> ale jak napisałem: warunek głębokości nie dotyczy mojego problemu.
Ok, to mamy z głowy.
>
> > Mogę zaproponować jeszcze jeden pośredni test, który mi pomagał. Otóż,
> > w pierwszych próbach, można użyć tablicy transpozycji tylko do
> > sortowania ruchów. W zależności od tego jak (poza tą techniką)
> > sortujesz ruchy i czy używasz iteracyjnego pogłębiania, powinno
> > znacznie albo bardzo znacznie przyspieszyć.
>
> Ale musiałbym w każdym wpisie tablicy transpozycji przechowywać
> kolejność ruchów jakie mam wykonać... trochę kosztowne...
Tak się nie robi. Zapamiętuje się tylko jeden (potencjalnie) najlepszy
ruch. Nie jest to kosztowne, a przyspieszenie jest ogromne.
To przyspieszenie widać gdy najpierw przeszukuje się na głębokość 1 ruchu,
potem 2 ruchów, itd. Czasami, w niektórych grach, w niektórych programach,
lepszy efekt jest gdy pogłębianie jest o dwa ruchy a nie o jeden.
> W moim problemie nie używam iteracyjnego pogłębiania, a po postu:
> https://en.wikipedia.org/wiki/Depth-first_search
Czy mógłbyś zdradzić tajemnicę, do jakiego zadania stosujesz
alpha-beta-ze-spamiętywaniem?
> Robię tak dlatego z dwóch powodów:
> 1. Chcę dokładny wynik więc muszę wykonać pełne przeszukiwanie;
> zapamiętanie jednej warstwy w moim problemie w docelowym rozmiarze
> wymagałoby grubych dziesiątków GB,
Bym musiał wiedzieć co to za problem, to co tutaj napisałeś generalnie
nie pasuje mi do moich doświadczeń z grami. Może do Twojego problemu
alpha beta ze spamiętywaniem w ogóle nie jest dobrym algorytmem?
> a może i więcej; na razie pracuję na
> problemie o ograniczonym rozmiarze więc mogę sobie pozwolić na pełne
> zapamiętanie drzewa gry,
Właśnie to co napisałem powyżej, nie ma nic wspólnego z pełnym zapamiętywaniem
drzewa gry. Jeśli tak zrozumiałeś, to znaczy, że kompletnie się nie rozumiemy.
> ale docelowo chcę jednak użyć tablicy
> transpozycji zaimplementowanej jako hash table i ma ona działać jako
> rodzaj cache,
Dokładnie tak się to robi!
> przy czym strategia zwolnienia miejsca na nowy wpis to:
> "wybór losowy" (co zapewnia funkcja hashująca).
Zwykle stosuje się technikę nie wybór losowy, ale stary zawsze zastępuj
nowym. Techniki bardziej zaawansowane dają minimalną poprawę i to tylko w
specyficznych warunkach, np. jest mało pamięci i bardzo długi czas
przeszukiwania drzewa gry.
> Mam już to
> zaimplementowane i początkowo nawet przypuszczałem, że właśnie owa
> "wybiórcza" memoryzacja jest problemem, ale nie...
Skąd wniosek że to nie ona jest problemem? Tam jest wiele miejsc w których
można się łatwo rąbnąć.
> 2. Sortowanie ruchów ma sens tylko jak jesteśmy w stanie dokonać jakieś
> heurystyczne oszacowania co do wartości poszczególnych ruchów.
Owszem, ale takie oszacowanie zazwyczaj można zrobić i to na kilka sposobów.
> W moim
> problemie wynik da się prawdopodobnie dopiero obliczyć na końcu "gry".
No właśnie, co to za gra? :D
> Taka dziwna gra: gracze wiedzą jak wykonywać ruchy, ale raczej nie mają
> żadnej wiedzy który ruch jest lepszy, a który gorszy -- dopiero na samym
> końcu gry następuje bum!
No nie wiedzą dokładnie, ale szacują jakoś prawdopodobieństwo, bo inaczej
jakby wykonywali ruchy?
> -- następują obliczenia oparte o finalną
> transpozycję
Nie wiem co to jest finalna transpozycja.
> i gracze dowiadują się o wyniku gry, który jest liczbą.
> Celem jednego gracza jest maksymalizacja tej liczby, a drugiego
> minimalizacja.
Hmmmm
> Jak poprzednio pisałem: aktualnie we wpisie tablicy transpozycji
> przechowuję:
> 1. transpozycję -- klucz,
> 2. wynik gry,
> 3. wartość alpha przy jakiej obliczono "wynik gry",
> 4. wartość beta przy jakiej obliczono "wynik gry".
Nie jestem pewny, ale chyba robisz to źle, na 99% powinien być najlepszy ruch.
> Wpisu używam tylko, gdy bieżące widełki alpha-beta mieszczą się w
> całości w widełkach alpha-beta z tablicy transpozycji, to rozumiem i to
> działa.
Z kolei ja nie rozumiem dlaczego taka wersja u Ciebie działa.
> Jestem również przekonany, że jeśli bieżące widełki alpha-beta obejmują
> w całości widełki alpha-beta z tablicy transpozycji to obliczenia trzeba
> wykonać ponownie.
Metakod alpha bety ze spamiętywaniem podpowiada że należy to zrobić inaczej.
> Zastanawiam się tylko nad sytuacją gdy widełki bieżące
> i te z tablicy transpozycji częściowo się pokrywają -- czy nie da się tu
> czegoś poczarować... teraz odrzucam taki wpis jako nienadający się do
> użycia.
Nie wiem co to za gra, ale raczej należy zastosować pogłębianie, zapamiętać
najlepszy ruch i napisać zgodnie z metacodem.
> Jeszcze wrócę do sortowania ruchów. Użycie tablicy transpozycji tylko do
> posortowania ruchów pewnie by i u mnie bez problemu działało. Wykonałem
> sobie taki test, że analizuję ruchy w losowej kolejności i algorytm
> alpha-beta (bez tablicy transpozycji) daje mi zawsze jednakowy i
> poprawny wynik.
A czas spada?
> Wspominając o sortowaniu, podsunąłeś mi myśl, że gdy nie mogę skorzystać
> z wartości z tablicy transpozycji ze względu na niezgodność widełek
> alpha-beta, to skoro już muszę przeliczać ponownie wartość danej
> transpozycji to najlepiej by zacząć analizę od ruchu który poprzednio
> dał najlepszą wartość. Ale to wymagało zapamiętania w tablicy
> transpozycji jeszcze jednej wartości:
> 5. najlepszy ruch
Tak, to wymaga zapamiętywania najlepszego ruchu i w sortowaniu ta informacja
jest najważniejsza. Jeśli ruch pochodzi z TT to jest wykonywany jako pierwszy,
a dopiero potem inne techniki sortowania.
> Co obmyślałem, zakodowałem, a uzyskany wynik... Czas obliczeń zmalał o
> około 15% :-)
> Niby niewiele, ale ziarnko do ziarnka... No ale kosztem rozmiaru tablicy
> transpozycji.
15% gdy jako pierwszy wykonujesz ruch z TT? To zobacz co się będzie działo
gdy dasz jeszcze pogłębianie - ale niestety musisz opracować heurystykę
oceny gdy nie przeszukałeś do końca.
>
> > Kolejna propozycja: użyj tablicy transpozycji bez alpha-beta. Sprawdź
> > czy ilość węzłów w poddrzewie jest identyczna. Jeśli nie będzie
> > identyczna, to masz na 100% błąd.
>
> Yyyy... tu czegoś nie rozumiem...
Przeszukuje się pełne drzew gry algorytmem min-max (albo negamax). Zlicza
się ilość węzłów, najlepszy ruch i wartość najlepszego ruchu. Potem
dodaje się tablicę transpozycji. W tablicy transpozycji zapamiętuje się
ilość ruchów w pod-drzewie. Jeśli odzyskuje się układ z TT, to nie
przeszukuje się, ale po prostu pobiera się wartość i ilość ruchów w
pod-drzewie. Normalnie masz dwie wartości do testów: najlepszy ruch i jego
wartość. Gdy zliczysz jeszcze ilość węzłów, to masz wartość trzecią.
Zwykle błędy w TT wychodzą gdy właśnie nie zgadza się ilość węzłów.
> Tablica transpozycji dla algorytmu *bez* alpha-beta jest większa niż ta
> przy algorytmie *z* alpha-beta.
Nie trzeba zapamiętywać wszystkich węzłów w TT, wystarczy zapamiętać tyle, na
ile pozwala pamięć komputera i zaimplementować schemat wymiany.
> Wcale się temu nie dziwię i tego
> oczekuję po "przycinaniu" alpha-beta: wszak przerywamy analizę, gdy
> bieżący gracz osiąga wynik na który nie zgodzi się przeciwnik (gdyż ma w
> dyspozycji lepszy ruch na którymś z wyższych poziomów) tj. gdy alpha >=
> beta.
Tak, w grze to nie ma sensu, ale w testach mam ogromny sens :)
> > Warto te wyniki porównać z
> > innym programem na co najmniej 1000 pozycji.
> > Tam kilka moich testów do porównania:
> > http://brodacz100.republika.pl/perft.htm
>
> Chętnie porównam, nie mam tylko zielonego pojęcia czym jest
> "brodacz100". ;-)
Eh, to program do szachów :D
> U mnie (zmniejszona do testów) gra ma < 10 mln transpozycji.
>
> >> W dyskusji dotyczącej artykułu jedna z osób narzeka, że i u niej
> >> algorytm z Wikipedii nie działa, inna osoba jednak kontruje, że algorytm
> >> jest na pewno poprawny, a wina jest po stronie niewłaściwego
> >> zaimplementowania tegoż algorytmu.
> > Wszystko zależy od pozostałych algorytmów. Inaczej będzie z pogłębieniami,
> > inaczej z qsearch, a już zupełna masakra z null-move...
>
> Przy częściowej, wybiórczej analizie drzewa gry wynik analizy oczywiście
> może zależeć od wielu szczegółów. Przy pełnej analizie drzewa gry
> niezgodne wyniki oznaczają... błąd!
Tak to jest z ryzykownymi heurystykami. 100 razy pomagają, a za 101 razem
powodują błąd.
>
> > Używam ciut innej implementacji i ciut innego algorytmu niż na wiki.
> > Moja działała minimalnie szybciej i przeszukiwała minimalnie mniej węzłów
> > (lepiej obcinała). Niestety nie mam pod ręką metakodu, jeśli znajdę,
> > to podrzucę.
>
> Jeśli bez zbędnego kłopotu się znajdzie, to chętnie wypróbuję.
Właśnie kłopot z tym pewien mam, a w niecie już nie widać tego
pięknego tutoriala :/
> Nie ukrywam, że i chciałbym rozumieć jak to działa, np. ten z Wiki.
> Póki rozumiem co się dzieje w moim programie, to wyniki mam poprawne.
> Ten z Wiki przeklepałem trochę jak małpa... i nie działa.
Powinien działać. Dużo programistów z którymi rozmawiałem, właśnie
przeklepało ten kod. Ja też nie umiem rzucić z rękawa dowodem, że
tamten kod da taki sam wynik jak bez tablicy transpozycji.
> Z drugiej
> strony nie mam dowodu na to, że algorytm z Wiki jest niepoprawny..., ale
> aktualnie bardziej gotowy jestem iść w tą stronę :-)
Porównaj z tą pracą:
http://people.csail.mit.edu/plaat/mtdf.html
Od razu uprzedzam, jakbyś chciał całą teorię zastosować w praktyce, to
okna zerowe rzadko działają i robi sie to inaczej. Bruce to też opisywał
przejrzyściej, mniej teoretycznie, bardziej praktycznie.
>
> > Opieram się na metakodzie który udostępnił kiedyś w sieci ten autor:
> > https://chessprogramming.wikispaces.com/Bruce+Morela
nd
> > Niestety samego metakodu już nie mogę znaleźć.
> >
> > Widać tylko kod samej alpha-bety:
> > https://cs.marlboro.edu/code/perl/TicTacToe/bruce-mo
reland/alphabeta.html
>
> Z czystą alpha-beta nie mam problemów.
> Ale dzięki za link, może coś na tej stronie wygrzebię dla siebie.
Były tam kiedyś linki do TT, do okien, null-move, itd. Niestety teraz
to wszystko nie działa, a przejrzystszego opisu nie widziałem.
>
> >> Cały czas też się zastanawiam, czy faktycznie nie wystarczy wspomniana w
> >> Wiki flaga, zamiast pełnej informacji alpha, beta.
> >> Różne próby robione "na macanta" dają jednak niepoprawne wyniki...
> > Wystarczy.
>
> Hmmm... będę miał to do przemyślenia pewnie na niejedną bezsenną noc.
Wystarczy znaczy, że ten algorytm działa, o ile nie ma błędów
na wiki w metakodzie, albo innych w Twoim programie. Polecam test z
ilością węzłów w TT - dobry test poprawności TT.
> >> Jak powinien wyglądać algorytm alpha beta prunning z memoryzacją?
> >> Może jednak ten z Wiki jest dobry, a ja popełniam błąd w implementacji?
> > Ten na wiki (chyba) jest poprawny, aczkolwiek Bruce Moreland podał
> > znacznie bardziej zwartą i czytelną wersję, a poza tym, u mnie
> > obcinała ona więcej węzłów.
>
> Dziękuję za namiary -- spróbuję pogooglać.
Pozdrawiam
Następne wpisy z tego wątku
Najnowsze wątki z tej grupy
- Arch. Prog. Nieuprzywilejowanych w pełnej wer. na nowej s. WWW energokod.pl
- 7. Raport Totaliztyczny: Sprawa Qt Group wer. 424
- TCL - problem z escape ostatniego \ w nawiasach {}
- Nauka i Praca Programisty C++ w III Rzeczy (pospolitej)
- testy-wyd-sort - Podsumowanie
- Tworzenie Programów Nieuprzywilejowanych Opartych Na Wtyczkach
- Do czego nadaje się QDockWidget z bibl. Qt?
- Bibl. Qt jest sztucznie ograniczona - jest nieprzydatna do celów komercyjnych
- Co sciaga kretynow
- AEiC 2024 - Ada-Europe conference - Deadlines Approaching
- Jakie są dobre zasady programowania programów opartych na wtyczkach?
- sprawdzanie słów kluczowych dot. zła
- Re: W czym sie teraz pisze programy??
- Re: (PDF) Surgical Pathology of Non-neoplastic Gastrointestinal Diseases by Lizhi Zhang
- CfC 28th Ada-Europe Int. Conf. Reliable Software Technologies
Najnowsze wątki
- 2024-12-23 Riga => Specjalista ds. public relations <=
- 2024-12-23 Łódź => Specjalista ds. Sprzedaży <=
- 2024-12-23 Kraków => International Freight Forwarder <=
- 2024-12-23 Co nalezy do Cinkciarza, a co do Conotoxia ?
- 2024-12-23 Poznań => Key Account Manager <=
- 2024-12-23 Warszawa => Presales / Inżynier Wsparcia Technicznego IT <=
- 2024-12-23 Rzeszów => Spedytor Międzynarodowy <=
- 2024-12-23 Warszawa => Infrastructure Automation Engineer <=
- 2024-12-23 Białystok => Analityk w dziale Trade Development (doświadczenie z Po
- 2024-12-23 Warszawa => Site Reliability Engineer (SRE) <=
- 2024-12-23 Warszawa => DevOps Engineer <=
- 2024-12-23 Warszawa => Senior Account Manager <=
- 2024-12-23 Katowice => Regionalny Kierownik Sprzedaży (OZE) <=
- 2024-12-23 Katowice => Administrator IT - Wirtualizacja i Konteneryzacja <=
- 2024-12-23 Mińsk Mazowiecki => Spedytor Międzynarodowy <=