Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

DfsSolver.hpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file DfsSolver.hpp
00003  */
00004 //----------------------------------------------------------------------------
00005 
00006 #ifndef DFSSOLVER_H
00007 #define DFSSOLVER_H
00008 
00009 #include <boost/scoped_ptr.hpp>
00010 
00011 #include "Hex.hpp"
00012 #include "HexBoard.hpp"
00013 #include "VC.hpp"
00014 #include "TransTable.hpp"
00015 #include "DfsData.hpp"
00016 #include "SolverDB.hpp"
00017 #include "StateDB.hpp"
00018 #include "HexEval.hpp"
00019 
00020 _BEGIN_BENZENE_NAMESPACE_
00021 
00022 //----------------------------------------------------------------------------
00023 
00024 /** Transposition table for use in DfsSolver. */
00025 typedef TransTable<DfsData> DfsHashTable;
00026 
00027 /** Database for use in DfsSolver. */
00028 class DfsDB : public StateDB<DfsData>
00029 {
00030 public:
00031     static const std::string DFS_DB_VERSION;
00032 
00033     DfsDB(const std::string& filename)
00034         : StateDB<DfsData>(filename, DFS_DB_VERSION)
00035     { }
00036 };
00037 
00038 /** Solver database combining both of the above. */
00039 typedef SolverDB<DfsHashTable, DfsDB, DfsData> DfsStates;
00040 
00041 //----------------------------------------------------------------------------
00042 
00043 /** Stats for a branch of the search tree. */
00044 struct DfsBranchStatistics
00045 {
00046     /** Total states in tree if no DB and no TT. */
00047     unsigned total_states;
00048 
00049     /** States actually visited; includes leafs, tt and db hits. */
00050     unsigned explored_states;
00051 
00052     /** Expanded nodes; non leaf, non tt and db hit states. */
00053     unsigned expanded_states;
00054 
00055     /** Number of expanded nodes assuming perfect move ordering 
00056         (assuming the same set of winning moves). */
00057     unsigned minimal_explored;
00058         
00059     /** Decompositions found; if black is to move, it must be a
00060         decomposition for white. */
00061     unsigned decompositions;
00062 
00063     /** Decompositions where the player to move won. */
00064     unsigned decompositions_won;
00065     
00066     /** Total number of moves to consider in expanded states. 
00067         Includes moves that are later pruned (by mustplay or
00068         from skipping due to finding a win). */
00069     unsigned moves_to_consider;
00070     
00071     /** Number of expanded states that had winning moves. */
00072     unsigned winning_expanded;
00073     
00074     /** Number of branches tried before win was found. */
00075     unsigned branches_to_win;
00076 
00077     /** States pruned by mustplay pruning. */
00078     unsigned pruned;
00079     
00080     /** Number of proofs that were successfully shrunk. */
00081     unsigned shrunk;
00082     
00083     /** Total number of cells removed in all successful proof
00084         shrinkings. */
00085     unsigned cells_removed;
00086     
00087     DfsBranchStatistics();
00088 
00089     void operator+=(const DfsBranchStatistics& o);
00090 };
00091 
00092 inline DfsBranchStatistics::DfsBranchStatistics()
00093     : total_states(0), 
00094       explored_states(0), 
00095       expanded_states(0), 
00096       minimal_explored(0), 
00097       decompositions(0), 
00098       decompositions_won(0), 
00099       moves_to_consider(0), 
00100       winning_expanded(0), 
00101       branches_to_win(0),
00102       pruned(0), 
00103       shrunk(0), 
00104       cells_removed(0)
00105 {
00106 }
00107 
00108 inline void DfsBranchStatistics::operator+=(const DfsBranchStatistics& o)
00109 {
00110     total_states += o.total_states;
00111     explored_states += o.explored_states;
00112     expanded_states += o.expanded_states;
00113     minimal_explored += o.minimal_explored;
00114     decompositions += o.decompositions;
00115     decompositions_won += o.decompositions_won;
00116     moves_to_consider += o.moves_to_consider;
00117     winning_expanded += o.winning_expanded;
00118     branches_to_win += o.branches_to_win;
00119     pruned += o.pruned;
00120     shrunk += o.shrunk;
00121     cells_removed += o.cells_removed;
00122 }
00123 
00124 //----------------------------------------------------------------------------
00125 
00126 /** Stats for the entire search tree broken down by level. */
00127 struct DfsHistogram
00128 {
00129     /** Map of # of stones to a counter. */
00130     typedef std::map<int, std::size_t> StatsMap;
00131 
00132     /** Terminal states encountered at each depth. */
00133     StatsMap terminal;
00134         
00135     /** Internal states encountered at each depth. */
00136     StatsMap states;
00137     
00138     /** Winning states encountered at each depth. */
00139     StatsMap winning;
00140     
00141     StatsMap size_of_winning_states;
00142     
00143     StatsMap size_of_losing_states;
00144     
00145     /** Branches taken to find winning move at each depth. */
00146     StatsMap branches;
00147     
00148     /** Size of original mustplay in winning states. */
00149     StatsMap mustplay;
00150     
00151     /** States under losing moves before winning move. */
00152     StatsMap states_under_losing;
00153     
00154     /** DB/TT hits at each depth. */
00155     StatsMap tthits;
00156     
00157     /** Writes histogram in human-readable format to a string. */
00158     std::string Write();
00159 };
00160 
00161 //----------------------------------------------------------------------------
00162 
00163 /** Contains all relevant data for a solution to a state. */
00164 struct DfsSolutionSet
00165 {
00166     bitset_t proof;
00167     
00168     int m_numMoves;
00169     
00170     PointSequence pv;
00171     
00172     DfsBranchStatistics stats;
00173     
00174     DfsSolutionSet();
00175 
00176     void SetPV(HexPoint cell);
00177 
00178     void SetPV(HexPoint cell, const PointSequence& pv);
00179 };
00180 
00181 inline DfsSolutionSet::DfsSolutionSet()
00182     : m_numMoves(0)
00183 {
00184 }
00185 
00186 inline void DfsSolutionSet::SetPV(HexPoint cell)
00187 {
00188     pv.clear();
00189     pv.push_back(cell);
00190 }
00191 
00192 inline void DfsSolutionSet::SetPV(HexPoint cell, const PointSequence& old)
00193 {
00194     pv.clear();
00195     pv.push_back(cell);
00196     pv.insert(pv.end(), old.begin(), old.end());
00197 }
00198 
00199 //----------------------------------------------------------------------------
00200 
00201 namespace DfsMoveOrderFlags
00202 {
00203     /** Each move is played and the size of the resulting mustplay is
00204         stored. Moves are ordered in increasing order of mustplay.
00205         This is a very expensive move ordering, since the vcs
00206         and inferior cells must be updated for every possible move in
00207         every possible state.  However, the move ordering is usually
00208         very good. */
00209     static const int WITH_MUSTPLAY = 1;    
00210 
00211     /** Resistance score is used to break ties instead of distance
00212         from the center of the board. */
00213     static const int WITH_RESIST = 2;
00214 
00215     /** Moves near center of board get higher priority than moves near
00216         the edge of the board. */
00217     static const int FROM_CENTER = 4;
00218 }
00219 
00220 //----------------------------------------------------------------------------
00221 
00222 /** Determines the winner of a gamestate.
00223     DfsSolver uses a mustplay driven depth-first search to determine the
00224     winner in the given state.
00225 */
00226 class DfsSolver 
00227 {
00228 public:
00229     DfsSolver();
00230 
00231     ~DfsSolver();
00232 
00233     //------------------------------------------------------------------------
00234 
00235     /** Solves state using the given previously solved positions.
00236         Returns color of winner or EMPTY if aborted before state was
00237         solved.
00238     */
00239     HexColor Solve(const HexState& state, HexBoard& board, 
00240                    DfsSolutionSet& solution,
00241                    DfsStates& positions, int depthLimit = -1, 
00242                    double timeLimit = -1.0);
00243 
00244     //------------------------------------------------------------------------
00245 
00246     /** @name Parameters */
00247     // @{
00248 
00249     /** Controls whether gamestates decomposible into separate
00250         components have each side solved separately and the proofs
00251         combined as necessary. */
00252     bool UseDecompositions() const;
00253 
00254     /** See UseDecompositions() */
00255     void SetUseDecompositions(bool enable);
00256 
00257     /** Depth from root in which the current variation is printed. */
00258     int ProgressDepth() const;
00259 
00260     /** See ProgressDepth() */
00261     void SetProgressDepth(int depth);
00262 
00263     /** Depth at which the current state is dumped to the log. */
00264     int UpdateDepth() const;
00265 
00266     /** See UpdateDepth() */
00267     void SetUpdateDepth(int depth);
00268 
00269     /** Whether ICE is used to provably shrink proofs. */
00270     bool ShrinkProofs() const;
00271 
00272     /** See ShrinkProofs() */
00273     void SetShrinkProofs(bool enable);
00274 
00275     /** Use newly acquired ICE-info after the move ordering stage to
00276         prune the moves to consider. */
00277     bool BackupIceInfo() const;
00278 
00279     /** See BackupIceInfo() */
00280     void SetBackupIceInfo(bool enable);
00281 
00282     bool UseGuiFx() const;
00283 
00284     /** See UseGuiFx() */
00285     void SetUseGuiFx(bool enable);
00286 
00287     /** Returns the move order flags. */
00288     int MoveOrdering() const;
00289 
00290     /** See MoveOrdering() */
00291     void SetMoveOrdering(int flags);
00292 
00293     // @}
00294 
00295     //------------------------------------------------------------------------
00296 
00297     /** Dumps the stats on # of states, branching factors, etc, for
00298         the last run. */
00299     void DumpStats(const DfsSolutionSet& solution) const;
00300 
00301     /** Returns histogram of last search. */
00302     DfsHistogram Histogram() const;
00303 
00304 private:
00305 
00306     //------------------------------------------------------------------------
00307     
00308     /** Globabl statistics for the current solver run. */
00309     struct GlobalStatistics
00310     {
00311         /** Times HexBoard::PlayMove() was called. */
00312         unsigned played;
00313 
00314         GlobalStatistics()
00315             : played(0)
00316         { }
00317     };
00318 
00319     //------------------------------------------------------------------------
00320 
00321     DfsStates* m_positions;
00322 
00323     HexBoard* m_workBrd;
00324 
00325     double m_start_time;
00326         
00327     double m_end_time;
00328 
00329     std::vector<std::pair<int, int> > m_completed;
00330 
00331     bool m_aborted;
00332 
00333     mutable DfsHistogram m_histogram;
00334 
00335     mutable GlobalStatistics m_statistics;
00336     
00337     boost::scoped_ptr<HexState> m_state;
00338 
00339     /** See UseDecompositions() */
00340     bool m_use_decompositions;
00341 
00342     /** See UpdateDepth() */
00343     int m_update_depth;
00344 
00345     /** See ShrinkProofs() */
00346     bool m_shrink_proofs;
00347 
00348     /** See BackupIceInfo() */
00349     bool m_backup_ice_info;
00350 
00351     /** See UseGuiFx() */
00352     bool m_use_guifx;
00353 
00354     /** See MoveOrdering() */
00355     int m_move_ordering;
00356 
00357     unsigned m_last_histogram_dump;
00358 
00359     int m_depthLimit;
00360     
00361     double m_timeLimit;
00362 
00363     //------------------------------------------------------------------------
00364 
00365     void PlayMove(HexPoint cell);
00366     
00367     void UndoMove(HexPoint cell);
00368 
00369     bool CheckTransposition(DfsData& state) const;
00370 
00371     void StoreState(const DfsData& state, const bitset_t& proof);
00372 
00373     bool CheckAbort();
00374     
00375     bool HandleLeafNode(DfsData& state, bitset_t& proof) const;
00376 
00377     bool HandleTerminalNode(DfsData& state, bitset_t& proof) const;
00378 
00379     bool OrderMoves(bitset_t& mustplay, DfsSolutionSet& solution, 
00380                     std::vector<HexMoveValue>& moves);
00381 
00382     bool SolveState(PointSequence& variation, DfsSolutionSet& solution);
00383 
00384     bool SolveDecomposition(PointSequence& variation,
00385                             DfsSolutionSet& solution, HexPoint group);
00386 
00387     bool SolveInteriorState(PointSequence& variation, 
00388                             DfsSolutionSet& solution);
00389 
00390     void HandleProof(const PointSequence& variation,
00391                      bool winning_state, DfsSolutionSet& solution);
00392 };
00393 
00394 //----------------------------------------------------------------------------
00395 
00396 inline bool DfsSolver::UseDecompositions() const
00397 {
00398     return m_use_decompositions;
00399 }
00400 
00401 inline void DfsSolver::SetUseDecompositions(bool enable)
00402 {
00403     m_use_decompositions = enable;
00404 }
00405 
00406 inline int DfsSolver::UpdateDepth() const
00407 {
00408     return m_update_depth;
00409 }
00410 
00411 inline void DfsSolver::SetUpdateDepth(int depth)
00412 {
00413     m_update_depth = depth;
00414 }
00415 
00416 inline bool DfsSolver::ShrinkProofs() const
00417 {
00418     return m_shrink_proofs;
00419 }
00420 
00421 inline void DfsSolver::SetShrinkProofs(bool enable)
00422 {
00423     m_shrink_proofs = enable;
00424 }
00425 
00426 inline bool DfsSolver::BackupIceInfo() const
00427 {
00428     return m_backup_ice_info;
00429 }
00430 
00431 inline void DfsSolver::SetBackupIceInfo(bool enable)
00432 {
00433     m_backup_ice_info = enable;
00434 }
00435 
00436 inline bool DfsSolver::UseGuiFx() const
00437 {
00438     return m_use_guifx;
00439 }
00440 
00441 inline void DfsSolver::SetUseGuiFx(bool enable)
00442 {
00443     m_use_guifx = enable;
00444 }
00445 
00446 inline int DfsSolver::MoveOrdering() const
00447 {
00448     return m_move_ordering;
00449 }
00450 
00451 inline void DfsSolver::SetMoveOrdering(int flags)
00452 {
00453     m_move_ordering = flags;
00454 }
00455 
00456 inline DfsHistogram DfsSolver::Histogram() const
00457 {
00458     return m_histogram;
00459 }
00460 
00461 //----------------------------------------------------------------------------
00462 
00463 /** Methods in DfsSolver that do not need DfsSolver's private data. */
00464 namespace DfsSolverUtil 
00465 {
00466     /** Computes distance from the center of the board. */
00467     int DistanceFromCenter(const ConstBoard& brd, HexPoint p);
00468 }
00469 
00470 //----------------------------------------------------------------------------
00471 
00472 _END_BENZENE_NAMESPACE_
00473 
00474 #endif // DFSSOLVER_H


6 Jan 2011 Doxygen 1.6.3