00001
00002
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
00022
00023
00024
00025
00026
00027
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
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
00055
00056
00057 std::size_t NumThreads() const;
00058
00059
00060 void SetNumThreads(std::size_t num);
00061
00062
00063 std::size_t NumGamesPerEvaluation() const;
00064
00065
00066 void SetNumGamesPerEvaluation(std::size_t num);
00067
00068
00069 std::size_t NumGamesPerSort() const;
00070
00071
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
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
00129 GoAutoBook* m_book;
00130
00131 PLAYER* m_origPlayer;
00132
00133 GoAutoBookState m_state;
00134
00135 std::set<SgHashCode> m_visited;
00136
00137
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
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
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
00243
00244
00245
00246 newPlayer->SetForcedOpeningMoves(false);
00247
00248 newPlayer->Search().SetMoveSelect(SG_UCTMOVESELECT_ESTIMATE);
00249
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
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
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
00401 template<class PLAYER>
00402 bool GoUctBookBuilder<PLAYER>::GenerateMoves(std::vector<SgMove>& moves,
00403 float& value)
00404 {
00405 SG_UNUSED(value);
00406
00407
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
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
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
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