Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

GoUctBookBuilder.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file GoUctBookBuilder.h
00003  */
00004 //----------------------------------------------------------------------------
00005 
00006 #ifndef GOBOOKBUILDER_H
00007 #define GOBOOKBUILDER_H
00008 
00009 #include <cmath>
00010 #include <iostream>
00011 #include <fstream>
00012 #include <set>
00013 #include "SgBookBuilder.h"
00014 #include "SgThreadedWorker.h"
00015 #include "GoBoard.h"
00016 #include "GoAutoBook.h"
00017 #include "GoBoardSynchronizer.h"
00018 
00019 //----------------------------------------------------------------------------
00020 
00021 /** Expands a Book using the given player to evaluate game positions.
00022 
00023     Supports multithreaded evaluation of children.
00024 
00025     @todo Copy settings from passed player to other players.
00026 
00027     @ingroup openingbook
00028 */
00029 template<class PLAYER>
00030 class GoUctBookBuilder : public SgBookBuilder
00031 {
00032 public:
00033     GoUctBookBuilder(const GoBoard& brd);
00034     
00035     ~GoUctBookBuilder();
00036 
00037     //---------------------------------------------------------------------
00038     
00039     void SetPlayer(PLAYER& player);
00040 
00041     /** Sets the state to start work from. */
00042     void SetState(GoAutoBook& book);
00043 
00044     //---------------------------------------------------------------------    
00045 
00046     float InverseEval(float eval) const;
00047 
00048     bool IsLoss(float eval) const;
00049 
00050     float Value(const SgBookNode& node) const;
00051 
00052     //---------------------------------------------------------------------    
00053 
00054     /** Number of players to use during leaf expansion. Each player
00055         may use a multi-threaded search. Should speed up the expansion
00056         of leaf states by a factor of (very close to) NumThreads(). */
00057     std::size_t NumThreads() const;
00058 
00059     /** See NumThreads() */
00060     void SetNumThreads(std::size_t num);
00061 
00062     /** Number of games to play when evaluation a state. */
00063     std::size_t NumGamesPerEvaluation() const;
00064 
00065     /** See NumGamesPerEvaluation. */
00066     void SetNumGamesPerEvaluation(std::size_t num);
00067 
00068     /** Number of games to play when sorting children. */
00069     std::size_t NumGamesPerSort() const;
00070 
00071     /** See NumGamesForSort() */
00072     void SetNumGamesPerSort(std::size_t num);
00073 
00074 protected:
00075     void PrintMessage(std::string msg);
00076 
00077     void PlayMove(SgMove move);
00078 
00079     void UndoMove(SgMove move);
00080 
00081     bool GetNode(SgBookNode& node) const;
00082 
00083     void WriteNode(const SgBookNode& node);
00084 
00085     void FlushBook();
00086 
00087     void EnsureRootExists();
00088 
00089     bool GenerateMoves(std::vector<SgMove>& moves, float& value);
00090 
00091     void GetAllLegalMoves(std::vector<SgMove>& moves);
00092 
00093     void EvaluateChildren(const std::vector<SgMove>& childrenToDo,
00094                           std::vector<std::pair<SgMove, float> >& scores);
00095     void Init();
00096 
00097     void StartIteration(int iteration);
00098 
00099     void EndIteration();
00100 
00101     void BeforeEvaluateChildren();
00102 
00103     void AfterEvaluateChildren();
00104 
00105     void Fini();
00106 
00107     void ClearAllVisited();
00108     
00109     void MarkAsVisited();
00110     
00111     bool HasBeenVisited();
00112         
00113 private:
00114     /** Copyable worker. */
00115     class Worker
00116     {
00117     public:
00118         Worker(std::size_t id, PLAYER& player);
00119 
00120         float operator()(const SgMove& move);
00121 
00122     private:
00123         std::size_t m_id;
00124         
00125         PLAYER* m_player;
00126     };
00127 
00128     /** Book this builder is expanding */
00129     GoAutoBook* m_book;
00130    
00131     PLAYER* m_origPlayer;
00132 
00133     GoAutoBookState m_state;
00134 
00135     std::set<SgHashCode> m_visited;
00136 
00137     /** See NumberThreads() */
00138     std::size_t m_numThreads;
00139 
00140     std::size_t m_numGamesPerEvaluation;
00141 
00142     std::size_t m_numGamesPerSort;
00143 
00144     std::size_t m_num_evals;
00145 
00146     std::size_t m_num_widenings;
00147 
00148     std::size_t m_value_updates;
00149 
00150     std::size_t m_priority_updates;
00151 
00152     std::size_t m_internal_nodes;
00153 
00154     std::size_t m_leaf_nodes;
00155 
00156     std::size_t m_terminal_nodes;
00157 
00158     /** Players for each thread. */
00159     std::vector<PLAYER*> m_players;
00160 
00161     std::vector<Worker> m_workers;
00162 
00163     SgThreadedWorker<SgMove,float,Worker>* m_threadedWorker;
00164 
00165     void CreateWorkers();
00166 
00167     void DestroyWorkers();
00168 };
00169 
00170 //----------------------------------------------------------------------------
00171 
00172 template<class PLAYER>
00173 inline std::size_t GoUctBookBuilder<PLAYER>::NumThreads() const
00174 {
00175     return m_numThreads;
00176 }
00177 
00178 template<class PLAYER>
00179 inline void GoUctBookBuilder<PLAYER>::SetNumThreads(std::size_t num)
00180 {
00181     m_numThreads = num;
00182 }
00183 
00184 template<class PLAYER>
00185 inline std::size_t GoUctBookBuilder<PLAYER>
00186 ::NumGamesPerEvaluation() const
00187 {
00188     return m_numGamesPerEvaluation;
00189 }
00190 
00191 template<class PLAYER>
00192 inline void GoUctBookBuilder<PLAYER>
00193 ::SetNumGamesPerEvaluation(std::size_t num)
00194 {
00195     m_numGamesPerEvaluation = num;
00196 }
00197 
00198 template<class PLAYER>
00199 inline std::size_t GoUctBookBuilder<PLAYER>::NumGamesPerSort() const
00200 {
00201     return m_numGamesPerSort;
00202 }
00203 
00204 template<class PLAYER>
00205 inline void GoUctBookBuilder<PLAYER>::SetNumGamesPerSort(std::size_t num)
00206 {
00207     m_numGamesPerSort = num;
00208 }
00209 
00210 //----------------------------------------------------------------------------
00211 
00212 template<class PLAYER>
00213 GoUctBookBuilder<PLAYER>::GoUctBookBuilder(const GoBoard& bd)
00214     : SgBookBuilder(), 
00215       m_book(0),
00216       m_origPlayer(0),
00217       m_state(bd),
00218       m_numThreads(1),
00219       m_numGamesPerEvaluation(10000),
00220       m_numGamesPerSort(10000)
00221 {
00222     SetAlpha(30.0);
00223     SetExpandWidth(8);
00224 }
00225 
00226 template<class PLAYER>
00227 GoUctBookBuilder<PLAYER>::~GoUctBookBuilder()
00228 {
00229 }
00230 
00231 //----------------------------------------------------------------------------
00232 
00233 /** Copies the player and board and creates the threads. */
00234 template<class PLAYER>
00235 void GoUctBookBuilder<PLAYER>::CreateWorkers()
00236 {
00237     PrintMessage("GoUctBookBuilder::CreateWorkers()\n");
00238     for (std::size_t i = 0; i < m_numThreads; ++i)
00239     {
00240         PLAYER* newPlayer = new PLAYER(m_state.Board());
00241 
00242         // TODO: COPY SETTINGS SOMEHOW
00243         //newPlayer->CopySettingsFrom(m_origPlayer);
00244         
00245         // Always search, don't use forced moves
00246         newPlayer->SetForcedOpeningMoves(false);
00247         // Ensure all games are played; ie, do not use early count abort.
00248         newPlayer->Search().SetMoveSelect(SG_UCTMOVESELECT_ESTIMATE);
00249         // Should be enough for a 100k search. Needs 10GB 8 threaded.
00250         newPlayer->Search().SetMaxNodes(8500000);
00251         newPlayer->SetWriteDebugOutput(false);
00252 
00253         m_players.push_back(newPlayer);
00254         m_workers.push_back(Worker(i, *m_players[i]));
00255     }
00256     m_threadedWorker 
00257         = new SgThreadedWorker<SgMove,float,Worker>(m_workers);
00258 }
00259 
00260 /** Destroys copied players, boards, and threads. */
00261 template<class PLAYER>
00262 void GoUctBookBuilder<PLAYER>::DestroyWorkers()
00263 {
00264     PrintMessage("GoUctBookBuilder::DestroyWorkers()\n");
00265     for (std::size_t i = 0; i < m_numThreads; ++i)
00266         delete m_players[i];
00267     delete m_threadedWorker;
00268     m_workers.clear();
00269     m_players.clear();
00270 }
00271 
00272 template<class PLAYER>
00273 void GoUctBookBuilder<PLAYER>::Init()
00274 {
00275     CreateWorkers();
00276 }
00277 
00278 template<class PLAYER>
00279 void GoUctBookBuilder<PLAYER>::Fini()
00280 {
00281     DestroyWorkers();
00282 }
00283 
00284 //----------------------------------------------------------------------------
00285 
00286 template<class PLAYER>
00287 GoUctBookBuilder<PLAYER>::Worker::Worker(std::size_t id, PLAYER& player)
00288 
00289     : m_id(id), 
00290       m_player(&player)
00291 {
00292 }
00293 
00294 template<class PLAYER>
00295 float GoUctBookBuilder<PLAYER>::Worker::operator()(const SgMove& move)
00296 {
00297     m_player->UpdateSubscriber();
00298     if (move >= 0)
00299         m_player->Board().Play(move);
00300     m_player->GenMove(SgTimeRecord(true, 9999), m_player->Board().ToPlay());
00301     GoUctSearch& search 
00302         = dynamic_cast<GoUctSearch&>(m_player->Search());
00303     float score = search.Tree().Root().Mean();
00304     return score;
00305 }
00306 
00307 //----------------------------------------------------------------------------
00308 
00309 template<class PLAYER>
00310 inline void GoUctBookBuilder<PLAYER>::SetPlayer(PLAYER& player)
00311 {
00312     m_origPlayer = &player;
00313 }
00314 
00315 template<class PLAYER>
00316 inline void GoUctBookBuilder<PLAYER>::SetState(GoAutoBook& book)
00317 {
00318     m_book = &book;
00319     m_state.Synchronize();
00320 }
00321 
00322 template<class PLAYER>
00323 void GoUctBookBuilder<PLAYER>::PrintMessage(std::string msg)
00324 {
00325     SgDebug() << msg;
00326 }
00327 
00328 template<class PLAYER>
00329 inline float GoUctBookBuilder<PLAYER>::InverseEval(float eval) const
00330 {
00331     return 1.0 - eval;
00332 }
00333 
00334 template<class PLAYER>
00335 inline bool GoUctBookBuilder<PLAYER>::IsLoss(float eval) const
00336 {
00337     return eval < -100;
00338 }
00339 
00340 template<class PLAYER>
00341 void GoUctBookBuilder<PLAYER>::PlayMove(SgMove move)
00342 {
00343     m_state.Play(move);
00344 }
00345 
00346 template<class PLAYER>
00347 void GoUctBookBuilder<PLAYER>::UndoMove(SgMove move)
00348 {
00349     SG_UNUSED(move);
00350     m_state.Undo();
00351 }
00352 
00353 template<class PLAYER>
00354 bool GoUctBookBuilder<PLAYER>::GetNode(SgBookNode& node) const
00355 {
00356     return m_book->Get(m_state, node);
00357 }
00358 
00359 template<class PLAYER>
00360 void GoUctBookBuilder<PLAYER>::WriteNode(const SgBookNode& node)
00361 {
00362     m_book->Put(m_state, node);
00363 }
00364 
00365 template<class PLAYER>
00366 void GoUctBookBuilder<PLAYER>::FlushBook()
00367 {
00368     SgDebug() << "Flushing DB...\n";
00369     m_book->Flush();
00370 }
00371 
00372 template<class PLAYER>
00373 float GoUctBookBuilder<PLAYER>::Value(const SgBookNode& node) const
00374 {
00375     return node.m_value;
00376 }
00377 
00378 template<class PLAYER>
00379 void GoUctBookBuilder<PLAYER>::GetAllLegalMoves(std::vector<SgMove>& moves)
00380 {
00381     for (GoBoard::Iterator it(m_state.Board()); it; ++it)
00382         if (m_state.Board().IsLegal(*it))
00383             moves.push_back(*it);
00384 }
00385 
00386 /** Creates root node if necessary. */
00387 template<class PLAYER>
00388 void GoUctBookBuilder<PLAYER>::EnsureRootExists()
00389 {
00390     SgBookNode root;
00391     if (!GetNode(root))
00392     {
00393         BeforeEvaluateChildren();
00394         PrintMessage("Creating root node...\n");
00395         float value = m_workers[0](SG_NULLMOVE);
00396         WriteNode(SgBookNode(value));
00397     }
00398 }
00399 
00400 /** Computes an ordered set of moves to consider. */
00401 template<class PLAYER>
00402 bool GoUctBookBuilder<PLAYER>::GenerateMoves(std::vector<SgMove>& moves,
00403                                              float& value)
00404 {
00405     SG_UNUSED(value);
00406 
00407     // Search for a few seconds.
00408     SgDebug() << m_state.Board() << '\n';
00409     m_players[0]->SetMaxGames(m_numGamesPerSort);
00410     m_workers[0](SG_NULLMOVE);
00411     std::vector<std::pair<int, SgMove> > ordered;
00412     // Store counts for each move in vector.
00413     {
00414         const SgUctTree& tree = m_players[0]->Search().Tree();
00415         const SgUctNode& root = tree.Root();
00416         for (GoBoard::Iterator it(m_state.Board()); it; ++it)
00417             if (m_state.Board().IsLegal(*it))
00418             {
00419                 SgMove move = *it;
00420                 const SgUctNode* node = 
00421                     SgUctTreeUtil::FindChildWithMove(tree, root, move);
00422                 if (node && node->PosCount() > 0)
00423                 {
00424                     ordered.push_back(std::make_pair(-node->PosCount(), move));
00425                 }
00426             }
00427     }
00428     // Sort moves based on count of this search. 
00429     std::stable_sort(ordered.begin(), ordered.end());
00430     for (std::size_t i = 0; i < ordered.size(); ++i)
00431         moves.push_back(ordered[i].second);
00432     SgDebug() << '\n';
00433     return false;
00434 }
00435 
00436 template<class PLAYER>
00437 void GoUctBookBuilder<PLAYER>::BeforeEvaluateChildren()
00438 {
00439     for (std::size_t i = 0; i < m_numThreads; ++i)
00440         m_players[i]->SetMaxGames(m_numGamesPerEvaluation);
00441 }
00442 
00443 template<class PLAYER>
00444 void GoUctBookBuilder<PLAYER>
00445 ::EvaluateChildren(const std::vector<SgMove>& childrenToDo,
00446                    std::vector<std::pair<SgMove, float> >& scores)
00447 {
00448     SgDebug() << "Evaluating children:";
00449     for (std::size_t i = 0; i < childrenToDo.size(); ++i)
00450         SgDebug() << ' ' << SgWritePoint(childrenToDo[i]);
00451     SgDebug() << '\n';
00452     m_threadedWorker->DoWork(childrenToDo, scores);
00453 }
00454 
00455 template<class PLAYER>
00456 void GoUctBookBuilder<PLAYER>::AfterEvaluateChildren()
00457 {
00458 }
00459 
00460 template<class PLAYER>
00461 void GoUctBookBuilder<PLAYER>::StartIteration(int iteration)
00462 {
00463     SgDebug() << "\n--Iteration " << iteration << "--\n";
00464 }
00465 
00466 template<class PLAYER>
00467 void GoUctBookBuilder<PLAYER>::EndIteration()
00468 {
00469     // DO NOTHING FOR NOW
00470 }
00471 
00472 template<class PLAYER>
00473 void GoUctBookBuilder<PLAYER>::ClearAllVisited()
00474 {
00475     m_visited.clear();
00476 }
00477     
00478 template<class PLAYER>
00479 void GoUctBookBuilder<PLAYER>::MarkAsVisited()
00480 {
00481     m_visited.insert(m_state.GetHashCode());
00482 }
00483     
00484 template<class PLAYER>
00485 bool GoUctBookBuilder<PLAYER>::HasBeenVisited()
00486 {
00487     return m_visited.count(m_state.GetHashCode()) == 1;
00488 }
00489 
00490 //----------------------------------------------------------------------------
00491 
00492 #endif // GOBOOKBUILDER_HPP


17 Jun 2010 Doxygen 1.4.7