00001 //---------------------------------------------------------------------------- 00002 /** @file StateDB.hpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef POSITIONDB_HPP 00007 #define POSITIONDB_HPP 00008 00009 #include <boost/concept_check.hpp> 00010 #include "HashDB.hpp" 00011 #include "HexState.hpp" 00012 00013 _BEGIN_BENZENE_NAMESPACE_ 00014 00015 //---------------------------------------------------------------------------- 00016 00017 namespace { 00018 00019 hash_t GetHash(const HexState& state) 00020 { 00021 hash_t hash1 = state.Hash(); 00022 HexState rotatedState(state); 00023 rotatedState.Position().RotateBoard(); 00024 hash_t hash2 = rotatedState.Hash(); 00025 return std::min(hash1, hash2); 00026 } 00027 00028 /** Data must be stored for the state of the minimum hash. */ 00029 inline bool NeedToRotate(const HexState& state, hash_t minHash) 00030 { 00031 return state.Hash() != minHash; 00032 } 00033 00034 } 00035 00036 //---------------------------------------------------------------------------- 00037 00038 /** Class is rotatable by calling Rotate(). */ 00039 template<class T> 00040 struct RotatableConcept 00041 { 00042 void constraints() 00043 { 00044 const ConstBoard& brd = ConstBoard::Get(1, 1); 00045 T t; 00046 t.Rotate(brd); 00047 } 00048 }; 00049 00050 /** Concept of a state in a HashDB. */ 00051 template<class T> 00052 struct StateDBStateConcept 00053 { 00054 void constraints() 00055 { 00056 boost::function_requires< HashDBStateConcept<T> >(); 00057 boost::function_requires< RotatableConcept<T> >(); 00058 } 00059 }; 00060 00061 //---------------------------------------------------------------------------- 00062 00063 /** Database of hex positions handling rotations. */ 00064 template<class T> 00065 class StateDB 00066 { 00067 BOOST_CLASS_REQUIRE(T, benzene, StateDBStateConcept); 00068 00069 public: 00070 00071 struct Statistics 00072 { 00073 std::size_t m_gets; 00074 00075 std::size_t m_hits; 00076 00077 std::size_t m_puts; 00078 00079 std::size_t m_rotations; 00080 00081 std::string Write() const; 00082 00083 Statistics(); 00084 }; 00085 00086 /** Opens database, creates it if it does not exist. */ 00087 StateDB(const std::string& filename, const std::string& type); 00088 00089 /** Closes database. */ 00090 ~StateDB(); 00091 00092 /** Returns true if position exists in database. */ 00093 bool Exists(const HexState& pos) const; 00094 00095 /** Returns true if get is successful. */ 00096 bool Get(const HexState& pos, T& data) const; 00097 00098 /** Returns true if put is successful. */ 00099 bool Put(const HexState& brd, const T& data); 00100 00101 void Flush(); 00102 00103 Statistics GetStatistics() const; 00104 00105 std::string BDBStatistics(); 00106 00107 private: 00108 HashDB<T> m_db; 00109 00110 mutable Statistics m_stats; 00111 }; 00112 00113 template<class T> 00114 StateDB<T>::StateDB(const std::string& filename, const std::string& type) 00115 : m_db(filename, type), 00116 m_stats() 00117 { 00118 } 00119 00120 template<class T> 00121 StateDB<T>::~StateDB() 00122 { 00123 } 00124 00125 template<class T> 00126 bool StateDB<T>::Exists(const HexState& state) const 00127 { 00128 return m_db.Exists(GetHash(state)); 00129 } 00130 00131 template<class T> 00132 bool StateDB<T>::Get(const HexState& state, T& data) const 00133 { 00134 m_stats.m_gets++; 00135 hash_t hash = GetHash(state); 00136 if (!m_db.Get(hash, data)) 00137 return false; 00138 m_stats.m_hits++; 00139 if (NeedToRotate(state, hash)) 00140 { 00141 m_stats.m_rotations++; 00142 data.Rotate(state.Position().Const()); 00143 } 00144 return true; 00145 } 00146 00147 template<class T> 00148 bool StateDB<T>::Put(const HexState& state, const T& data) 00149 { 00150 m_stats.m_puts++; 00151 hash_t hash = GetHash(state); 00152 T myData(data); 00153 if (NeedToRotate(state, hash)) 00154 { 00155 m_stats.m_rotations++; 00156 myData.Rotate(state.Position().Const()); 00157 } 00158 return m_db.Put(hash, myData); 00159 } 00160 00161 template<class T> 00162 void StateDB<T>::Flush() 00163 { 00164 m_db.Flush(); 00165 } 00166 00167 template<class T> 00168 typename StateDB<T>::Statistics 00169 StateDB<T>::GetStatistics() const 00170 { 00171 return m_stats; 00172 } 00173 00174 template<class T> 00175 StateDB<T>::Statistics::Statistics() 00176 : m_gets(0), 00177 m_hits(0), 00178 m_puts(0), 00179 m_rotations(0) 00180 { 00181 } 00182 00183 template<class T> 00184 std::string StateDB<T>::Statistics::Write() const 00185 { 00186 std::ostringstream os; 00187 os << "StateDB statistics\n" 00188 << "Reads " << m_gets << '\n' 00189 << "Hits " << m_hits << '\n' 00190 << "Writes " << m_puts << '\n' 00191 << "Rotations " << m_rotations; 00192 return os.str(); 00193 } 00194 00195 template<class T> 00196 std::string StateDB<T>::BDBStatistics() 00197 { 00198 return m_db.BDBStatistics(); 00199 } 00200 00201 //---------------------------------------------------------------------------- 00202 00203 /** Set of positions; handles rotations. */ 00204 class StateSet 00205 { 00206 public: 00207 StateSet(); 00208 00209 ~StateSet(); 00210 00211 void Insert(const HexState& state); 00212 00213 bool Exists(const HexState& state) const; 00214 00215 std::size_t Size() const; 00216 00217 private: 00218 std::set<hash_t> m_set; 00219 }; 00220 00221 inline StateSet::StateSet() 00222 { 00223 } 00224 00225 inline StateSet::~StateSet() 00226 { 00227 } 00228 00229 inline void StateSet::Insert(const HexState& state) 00230 { 00231 m_set.insert(GetHash(state)); 00232 } 00233 00234 inline bool StateSet::Exists(const HexState& state) const 00235 { 00236 return m_set.count(GetHash(state)) > 0; 00237 } 00238 00239 inline std::size_t StateSet::Size() const 00240 { 00241 return m_set.size(); 00242 } 00243 00244 //---------------------------------------------------------------------------- 00245 00246 /** Map of positions; handles rotations. */ 00247 template<class T> 00248 class StateMap 00249 { 00250 public: 00251 StateMap(); 00252 00253 ~StateMap(); 00254 00255 bool Exists(const HexState& state) const; 00256 00257 T& operator[](const HexState& state); 00258 00259 std::size_t Size() const; 00260 00261 private: 00262 std::map<hash_t, T> m_map; 00263 }; 00264 00265 template<class T> 00266 inline StateMap<T>::StateMap() 00267 { 00268 } 00269 00270 template<class T> 00271 inline StateMap<T>::~StateMap() 00272 { 00273 } 00274 00275 template<class T> 00276 bool StateMap<T>::Exists(const HexState& state) const 00277 { 00278 return m_map.find(GetHash(state)) != m_map.end(); 00279 } 00280 00281 template<class T> 00282 inline T& StateMap<T>::operator[](const HexState& state) 00283 { 00284 return m_map[GetHash(state)]; 00285 } 00286 00287 template<class T> 00288 inline std::size_t StateMap<T>::Size() const 00289 { 00290 return m_map.size(); 00291 } 00292 00293 //---------------------------------------------------------------------------- 00294 00295 _END_BENZENE_NAMESPACE_ 00296 00297 #endif // POSITIONDB_HPP 00298