Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

DfsCommands.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file DfsCommands.cpp
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' // FIXME: PRINT NICELY!!
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 /** Solves the given state.
00133     Usage: "solve-state [color to play]
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 /** Clears the current TT. */
00154 void DfsCommands::CmdSolverClearTT(HtpCommand& cmd)
00155 {
00156     UNUSED(cmd);
00157     m_tt->Clear();
00158 }
00159 
00160 /** Finds all winning moves in this state by calling 'solve-state'
00161     on each child move. 
00162     Usage: same as 'solve-state'.
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 /** Opens a database. 
00210     Usage: "db-open [filename]"
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 /** Closes an open database. */
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 /** Dumps info from on current state. */
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 /** Prints database statistics. */
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 /** Prints histogram of last search. */
00298 void DfsCommands::CmdHistogram(HtpCommand& cmd)
00299 {
00300     cmd.CheckNuArg(0);
00301     cmd << m_solver.Histogram().Write();
00302 }
00303 
00304 /** Prints PV from the current state from the last search. */
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 //----------------------------------------------------------------------------


6 Jan 2011 Doxygen 1.6.3