Go to the documentation of this file.00001
00002
00003
00004
00005 #ifndef GOBOOKBUILDER_H
00006 #define GOBOOKBUILDER_H
00007
00008 #include <cmath>
00009 #include <iostream>
00010 #include <fstream>
00011 #include <set>
00012 #include "SgBookBuilder.h"
00013 #include "SgThreadedWorker.h"
00014 #include "GoBoard.h"
00015 #include "GoAutoBook.h"
00016 #include "GoBoardSynchronizer.h"
00017
00018
00019
00020
00021
00022
00023 template<class PLAYER>
00024 class GoUctBookBuilder : public SgBookBuilder
00025 {
00026 public:
00027 GoUctBookBuilder(const GoBoard& brd);
00028
00029 ~GoUctBookBuilder();
00030
00031
00032
00033
00034
00035
00036
00037 void SetPlayer(PLAYER& player);
00038
00039
00040 void SetState(GoAutoBook& book);
00041
00042
00043
00044
00045
00046
00047 std::size_t NumThreads() const;
00048
00049
00050 void SetNumThreads(std::size_t num);
00051
00052
00053 SgUctValue NumGamesPerEvaluation() const;
00054
00055
00056 void SetNumGamesPerEvaluation(SgUctValue num);
00057
00058
00059 SgUctValue NumGamesPerSort() const;
00060
00061
00062 void SetNumGamesPerSort(SgUctValue num);
00063
00064
00065
00066 float InverseEval(float eval) const;
00067
00068 bool IsLoss(float eval) const;
00069
00070 float Value(const SgBookNode& node) const;
00071
00072 protected:
00073 std::string MoveString(SgMove move) const;
00074
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();
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
00141 SgUctValue m_numGamesPerEvaluation;
00142
00143
00144 SgUctValue m_numGamesPerSort;
00145
00146 std::size_t m_numEvals;
00147
00148 std::size_t m_numWidenings;
00149
00150 std::size_t m_valueUpdates;
00151
00152 std::size_t m_priorityUpdates;
00153
00154 std::size_t m_internalNodes;
00155
00156 std::size_t m_leafNodes;
00157
00158 std::size_t m_terminalNodes;
00159
00160
00161 std::vector<PLAYER*> m_players;
00162
00163
00164 std::vector<Worker> m_workers;
00165
00166 SgThreadedWorker<SgMove,float,Worker>* m_threadedWorker;
00167
00168 void CreateWorkers();
00169
00170 void DestroyWorkers();
00171 };
00172
00173
00174
00175 template<class PLAYER>
00176 inline std::size_t GoUctBookBuilder<PLAYER>::NumThreads() const
00177 {
00178 return m_numThreads;
00179 }
00180
00181 template<class PLAYER>
00182 inline void GoUctBookBuilder<PLAYER>::SetNumThreads(std::size_t num)
00183 {
00184 m_numThreads = num;
00185 }
00186
00187 template<class PLAYER>
00188 inline SgUctValue GoUctBookBuilder<PLAYER>::NumGamesPerEvaluation() const
00189 {
00190 return m_numGamesPerEvaluation;
00191 }
00192
00193 template<class PLAYER>
00194 inline void GoUctBookBuilder<PLAYER>::SetNumGamesPerEvaluation(SgUctValue num)
00195 {
00196 m_numGamesPerEvaluation = num;
00197 }
00198
00199 template<class PLAYER>
00200 inline SgUctValue GoUctBookBuilder<PLAYER>::NumGamesPerSort() const
00201 {
00202 return m_numGamesPerSort;
00203 }
00204
00205 template<class PLAYER>
00206 inline void GoUctBookBuilder<PLAYER>::SetNumGamesPerSort(SgUctValue num)
00207 {
00208 m_numGamesPerSort = num;
00209 }
00210
00211
00212
00213 template<class PLAYER>
00214 GoUctBookBuilder<PLAYER>::GoUctBookBuilder(const GoBoard& bd)
00215 : SgBookBuilder(),
00216 m_book(0),
00217 m_origPlayer(0),
00218 m_state(bd),
00219 m_numThreads(1),
00220 m_numGamesPerEvaluation(10000),
00221 m_numGamesPerSort(10000)
00222 {
00223 SetAlpha(30.0);
00224 SetExpandWidth(8);
00225 }
00226
00227 template<class PLAYER>
00228 GoUctBookBuilder<PLAYER>::~GoUctBookBuilder()
00229 {
00230 }
00231
00232
00233
00234
00235 template<class PLAYER>
00236 void GoUctBookBuilder<PLAYER>::CreateWorkers()
00237 {
00238 PrintMessage("GoUctBookBuilder::CreateWorkers()\n");
00239 for (std::size_t i = 0; i < m_numThreads; ++i)
00240 {
00241 PLAYER* newPlayer = new PLAYER(m_state.Board());
00242
00243
00244
00245
00246
00247 newPlayer->SetForcedOpeningMoves(false);
00248
00249 newPlayer->Search().SetMoveSelect(SG_UCTMOVESELECT_ESTIMATE);
00250
00251 newPlayer->Search().SetMaxNodes(8500000);
00252 newPlayer->SetWriteDebugOutput(false);
00253
00254 m_players.push_back(newPlayer);
00255 m_workers.push_back(Worker(i, *m_players[i]));
00256 }
00257 m_threadedWorker
00258 = new SgThreadedWorker<SgMove,float,Worker>(m_workers);
00259 }
00260
00261
00262 template<class PLAYER>
00263 void GoUctBookBuilder<PLAYER>::DestroyWorkers()
00264 {
00265 PrintMessage("GoUctBookBuilder::DestroyWorkers()\n");
00266 for (std::size_t i = 0; i < m_numThreads; ++i)
00267 delete m_players[i];
00268 delete m_threadedWorker;
00269 m_workers.clear();
00270 m_players.clear();
00271 }
00272
00273 template<class PLAYER>
00274 void GoUctBookBuilder<PLAYER>::Init()
00275 {
00276 CreateWorkers();
00277 }
00278
00279 template<class PLAYER>
00280 void GoUctBookBuilder<PLAYER>::Fini()
00281 {
00282 DestroyWorkers();
00283 }
00284
00285
00286
00287 template<class PLAYER>
00288 GoUctBookBuilder<PLAYER>::Worker::Worker(std::size_t id, PLAYER& player)
00289
00290 : m_id(id),
00291 m_player(&player)
00292 {
00293 }
00294
00295 template<class PLAYER>
00296 float GoUctBookBuilder<PLAYER>::Worker::operator()(const SgMove& move)
00297 {
00298 m_player->UpdateSubscriber();
00299 if (move >= 0)
00300 m_player->Board().Play(move);
00301 m_player->GenMove(SgTimeRecord(true, 9999), m_player->Board().ToPlay());
00302 GoUctSearch& search
00303 = dynamic_cast<GoUctSearch&>(m_player->Search());
00304 float score = static_cast<float>(search.Tree().Root().Mean());
00305 return score;
00306 }
00307
00308
00309
00310 template<class PLAYER>
00311 inline void GoUctBookBuilder<PLAYER>::SetPlayer(PLAYER& player)
00312 {
00313 m_origPlayer = &player;
00314 }
00315
00316 template<class PLAYER>
00317 inline void GoUctBookBuilder<PLAYER>::SetState(GoAutoBook& book)
00318 {
00319 m_book = &book;
00320 m_state.Synchronize();
00321 }
00322
00323 template<class PLAYER>
00324 inline std::string GoUctBookBuilder<PLAYER>::MoveString(SgMove move) const
00325 {
00326 return SgPointUtil::PointToString(move);
00327 }
00328
00329 template<class PLAYER>
00330 void GoUctBookBuilder<PLAYER>::PrintMessage(std::string msg)
00331 {
00332 SgDebug() << msg;
00333 }
00334
00335 template<class PLAYER>
00336 inline float GoUctBookBuilder<PLAYER>::InverseEval(float eval) const
00337 {
00338 return 1.f - eval;
00339 }
00340
00341 template<class PLAYER>
00342 inline bool GoUctBookBuilder<PLAYER>::IsLoss(float eval) const
00343 {
00344 return eval < -100;
00345 }
00346
00347 template<class PLAYER>
00348 void GoUctBookBuilder<PLAYER>::PlayMove(SgMove move)
00349 {
00350 m_state.Play(move);
00351 }
00352
00353 template<class PLAYER>
00354 void GoUctBookBuilder<PLAYER>::UndoMove(SgMove move)
00355 {
00356 SG_UNUSED(move);
00357 m_state.Undo();
00358 }
00359
00360 template<class PLAYER>
00361 bool GoUctBookBuilder<PLAYER>::GetNode(SgBookNode& node) const
00362 {
00363 return m_book->Get(m_state, node);
00364 }
00365
00366 template<class PLAYER>
00367 void GoUctBookBuilder<PLAYER>::WriteNode(const SgBookNode& node)
00368 {
00369 m_book->Put(m_state, node);
00370 }
00371
00372 template<class PLAYER>
00373 void GoUctBookBuilder<PLAYER>::FlushBook()
00374 {
00375 SgDebug() << "Flushing DB...\n";
00376 m_book->Flush();
00377 }
00378
00379 template<class PLAYER>
00380 float GoUctBookBuilder<PLAYER>::Value(const SgBookNode& node) const
00381 {
00382 return node.m_value;
00383 }
00384
00385 template<class PLAYER>
00386 void GoUctBookBuilder<PLAYER>::GetAllLegalMoves(std::vector<SgMove>& moves)
00387 {
00388 for (GoBoard::Iterator it(m_state.Board()); it; ++it)
00389 if (m_state.Board().IsLegal(*it))
00390 moves.push_back(*it);
00391 }
00392
00393
00394 template<class PLAYER>
00395 void GoUctBookBuilder<PLAYER>::EnsureRootExists()
00396 {
00397 SgBookNode root;
00398 if (!GetNode(root))
00399 {
00400 BeforeEvaluateChildren();
00401 PrintMessage("Creating root node...\n");
00402 float value = m_workers[0](SG_NULLMOVE);
00403 WriteNode(SgBookNode(value));
00404 }
00405 }
00406
00407
00408 template<class PLAYER>
00409 bool GoUctBookBuilder<PLAYER>::GenerateMoves(std::vector<SgMove>& moves,
00410 float& value)
00411 {
00412 SG_UNUSED(value);
00413
00414
00415 SgDebug() << m_state.Board() << '\n';
00416 m_players[0]->SetMaxGames(m_numGamesPerSort);
00417 m_workers[0](SG_NULLMOVE);
00418 std::vector<std::pair<SgUctValue, SgMove> > ordered;
00419
00420 {
00421 const SgUctTree& tree = m_players[0]->Search().Tree();
00422 const SgUctNode& root = tree.Root();
00423 for (GoBoard::Iterator it(m_state.Board()); it; ++it)
00424 if (m_state.Board().IsLegal(*it))
00425 {
00426 SgMove move = *it;
00427 const SgUctNode* node =
00428 SgUctTreeUtil::FindChildWithMove(tree, root, move);
00429 if (node && node->PosCount() > 0)
00430 {
00431 ordered.push_back(std::make_pair(-node->PosCount(), move));
00432 }
00433 }
00434 }
00435
00436 std::stable_sort(ordered.begin(), ordered.end());
00437 for (std::size_t i = 0; i < ordered.size(); ++i)
00438 moves.push_back(ordered[i].second);
00439 SgDebug() << '\n';
00440 return false;
00441 }
00442
00443 template<class PLAYER>
00444 void GoUctBookBuilder<PLAYER>::BeforeEvaluateChildren()
00445 {
00446 for (std::size_t i = 0; i < m_numThreads; ++i)
00447 m_players[i]->SetMaxGames(m_numGamesPerEvaluation);
00448 }
00449
00450 template<class PLAYER>
00451 void GoUctBookBuilder<PLAYER>
00452 ::EvaluateChildren(const std::vector<SgMove>& childrenToDo,
00453 std::vector<std::pair<SgMove, float> >& scores)
00454 {
00455 SgDebug() << "Evaluating children:";
00456 for (std::size_t i = 0; i < childrenToDo.size(); ++i)
00457 SgDebug() << ' ' << SgWritePoint(childrenToDo[i]);
00458 SgDebug() << '\n';
00459 m_threadedWorker->DoWork(childrenToDo, scores);
00460 }
00461
00462 template<class PLAYER>
00463 void GoUctBookBuilder<PLAYER>::AfterEvaluateChildren()
00464 {
00465 }
00466
00467 template<class PLAYER>
00468 void GoUctBookBuilder<PLAYER>::StartIteration()
00469 {
00470 }
00471
00472 template<class PLAYER>
00473 void GoUctBookBuilder<PLAYER>::EndIteration()
00474 {
00475 }
00476
00477 template<class PLAYER>
00478 void GoUctBookBuilder<PLAYER>::ClearAllVisited()
00479 {
00480 m_visited.clear();
00481 }
00482
00483 template<class PLAYER>
00484 void GoUctBookBuilder<PLAYER>::MarkAsVisited()
00485 {
00486 m_visited.insert(m_state.GetHashCode());
00487 }
00488
00489 template<class PLAYER>
00490 bool GoUctBookBuilder<PLAYER>::HasBeenVisited()
00491 {
00492 return m_visited.count(m_state.GetHashCode()) == 1;
00493 }
00494
00495
00496
00497 #endif // GOBOOKBUILDER_HPP