Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgSortedMoves.h

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


Sun Mar 13 2011 Doxygen 1.7.1