00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef SG_SORTEDMOVES_H
00011 #define SG_SORTEDMOVES_H
00012
00013 #include <iostream>
00014 #include "SgRandom.h"
00015 #include "SgVector.h"
00016
00017
00018
00019
00020 template<typename MOVE, typename VALUE, int SIZE>
00021 class SgSortedMoves
00022 {
00023 public:
00024
00025 static const bool CHECKMOVES = SG_CHECK;
00026
00027 explicit SgSortedMoves(int maxNuMoves);
00028
00029
00030 void CheckOverflow() {m_checkOverflow = true;}
00031
00032
00033 void Clear();
00034
00035
00036 void DeleteEqual();
00037
00038
00039
00040
00041 void Delete(int index);
00042
00043
00044
00045
00046 void Insert(const MOVE& move, VALUE value);
00047
00048
00049 bool GetMove(const MOVE& move, VALUE &value, int &index) const;
00050
00051
00052 void GetMoves(SgVector<MOVE>* moves) const;
00053
00054
00055 void SetMinValue(const MOVE& move, VALUE value);
00056
00057
00058 void SetMove(int i, const MOVE& move)
00059 {
00060 AssertIndexRange(i);
00061 m_move[i] = move;
00062 }
00063
00064
00065 void SetValue(int i, VALUE value)
00066 {
00067 AssertIndexRange(i);
00068 m_value[i] = value;
00069 }
00070
00071
00072
00073
00074 void SetMaxMoves(int nu);
00075
00076
00077 void SetMaxNuMoves(int max);
00078
00079
00080 void SetLowerBound(VALUE bound) {m_lowerBound = bound;};
00081
00082
00083 void SetInitLowerBound(VALUE bound) {m_initLowerBound = bound;};
00084
00085
00086 int LowerBound() const {return m_lowerBound;}
00087
00088
00089 int NuMoves() const {return m_nuMoves;}
00090
00091
00092 int MaxNuMoves() const {return m_maxNuMoves;}
00093
00094
00095 const MOVE& Move(int i) const {AssertIndexRange(i); return m_move[i];}
00096
00097
00098 const MOVE& BestMove() const {return Move(0);}
00099
00100
00101 VALUE Value(int i) const {AssertIndexRange(i); return m_value[i];}
00102
00103
00104 VALUE BestValue() const
00105 {
00106 SG_ASSERT(m_nuMoves > 0);
00107 return m_value[0];
00108 }
00109
00110
00111 void DecNuMoves()
00112 {
00113 SG_ASSERT(m_nuMoves > 0);
00114 --m_nuMoves;
00115 }
00116
00117
00118 void AssertIndexRange(int i) const
00119 {
00120 SG_DEBUG_ONLY(i);
00121 SG_ASSERTRANGE(i, 0, m_nuMoves - 1);
00122 }
00123
00124
00125 void Shuffle();
00126
00127 private:
00128
00129 int m_maxNuMoves;
00130
00131
00132 int m_nuMoves;
00133
00134
00135 VALUE m_lowerBound;
00136
00137
00138 VALUE m_initLowerBound;
00139
00140
00141 bool m_checkOverflow;
00142
00143
00144 bool m_considerEqual;
00145
00146
00147 MOVE m_move[SIZE];
00148
00149
00150 VALUE m_value[SIZE];
00151
00152
00153 void CheckMoves() const;
00154
00155
00156 void ShuffleInterval(int from, int to);
00157 };
00158
00159 template<typename MOVE, typename VALUE, int SIZE>
00160 SgSortedMoves<MOVE, VALUE, SIZE>::SgSortedMoves(int maxNuMoves)
00161 : m_maxNuMoves(maxNuMoves),
00162 m_checkOverflow(false),
00163 m_considerEqual(true)
00164 {
00165 SG_ASSERT(maxNuMoves <= SIZE);
00166 Clear();
00167 }
00168
00169 template<typename MOVE, typename VALUE, int SIZE>
00170 void SgSortedMoves<MOVE, VALUE, SIZE>::Clear()
00171 {
00172 m_initLowerBound = INT_MIN;
00173 SG_ASSERT(m_maxNuMoves >= 1);
00174 m_lowerBound = m_initLowerBound;
00175 m_nuMoves = 0;
00176 }
00177
00178 template<typename MOVE, typename VALUE, int SIZE>
00179 void SgSortedMoves<MOVE, VALUE, SIZE>::Delete(int index)
00180 {
00181 if (CHECKMOVES)
00182 CheckMoves();
00183 SG_ASSERT(index < m_nuMoves);
00184
00185 --m_nuMoves;
00186 for (int k = index; k <= m_nuMoves - 1; ++k)
00187 {
00188 m_move[k] = m_move[k + 1];
00189 m_value[k] = m_value[k + 1];
00190 }
00191
00192 if (m_nuMoves >= m_maxNuMoves)
00193 m_lowerBound = m_value[m_maxNuMoves - 1];
00194 else
00195 m_lowerBound = m_initLowerBound;
00196
00197 if (CHECKMOVES)
00198 CheckMoves();
00199 }
00200
00201 template<typename MOVE, typename VALUE, int SIZE>
00202 void SgSortedMoves<MOVE, VALUE, SIZE>::DeleteEqual()
00203 {
00204 for (int j = m_nuMoves - 2; j >= 0; --j)
00205 {
00206 for (int i = m_nuMoves - 1; i >= j + 1; --i)
00207 {
00208 if (m_value[i] == m_value[j])
00209 {
00210 Delete(SgRandom::Global().Int(2) ? j : i);
00211 return;
00212 }
00213 }
00214 }
00215
00216 SG_ASSERT(false);
00217 }
00218
00219 template<typename MOVE, typename VALUE, int SIZE>
00220 void SgSortedMoves<MOVE, VALUE, SIZE>::CheckMoves() const
00221 {
00222 SG_ASSERT(m_maxNuMoves <= SIZE);
00223 SG_ASSERT(m_nuMoves <= SIZE);
00224
00225 for (int i = 0; i < m_nuMoves - 1; ++i)
00226 SG_ASSERT(m_value[i] >= m_value[i + 1]);
00227 for (int i = m_maxNuMoves; i < m_nuMoves; ++i)
00228 SG_ASSERT(m_value[i] == m_value[m_maxNuMoves - 1]);
00229
00230 SG_ASSERT((m_nuMoves == 0) || (m_value[m_nuMoves - 1] >= m_lowerBound));
00231 }
00232
00233 template<typename MOVE, typename VALUE, int SIZE>
00234 void SgSortedMoves<MOVE, VALUE, SIZE>::Insert(const MOVE& m, VALUE val)
00235 {
00236 if (CHECKMOVES)
00237 CheckMoves();
00238
00239 if (val < m_lowerBound)
00240 return;
00241
00242 int i = 0;
00243 while (i < m_nuMoves && m_value[i] > val)
00244 ++i;
00245 int maxMoves = m_nuMoves;
00246 if (maxMoves >= SIZE)
00247 {
00248 if (m_checkOverflow)
00249 {
00250 SG_ASSERT(false);
00251 }
00252 maxMoves = SIZE - 1;
00253 }
00254 else
00255 ++m_nuMoves;
00256
00257 for (int j = maxMoves; j >= i + 1; --j)
00258 {
00259 m_move[j] = m_move[j - 1];
00260 m_value[j] = m_value[j - 1];
00261 }
00262
00263 m_move[i] = m;
00264 m_value[i] = val;
00265
00266
00267
00268 if (m_nuMoves >= m_maxNuMoves)
00269 m_lowerBound = std::max(m_lowerBound, m_value[m_maxNuMoves - 1]);
00270
00271 if (m_nuMoves > m_maxNuMoves)
00272
00273 while ( m_value[m_nuMoves - 1] < m_lowerBound
00274 || ( m_nuMoves > m_maxNuMoves
00275 && ! m_considerEqual
00276 && m_value[m_nuMoves - 1] == m_lowerBound
00277 )
00278 )
00279 --m_nuMoves;
00280
00281 if (CHECKMOVES)
00282 CheckMoves();
00283 }
00284
00285 template<typename MOVE, typename VALUE, int SIZE>
00286 bool SgSortedMoves<MOVE, VALUE, SIZE>::GetMove(const MOVE& move,
00287 VALUE &value, int &index) const
00288 {
00289 for (int i = 0; i <= m_nuMoves - 1 ; ++i)
00290 if (m_move[i] == move)
00291 {
00292 value = m_value[i];
00293 index = i;
00294 return true;
00295 }
00296 return false;
00297 }
00298
00299 template<typename MOVE, typename VALUE, int SIZE>
00300 void SgSortedMoves<MOVE, VALUE, SIZE>::ShuffleInterval(int from, int to)
00301 {
00302 AssertIndexRange(from);
00303 AssertIndexRange(to);
00304 SG_ASSERT(m_value[from] == m_value[to]);
00305
00306 for (; to > from; --to)
00307 {
00308 int i = from + SgRandom::Global().Int(to - from + 1);
00309 SG_ASSERT(m_value[i] == m_value[to]);
00310 MOVE t = m_move[i];
00311 m_move[i] = m_move[to];
00312 m_move[to] = t;
00313 }
00314 }
00315
00316 template<typename MOVE, typename VALUE, int SIZE>
00317 void SgSortedMoves<MOVE, VALUE, SIZE>::Shuffle()
00318 {
00319 for (int i = 0; i < m_nuMoves; ++i)
00320 {
00321 int val = m_value[i];
00322 int j;
00323 for (j = i + 1; j < m_nuMoves && (val == m_value[j]); ++j)
00324 { }
00325 if (j > i + 1)
00326 ShuffleInterval(i, j - 1);
00327 }
00328 }
00329
00330 template<typename MOVE, typename VALUE, int SIZE>
00331 void SgSortedMoves<MOVE, VALUE, SIZE>::GetMoves(SgVector<MOVE>* moves) const
00332 {
00333 for (int i = 0; i < m_nuMoves; ++i)
00334 moves->PushBack(m_move[i]);
00335 }
00336
00337 template<typename MOVE, typename VALUE, int SIZE>
00338 void SgSortedMoves<MOVE, VALUE, SIZE>::SetMinValue(const MOVE& move,
00339 VALUE val)
00340 {
00341 VALUE oldValue;
00342 int index;
00343 bool insert = true;
00344
00345 if (GetMove(move, oldValue, index))
00346 {
00347 if (val > oldValue)
00348 Delete(index);
00349 else
00350 insert = false;
00351 }
00352 if (insert)
00353 Insert(move, val);
00354 }
00355
00356 template<typename MOVE, typename VALUE, int SIZE>
00357 void SgSortedMoves<MOVE, VALUE, SIZE>::SetMaxNuMoves(int max)
00358 {
00359 SG_ASSERT(max >= 1);
00360 SG_ASSERT(max <= SIZE);
00361 m_maxNuMoves = max;
00362 }
00363
00364 template<typename MOVE, typename VALUE, int SIZE>
00365 void SgSortedMoves<MOVE, VALUE, SIZE>::SetMaxMoves(int nu)
00366 {
00367 SetMaxNuMoves(nu);
00368
00369 if ( m_nuMoves >= m_maxNuMoves
00370 && m_value[m_maxNuMoves - 1] > m_lowerBound
00371 )
00372 m_lowerBound = m_value[m_maxNuMoves - 1];
00373 if (m_nuMoves > m_maxNuMoves)
00374 {
00375
00376 while ( m_value[m_nuMoves - 1] < m_lowerBound
00377 || ( m_nuMoves > m_maxNuMoves
00378 && ! m_considerEqual
00379 && m_value[m_nuMoves - 1] == m_lowerBound
00380 )
00381 )
00382 --m_nuMoves;
00383 }
00384 }
00385
00386
00387
00388
00389 template<typename MOVE, typename VALUE, int SIZE>
00390 std::ostream& operator<<(std::ostream& str,
00391 const SgSortedMoves<MOVE, VALUE, SIZE>& m)
00392 {
00393 if (m.NuMoves() == 0)
00394 str << "none\n";
00395 else
00396 {
00397 str << m.NuMoves() << " (Moves, Values): ";
00398 for (int i = 0; i < m.NuMoves(); ++i)
00399 {
00400 str << '('
00401 << m.Move(i) << ", "
00402 << m.Value(i)
00403 << ')';
00404 }
00405 str << '\n';
00406 }
00407 return str;
00408 }
00409
00410
00411
00412 #endif // SG_SORTEDMOVES_H