00001
00002
00003
00004
00005
00006 #include "SgSystem.h"
00007 #include "SgTimer.h"
00008 #include "BitsetIterator.hpp"
00009 #include "EndgameUtils.hpp"
00010 #include "DfsCommands.hpp"
00011
00012 using namespace benzene;
00013
00014
00015
00016 DfsCommands::DfsCommands(Game& game, HexEnvironment& env,
00017 DfsSolver& solver,
00018 boost::scoped_ptr<DfsHashTable>& hashTable,
00019 boost::scoped_ptr<DfsDB>& db,
00020 DfsStates& positions)
00021 : m_game(game),
00022 m_env(env),
00023 m_solver(solver),
00024 m_tt(hashTable),
00025 m_db(db),
00026 m_positions(positions)
00027 {
00028 }
00029
00030 void DfsCommands::Register(GtpEngine& e)
00031 {
00032 Register(e, "param_dfs", &DfsCommands::CmdParamSolver);
00033 Register(e, "param_dfs_db", &DfsCommands::CmdParamSolverDB);
00034 Register(e, "dfs-solve-state", &DfsCommands::CmdSolveState);
00035 Register(e, "dfs-clear-tt", &DfsCommands::CmdSolverClearTT);
00036 Register(e, "dfs-solver-find-winning",
00037 &DfsCommands::CmdSolverFindWinning);
00038 Register(e, "dfs-get-state", &DfsCommands::CmdGetState);
00039 Register(e, "dfs-get-histogram", &DfsCommands::CmdHistogram);
00040 Register(e, "dfs-get-pv", &DfsCommands::CmdGetPV);
00041 Register(e, "dfs-open-db", &DfsCommands::CmdDBOpen);
00042 Register(e, "dfs-close-db", &DfsCommands::CmdDBClose);
00043 Register(e, "dfs-db-stat", &DfsCommands::CmdDBStat);
00044 }
00045
00046 void DfsCommands::Register(GtpEngine& engine, const std::string& command,
00047 GtpCallback<DfsCommands>::Method method)
00048 {
00049 engine.Register(command, new GtpCallback<DfsCommands>(this, method));
00050 }
00051
00052
00053
00054 void DfsCommands::CmdParamSolverDB(HtpCommand& cmd)
00055 {
00056 SolverDBParameters& param = m_positions.Parameters();
00057 if (cmd.NuArg() == 0)
00058 {
00059 cmd << '\n'
00060 << "[bool] use_flipped_states " << param.m_useFlippedStates << '\n'
00061 << "[bool] use_proof_transpositions "
00062 << param.m_useProofTranspositions << '\n'
00063 << "[string] max_stones " << param.m_maxStones << '\n'
00064 << "[string] trans_stones " << param.m_transStones << '\n';
00065 }
00066 else if (cmd.NuArg() == 2)
00067 {
00068 std::string name = cmd.Arg(0);
00069 if (name == "use_flipped_states")
00070 param.m_useFlippedStates = cmd.BoolArg(1);
00071 else if (name == "use_proof_transpositions")
00072 param.m_useProofTranspositions = cmd.BoolArg(1);
00073 else if (name == "max_stones")
00074 param.m_maxStones = cmd.IntArg(1, 0);
00075 else if (name == "trans_stones")
00076 param.m_transStones = cmd.IntArg(1, 0);
00077 else
00078 throw HtpFailure() << "unknown parameter: " << name;
00079 }
00080 else
00081 throw HtpFailure("Expected 0 or 2 arguments");
00082 }
00083
00084 void DfsCommands::CmdParamSolver(HtpCommand& cmd)
00085 {
00086 if (cmd.NuArg() == 0)
00087 {
00088 cmd << '\n'
00089 << "[bool] backup_ice_info "
00090 << m_solver.BackupIceInfo() << '\n'
00091 << "[bool] shrink_proofs "
00092 << m_solver.ShrinkProofs() << '\n'
00093 << "[bool] use_decompositions "
00094 << m_solver.UseDecompositions() << '\n'
00095 << "[bool] use_guifx "
00096 << m_solver.UseGuiFx() << '\n'
00097 << "[string] move_ordering "
00098 << m_solver.MoveOrdering() << '\n'
00099 << "[string] tt_bits "
00100 << ((m_tt.get() == 0) ? 0 : m_tt->Bits()) << '\n'
00101 << "[string] update_depth "
00102 << m_solver.UpdateDepth() << '\n';
00103 }
00104 else if (cmd.NuArg() == 2)
00105 {
00106 std::string name = cmd.Arg(0);
00107 if (name == "backup_ice_info")
00108 m_solver.SetBackupIceInfo(cmd.BoolArg(1));
00109 else if (name == "shrink_proofs")
00110 m_solver.SetShrinkProofs(cmd.BoolArg(1));
00111 else if (name == "use_decompositions")
00112 m_solver.SetUseDecompositions(cmd.BoolArg(1));
00113 else if (name == "use_guifx")
00114 m_solver.SetUseGuiFx(cmd.BoolArg(1));
00115 else if (name == "move_ordering")
00116 m_solver.SetMoveOrdering(cmd.IntArg(1,0,7));
00117 else if (name == "tt_bits")
00118 {
00119 int bits = cmd.IntArg(1, 0);
00120 if (bits == 0)
00121 m_tt.reset(0);
00122 else
00123 m_tt.reset(new DfsHashTable(bits));
00124 }
00125 else if (name == "update_depth")
00126 m_solver.SetUpdateDepth(cmd.IntArg(1, 0));
00127 else
00128 throw HtpFailure() << "unknown parameter: " << name;
00129 }
00130 }
00131
00132
00133
00134
00135 void DfsCommands::CmdSolveState(HtpCommand& cmd)
00136 {
00137 cmd.CheckNuArg(1);
00138 HexColor color = HtpUtil::ColorArg(cmd, 0);
00139 HexBoard& brd = m_env.SyncBoard(m_game.Board());
00140 if (brd.ICE().FindPermanentlyInferior())
00141 throw HtpFailure("Permanently inferior not supported in DfsSolver.");
00142 HexState state(m_game.Board(), color);
00143 DfsSolutionSet solution;
00144 HexColor winner = m_solver.Solve(state, brd, solution, m_positions);
00145 m_solver.DumpStats(solution);
00146 if (winner != EMPTY)
00147 LogInfo() << winner << " wins!\n" << brd.Write(solution.proof) << '\n';
00148 else
00149 LogInfo() << "Search aborted!\n";
00150 cmd << winner;
00151 }
00152
00153
00154 void DfsCommands::CmdSolverClearTT(HtpCommand& cmd)
00155 {
00156 UNUSED(cmd);
00157 m_tt->Clear();
00158 }
00159
00160
00161
00162
00163
00164 void DfsCommands::CmdSolverFindWinning(HtpCommand& cmd)
00165 {
00166 cmd.CheckNuArg(1);
00167 HexColor color = HtpUtil::ColorArg(cmd, 0);
00168 HexBoard& brd = m_env.SyncBoard(m_game.Board());
00169 if (brd.ICE().FindPermanentlyInferior())
00170 throw HtpFailure("Permanently inferior not supported in DfsSolver");
00171 brd.ComputeAll(color);
00172 bitset_t consider = (EndgameUtils::IsDeterminedState(brd, color) ?
00173 brd.GetPosition().GetEmpty() :
00174 EndgameUtils::MovesToConsider(brd, color));
00175 bitset_t winning;
00176 SgTimer timer;
00177 HexState state(m_game.Board(), color);
00178 for (BitsetIterator p(consider); p; ++p)
00179 {
00180 if (!consider.test(*p))
00181 continue;
00182 state.PlayMove(*p);
00183 HexBoard& brd = m_env.SyncBoard(state.Position());
00184 LogInfo() << "****** Trying " << *p << " ******\n" << brd << '\n';
00185 DfsSolutionSet solution;
00186 HexColor winner = m_solver.Solve(state, brd, solution, m_positions);
00187 m_solver.DumpStats(solution);
00188 LogInfo() << "Proof:" << brd.Write(solution.proof) << '\n';
00189 state.UndoMove(*p);
00190
00191 if (winner != EMPTY)
00192 LogInfo() << "****** " << winner << " wins ******\n";
00193 else
00194 LogInfo() << "****** unknown ******\n";
00195
00196 if (winner == color)
00197 winning.set(*p);
00198 else
00199 consider &= solution.proof;
00200 }
00201 LogInfo() << "****** Winning Moves ******\n"
00202 << m_game.Board().Write(winning) << '\n';
00203 LogInfo() << "Total Elapsed Time: " << timer.GetTime() << '\n';
00204 cmd << HexPointUtil::ToString(winning);
00205 }
00206
00207
00208
00209
00210
00211
00212 void DfsCommands::CmdDBOpen(HtpCommand& cmd)
00213 {
00214 cmd.CheckNuArgLessEqual(3);
00215 std::string filename = cmd.Arg(0);
00216 try {
00217 m_db.reset(new DfsDB(filename));
00218 }
00219 catch (BenzeneException& e) {
00220 m_db.reset(0);
00221 throw HtpFailure() << "Error opening db: '" << e.what() << "'\n";
00222 }
00223 }
00224
00225
00226 void DfsCommands::CmdDBClose(HtpCommand& cmd)
00227 {
00228 cmd.CheckNuArg(0);
00229 if (m_db.get() == 0)
00230 throw HtpFailure("No open database!\n");
00231 m_db.reset(0);
00232 }
00233
00234
00235 void DfsCommands::CmdGetState(HtpCommand& cmd)
00236 {
00237 cmd.CheckNuArg(0);
00238 HexColor toPlay = m_game.Board().WhoseTurn();
00239 HexState state(m_game.Board(), toPlay);
00240 DfsData data;
00241 if (!m_positions.Get(state, data))
00242 {
00243 cmd << "State not available.";
00244 return;
00245 }
00246 cmd << (data.m_win ? toPlay : !toPlay);
00247 cmd << ' ' << data.m_numMoves;
00248
00249 std::vector<int> nummoves(BITSETSIZE);
00250 std::vector<int> flags(BITSETSIZE);
00251 std::vector<HexPoint> winning, losing;
00252 for (BitsetIterator p(state.Position().GetEmpty()); p; ++p)
00253 {
00254 state.PlayMove(*p);
00255 if (m_positions.Get(state, data))
00256 {
00257 if (data.m_win)
00258 losing.push_back(*p);
00259 else
00260 winning.push_back(*p);
00261 nummoves[*p] = data.m_numMoves;
00262 flags[*p] = data.m_flags;
00263 }
00264 state.UndoMove(*p);
00265 }
00266 cmd << " Winning";
00267 for (unsigned i = 0; i < winning.size(); ++i)
00268 {
00269 cmd << " " << winning[i];
00270 cmd << " " << nummoves[winning[i]];
00271 if (flags[winning[i]] & SolverDataFlags::MIRROR_TRANSPOSITION)
00272 cmd << "m";
00273 else if (flags[winning[i]] & SolverDataFlags::TRANSPOSITION)
00274 cmd << "t";
00275 }
00276 cmd << " Losing";
00277 for (unsigned i = 0; i < losing.size(); ++i)
00278 {
00279 cmd << " " << losing[i];
00280 cmd << " " << nummoves[losing[i]];
00281 if (flags[losing[i]] & SolverDataFlags::MIRROR_TRANSPOSITION)
00282 cmd << "m";
00283 else if (flags[losing[i]] & SolverDataFlags::TRANSPOSITION)
00284 cmd << "t";
00285 }
00286 }
00287
00288
00289 void DfsCommands::CmdDBStat(HtpCommand& cmd)
00290 {
00291 cmd.CheckNuArg(0);
00292 if (m_db.get() == 0)
00293 throw HtpFailure("No open database!\n");
00294 cmd << m_db->BDBStatistics();
00295 }
00296
00297
00298 void DfsCommands::CmdHistogram(HtpCommand& cmd)
00299 {
00300 cmd.CheckNuArg(0);
00301 cmd << m_solver.Histogram().Write();
00302 }
00303
00304
00305 void DfsCommands::CmdGetPV(HtpCommand& cmd)
00306 {
00307 cmd.CheckNuArg(1);
00308 HexColor colorToMove = HtpUtil::ColorArg(cmd, 0);
00309 PointSequence pv;
00310 SolverDBUtil::GetVariation(HexState(m_game.Board(), colorToMove),
00311 m_positions, pv);
00312 cmd << HexPointUtil::ToString(pv);
00313 }
00314
00315