BookBuilder.hpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006 #ifndef BOOKBUILDER_HPP
00007 #define BOOKBUILDER_HPP
00008
00009 #include <cmath>
00010 #include "BenzenePlayer.hpp"
00011 #include "BitsetIterator.hpp"
00012 #include "HashDB.hpp"
00013 #include "Book.hpp"
00014 #include "EndgameUtils.hpp"
00015 #include "StateDB.hpp"
00016 #include "Resistance.hpp"
00017 #include "SgThreadedWorker.h"
00018 #include "SgBookBuilder.h"
00019 #include "SgUctSearch.h"
00020
00021 _BEGIN_BENZENE_NAMESPACE_
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 template<class PLAYER>
00038 class BookBuilder : public SgBookBuilder
00039 {
00040 public:
00041
00042
00043
00044
00045 BookBuilder(PLAYER& player);
00046
00047
00048 ~BookBuilder();
00049
00050
00051
00052
00053 void SetState(Book& book, const HexState& state);
00054
00055
00056 void SetWorkBoard(HexBoard& brd);
00057
00058
00059
00060
00061 bool UseICE() const;
00062
00063
00064 void SetUseICE(bool flag);
00065
00066
00067
00068
00069 std::size_t NumThreads() const;
00070
00071
00072 void SetNumThreads(std::size_t num);
00073
00074 protected:
00075 std::string MoveString(SgMove move) const;
00076
00077 void PrintMessage(std::string msg);
00078
00079 float InverseEval(float eval) const;
00080
00081 bool IsLoss(float eval) const;
00082
00083 void PlayMove(SgMove move);
00084
00085 void UndoMove(SgMove move);
00086
00087 bool GetNode(SgBookNode& node) const;
00088
00089 float Value(const SgBookNode& node) const;
00090
00091 void WriteNode(const SgBookNode& node);
00092
00093 void FlushBook();
00094
00095 void EnsureRootExists();
00096
00097 bool GenerateMoves(std::vector<SgMove>& moves, float& value);
00098
00099 void GetAllLegalMoves(std::vector<SgMove>& moves);
00100
00101 void EvaluateChildren(const std::vector<SgMove>& childrenToDo,
00102 std::vector<std::pair<SgMove, float> >& scores);
00103 void Init();
00104
00105 void StartIteration(int iteration);
00106
00107 void EndIteration();
00108
00109 void BeforeEvaluateChildren();
00110
00111 void AfterEvaluateChildren();
00112
00113 void Fini();
00114
00115 void ClearAllVisited();
00116
00117 void MarkAsVisited();
00118
00119 bool HasBeenVisited();
00120
00121 private:
00122
00123
00124 class Worker
00125 {
00126 public:
00127 Worker(std::size_t id, BenzenePlayer& player, HexBoard& brd);
00128
00129 void SetState(const HexState& state);
00130
00131 float operator()(const SgMove& move);
00132
00133 private:
00134
00135 std::size_t m_id;
00136
00137 HexBoard* m_brd;
00138
00139 BenzenePlayer* m_player;
00140
00141 HexState m_state;
00142 };
00143
00144
00145 Book* m_book;
00146
00147
00148 PLAYER& m_orig_player;
00149
00150 HexBoard* m_brd;
00151
00152 HexState m_state;
00153
00154 std::set<hash_t> m_visited;
00155
00156
00157 bool m_use_ice;
00158
00159
00160 std::size_t m_num_threads;
00161
00162 std::size_t m_num_evals;
00163
00164 std::size_t m_num_widenings;
00165
00166 std::size_t m_value_updates;
00167
00168 std::size_t m_priority_updates;
00169
00170 std::size_t m_internal_nodes;
00171
00172 std::size_t m_leaf_nodes;
00173
00174 std::size_t m_terminal_nodes;
00175
00176
00177 std::vector<HexBoard*> m_boards;
00178
00179
00180 std::vector<BenzenePlayer*> m_players;
00181
00182 std::vector<Worker> m_workers;
00183
00184 SgThreadedWorker<SgMove,float,Worker>* m_threadedWorker;
00185
00186 void CreateWorkers();
00187
00188 void DestroyWorkers();
00189 };
00190
00191
00192
00193 template<class PLAYER>
00194 BookBuilder<PLAYER>::BookBuilder(PLAYER& player)
00195 : SgBookBuilder(),
00196 m_book(0),
00197 m_orig_player(player),
00198 m_brd(0),
00199 m_use_ice(false),
00200 m_num_threads(1)
00201 {
00202 }
00203
00204 template<class PLAYER>
00205 BookBuilder<PLAYER>::~BookBuilder()
00206 {
00207 }
00208
00209
00210
00211 template<class PLAYER>
00212 inline bool BookBuilder<PLAYER>::UseICE() const
00213 {
00214 return m_use_ice;
00215 }
00216
00217 template<class PLAYER>
00218 inline void BookBuilder<PLAYER>::SetUseICE(bool flag)
00219 {
00220 m_use_ice = flag;
00221 }
00222
00223 template<class PLAYER>
00224 inline std::size_t BookBuilder<PLAYER>::NumThreads() const
00225 {
00226 return m_num_threads;
00227 }
00228
00229 template<class PLAYER>
00230 inline void BookBuilder<PLAYER>::SetNumThreads(std::size_t num)
00231 {
00232 m_num_threads = num;
00233 }
00234
00235
00236
00237
00238 template<class PLAYER>
00239 void BookBuilder<PLAYER>::CreateWorkers()
00240 {
00241 LogInfo() << "BookBuilder::CreateWorkers()\n";
00242 for (std::size_t i = 0; i < m_num_threads; ++i)
00243 {
00244 PLAYER* newPlayer = new PLAYER();
00245
00246 newPlayer->CopySettingsFrom(m_orig_player);
00247 newPlayer->SetSearchSingleton(true);
00248
00249
00250 newPlayer->Search().SetMoveSelect(SG_UCTMOVESELECT_BOUND);
00251
00252 m_players.push_back(newPlayer);
00253 m_boards.push_back(new HexBoard(*m_brd));
00254 m_workers.push_back(Worker(i, *m_players[i], *m_boards[i]));
00255 }
00256 m_threadedWorker
00257 = new SgThreadedWorker<SgMove,float,Worker>(m_workers);
00258 }
00259
00260
00261 template<class PLAYER>
00262 void BookBuilder<PLAYER>::DestroyWorkers()
00263 {
00264 LogInfo() << "BookBuilder::DestroyWorkers()\n";
00265 for (std::size_t i = 0; i < m_num_threads; ++i)
00266 {
00267 delete m_boards[i];
00268 delete m_players[i];
00269 }
00270 delete m_threadedWorker;
00271 m_workers.clear();
00272 m_boards.clear();
00273 m_players.clear();
00274 }
00275
00276 template<class PLAYER>
00277 void BookBuilder<PLAYER>::Init()
00278 {
00279 CreateWorkers();
00280 }
00281
00282 template<class PLAYER>
00283 void BookBuilder<PLAYER>::Fini()
00284 {
00285 DestroyWorkers();
00286 }
00287
00288
00289
00290 template<class PLAYER>
00291 BookBuilder<PLAYER>::Worker::Worker(std::size_t id, BenzenePlayer& player,
00292 HexBoard& brd)
00293
00294 : m_id(id),
00295 m_brd(&brd),
00296 m_player(&player)
00297 {
00298 }
00299
00300 template<class PLAYER>
00301 void BookBuilder<PLAYER>::Worker::SetState(const HexState& state)
00302 {
00303 m_state = state;
00304 }
00305
00306 template<class PLAYER>
00307 float BookBuilder<PLAYER>::Worker::operator()(const SgMove& move)
00308 {
00309 HexState state(m_state);
00310 if (move >= 0)
00311 state.PlayMove(static_cast<HexPoint>(move));
00312
00313
00314 StoneBoard blah(state.Position());
00315 Game game(blah);
00316
00317 LogInfo() << "Evaluating: " << state.Position() << '\n';
00318
00319 HexEval score;
00320 m_brd->GetPosition().SetPosition(state.Position());
00321 m_player->GenMove(state, game, *m_brd, 99999, score);
00322 return score;
00323 }
00324
00325
00326
00327 template<class PLAYER>
00328 inline void BookBuilder<PLAYER>::SetState(Book& book, const HexState& state)
00329 {
00330 m_book = &book;
00331 m_state = state;
00332 }
00333
00334 template<class PLAYER>
00335 inline void BookBuilder<PLAYER>::SetWorkBoard(HexBoard& workBoard)
00336 {
00337 m_brd = &workBoard;
00338 }
00339
00340 template<class PLAYER>
00341 std::string BookBuilder<PLAYER>::MoveString(SgMove move) const
00342 {
00343 return HexPointUtil::ToString(static_cast<HexPoint>(move));
00344 }
00345
00346 template<class PLAYER>
00347 void BookBuilder<PLAYER>::PrintMessage(std::string msg)
00348 {
00349 LogInfo() << msg;
00350 }
00351
00352 template<class PLAYER>
00353 inline float BookBuilder<PLAYER>::InverseEval(float eval) const
00354 {
00355 return BookUtil::InverseEval(eval);
00356 }
00357
00358 template<class PLAYER>
00359 inline bool BookBuilder<PLAYER>::IsLoss(float eval) const
00360 {
00361 return HexEvalUtil::IsLoss(eval);
00362 }
00363
00364 template<class PLAYER>
00365 void BookBuilder<PLAYER>::PlayMove(SgMove move)
00366 {
00367 m_state.PlayMove(static_cast<HexPoint>(move));
00368 }
00369
00370 template<class PLAYER>
00371 void BookBuilder<PLAYER>::UndoMove(SgMove move)
00372 {
00373 m_state.UndoMove(static_cast<HexPoint>(move));
00374 }
00375
00376 template<class PLAYER>
00377 bool BookBuilder<PLAYER>::GetNode(SgBookNode& node) const
00378 {
00379 HexBookNode hexNode;
00380 if (m_book->Get(m_state, hexNode))
00381 {
00382 node = hexNode;
00383 return true;
00384 }
00385 return false;
00386 }
00387
00388 template<class PLAYER>
00389 void BookBuilder<PLAYER>::WriteNode(const SgBookNode& node)
00390 {
00391 HexBookNode hexNode(node);
00392 m_book->Put(m_state, hexNode);
00393 }
00394
00395 template<class PLAYER>
00396 void BookBuilder<PLAYER>::FlushBook()
00397 {
00398 LogInfo() << "Flushing DB...\n";
00399 m_book->Flush();
00400 }
00401
00402 template<class PLAYER>
00403 float BookBuilder<PLAYER>::Value(const SgBookNode& node) const
00404 {
00405 return BookUtil::Value(node, m_state);
00406 }
00407
00408 template<class PLAYER>
00409 void BookBuilder<PLAYER>::GetAllLegalMoves(std::vector<SgMove>& moves)
00410 {
00411 for (BitsetIterator it(m_state.Position().GetEmpty()); it; ++it)
00412 moves.push_back(*it);
00413 }
00414
00415
00416 template<class PLAYER>
00417 void BookBuilder<PLAYER>::EnsureRootExists()
00418 {
00419 SgBookNode root;
00420 if (!GetNode(root))
00421 {
00422 m_workers[0].SetState(m_state);
00423 float value = m_workers[0](SG_NULLMOVE);
00424 WriteNode(SgBookNode(value));
00425 }
00426 }
00427
00428
00429
00430
00431
00432 template<class PLAYER>
00433 bool BookBuilder<PLAYER>::GenerateMoves(std::vector<SgMove>& moves,
00434 float& value)
00435 {
00436
00437
00438
00439 HexColor toMove = m_state.ToPlay();
00440 bool useICE = m_brd->UseICE();
00441 m_brd->SetUseICE(m_use_ice);
00442 m_brd->GetPosition().SetPosition(m_state.Position());
00443 m_brd->ComputeAll(toMove);
00444 m_brd->SetUseICE(useICE);
00445
00446 {
00447 HexEval hexValue;
00448 if (EndgameUtils::IsDeterminedState(*m_brd, toMove, hexValue))
00449 {
00450 value = hexValue;
00451 return true;
00452 }
00453 }
00454
00455 bitset_t children = EndgameUtils::MovesToConsider(*m_brd, toMove);
00456 HexAssert(children.any());
00457
00458 Resistance resist;
00459 resist.Evaluate(*m_brd);
00460 std::vector<HexMoveValue> ordered;
00461
00462
00463
00464
00465
00466
00467
00468 for (BitsetIterator it(children); it; ++it)
00469
00470 ordered.push_back(HexMoveValue(*it, -resist.Score(*it)));
00471 std::stable_sort(ordered.begin(), ordered.end());
00472 for (std::size_t i = 0; i < ordered.size(); ++i)
00473 moves.push_back(ordered[i].point());
00474 return false;
00475 }
00476
00477 template<class PLAYER>
00478 void BookBuilder<PLAYER>::BeforeEvaluateChildren()
00479 {
00480 for (std::size_t i = 0; i < m_workers.size(); ++i)
00481 m_workers[i].SetState(m_state);
00482 }
00483
00484 template<class PLAYER>
00485 void BookBuilder<PLAYER>
00486 ::EvaluateChildren(const std::vector<SgMove>& childrenToDo,
00487 std::vector<std::pair<SgMove, float> >& scores)
00488 {
00489 m_threadedWorker->DoWork(childrenToDo, scores);
00490 }
00491
00492 template<class PLAYER>
00493 void BookBuilder<PLAYER>::AfterEvaluateChildren()
00494 {
00495 }
00496
00497 template<class PLAYER>
00498 void BookBuilder<PLAYER>::StartIteration(int iteration)
00499 {
00500 LogInfo() << "\n--Iteration " << iteration << "--\n";
00501 }
00502
00503 template<class PLAYER>
00504 void BookBuilder<PLAYER>::EndIteration()
00505 {
00506
00507 }
00508
00509 template<class PLAYER>
00510 void BookBuilder<PLAYER>::ClearAllVisited()
00511 {
00512 m_visited.clear();
00513 }
00514
00515 template<class PLAYER>
00516 void BookBuilder<PLAYER>::MarkAsVisited()
00517 {
00518 m_visited.insert(m_state.Hash());
00519 }
00520
00521 template<class PLAYER>
00522 bool BookBuilder<PLAYER>::HasBeenVisited()
00523 {
00524 return m_visited.count(m_state.Hash()) == 1;
00525 }
00526
00527
00528
00529 _END_BENZENE_NAMESPACE_
00530
00531 #endif // BOOKBUILDER_HPP