Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgBookBuilder.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgBookBuilder.h */
00003 //----------------------------------------------------------------------------
00004 
00005 #ifndef SG_BOOKBUILDER_HPP
00006 #define SG_BOOKBUILDER_HPP
00007 
00008 #include <cmath>
00009 #include <iostream>
00010 #include <iomanip>
00011 #include <vector>
00012 #include "SgMove.h"
00013 
00014 //----------------------------------------------------------------------------
00015 
00016 /** @defgroup sgopeningbook Automatic Opening Book Construction
00017     Game independent Opening Book Construction.
00018 
00019     Code is based on Thomas R. Lincke's paper "Strategies for the
00020     Automatic Construction of Opening Books" published in 2001.
00021     
00022     We make the following adjustments:
00023     - Neither side is assumed to be the book player, so the expansion
00024       formula is identical for all nodes (see page 80 of the paper). In other
00025       words, both sides can play sub-optimal moves.
00026     - A single node for each state is stored, such that transpositions
00027       are not re-computed. Hence the book forms a DAG of states, not a tree.
00028     - Progressive widening is used on internal nodes to restrict the 
00029       search initially. 
00030 
00031     We also think there is a typo with respect to the formula of epo_i on
00032     page 80. Namely, since p_i is the negamax of p_{s_j}s, then we should
00033     sum the values to find the distance from optimal, not subtract. That is,
00034     we use epo_i = 1 + min(s_j) (epb_{s_j} + alpha*(p_i + p_{s_j}) instead. */
00035 
00036 //----------------------------------------------------------------------------
00037 
00038 /** State in the Opening Book.
00039     @ingroup sgopeningbook */
00040 class SgBookNode
00041 {
00042 public:
00043     //------------------------------------------------------------------------
00044 
00045     /** Priority of newly created leaves. */
00046     static const float LEAF_PRIORITY;
00047 
00048     //------------------------------------------------------------------------
00049 
00050     /** Heuristic value of this state. */
00051     float m_heurValue;
00052 
00053     /** Minmax value of this state. */
00054     float m_value;
00055 
00056     /** Expansion priority. */
00057     float m_priority;
00058 
00059     /** Number of times this node was explored. */
00060     unsigned m_count;
00061     
00062     //------------------------------------------------------------------------
00063 
00064     SgBookNode();
00065 
00066     /** Creates a leaf with the given heuristic value. */
00067     SgBookNode(float heuristicValue);
00068 
00069     /** Creates a node from data in string. Uses same format as
00070         ToString(). */
00071     SgBookNode(const std::string& str);
00072 
00073     /** Returns true if this node is a leaf in the opening book, ie,
00074         its count is zero. */
00075     bool IsLeaf() const;
00076 
00077     /** Returns true if propagated value is a win or a loss. */
00078     bool IsTerminal() const;
00079 
00080     /** Increment the node's counter. */
00081     void IncrementCount();
00082 
00083     /** Outputs node in string form. */
00084     std::string ToString() const;
00085 
00086 private:
00087     void FromString(const std::string& str);
00088 };
00089 
00090 inline SgBookNode::SgBookNode()
00091 {
00092 }
00093 
00094 inline SgBookNode::SgBookNode(float heuristicValue)
00095     : m_heurValue(heuristicValue),
00096       m_value(heuristicValue),
00097       m_priority(LEAF_PRIORITY),
00098       m_count(0)
00099 {
00100 }
00101 
00102 inline SgBookNode::SgBookNode(const std::string& str)
00103 {
00104     FromString(str);
00105 }
00106 
00107 inline void SgBookNode::IncrementCount()
00108 {
00109     m_count++;
00110 }
00111 
00112 /** Extends standard stream output operator for SgBookNodes. */
00113 inline std::ostream& operator<<(std::ostream& os, const SgBookNode& node)
00114 {
00115     os << node.ToString();
00116     return os;
00117 }
00118 
00119 //----------------------------------------------------------------------------
00120 
00121 /** @page bookrefresh Book Refresh
00122     @ingroup sgopeningbook
00123 
00124     Due to transpositions, it is possible that a node's value changes,
00125     but because the node has not been revisited yet the information is
00126     not passed to its parent. Refreshing the book forces these
00127     propagations.
00128 
00129     SgBookBuilder::Refresh() computes the correct propagation value for
00130     all internal nodes given the current set of leaf nodes. A node in
00131     which SgBookNode::IsLeaf() is true is treated as a leaf even
00132     if it has children in the book (ie, children from transpositions) */
00133 
00134 /** @page bookcover "Book Cover
00135     @ingroup sgopeningbook
00136 
00137     The book cover operation ensures that a given set of lines is
00138     covered with the required number of expansions. When completed,
00139     each position in each line will have had at least the required
00140     number of expansions performed from it. 
00141     
00142     For each line, each position is processed in order. Expansions are
00143     performed until the required number are obtained (nothing is done
00144     if it already has enough). Then the next position in the line is
00145     processed.  
00146 
00147     If the additive flag is true, then the given number of expansions
00148     are added to the node no matter how many expansions it has already
00149     received.
00150 
00151     A book refresh should be performed after this operation. */
00152 
00153 //----------------------------------------------------------------------------
00154 
00155 /** Base class for automated book building.
00156     @ingroup sgopeningbook */
00157 class SgBookBuilder
00158 {
00159 public:
00160     SgBookBuilder();
00161 
00162     virtual ~SgBookBuilder();
00163 
00164     //---------------------------------------------------------------------
00165 
00166     /** Expands the book by expanding numExpansions leaves. */
00167     void Expand(int numExpansions);
00168 
00169     /** Ensures each node in each line has at least the given number
00170         of expansions. 
00171         @ref bookcover. */
00172     void Cover(int requiredExpansions, bool additive, 
00173                const std::vector< std::vector<SgMove> >& lines);
00174 
00175     /** Propagates leaf values up through the entire tree.  
00176         @ref bookrefresh. */
00177     void Refresh();
00178 
00179     /** Performs widening on all internal nodes that require it. Use
00180         this after increasing ExpandWidth() or decreasing
00181         ExpandThreshold() on an already existing book to update all
00182         the internal nodes with the new required width. Will do
00183         nothing unless parameters were changed accordingly.
00184         
00185         Does not propagate values up tree, run Refresh() afterwards to
00186         do so. */
00187     void IncreaseWidth();
00188 
00189     //---------------------------------------------------------------------    
00190 
00191     /** The parameter alpha controls state expansion (big values give
00192         rise to deeper lines, while small values perform like a
00193         BFS). */
00194     float Alpha() const;
00195 
00196     /** See Alpha() */
00197     void SetAlpha(float alpha);
00198 
00199     /** Expand only the top ExpandWidth() children of a node
00200         initially, and after every ExpansionThreshold() visits add
00201         ExpandWidth() more children. */
00202     bool UseWidening() const;
00203 
00204     /** See UseWidening() */
00205     void SetUseWidening(bool flag);
00206     
00207     /** See UseWidening() */
00208     std::size_t ExpandWidth() const;
00209 
00210     /** See UseWidening() */
00211     void SetExpandWidth(std::size_t width);
00212 
00213     /** See UseWidening() */
00214     std::size_t ExpandThreshold() const;
00215 
00216     /** See UseWidening() */
00217     void SetExpandThreshold(std::size_t threshold);
00218 
00219     //---------------------------------------------------------------------    
00220 
00221     /** Computes the expansion priority for the child using Alpha(),
00222         the value of the parent, and the provided values of child. */
00223     float ComputePriority(const SgBookNode& parent, const float childValue,
00224                           const float childPriority) const;
00225 
00226     //---------------------------------------------------------------------    
00227 
00228     /** Returns the evaluation from other player's perspective. */
00229     virtual float InverseEval(float eval) const = 0;
00230 
00231     /** Returns true if the eval is a loss. */
00232     virtual bool IsLoss(float eval) const = 0;
00233 
00234     /** Returns the value of the state according this node.
00235         Ie, takes into account swap moves, etc. */
00236     virtual float Value(const SgBookNode& node) const = 0;
00237 
00238 protected:
00239     /** See Alpha() */
00240     float m_alpha;
00241 
00242     /** See UseWidening() */
00243     bool m_useWidening;
00244 
00245     /** See UseWidening() */
00246     std::size_t m_expandWidth;
00247 
00248     /** See UseWidening() */
00249     std::size_t m_expandThreshold;
00250     
00251     /** Number of iterations after which the db is flushed to disk. */
00252     std::size_t m_flushIterations;
00253 
00254     //------------------------------------------------------------------------
00255 
00256     /** Converts move to a string (game dependent). */
00257     virtual std::string MoveString(SgMove move) const = 0;
00258 
00259     /** Print a message to a log/debug stream. */
00260     virtual void PrintMessage(std::string msg) = 0;
00261 
00262     /** Plays a move. */
00263     virtual void PlayMove(SgMove move) = 0;
00264 
00265     /** Undo last move. */
00266     virtual void UndoMove(SgMove move) = 0;
00267 
00268     /** Reads node. Returns false if node does not exist. */
00269     virtual bool GetNode(SgBookNode& node) const = 0;
00270 
00271     /** Writes node. */
00272     virtual void WriteNode(const SgBookNode& node) = 0;
00273 
00274     /** Save the book. */
00275     virtual void FlushBook() = 0;
00276 
00277     /** If current state does not exist, evaluate it and store in the
00278         book. */
00279     virtual void EnsureRootExists() = 0;
00280 
00281     /** Generates the set of moves to use in the book for this state. */
00282     virtual bool GenerateMoves(std::vector<SgMove>& moves, float& value) = 0;
00283 
00284     /** Returns all legal moves; should be a superset of those moves 
00285         returned by GenerateMoves() */
00286     virtual void GetAllLegalMoves(std::vector<SgMove>& moves) = 0;
00287 
00288     /** Evaluate the children of the current state, return the values
00289         in a vector of pairs. */
00290     virtual void EvaluateChildren(const std::vector<SgMove>& childrenToDo,
00291                     std::vector<std::pair<SgMove, float> >& scores) = 0;
00292 
00293     /** Hook function: called before any work is done. 
00294         Default implementation does nothing. */
00295     virtual void Init();
00296 
00297     /** Hook function: called after all work is complete. 
00298         Default implementation does nothing. */
00299     virtual void Fini();
00300 
00301     /** Hook function: called at start of iteration.
00302         Default implementation does nothing. */
00303     virtual void StartIteration();
00304     
00305     /** Hook function: called at end of iteration. 
00306         Default implementation does nothing. */
00307     virtual void EndIteration();
00308 
00309     virtual void BeforeEvaluateChildren();
00310 
00311     virtual void AfterEvaluateChildren();
00312 
00313     virtual void ClearAllVisited() = 0;
00314 
00315     virtual void MarkAsVisited() = 0;
00316     
00317     virtual bool HasBeenVisited() = 0;
00318 
00319 private:
00320     std::size_t m_numEvals;
00321 
00322     std::size_t m_numWidenings;
00323 
00324     std::size_t m_valueUpdates;
00325 
00326     std::size_t m_priorityUpdates;
00327 
00328     std::size_t m_internalNodes;
00329 
00330     std::size_t m_leafNodes;
00331 
00332     std::size_t m_terminalNodes;
00333 
00334     //---------------------------------------------------------------------
00335 
00336     std::size_t NumChildren(const std::vector<SgMove>& legal);
00337 
00338     void UpdateValue(SgBookNode& node, const std::vector<SgMove>& legal);
00339 
00340     void UpdateValue(SgBookNode& node);
00341 
00342     SgMove UpdatePriority(SgBookNode& node);
00343 
00344     void DoExpansion(std::vector<SgMove>& pv);
00345 
00346     bool Refresh(bool root);
00347 
00348     void IncreaseWidth(bool root);
00349     
00350     bool ExpandChildren(std::size_t count);
00351 };
00352 
00353 //----------------------------------------------------------------------------
00354 
00355 inline float SgBookBuilder::Alpha() const
00356 {
00357     return m_alpha;
00358 }
00359 
00360 inline void SgBookBuilder::SetAlpha(float alpha)
00361 {
00362     m_alpha = alpha;
00363 }
00364 
00365 inline bool SgBookBuilder::UseWidening() const
00366 {
00367     return m_useWidening;
00368 }
00369 
00370 inline void SgBookBuilder::SetUseWidening(bool flag)
00371 {
00372     m_useWidening = flag;
00373 }
00374 
00375 inline std::size_t SgBookBuilder::ExpandWidth() const
00376 {
00377     return m_expandWidth;
00378 }
00379 
00380 inline void SgBookBuilder::SetExpandWidth(std::size_t width)
00381 {
00382     m_expandWidth = width;
00383 }
00384 
00385 inline std::size_t SgBookBuilder::ExpandThreshold() const
00386 {
00387     return m_expandThreshold;
00388 }
00389 
00390 inline void SgBookBuilder::SetExpandThreshold(std::size_t threshold)
00391 {
00392     m_expandThreshold = threshold;
00393 }
00394 
00395 //----------------------------------------------------------------------------
00396 
00397 #endif // SG_BOOKBUILDER_HPP


Sun Mar 13 2011 Doxygen 1.7.1