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 
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 /** Small array with moves sorted by their value */
00020 template<typename MOVE, typename VALUE, int SIZE>
00021 class SgSortedMoves
00022 {
00023 public:
00024     /** check move table before and after each operation */
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     /** delete all but one of equal-valued moves */
00036     void DeleteEqual();
00037 
00038     /** Delete move at index.
00039         Shift remaining moves forward and adjust lower bound if necessary.
00040     */
00041     void Delete(int index);
00042 
00043     /** Insert move with given value in table.
00044         Update m_nuMoves, m_lowerBound of table if necessary.
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     /** If move in table: increase its value. otherwise insert (move,value) */
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     /**  Adjust number of moves: throw out all moves whose value has become
00072         less than the value of m_move[m_maxNuMoves - 1]
00073     */
00074     void SetMaxMoves(int nu); // adjust all other values too
00075 
00076     /** Limit number of moves */
00077     void SetMaxNuMoves(int max);
00078 
00079     /** Lower bound for accepting moves */
00080     void SetLowerBound(VALUE bound) {m_lowerBound = bound;};
00081 
00082     /** See m_initLowerBound */
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     /** Get move at given index i */
00095     const MOVE& Move(int i) const {AssertIndexRange(i); return m_move[i];}
00096 
00097     /** The best move is sorted first in the table */
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     /** Assert i is an index within the table */
00118     void AssertIndexRange(int i) const
00119     {
00120         SG_DEBUG_ONLY(i);
00121         SG_ASSERTRANGE(i, 0, m_nuMoves - 1);
00122     }
00123 
00124     /** randomly shuffle all the moves of equal value. */
00125     void Shuffle();
00126 
00127 private:
00128     /**  */
00129     int m_maxNuMoves;
00130 
00131     /**  */
00132     int m_nuMoves;
00133 
00134     /** Lower bound for accepting moves */
00135     VALUE m_lowerBound;
00136 
00137     /** Initial value of m_lowerBound after a Clear() */
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     /** Randomly shuffle all moves in interval. They must be of equal value */
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     // must exit through return in the for loop above
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); // Index[0..MAX - 1]
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     // must leave 1 free element as scratch space
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     // throw out all m_move's whose minValue has become
00267     //  less than the minValue of m_move[m_maxNuMoves - 1]
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         // throw out the Max-weakest moves
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; // same effect as: Delete(m_nuMoves - 1);
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     {// put random element in [from..to] into to
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         // throw out weakest moves
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; // same as: Delete(m_nuMoves - 1);
00383     }
00384 }
00385 
00386 //----------------------------------------------------------------------------
00387 
00388 /** write all moves in the table and their values */
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


17 Jun 2010 Doxygen 1.4.7