Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

DfpnCommands.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file DfpnCommands.cpp
00003  */
00004 //----------------------------------------------------------------------------
00005 
00006 #include "BitsetIterator.hpp"
00007 #include "EndgameUtils.hpp"
00008 #include "DfpnCommands.hpp"
00009 
00010 using namespace benzene;
00011 
00012 //----------------------------------------------------------------------------
00013 
00014 DfpnCommands::DfpnCommands(Game& game, HexEnvironment& env,
00015                            DfpnSolver& solver,
00016                            boost::scoped_ptr<DfpnHashTable>& tt,
00017                            boost::scoped_ptr<DfpnDB>& db,
00018                            DfpnStates& positions)
00019     : m_game(game), 
00020       m_env(env),
00021       m_solver(solver),
00022       m_tt(tt),
00023       m_db(db),
00024       m_positions(positions)
00025 {
00026 }
00027 
00028 void DfpnCommands::Register(GtpEngine& e)
00029 {
00030     Register(e, "param_dfpn", &DfpnCommands::CmdParam);
00031     Register(e, "param_dfpn_db", &DfpnCommands::CmdParamSolverDB);
00032     Register(e, "dfpn-clear-tt", &DfpnCommands::CmdClearTT);
00033     Register(e, "dfpn-get-bounds", &DfpnCommands::CmdGetBounds);
00034     Register(e, "dfpn-get-state", &DfpnCommands::CmdGetState);    
00035     Register(e, "dfpn-get-work", &DfpnCommands::CmdGetWork);
00036     Register(e, "dfpn-get-pv", &DfpnCommands::CmdGetPV);
00037     Register(e, "dfpn-solve-state", &DfpnCommands::CmdSolveState);
00038     Register(e, "dfpn-solver-find-winning", &DfpnCommands::CmdFindWinning);
00039     Register(e, "dfpn-open-db", &DfpnCommands::CmdOpenDB);
00040     Register(e, "dfpn-close-db", &DfpnCommands::CmdCloseDB);
00041     Register(e, "dfpn-db-stat", &DfpnCommands::CmdDBStat);
00042     Register(e, "dfpn-evaluation-info", &DfpnCommands::CmdEvaluationInfo);
00043 }
00044 
00045 void DfpnCommands::Register(GtpEngine& engine, const std::string& command,
00046                             GtpCallback<DfpnCommands>::Method method)
00047 {
00048     engine.Register(command, new GtpCallback<DfpnCommands>(this, method));
00049 }
00050 
00051 //----------------------------------------------------------------------------
00052 
00053 void DfpnCommands::CmdParamSolverDB(HtpCommand& cmd)
00054 {
00055     SolverDBParameters& param = m_positions.Parameters();
00056     if (cmd.NuArg() == 0)
00057     {
00058         cmd << '\n'
00059             << "[bool] use_flipped_states " << param.m_useFlippedStates << '\n'
00060             << "[bool] use_proof_transpositions " 
00061             << param.m_useProofTranspositions << '\n'
00062             << "[string] max_stones " << param.m_maxStones << '\n'
00063             << "[string] trans_stones " << param.m_transStones << '\n';
00064     }
00065     else if (cmd.NuArg() == 2)
00066     {
00067         std::string name = cmd.Arg(0);
00068         if (name == "use_flipped_states")
00069             param.m_useFlippedStates = cmd.BoolArg(1);
00070         else if (name == "use_proof_transpositions")
00071             param.m_useProofTranspositions = cmd.BoolArg(1);
00072         else if (name == "max_stones")
00073             param.m_maxStones = cmd.IntArg(1, 0);
00074         else if (name == "trans_stones")
00075             param.m_transStones = cmd.IntArg(1, 0);
00076         else
00077             throw HtpFailure() << "unknown parameter: " << name;
00078     }
00079     else 
00080         throw HtpFailure("Expected 0 or 2 arguments");
00081 }
00082 
00083 void DfpnCommands::CmdParam(HtpCommand& cmd)
00084 {
00085     if (cmd.NuArg() == 0)
00086     {
00087         cmd << '\n'
00088             << "[bool] use_guifx "
00089             << m_solver.UseGuiFx() << '\n'
00090             << "[string] timelimit "
00091             << m_solver.Timelimit() << '\n'
00092             << "[string] tt_bits "  
00093             << ((m_tt.get() == 0) ? 0 : m_tt->Bits()) << '\n'
00094             << "[string] widening_base "
00095             << m_solver.WideningBase() << '\n'
00096             << "[string] widening_factor "
00097             << m_solver.WideningFactor() << '\n';
00098     }
00099     else if (cmd.NuArg() == 2)
00100     {
00101         std::string name = cmd.Arg(0);
00102         if (name == "use_guifx")
00103             m_solver.SetUseGuiFx(cmd.BoolArg(1));
00104         else if (name == "timelimit")
00105             m_solver.SetTimelimit(cmd.FloatArg(1));
00106     else if (name == "tt_bits")
00107     {
00108         int bits = cmd.IntArg(1, 0);
00109         if (bits == 0)
00110         m_tt.reset(0);
00111         else
00112         m_tt.reset(new DfpnHashTable(bits));
00113     }
00114         else if (name == "widening_base")
00115         {
00116             int value = cmd.IntArg(1, 0);
00117             if (0 < value)
00118                 m_solver.SetWideningBase(value);
00119             else
00120                 throw GtpFailure() << "widening_base must be positive.";
00121         }
00122         else if (name == "widening_factor")
00123         {
00124             float value = cmd.FloatArg(1);
00125             if (0.0f < value && value <= 1.0f)
00126                 m_solver.SetWideningFactor(value);
00127             else
00128                 throw GtpFailure() << "widening_factor must be in (0, 1]";
00129         }
00130         else
00131             throw GtpFailure() << "Unknown parameter: " << name;
00132     }
00133     else
00134         throw GtpFailure() << "Expected 0 or 2 arguments";
00135 }
00136 
00137 /** Solves the current state with dfpn using the current hashtable. */
00138 void DfpnCommands::CmdSolveState(HtpCommand& cmd)
00139 {
00140     cmd.CheckNuArgLessEqual(3);
00141     HexColor colorToMove = m_game.Board().WhoseTurn();
00142     if (cmd.NuArg() >= 1)
00143         colorToMove = HtpUtil::ColorArg(cmd, 0);
00144     DfpnBoundType maxPhi = DfpnBounds::MAX_WORK;
00145     DfpnBoundType maxDelta = DfpnBounds::MAX_WORK;
00146     if (cmd.NuArg() >= 2)
00147         maxPhi = cmd.IntArg(1, 0);
00148     if (cmd.NuArg() >= 3)
00149         maxDelta = cmd.IntArg(2, 0);
00150     DfpnBounds maxBounds(maxPhi, maxDelta);
00151     PointSequence pv;
00152     HexBoard& brd = m_env.SyncBoard(m_game.Board());
00153     HexColor winner 
00154         = m_solver.StartSearch(HexState(m_game.Board(), colorToMove), brd, 
00155                                m_positions, pv, maxBounds);
00156     cmd << winner;
00157 }
00158 
00159 /** Finds all winning moves in the current state with dfpn,
00160     using the current hashtable. */
00161 void DfpnCommands::CmdFindWinning(HtpCommand& cmd)
00162 {
00163     cmd.CheckNuArg(1);
00164     HexColor colorToMove = HtpUtil::ColorArg(cmd, 0);
00165     HexBoard& brd = m_env.SyncBoard(m_game.Board());
00166     brd.ComputeAll(colorToMove);
00167     bitset_t consider = (EndgameUtils::IsDeterminedState(brd, colorToMove) ?
00168                          brd.GetPosition().GetEmpty() :
00169                          EndgameUtils::MovesToConsider(brd, colorToMove));
00170     bitset_t winning;
00171     SgTimer timer;
00172 
00173     HexState state(m_game.Board(), colorToMove);
00174     for (BitsetIterator p(consider); p; ++p)
00175     {
00176         state.PlayMove(*p);
00177         HexBoard& brd = m_env.SyncBoard(state.Position());
00178         LogInfo() << "****** Trying " << *p << " ******\n" << brd << '\n';
00179         PointSequence pv;
00180         HexColor winner = m_solver.StartSearch(state, brd, m_positions, pv);
00181         if (winner == colorToMove)
00182             winning.set(*p);
00183         LogInfo() << "****** " << winner << " wins ******\n";
00184         state.UndoMove(*p);
00185     }
00186     LogInfo() << "Total Elapsed Time: " << timer.GetTime() << '\n';
00187     cmd << HexPointUtil::ToString(winning);
00188 }
00189 
00190 /** Clears the current dfpn hashtable. */
00191 void DfpnCommands::CmdClearTT(HtpCommand& cmd)
00192 {
00193     UNUSED(cmd);
00194     m_tt->Clear();
00195 }
00196 
00197 /** Displays information about the current state from the
00198     hashtable. */
00199 void DfpnCommands::CmdGetState(HtpCommand& cmd)
00200 {
00201     cmd.CheckNuArg(1);
00202     HexColor colorToMove = HtpUtil::ColorArg(cmd, 0);    
00203     HexState state(m_game.Board(), colorToMove);
00204     DfpnData data;
00205     if (m_positions.Get(state, data))
00206         cmd << data << '\n';
00207 }
00208 
00209 /** Displays bounds of every empty cell in current state.
00210     Bounds are obtained from the current hashtable. */
00211 void DfpnCommands::CmdGetBounds(HtpCommand& cmd)
00212 {
00213     cmd.CheckNuArg(1);
00214     HexColor colorToMove = HtpUtil::ColorArg(cmd, 0);
00215     HexState state(m_game.Board(), colorToMove);
00216     for (BitsetIterator it(state.Position().GetEmpty()); it; ++it)
00217     {
00218         state.PlayMove(*it);
00219         DfpnData data;
00220         if (m_positions.Get(state, data))
00221         {
00222             cmd << ' ' << *it << ' ';
00223             if (data.m_bounds.IsWinning())
00224                 cmd << 'L';
00225             else if (data.m_bounds.IsLosing())
00226                 cmd << 'W';
00227             else 
00228                 cmd << data.m_bounds.phi << ':' << data.m_bounds.delta;
00229         }
00230         state.UndoMove(*it);
00231     }
00232 }
00233 
00234 /** Displays work of every empty cell in current state.
00235     Bounds are obtained from the current hashtable. */
00236 void DfpnCommands::CmdGetWork(HtpCommand& cmd)
00237 {
00238     cmd.CheckNuArg(1);
00239     HexColor colorToMove = HtpUtil::ColorArg(cmd, 0);
00240     HexState state(m_game.Board(), colorToMove);
00241     for (BitsetIterator it(state.Position().GetEmpty()); it; ++it)
00242     {
00243         state.PlayMove(*it);
00244         DfpnData data;
00245         if (m_positions.Get(state, data))
00246             cmd << ' ' << *it << ' ' << data.m_work;
00247         state.UndoMove(*it);
00248     }
00249 }
00250 
00251 /** Displays PV from current position. */
00252 void DfpnCommands::CmdGetPV(HtpCommand& cmd)
00253 {
00254     cmd.CheckNuArg(1);
00255     HexColor colorToMove = HtpUtil::ColorArg(cmd, 0);
00256     PointSequence pv;
00257     SolverDBUtil::GetVariation(HexState(m_game.Board(), colorToMove), 
00258                                m_positions, pv);
00259     cmd << HexPointUtil::ToString(pv);
00260 }
00261 
00262 /** Opens a database. 
00263     Usage: "db-open [filename]"
00264 */
00265 void DfpnCommands::CmdOpenDB(HtpCommand& cmd)
00266 {
00267     cmd.CheckNuArgLessEqual(3);
00268     std::string filename = cmd.Arg(0);
00269     try {
00270         m_db.reset(new DfpnDB(filename));
00271     }
00272     catch (BenzeneException& e) {
00273         m_db.reset(0);
00274         throw HtpFailure() << "Error opening db: '" << e.what() << "'\n";
00275     }
00276 }
00277 
00278 /** Closes an open database. */
00279 void DfpnCommands::CmdCloseDB(HtpCommand& cmd)
00280 {
00281     cmd.CheckNuArg(0);
00282     if (m_db.get() == 0)
00283         throw HtpFailure("No open database!\n");
00284     m_db.reset(0);
00285 }
00286 
00287 /** Prints database statistics. */
00288 void DfpnCommands::CmdDBStat(HtpCommand& cmd)
00289 {
00290     cmd.CheckNuArg(0);
00291     if (m_db.get() == 0)
00292         throw HtpFailure("No open database!\n");
00293     cmd << m_db->BDBStatistics();
00294 }
00295 
00296 void DfpnCommands::CmdEvaluationInfo(HtpCommand& cmd)
00297 {
00298     cmd.CheckNuArg(0);
00299     cmd << m_solver.EvaluationInfo();
00300 }
00301 
00302 //----------------------------------------------------------------------------


6 Jan 2011 Doxygen 1.6.3