00001 //---------------------------------------------------------------------------- 00002 /** @file SolverDB.hpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef SolverDB_HPP 00007 #define SolverDB_HPP 00008 00009 #include "Hex.hpp" 00010 #include "BenzeneSolver.hpp" 00011 #include "HexState.hpp" 00012 #include <boost/concept_check.hpp> 00013 00014 _BEGIN_BENZENE_NAMESPACE_ 00015 00016 //---------------------------------------------------------------------------- 00017 00018 struct SolverDBParameters 00019 { 00020 /** States with fewer stones go into the database, otherwise the 00021 hashtable.*/ 00022 std::size_t m_maxStones; 00023 00024 /** States with fewer stones get transpositions/flipped states. */ 00025 std::size_t m_transStones; 00026 00027 bool m_useProofTranspositions; 00028 00029 bool m_useFlippedStates; 00030 00031 SolverDBParameters(); 00032 }; 00033 00034 inline SolverDBParameters::SolverDBParameters() 00035 : m_maxStones(10), 00036 m_transStones(0), 00037 m_useProofTranspositions(false), 00038 m_useFlippedStates(false) 00039 { 00040 } 00041 00042 //---------------------------------------------------------------------------- 00043 00044 /** Combines a hash table and a position database. */ 00045 template<class HASH, class DB, class DATA> 00046 class SolverDB 00047 { 00048 public: 00049 SolverDB(boost::scoped_ptr<HASH>& hashTable, 00050 boost::scoped_ptr<DB>& database, 00051 const SolverDBParameters& param); 00052 00053 ~SolverDB(); 00054 00055 bool Get(const HexState& state, DATA& data); 00056 00057 void Put(const HexState& state, const DATA& data); 00058 00059 HASH* HashTable(); 00060 00061 DB* Database(); 00062 00063 const SolverDBParameters& Parameters() const; 00064 00065 SolverDBParameters& Parameters(); 00066 00067 void SetParameters(const SolverDBParameters& param); 00068 00069 private: 00070 boost::scoped_ptr<HASH>& m_hashTable; 00071 00072 boost::scoped_ptr<DB>& m_database; 00073 00074 SolverDBParameters m_param; 00075 00076 bool UseDatabase() const; 00077 00078 bool UseHashTable() const; 00079 00080 }; 00081 00082 //---------------------------------------------------------------------------- 00083 00084 template<class HASH, class DB, class DATA> 00085 SolverDB<HASH, DB, DATA>::SolverDB(boost::scoped_ptr<HASH>& hashTable, 00086 boost::scoped_ptr<DB>& database, 00087 const SolverDBParameters& param) 00088 : m_hashTable(hashTable), 00089 m_database(database), 00090 m_param(param) 00091 { 00092 } 00093 00094 template<class HASH, class DB, class DATA> 00095 SolverDB<HASH, DB, DATA>::~SolverDB() 00096 { 00097 00098 } 00099 00100 template<class HASH, class DB, class DATA> 00101 HASH* SolverDB<HASH, DB, DATA>::HashTable() 00102 { 00103 return m_hashTable.get(); 00104 } 00105 00106 template<class HASH, class DB, class DATA> 00107 DB* SolverDB<HASH, DB, DATA>::Database() 00108 { 00109 return m_database.get(); 00110 } 00111 00112 template<class HASH, class DB, class DATA> 00113 const SolverDBParameters& SolverDB<HASH, DB, DATA>::Parameters() const 00114 { 00115 return m_param; 00116 } 00117 00118 template<class HASH, class DB, class DATA> 00119 SolverDBParameters& SolverDB<HASH, DB, DATA>::Parameters() 00120 { 00121 return m_param; 00122 } 00123 00124 template<class HASH, class DB, class DATA> 00125 void SolverDB<HASH, DB, DATA>::SetParameters(const SolverDBParameters& p) 00126 { 00127 return m_param = p; 00128 } 00129 00130 template<class HASH, class DB, class DATA> 00131 bool SolverDB<HASH, DB, DATA>::UseDatabase() const 00132 { 00133 return m_database.get() != 0; 00134 } 00135 00136 template<class HASH, class DB, class DATA> 00137 bool SolverDB<HASH, DB, DATA>::UseHashTable() const 00138 { 00139 return m_hashTable.get() != 0; 00140 } 00141 00142 template<class HASH, class DB, class DATA> 00143 bool SolverDB<HASH, DB, DATA>::Get(const HexState& state, DATA& data) 00144 { 00145 if (UseDatabase() && state.Position().NumStones() <= m_param.m_maxStones) 00146 return m_database->Get(state, data); 00147 if (UseHashTable()) 00148 return m_hashTable->Get(state.Hash(), data); 00149 return false; 00150 } 00151 00152 template<class HASH, class DB, class DATA> 00153 void SolverDB<HASH, DB, DATA>::Put(const HexState& state, const DATA& data) 00154 { 00155 if (UseDatabase() && state.Position().NumStones() <= m_param.m_maxStones) 00156 m_database->Put(state, data); 00157 else if (UseHashTable()) 00158 m_hashTable->Put(state.Hash(), data); 00159 } 00160 00161 //---------------------------------------------------------------------------- 00162 00163 namespace SolverDBUtil 00164 { 00165 /** Follows best move in DATA to create a variation. Variation ends 00166 when it hits a best move of INVALID_POINT or the move is not 00167 found in the database. */ 00168 template<class HASH, class DB, class DATA> 00169 void GetVariation(const HexState& state, 00170 SolverDB<HASH, DB, DATA>& positions, PointSequence& pv); 00171 00172 } 00173 00174 template<class HASH, class DB, class DATA> 00175 void SolverDBUtil::GetVariation(const HexState& origState, 00176 SolverDB<HASH, DB, DATA>& positions, 00177 PointSequence& pv) 00178 { 00179 boost::function_requires< HasBestMoveConcept<DATA> >(); 00180 HexState state(origState); 00181 while (true) 00182 { 00183 DATA data; 00184 if (!positions.Get(state, data)) 00185 break; 00186 if (data.m_bestMove == INVALID_POINT) 00187 break; 00188 pv.push_back(data.m_bestMove); 00189 state.PlayMove(data.m_bestMove); 00190 } 00191 } 00192 00193 //---------------------------------------------------------------------------- 00194 00195 _END_BENZENE_NAMESPACE_ 00196 00197 #endif // SOLVERDB_HPP