00001
00002
00003
00004
00005 #ifndef GOUCT_BOOKBUILDERCOMMANDS_H
00006 #define GOUCT_BOOKBUILDERCOMMANDS_H
00007
00008 #include <string>
00009 #include <typeinfo>
00010 #include "GtpEngine.h"
00011 #include "GoUctPlayoutPolicy.h"
00012 #include "GoUctGlobalSearch.h"
00013 #include "GoUctPlayer.h"
00014 #include "GoUctBookBuilder.h"
00015
00016 class GoBoard;
00017 class GoPlayer;
00018 class GoUctBoard;
00019 class GoUctSearch;
00020
00021
00022
00023
00024 template<class PLAYER>
00025 class GoUctBookBuilderCommands
00026 {
00027 public:
00028
00029
00030
00031
00032
00033
00034
00035 GoUctBookBuilderCommands(const GoBoard& bd, GoPlayer*& player,
00036 boost::scoped_ptr<GoAutoBook>& book);
00037
00038 void AddGoGuiAnalyzeCommands(GtpCommand& cmd);
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 void CmdOpen(GtpCommand& cmd);
00062 void CmdClose(GtpCommand& cmd);
00063 void CmdSave(GtpCommand& cmd);
00064 void CmdExpand(GtpCommand& cmd);
00065 void CmdCover(GtpCommand& cmd);
00066 void CmdAdditiveCover(GtpCommand& cmd);
00067 void CmdRefresh(GtpCommand& cmd);
00068 void CmdMerge(GtpCommand& cmd);
00069 void CmdParam(GtpCommand& cmd);
00070 void CmdScores(GtpCommand& cmd);
00071 void CmdStateInfo(GtpCommand& cmd);
00072 void CmdCounts(GtpCommand& cmd);
00073 void CmdPriority(GtpCommand& cmd);
00074 void CmdLoadDisabled(GtpCommand& cmd);
00075 void CmdTruncateByDepth(GtpCommand& cmd);
00076 void CmdImport(GtpCommand& cmd);
00077 void CmdExport(GtpCommand& cmd);
00078 void CmdMainLine(GtpCommand& cmd);
00079
00080
00081 void Register(GtpEngine& engine);
00082
00083 private:
00084 const GoBoard& m_bd;
00085
00086 GoPlayer*& m_player;
00087
00088 boost::scoped_ptr<GoAutoBook>& m_book;
00089
00090 GoUctBookBuilder<PLAYER> m_bookBuilder;
00091
00092 GoAutoBookParam m_param;
00093
00094 PLAYER& Player();
00095
00096 void Register(GtpEngine& e, const std::string& command,
00097 typename GtpCallback<GoUctBookBuilderCommands>::Method method);
00098
00099 void ShowInfluence(GtpCommand& cmd, GoAutoBookState& state);
00100
00101 GoAutoBookMoveSelectType MoveSelectArg(const GtpCommand& cmd,
00102 std::size_t number);
00103
00104 std::string MoveSelectToString(GoAutoBookMoveSelectType moveSelect);
00105 };
00106
00107
00108
00109 template<class PLAYER>
00110 GoUctBookBuilderCommands<PLAYER>
00111 ::GoUctBookBuilderCommands(const GoBoard& bd, GoPlayer*& player,
00112 boost::scoped_ptr<GoAutoBook>& book)
00113 : m_bd(bd),
00114 m_player(player),
00115 m_book(book),
00116 m_bookBuilder(bd),
00117 m_param()
00118 {
00119 }
00120
00121 template<class PLAYER>
00122 void GoUctBookBuilderCommands<PLAYER>::AddGoGuiAnalyzeCommands(GtpCommand& cmd)
00123 {
00124 cmd <<
00125 "none/AutoBook Additive Cover/autobook_additive_cover\n"
00126 "none/AutoBook Close/autobook_close\n"
00127 "none/AutoBook Cover/autobook_cover\n"
00128 "none/AutoBook Expand/autobook_expand\n"
00129 "none/AutoBook Open/autobook_open %r\n"
00130 "none/AutoBook Save/autobook_save\n"
00131 "none/AutoBook Refresh/autobook_refresh\n"
00132 "none/AutoBook Merge/autobook_merge %r\n"
00133 "none/AutoBook Load Disabled Lines/autobook_load_disabled_lines %r\n"
00134 "none/AutoBook Truncate By Depth/autobook_truncate_by_depth\n"
00135 "none/AutoBook Import/autobook_import\n"
00136 "none/AutoBook Export/autobook_export\n"
00137 "param/AutoBook Param/autobook_param\n"
00138 "string/AutoBook State Info/autobook_state_info\n"
00139 "gfx/AutoBook Scores/autobook_scores\n"
00140 "gfx/AutoBook Counts/autobook_counts\n"
00141 "gfx/AutoBook Main Line/autobook_mainline\n"
00142 "gfx/AutoBook Priority/autobook_priority\n";
00143 }
00144
00145 template<class PLAYER>
00146 void GoUctBookBuilderCommands<PLAYER>::Register(GtpEngine& e)
00147 {
00148 Register(e, "autobook_close", &GoUctBookBuilderCommands<PLAYER>::CmdClose);
00149 Register(e, "autobook_counts",
00150 &GoUctBookBuilderCommands<PLAYER>::CmdCounts);
00151 Register(e, "autobook_cover",
00152 &GoUctBookBuilderCommands<PLAYER>::CmdCover);
00153 Register(e, "autobook_additive_cover",
00154 &GoUctBookBuilderCommands<PLAYER>::CmdAdditiveCover);
00155 Register(e, "autobook_expand",
00156 &GoUctBookBuilderCommands<PLAYER>::CmdExpand);
00157 Register(e, "autobook_export",
00158 &GoUctBookBuilderCommands<PLAYER>::CmdExport);
00159 Register(e, "autobook_import",
00160 &GoUctBookBuilderCommands<PLAYER>::CmdImport);
00161 Register(e, "autobook_open", &GoUctBookBuilderCommands<PLAYER>::CmdOpen);
00162 Register(e, "autobook_load_disabled_lines",
00163 &GoUctBookBuilderCommands<PLAYER>::CmdLoadDisabled);
00164 Register(e, "autobook_mainline",
00165 &GoUctBookBuilderCommands<PLAYER>::CmdMainLine);
00166 Register(e, "autobook_merge",
00167 &GoUctBookBuilderCommands<PLAYER>::CmdMerge);
00168 Register(e, "autobook_param", &GoUctBookBuilderCommands<PLAYER>::CmdParam);
00169 Register(e, "autobook_priority",
00170 &GoUctBookBuilderCommands<PLAYER>::CmdPriority);
00171 Register(e, "autobook_refresh",
00172 &GoUctBookBuilderCommands<PLAYER>::CmdRefresh);
00173 Register(e, "autobook_save",
00174 &GoUctBookBuilderCommands<PLAYER>::CmdSave);
00175 Register(e, "autobook_scores",
00176 &GoUctBookBuilderCommands<PLAYER>::CmdScores);
00177 Register(e, "autobook_state_info",
00178 &GoUctBookBuilderCommands<PLAYER>::CmdStateInfo);
00179 Register(e, "autobook_truncate_by_depth",
00180 &GoUctBookBuilderCommands<PLAYER>::CmdTruncateByDepth);
00181 }
00182
00183 template<class PLAYER>
00184 void GoUctBookBuilderCommands<PLAYER>::
00185 Register(GtpEngine& engine, const std::string& command,
00186 typename GtpCallback<GoUctBookBuilderCommands>::Method method)
00187 {
00188 engine.Register(command,
00189 new GtpCallback<GoUctBookBuilderCommands>(this, method));
00190 }
00191
00192 template<class PLAYER>
00193 PLAYER& GoUctBookBuilderCommands<PLAYER>::Player()
00194 {
00195 if (m_player == 0)
00196 throw GtpFailure("player not GoUctPlayer");
00197 try
00198 {
00199 return dynamic_cast<PLAYER&>(*m_player);
00200 }
00201 catch (const std::bad_cast&)
00202 {
00203 throw GtpFailure("player not of right type!");
00204 }
00205 }
00206
00207 template<class PLAYER>
00208 GoAutoBookMoveSelectType GoUctBookBuilderCommands<PLAYER>
00209 ::MoveSelectArg(const GtpCommand& cmd, std::size_t number)
00210 {
00211 std::string arg = cmd.ArgToLower(number);
00212 if (arg == "value")
00213 return GO_AUTOBOOK_SELECT_VALUE;
00214 if (arg == "count")
00215 return GO_AUTOBOOK_SELECT_COUNT;
00216 throw GtpFailure() << "unknown move select argument \"" << arg << '"';
00217 }
00218
00219 template<class PLAYER>
00220 std::string GoUctBookBuilderCommands<PLAYER>::
00221 MoveSelectToString(GoAutoBookMoveSelectType moveSelect)
00222 {
00223 switch (moveSelect)
00224 {
00225 case GO_AUTOBOOK_SELECT_VALUE:
00226 return "value";
00227 case GO_AUTOBOOK_SELECT_COUNT:
00228 return "count";
00229 default:
00230 SG_ASSERT(false);
00231 return "?";
00232 }
00233 }
00234
00235
00236
00237 template<class PLAYER>
00238 void GoUctBookBuilderCommands<PLAYER>::ShowInfluence(GtpCommand& cmd,
00239 GoAutoBookState& state)
00240 {
00241 cmd << "INFLUENCE ";
00242 for (GoBoard::Iterator it(m_bd); it; ++it)
00243 {
00244 if (m_bd.IsLegal(*it))
00245 {
00246 state.Play(*it);
00247 SgBookNode node;
00248 if (m_book->Get(state, node))
00249 {
00250 float value
00251 = m_bookBuilder.InverseEval(m_bookBuilder.Value(node));
00252 float scaledValue = (value * 2 - 1);
00253 if (m_bd.ToPlay() != SG_BLACK)
00254 scaledValue *= -1;
00255 cmd << ' ' << SgWritePoint(*it) << ' ' << scaledValue;
00256 }
00257 state.Undo();
00258 }
00259 }
00260 }
00261
00262
00263
00264
00265
00266 template<class PLAYER>
00267 void GoUctBookBuilderCommands<PLAYER>::CmdOpen(GtpCommand& cmd)
00268 {
00269 m_book.reset(new GoAutoBook(cmd.Arg(), m_param));
00270 }
00271
00272
00273 template<class PLAYER>
00274 void GoUctBookBuilderCommands<PLAYER>::CmdClose(GtpCommand& cmd)
00275 {
00276 cmd.CheckArgNone();
00277 m_book.reset(0);
00278 }
00279
00280
00281 template<class PLAYER>
00282 void GoUctBookBuilderCommands<PLAYER>::CmdSave(GtpCommand& cmd)
00283 {
00284 if (m_book.get() == 0)
00285 throw GtpFailure() << "No opened autobook!\n";
00286 cmd.CheckArgNone();
00287 m_book->Flush();
00288 }
00289
00290
00291 template<class PLAYER>
00292 void GoUctBookBuilderCommands<PLAYER>::CmdStateInfo(GtpCommand& cmd)
00293 {
00294 if (m_book.get() == 0)
00295 throw GtpFailure() << "No opened autobook!\n";
00296 cmd.CheckArgNone();
00297 GoAutoBookState state(m_bd);
00298 state.Synchronize();
00299 SgBookNode node;
00300 if (!m_book->Get(state, node))
00301 throw GtpFailure() << "State not in autobook.\n";
00302 cmd << node;
00303 }
00304
00305
00306 template<class PLAYER>
00307 void GoUctBookBuilderCommands<PLAYER>::CmdExpand(GtpCommand& cmd)
00308 {
00309 if (m_book.get() == 0)
00310 throw GtpFailure() << "No opened autobook!\n";
00311 cmd.CheckNuArg(1);
00312 int numExpansions = cmd.ArgMin<int>(0, 1);
00313 m_bookBuilder.SetPlayer(Player());
00314 m_bookBuilder.SetState(*m_book);
00315 m_bookBuilder.Expand(numExpansions);
00316 }
00317
00318
00319
00320 template<class PLAYER>
00321 void GoUctBookBuilderCommands<PLAYER>::CmdCover(GtpCommand& cmd)
00322 {
00323 if (m_book.get() == 0)
00324 throw GtpFailure() << "No opened autobook!\n";
00325 cmd.CheckNuArg(2);
00326 std::vector< std::vector<SgMove> > workList;
00327 {
00328 std::string filename = cmd.Arg(0);
00329 std::ifstream in(filename.c_str());
00330 if (!in)
00331 throw GtpFailure() << "Could not open '" << filename << "'\n";
00332 workList = GoAutoBook::ParseWorkList(in);
00333 if (workList.empty())
00334 throw GtpFailure() << "Empty worklist! No action performed";
00335 }
00336 int expansionsRequired = cmd.ArgMin<int>(1, 1);
00337 m_bookBuilder.SetPlayer(Player());
00338 m_bookBuilder.SetState(*m_book);
00339 m_bookBuilder.Cover(expansionsRequired, false, workList);
00340 }
00341
00342
00343
00344 template<class PLAYER>
00345 void GoUctBookBuilderCommands<PLAYER>::CmdAdditiveCover(GtpCommand& cmd)
00346 {
00347 if (m_book.get() == 0)
00348 throw GtpFailure() << "No opened autobook!\n";
00349 cmd.CheckNuArg(2);
00350 std::vector< std::vector<SgMove> > workList;
00351 {
00352 std::string filename = cmd.Arg(0);
00353 std::ifstream in(filename.c_str());
00354 if (!in)
00355 throw GtpFailure() << "Could not open '" << filename << "'\n";
00356 workList = GoAutoBook::ParseWorkList(in);
00357 if (workList.empty())
00358 throw GtpFailure() << "Empty worklist! No action performed";
00359 }
00360 int expansionsRequired = cmd.ArgMin<int>(1, 1);
00361 m_bookBuilder.SetPlayer(Player());
00362 m_bookBuilder.SetState(*m_book);
00363 m_bookBuilder.Cover(expansionsRequired, true, workList);
00364 }
00365
00366
00367
00368 template<class PLAYER>
00369 void GoUctBookBuilderCommands<PLAYER>::CmdRefresh(GtpCommand& cmd)
00370 {
00371 if (m_book.get() == 0)
00372 throw GtpFailure() << "No opened autobook!\n";
00373 cmd.CheckArgNone();
00374 m_bookBuilder.SetPlayer(Player());
00375 m_bookBuilder.SetState(*m_book);
00376 m_bookBuilder.Refresh();
00377 }
00378
00379
00380
00381 template<class PLAYER>
00382 void GoUctBookBuilderCommands<PLAYER>::CmdMerge(GtpCommand& cmd)
00383 {
00384 if (m_book.get() == 0)
00385 throw GtpFailure() << "No opened autobook!\n";
00386 GoAutoBook other(cmd.Arg(), m_param);
00387 m_book->Merge(other);
00388 }
00389
00390
00391
00392 template<class PLAYER>
00393 void GoUctBookBuilderCommands<PLAYER>::CmdImport(GtpCommand& cmd)
00394 {
00395 if (m_book.get() == 0)
00396 throw GtpFailure() << "No opened autobook!\n";
00397 std::string filename = cmd.Arg();
00398 std::ifstream in(filename.c_str());
00399 if (!in)
00400 throw GtpFailure() << "Could not open '" << filename << "'\n";
00401 m_book->ImportHashValuePairs(in);
00402 }
00403
00404
00405 template<class PLAYER>
00406 void GoUctBookBuilderCommands<PLAYER>::CmdExport(GtpCommand& cmd)
00407 {
00408 if (m_book.get() == 0)
00409 throw GtpFailure() << "No opened autobook!\n";
00410 std::string filename = cmd.Arg();
00411 std::ofstream of(filename.c_str());
00412 if (!of)
00413 throw GtpFailure() << "Could not open '" << filename << "'\n";
00414 GoAutoBookState state(m_bd);
00415 state.Synchronize();
00416 m_book->ExportToOldFormat(state, of);
00417 }
00418
00419
00420
00421 template<class PLAYER>
00422 void GoUctBookBuilderCommands<PLAYER>::CmdTruncateByDepth(GtpCommand& cmd)
00423 {
00424 if (m_book.get() == 0)
00425 throw GtpFailure() << "No opened autobook!\n";
00426 cmd.CheckNuArg(2);
00427 int depth = cmd.ArgMin<int>(0, 0);
00428 GoAutoBook other(cmd.Arg(1), m_param);
00429 GoAutoBookState state(m_bd);
00430 state.Synchronize();
00431 m_book->TruncateByDepth(depth, state, other);
00432 other.Flush();
00433 }
00434
00435 template<class PLAYER>
00436 void GoUctBookBuilderCommands<PLAYER>::CmdParam(GtpCommand& cmd)
00437 {
00438 if (cmd.NuArg() == 0)
00439 {
00440 cmd << "[bool] use_widening " << m_bookBuilder.UseWidening() << '\n'
00441 << "[string] alpha " << m_bookBuilder.Alpha() << '\n'
00442 << "[string] expand_width " << m_bookBuilder.ExpandWidth() << '\n'
00443 << "[string] expand_threshold "
00444 << m_bookBuilder.ExpandThreshold() << '\n'
00445 << "[string] num_threads " << m_bookBuilder.NumThreads() << '\n'
00446 << "[string] num_games_per_evaluation "
00447 << m_bookBuilder.NumGamesPerEvaluation() << '\n'
00448 << "[string] num_games_per_sort "
00449 << m_bookBuilder.NumGamesPerSort() << '\n'
00450 << "[string] usage_count "
00451 << m_param.m_usageCountThreshold << '\n'
00452 << "[list/value/count] move_select "
00453 << MoveSelectToString(m_param.m_selectType) << '\n';
00454 }
00455 else if (cmd.NuArg() == 2)
00456 {
00457 std::string name = cmd.Arg(0);
00458 if (name == "num_threads")
00459 m_bookBuilder.SetNumThreads(cmd.ArgMin<int>(1, 1));
00460 else if (name == "num_games_per_evaluation")
00461 m_bookBuilder.SetNumGamesPerEvaluation(
00462 cmd.ArgMin<SgUctValue>(1, 1));
00463 else if (name == "num_games_per_sort")
00464 m_bookBuilder.SetNumGamesPerSort(cmd.ArgMin<SgUctValue>(1, 1));
00465 else if (name == "use_widening")
00466 m_bookBuilder.SetUseWidening(cmd.Arg<bool>(1));
00467 else if (name == "expand_width")
00468 m_bookBuilder.SetExpandWidth(cmd.ArgMin<int>(1, 1));
00469 else if (name == "expand_threshold")
00470 m_bookBuilder.SetExpandThreshold(cmd.ArgMin<int>(1, 1));
00471 else if (name == "usage_count")
00472 m_param.m_usageCountThreshold = cmd.ArgMin<size_t>(1, 0);
00473 else if (name == "move_select")
00474 m_param.m_selectType = MoveSelectArg(cmd, 1);
00475 else if (name == "alpha")
00476 {
00477 float alpha = cmd.Arg<float>(1);
00478 if (alpha < 0)
00479 throw GtpFailure("Alpha must be greater than 0!");
00480 m_bookBuilder.SetAlpha(alpha);
00481 }
00482 }
00483 else
00484 throw GtpFailure() << "Expected 0 or 2 arguments!\n";
00485 }
00486
00487
00488
00489 template<class PLAYER>
00490 void GoUctBookBuilderCommands<PLAYER>::CmdLoadDisabled(GtpCommand& cmd)
00491 {
00492 if (m_book.get() == 0)
00493 throw GtpFailure() << "No opened autobook!\n";
00494 std::vector< std::vector<SgMove> > workList;
00495 {
00496 std::string filename = cmd.Arg();
00497 std::ifstream in(filename.c_str());
00498 if (!in)
00499 throw GtpFailure() << "Could not open '" << filename << "'\n";
00500 workList = GoAutoBook::ParseWorkList(in);
00501 }
00502 GoBoard brd(m_bd.Size());
00503 GoAutoBookState state(brd);
00504 state.Synchronize();
00505 std::set<SgHashCode> disabled;
00506 for (std::size_t i = 0; i < workList.size(); ++i)
00507 {
00508 for (std::size_t j = 0; j < workList[i].size(); ++j)
00509 state.Play(workList[i][j]);
00510 disabled.insert(state.GetHashCode());
00511 for (std::size_t j = 0; j < workList[i].size(); ++j)
00512 state.Undo();
00513 }
00514 m_book->AddDisabledLines(disabled);
00515 }
00516
00517
00518 template<class PLAYER>
00519 void GoUctBookBuilderCommands<PLAYER>::CmdScores(GtpCommand& cmd)
00520 {
00521 if (m_book.get() == 0)
00522 throw GtpFailure() << "No opened autobook!\n";
00523 cmd.CheckArgNone();
00524 GoAutoBookState state(m_bd);
00525 state.Synchronize();
00526 ShowInfluence(cmd, state);
00527 cmd << "\nLABEL ";
00528 for (GoBoard::Iterator it(m_bd); it; ++it)
00529 {
00530 if (m_bd.IsLegal(*it))
00531 {
00532 state.Play(*it);
00533 SgBookNode node;
00534 if (m_book->Get(state, node))
00535 {
00536 float value
00537 = m_bookBuilder.InverseEval(m_bookBuilder.Value(node));
00538 cmd << ' ' << SgWritePoint(*it)
00539 << ' ' << std::fixed << std::setprecision(3) << value;
00540 }
00541 state.Undo();
00542 }
00543 }
00544 cmd << '\n';
00545 }
00546
00547
00548 template<class PLAYER>
00549 void GoUctBookBuilderCommands<PLAYER>::CmdCounts(GtpCommand& cmd)
00550 {
00551 if (m_book.get() == 0)
00552 throw GtpFailure() << "No opened autobook!\n";
00553 cmd.CheckArgNone();
00554 GoAutoBookState state(m_bd);
00555 state.Synchronize();
00556 ShowInfluence(cmd, state);
00557 cmd << "\nLABEL ";
00558 for (GoBoard::Iterator it(m_bd); it; ++it)
00559 {
00560 if (m_bd.IsLegal(*it))
00561 {
00562 state.Play(*it);
00563 SgBookNode node;
00564 if (m_book->Get(state, node))
00565 cmd << ' ' << SgWritePoint(*it) << ' ' << node.m_count;
00566 state.Undo();
00567 }
00568 }
00569 cmd << '\n';
00570 }
00571
00572
00573 template<class PLAYER>
00574 void GoUctBookBuilderCommands<PLAYER>::CmdPriority(GtpCommand& cmd)
00575 {
00576 if (m_book.get() == 0)
00577 throw GtpFailure() << "No opened autobook!\n";
00578 cmd.CheckArgNone();
00579 GoAutoBookState state(m_bd);
00580 state.Synchronize();
00581 SgBookNode parent;
00582 if (!m_book->Get(state, parent))
00583 throw GtpFailure("Current state not in book!");
00584 ShowInfluence(cmd, state);
00585 cmd << "\nLABEL ";
00586 for (GoBoard::Iterator it(m_bd); it; ++it)
00587 {
00588 if (m_bd.IsLegal(*it))
00589 {
00590 state.Play(*it);
00591 SgBookNode child;
00592 if (m_book->Get(state, child))
00593 {
00594 float priority = m_bookBuilder.ComputePriority
00595 (parent, child.m_value, child.m_priority);
00596 cmd << ' ' << SgWritePoint(*it) << ' '
00597 << std::fixed << std::setprecision(1) << priority;
00598 }
00599 state.Undo();
00600 }
00601 }
00602 cmd << '\n';
00603 }
00604
00605
00606 template<class PLAYER>
00607 void GoUctBookBuilderCommands<PLAYER>::CmdMainLine(GtpCommand& cmd)
00608 {
00609 if (m_book.get() == 0)
00610 throw GtpFailure() << "No opened autobook!\n";
00611 cmd.CheckArgNone();
00612 GoAutoBookState state(m_bd);
00613 state.Synchronize();
00614 cmd << "VAR";
00615 SgBookNode node;
00616 while(true)
00617 {
00618 SgMove move = m_book->FindBestChild(state);
00619 if (move == SG_NULLMOVE)
00620 break;
00621 cmd << (state.Board().ToPlay() == SG_BLACK ? " B ": " W ")
00622 << SgWritePoint(move);
00623 state.Play(move);
00624 }
00625 cmd << '\n';
00626 }
00627
00628
00629
00630 #endif // GOUCT_BOOKBUILDERCOMMANDS_H