Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgUctSearch.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgUctSearch.h
00003     Class SgUctSearch and helper classes.
00004 */
00005 //----------------------------------------------------------------------------
00006 
00007 #ifndef SG_UCTSEARCH_H
00008 #define SG_UCTSEARCH_H
00009 
00010 #include <fstream>
00011 #include <vector>
00012 #include <boost/scoped_array.hpp>
00013 #include <boost/shared_ptr.hpp>
00014 #include <boost/thread/barrier.hpp>
00015 #include <boost/thread/condition.hpp>
00016 #include <boost/thread/mutex.hpp>
00017 #include <boost/thread/recursive_mutex.hpp>
00018 #include <boost/thread/thread.hpp>
00019 #include "SgBlackWhite.h"
00020 #include "SgBWArray.h"
00021 #include "SgTimer.h"
00022 #include "SgUctTree.h"
00023 #include "SgMpiSynchronizer.h"
00024 
00025 #define SG_UCTFASTLOG 1
00026 #if SG_UCTFASTLOG
00027 #include "SgFastLog.h"
00028 #endif
00029 
00030 //----------------------------------------------------------------------------
00031 
00032 /** @defgroup sguctgroup Monte Carlo tree search
00033     Game-independent Monte Carlo tree search using UCT.
00034 
00035     The main class SgUctSearch keeps a tree with statistics for each node
00036     visited more than a certain number of times, and then continues with
00037     random playout (not necessarily uniform random).
00038     Within the tree, the move with the highest upper confidence bound is
00039     chosen according to the basic UCT formula:
00040     @f[ \bar{X}_j + c \sqrt{\frac{\log{n}}{T_j(n)}} @f]
00041     with:
00042     - @f$ j @f$ the move index
00043     - @f$ X_{j,\gamma} @f$ reward for move @f$ j @f$ at sample @f$ \gamma @f$
00044     - @f$ n @f$ number of times the father node was visited
00045     - @f$ T_j(n) @f$ number of times the move has been played
00046     - @f$ c @f$ an appropriate constant
00047 
00048     References:
00049     - Kocsis, Szepesvari:
00050       <a href="http://zaphod.aml.sztaki.hu/papers/ecml06.pdf">
00051       Bandit based Monte-Carlo Planning</a>
00052     - Auer, Cesa-Bianchi, Fischer:
00053       <a href="http://homes.dsi.unimi.it/~cesabian/Pubblicazioni/ml-02.pdf">
00054       Finite-time Analysis of the Multiarmed Bandit Problem</a>
00055     - Gelly, Wang, Munos, Teytaud:
00056       <a href="http://hal.inria.fr/docs/00/12/15/16/PDF/RR-6062.pdf">
00057       Modification of UCT with patterns in Monte-Carlo Go</a>
00058     - Silver, Gelly:
00059       <a href=
00060       "http://imls.engr.oregonstate.edu/www/htdocs/proceedings/icml2007/papers/387.pdf">
00061       Combining Online and Offline Knowledge in UCT</a>
00062 
00063     @see
00064     - @ref sguctsearchlockfree
00065     - @ref sguctsearchweights
00066     - @ref sguctsearchproven
00067 */
00068 
00069 /** @page sguctsearchlockfree Lock-free mode in SgUctSearch
00070 
00071 The basic idea of the lock-free mode in SgUctSearch is to share a tree between
00072 multiple threads without using any locks. Because of specific requirements on
00073 the memory model of the hardware platform, lock-free mode is an optional
00074 feature of the SgUctSearch and needs to be enabled explicitly.
00075 
00076 @section sguctsearchlockfreetree Modifying the Tree Structure
00077 
00078 The first change to make the lock-free search work is in the handling of
00079 concurrent changes to the structure of the tree. SgUctSearch never deletes
00080 nodes during a search; new nodes are created in a pre-allocated memory array.
00081 In the lock-free algorithm, each thread has its own memory array for creating
00082 new nodes. Only after the nodes are fully created and initialized, are they
00083 linked to the parent node. This can cause some memory overhead, because if
00084 several threads expand the same node only the children created by the last
00085 thread will be used in future simulations. It can also happen that some of the
00086 children that are lost already received value updates; these updates will be
00087 lost.
00088 
00089 The child information of a node consists of two variables: a pointer to the
00090 first child in the array, and the number of children. To avoid that another
00091 thread sees an inconsistent state of these variables, all threads assume that
00092 the number of children is valid if the pointer to the first child is not null.
00093 Linking a parent to a new set of children requires first writing the number of
00094 children, then the pointer to the first child. The compiler is prevented from
00095 reordering the writes by declaring these variables as volatile.
00096 
00097 @section sguctsearchlockfreevalues Updating Values
00098 
00099 The move and RAVE values are stored in the nodes as counts and mean values.
00100 The mean values are updated using an incremental algorithm. Updating them
00101 without protection by a mutex can cause updates of the mean to be lost with or
00102 without increment of the count, as well as updates of the mean occurring
00103 without increment of the count. It could also happen that one thread reads the
00104 count and mean while they are written by another thread, and the first thread
00105 sees an erroneous state that exists only temporarily. In practice, these
00106 faulty updates occur with a low probability and will have only a small effect
00107 on the counts and mean values. They are intentionally ignored.
00108 
00109 The only problematic case is if a count is zero, because the mean value is
00110 undefined if the count is zero, and this case has a special meaning at several
00111 places in the search. For example, the computation of the values for the
00112 selection of children in the in-tree phase distinguishes three cases: if the
00113 move count and RAVE count is non-zero, the value will be computed as a
00114 weighted linear combination of both mean values, if the move count is zero,
00115 only the RAVE mean is used, and if both counts are zero, a configurable
00116 constant value, the first play urgency, is used. To avoid this problem, all
00117 threads assume that a mean value is only valid if the corresponding count is
00118 non-zero. Updating a value requires first writing the new mean value, then the
00119 new count. The compiler is prevented from reordering the writes by declaring
00120 the counts and mean values as volatile.
00121 
00122 @section sguctsearchlockfreeplatform Platform Requirements
00123 
00124 There are some requirements on the memory model of the platform to make the
00125 lock-free search algorithm work. Writes of certain basic types (size_t, int,
00126 float, pointers) must be atomic. Writes by one thread must be seen by other
00127 threads in the same order. The IA-32 and Intel-64 CPU architectures, which are
00128 used in most modern standard computers, guarantee these assumptions. They also
00129 synchronize CPU caches after writes. (See
00130 <a href="http://download.intel.com/design/processor/manuals/253668.pdf">
00131 Intel 64 and IA-32 Architectures Software Developer's Manual</a>, chapter
00132 7.1 Locked Atomic Operations and 7.2 Memory Ordering).
00133 */
00134 
00135 /** @page sguctsearchweights Estimator weights in SgUctSearch
00136     The weights of the estimators (move value, RAVE value) are chosen by
00137     assuming that the estimators are uncorrelated and modeling the mean
00138     squared error of estimator @f$ i @f$ by a function that depends on the
00139     number of samples and parameter constants, which represent the variance
00140     and bias of the estimator and need to be determined experimentally:
00141 
00142     @f[
00143     w_i = \frac{1}{Z} \frac{1}{{\rm MSE}_i}
00144     \qquad Z = \sum_i \frac{1}{{\rm MSE}_i}
00145     \qquad {\rm MSE}_i = \frac{c_{\rm variance}}{N_i} + c_{\rm bias}^2
00146     @f]
00147 
00148     Note that this formula is nearly equivalent to the formula suggested
00149     by David Silver on the Computer Go mailing list for the case of two
00150     estimators (move value and RAVE value) and used in newer versions of MoGo.
00151     However, MoGo uses the measured variance of the current RAVE value (for
00152     both the move weight and RAVE weight) instead variance parameter
00153     constants.
00154 
00155     The formula is then reformulated to use different constants that describe
00156     the initial steepness and final asymptotic value of the unnormalized
00157     weight:
00158 
00159     @f[
00160     Z w_i =
00161     \frac{c_{\rm initial}}
00162          {\frac{1}{N} + \frac{c_{\rm initial}}{c_{\rm final}}}
00163     @f]
00164 
00165     with:
00166     - @f$ N @f$ sample count of the estimator
00167     - @f$ c_{\rm initial} @f$ Initial weight parameter; this is they weight if
00168       @f$ N = 1 @f$ and @f$ c_{\rm final} \gg c_{\rm initial} @f$
00169     - @f$ c_{\rm final} @f$ Final weight parameter; this is they weight if
00170       @f$ N \rightarrow \infty @f$
00171 
00172     For the move value, @f$ c_{\rm bias} = 0 @f$, and the variance can become
00173     part of the normalization constant, so the weight is simply
00174     @f$ N_{\rm move} @f$.
00175     If no estimator has a sample count yet, the first-play-urgency parameter
00176     is used for the value estimate.
00177 */
00178 
00179 /** @page sguctsearchproven Proven Nodes in SgUctSearch
00180 
00181     When expanding a node (or computing knowledge at a node) it is
00182     possible the derived class can prove that the state corresponding
00183     to the node is a proven win or loss. Note this differs from a
00184     terminal node since a terminal node by definition has no children,
00185     whereas a proven node can have any number of children.
00186 
00187     Any in-tree phase that encounters a proven node is immediately
00188     terminated and the result passed back up the tree just as if a
00189     playout (with the value corresponding to the proven value) had
00190     been performed.
00191 
00192     The existence of proven nodes in a SgUctTree does not change the
00193     move selection in any way. For example: a node with both winning
00194     and losing children will continue to select children without
00195     regard to their proven value. This means losing children will not
00196     be avoided and winning children will not be chosen except as a
00197     result of the playouts recorded as those children are visisted
00198     (the values of which would now be perfectly accurate).
00199 
00200     Proven values are not currently passed up the tree like in a
00201     min-max search. It would be possible to pass back winning moves,
00202     that is, mark the parent of winning moves as winning, but it is
00203     not possible mark a node as losing if all its moves are
00204     losing. This is because it is possible progressive widening (or
00205     other heuristics) are being used by the derived state and in such
00206     a case it may not be true that all the current children being
00207     losses implies the parent state is a loss.
00208 */
00209 
00210 //----------------------------------------------------------------------------
00211 
00212 typedef SgStatistics<float,std::size_t> SgUctStatistics;
00213 
00214 typedef SgStatisticsExt<float,std::size_t> SgUctStatisticsExt;
00215 
00216 //----------------------------------------------------------------------------
00217 
00218 /** Game result, sequence and nodes of one Monte-Carlo game in SgUctSearch.
00219     @ingroup sguctgroup
00220 */
00221 struct SgUctGameInfo
00222 {
00223     /** The game result of the playout(s).
00224         The result is from the view of the player at the root.
00225     */
00226     std::vector<float> m_eval;
00227 
00228     /** The sequence of the in-tree phase. */
00229     std::vector<SgMove> m_inTreeSequence;
00230 
00231     /** The sequence of the playout(s).
00232         For convenient usage, they also include the moves from
00233         m_inTreeSequence, even if they are the same for each playout.
00234     */
00235     std::vector<std::vector<SgMove> > m_sequence;
00236 
00237     /** Was the playout aborted due to maxGameLength (stored for each
00238         playout).
00239     */
00240     std::vector<bool> m_aborted;
00241 
00242     /** Nodes visited in the in-tree phase. */
00243     std::vector<const SgUctNode*> m_nodes;
00244 
00245     /** Flag to skip RAVE update for moves of the playout(s).
00246         For convenient usage, the index corresponds to the move number from
00247         the root position on, even if the flag is currently only used for
00248         moves in the playout phase, so the flag is false for all moves in the
00249         in-tree phase.
00250     */
00251     std::vector<std::vector<bool> > m_skipRaveUpdate;
00252 
00253     void Clear(std::size_t numberPlayouts);
00254 };
00255 
00256 //----------------------------------------------------------------------------
00257 
00258 /** Move selection strategy after search is finished.
00259     @ingroup sguctgroup
00260 */
00261 enum SgUctMoveSelect
00262 {
00263     /** Select move with highest mean value. */
00264     SG_UCTMOVESELECT_VALUE,
00265 
00266     /** Select move with highest count. */
00267     SG_UCTMOVESELECT_COUNT,
00268 
00269     /** Use UCT bound (or combined bound if RAVE is enabled). */
00270     SG_UCTMOVESELECT_BOUND,
00271 
00272     /** Use the weighted sum of UCT and RAVE value (but without
00273         bias terms).
00274     */
00275     SG_UCTMOVESELECT_ESTIMATE
00276 };
00277 
00278 //----------------------------------------------------------------------------
00279 
00280 /** Base class for the thread state.
00281     Subclasses must be thread-safe, it must be possible to use different
00282     instances of this class in different threads (after construction, the
00283     constructor does not need to be thread safe). Beware not to use classes
00284     that are not thread-safe, because they use global variables
00285     (e.g. SgRandom::Global())
00286     @note Technically it is possible to use a non-thread safe implementation
00287     of subclasses, as long as the search is run with only one thread.
00288     @ingroup sguctgroup
00289 */
00290 class SgUctThreadState
00291 {
00292 public:
00293     /** Number of the thread between 0 and SgUctSearch::NumberThreads() - 1 */
00294     const std::size_t m_threadId;
00295 
00296     bool m_isSearchInitialized;
00297 
00298     /** Flag indicating the a node could not be expanded, because the
00299         maximum tree size was reached.
00300     */
00301     bool m_isTreeOutOfMem;
00302 
00303     SgUctGameInfo m_gameInfo;
00304 
00305     /** Local variable for SgUctSearch::UpdateRaveValues().
00306         Reused for efficiency. Stores the first time a move was played
00307         by the color to play at the root position (move is used as an index,
00308         do m_moveRange must be > 0); numeric_limits<size_t>::max(), if the
00309         move was not played.
00310     */
00311     boost::scoped_array<std::size_t> m_firstPlay;
00312 
00313     /** Local variable for SgUctSearch::UpdateRaveValues().
00314         Like m_firstPlayToPlay, but for opponent color.
00315     */
00316     boost::scoped_array<std::size_t> m_firstPlayOpp;
00317 
00318     /** Local variable for SgUctSearch::PlayInTree().
00319         Reused for efficiency.
00320     */
00321     std::vector<SgMoveInfo> m_moves;
00322 
00323     /** Local variable for SgUctSearch::CheckCountAbort().
00324         Reused for efficiency.
00325     */
00326     std::vector<SgMove> m_excludeMoves;
00327 
00328     /** Thread's counter for Randomized Rave in SgUctSearch::SelectChild().
00329      */
00330     int m_randomizeCounter;
00331 
00332     SgUctThreadState(size_t threadId, int moveRange = 0);
00333 
00334     virtual ~SgUctThreadState();
00335 
00336     /** @name Pure virtual functions */
00337     // @{
00338 
00339     /** Evaluate end-of-game position.
00340         Will only be called if GenerateAllMoves() or GeneratePlayoutMove()
00341         returns no moves. Should return larger values if position is better
00342         for the player to move.
00343     */
00344     virtual float Evaluate() = 0;
00345 
00346     /** Execute a move.
00347         @param move The move
00348      */
00349     virtual void Execute(SgMove move) = 0;
00350 
00351     /** Execute a move in the playout phase.
00352         For optimization if the subclass uses uses a different game state
00353         representation in the playout phase. Otherwise the function can be
00354         implemented in the subclass by simply calling Execute().
00355         @param move The move
00356      */
00357     virtual void ExecutePlayout(SgMove move) = 0;
00358 
00359     /** Generate moves.
00360         Moves will be explored in the order of the returned list.
00361         If return is true, trees under children will be deleted.
00362         @param count Number of times node has been visited. For knowledge-
00363         based computations.
00364         @param[out] moves The generated moves or empty list at end of game
00365     */
00366     virtual bool GenerateAllMoves(std::size_t count, 
00367                                   std::vector<SgMoveInfo>& moves,
00368                                   SgProvenNodeType& provenType) = 0;
00369 
00370     /** Generate random move.
00371         Generate a random move in the play-out phase (outside the UCT tree).
00372         @param[out] skipRaveUpdate This value should be set to true, if the
00373         move should be excluded from RAVE updates. Otherwise it can be
00374         ignored.
00375         @return The move or SG_NULLMOVE at the end of the game.
00376     */
00377     virtual SgMove GeneratePlayoutMove(bool& skipRaveUpdate) = 0;
00378 
00379     /** Start search.
00380         This function should do any necessary preparations for playing games
00381         in the thread, like initializing the thread's copy of the game state
00382         from the global game state. The function does not have to be
00383         thread-safe.
00384     */
00385     virtual void StartSearch() = 0;
00386 
00387     /** Take back moves played in the in-tree phase. */
00388     virtual void TakeBackInTree(std::size_t nuMoves) = 0;
00389 
00390     /** Take back moves played in the playout phase.
00391         The search engine does not assume that the moves are really taken back
00392         after this function is called. If the subclass implements the playout
00393         in s separate state, which is initialized in StartPlayout() and does
00394         not support undo, the implementation of this function can be left
00395         empty in the subclass.
00396     */
00397     virtual void TakeBackPlayout(std::size_t nuMoves) = 0;
00398 
00399     // @} // name
00400 
00401 
00402     /** @name Virtual functions */
00403     // @{
00404 
00405     /** Function that will be called by PlayGame() before the game.
00406         Default implementation does nothing.
00407     */
00408     virtual void GameStart();
00409 
00410     /** Function that will be called at the beginning of the playout phase.
00411         Will be called only once (not once per playout!). Can be used for
00412         example to save some state of the current position for more efficient
00413         implementation of TakeBackPlayout().
00414         Default implementation does nothing.
00415     */
00416     virtual void StartPlayouts();
00417 
00418     /** Function that will be called at the beginning of each playout.
00419         Default implementation does nothing.
00420     */
00421     virtual void StartPlayout();
00422 
00423     /** Function that will be called after each playout.
00424         Default implementation does nothing.
00425     */
00426     virtual void EndPlayout();
00427 
00428     // @} // name
00429 };
00430 
00431 //----------------------------------------------------------------------------
00432 
00433 class SgUctSearch;
00434 
00435 /** Create game specific thread state.
00436     @see SgUctThreadState
00437     @ingroup sguctgroup
00438 */
00439 class SgUctThreadStateFactory
00440 {
00441 public:
00442     virtual ~SgUctThreadStateFactory();
00443 
00444     virtual SgUctThreadState* Create(std::size_t threadId,
00445                                      const SgUctSearch& search) = 0;
00446 };
00447 
00448 //----------------------------------------------------------------------------
00449 
00450 /** Statistics of the last search performed by SgUctSearch. */
00451 struct SgUctSearchStat
00452 {
00453     double m_time;
00454 
00455     /** Number of nodes for which the knowledge threshold was exceeded. */ 
00456     std::size_t m_knowledge;
00457 
00458     /** Games per second.
00459         Useful values only if search time is higher than resolution of
00460         SgTime::Get().
00461     */
00462     double m_gamesPerSecond;
00463 
00464     SgUctStatisticsExt m_gameLength;
00465 
00466     SgUctStatisticsExt m_movesInTree;
00467 
00468     SgUctStatistics m_aborted;
00469 
00470     void Clear();
00471 
00472     void Write(std::ostream& out) const;
00473 };
00474 
00475 //----------------------------------------------------------------------------
00476 
00477 /** Optional parameters to SgUctSearch::Search() to allow early aborts.
00478     If early abort is used, the search will be aborted after a fraction of the
00479     resources (max time, max nodes) are spent, if the value is a clear win
00480     (above a threshold).
00481 */
00482 struct SgUctEarlyAbortParam
00483 {
00484     /** The threshold to define what a clear win is. */
00485     float m_threshold;
00486 
00487     /** The minimum number of games to allow an early abort.
00488         For a very low number of simulations, the value can be very
00489         unreliable.
00490     */
00491     std::size_t m_minGames;
00492 
00493     /** The inverse fraction of the total resources (max time, max nodes),
00494         after which the early abort check is performed.
00495     */
00496     int m_reductionFactor;
00497 };
00498 
00499 //----------------------------------------------------------------------------
00500 
00501 /** Monte Carlo tree search using UCT.
00502     The evaluation function is assumed to be in <code>[0..1]</code> and
00503     inverted with <code>1 - eval</code>.
00504     @ingroup sguctgroup
00505 */
00506 class SgUctSearch
00507 {
00508 public:
00509     static float InverseEval(float eval);
00510 
00511     /** Constructor.
00512         @param threadStateFactory The tread state factory (takes ownership).
00513         Can be null and set later (before using the search) with
00514         SetThreadStateFactory to allow multi-step construction.
00515         @param moveRange Upper integer limit (exclusive) used for move
00516         representation. Certain enhancements of SgUctSearch (e.g. Rave())
00517         need to store data in arrays using the move as an index for
00518         efficient implementation. If the game does not use a small integer
00519         range for its move representation, this parameter should be 0.
00520         Then, enhancements that require a small move range cannot be enabled.
00521     */
00522     SgUctSearch(SgUctThreadStateFactory* threadStateFactory,
00523                 int moveRange = 0);
00524 
00525     virtual ~SgUctSearch();
00526 
00527     void SetThreadStateFactory(SgUctThreadStateFactory* factory);
00528 
00529     /** @name Pure virtual functions */
00530     // @{
00531 
00532     /** Convert move to string (game dependent).
00533         This function needs to be thread-safe.
00534     */
00535     virtual std::string MoveString(SgMove move) const = 0;
00536 
00537     /** Evaluation value to use if evaluation is unknown.
00538         This value will be used, if games are aborted, because they exceed
00539         the maximum game length.
00540         This function needs to be thread-safe.
00541     */
00542     virtual float UnknownEval() const = 0;
00543 
00544     // @} // name
00545 
00546 
00547     /** @name Virtual functions */
00548     // @{
00549 
00550     /** Hook function that will be called by Search() after each game.
00551         Default implementation does nothing.
00552         This function does not need to be thread-safe.
00553         @param gameNumber The number of this iteration.
00554         @param threadId
00555         @param info The game info of the thread which played this iteration.
00556         @warning If LockFree() is enabled, this function will be called from
00557         multiple threads without locking. The subclass should handle this
00558         case appropriately by using its own lock or disabling functionality
00559         that will not work without locking.
00560     */
00561     virtual void OnSearchIteration(std::size_t gameNumber, int threadId,
00562                                    const SgUctGameInfo& info);
00563 
00564     /** Hook function that will be called by StartSearch().
00565         Default implementation calls m_mpiSynchronizer.StartSearch().
00566         This function does not need to be thread-safe.
00567     */
00568     virtual void OnStartSearch();
00569 
00570     /** Hook function that will be called when search
00571     completes.  Default implementation calls
00572     m_mpiSynchronizer.EndSearch().  This function
00573     does not need to be thread-safe.
00574     */
00575     virtual void OnEndSearch();
00576 
00577     virtual void OnThreadStartSearch(SgUctThreadState& state);
00578 
00579     virtual void OnThreadEndSearch(SgUctThreadState& state);
00580 
00581     virtual std::size_t GamesPlayed() const;
00582 
00583     // @} // name
00584 
00585 
00586     /** @name Search functions */
00587     // @{
00588 
00589     /** Get a list of all generated moves.
00590         Sets up thread state 0 for a seach and calls GenerateAllMoves
00591         of the thread state.
00592     */
00593     void GenerateAllMoves(std::vector<SgMoveInfo>& moves);
00594 
00595     /** Play a single game.
00596         Plays a single game using the thread state of the first thread.
00597         Call StartSearch() before calling this function.
00598     */
00599     void PlayGame();
00600 
00601     /** Start search.
00602         Initializes search for current position and clears statistics.
00603         @param rootFilter Moves to filter at the root node
00604         @param initTree The tree to initialize the search with. 0 for no
00605         initialization. The trees are actually swapped, not copied.
00606     */
00607     void StartSearch(const std::vector<SgMove>& rootFilter
00608                      = std::vector<SgMove>(),
00609                      SgUctTree* initTree = 0);
00610 
00611     void EndSearch();
00612 
00613     /** Calls StartSearch() and then maxGames times PlayGame().
00614         @param maxGames The maximum number of games (greater or equal one).
00615         @param maxTime The maximum time in seconds.
00616         @param[out] sequence The move sequence with the best value.
00617         @param rootFilter Moves to filter at the root node
00618         @param initTree The tree to initialize the search with. 0 for no
00619         initialization. The trees are actually swapped, not copied.
00620         @param earlyAbort See SgUctEarlyAbortParam. Null means not to do an
00621         early abort.
00622         @return The value of the root position.
00623     */
00624     float Search(std::size_t maxGames, double maxTime,
00625                  std::vector<SgMove>& sequence,
00626                  const std::vector<SgMove>& rootFilter
00627                  = std::vector<SgMove>(),
00628                  SgUctTree* initTree = 0,
00629                  SgUctEarlyAbortParam* earlyAbort = 0);
00630 
00631     /** Do a one-ply Monte-Carlo search instead of the UCT search.
00632         @param maxGames
00633         @param maxTime
00634         @param[out] value The value of the best move
00635     */
00636     SgPoint SearchOnePly(size_t maxGames, double maxTime, float& value);
00637 
00638     /** Find child node with best move.
00639         @param node The father node.
00640         @param excludeMoves Optional list of moves to ignore in the children
00641         nodes.
00642         @return The best child or 0 if no child nodes exists.
00643     */
00644     const SgUctNode*
00645     FindBestChild(const SgUctNode& node,
00646                   const std::vector<SgMove>* excludeMoves = 0) const;
00647 
00648     /** Extract sequence of best moves from root node.
00649         @param[out] sequence The resulting sequence.
00650     */
00651     void FindBestSequence(std::vector<SgMove>& sequence) const;
00652 
00653     /** Return the bound of a move.
00654         This is the bound that was used for move selection. It can be the
00655         pure UCT bound or the combined bound if RAVE is used.
00656         @param useRave Whether rave should be used or not.
00657         @param node The node corresponding to the position
00658         @param child The node corresponding to the move
00659     */
00660     float GetBound(bool useRave, const SgUctNode& node, 
00661                    const SgUctNode& child) const;
00662 
00663     // @} // name
00664 
00665 
00666     /** @name Search data */
00667     // @{
00668 
00669     /** Info for last game.
00670         Returns the last game info of the first thread.
00671         This function is not thread-safe.
00672     */
00673     const SgUctGameInfo& LastGameInfo() const;
00674 
00675     /** One-line summary text for last game.
00676         Contains: move, count and mean for all nodes; result
00677         Returns the last game info of the first thread.
00678         This function is not thread-safe.
00679     */
00680     std::string LastGameSummaryLine() const;
00681 
00682     /** See parameter earlyAbort in Search() */
00683     bool WasEarlyAbort() const;
00684 
00685     const SgUctTree& Tree() const;
00686 
00687     /** Get temporary tree.
00688         Returns a tree that is compatible in size and number of allocators
00689         to the tree of the search. This tree is used by the search itself as
00690         a temporary tree for certain operations during the search, but can be
00691         used by other code while the search is not running.
00692     */
00693     SgUctTree& GetTempTree();
00694 
00695     // @} // name
00696 
00697 
00698     /** @name Parameters */
00699     // @{
00700 
00701     /** Constant c in the bias term.
00702         This constant corresponds to 2 C_p in the original UCT paper.
00703         The default value is 0.7, which works well in 9x9 Go.
00704     */
00705     float BiasTermConstant() const;
00706 
00707     /** See BiasTermConstant() */
00708     void SetBiasTermConstant(float biasTermConstant);
00709 
00710     /** Points at which to recompute children.  
00711         Specifies the number of visits at which GenerateAllMoves() is
00712         called again at the node. This is to allow multiple knowledge
00713         computations to occur as a node becomes more
00714         important. Returned move info will be merged with info in the
00715         tree. This is can be used prune, add children, give a bonus to
00716         a move, etc.
00717     */
00718     std::vector<std::size_t> KnowledgeThreshold() const;
00719 
00720     /** See KnowledgeThreshold() */
00721     void SetKnowledgeThreshold(const std::vector<std::size_t>& counts);
00722 
00723     /** Maximum number of nodes in the tree.
00724         @note The search owns two trees, one of which is used as a temporary
00725         tree for some operations (see GetTempTree()). This functions sets
00726         the maximum number of nodes per tree.
00727     */
00728     std::size_t MaxNodes() const;
00729 
00730     /** See MaxNodes()
00731         @param maxNodes Maximum number of nodes (>= 1)
00732     */
00733     void SetMaxNodes(std::size_t maxNodes);
00734 
00735     /** The number of threads to use during the search. */
00736     std::size_t NumberThreads() const;
00737 
00738     /** See SetNumberThreads() */
00739     void SetNumberThreads(std::size_t n);
00740 
00741     /** Lock-free usage of multi-threaded search.
00742         @ref sguctsearchlockfree
00743     */
00744     bool LockFree() const;
00745 
00746     /** See LockFree() */
00747     void SetLockFree(bool enable);
00748 
00749     /** See SetRandomizeRaveFrequency() */
00750     int RandomizeRaveFrequency() const;
00751 
00752     /** Randomly turns off rave with given frequency -
00753         once in every frequency child selections.
00754         Helps in rare cases where rave ignores the best move. 
00755         Set frequency to 0 to switch it off.
00756     */
00757     void SetRandomizeRaveFrequency(int frequency);
00758 
00759     /** Don't update RAVE value if opponent played the same move first.
00760         Default is false (since it depends on the game and move
00761         representation, if it should be used).
00762     */
00763     bool RaveCheckSame() const;
00764 
00765     /** See RaveCheckSame() */
00766     void SetRaveCheckSame(bool enable);
00767 
00768     /** First play urgency.
00769         The value for unexplored moves. According to UCT they should
00770         always be preferred to moves, that have been played at least once.
00771         According to the MoGo tech report, it can be useful to use smaller
00772         values (as low as 1) to encorouge early exploitation.
00773         Default value is 10000.
00774         @see @ref sguctsearchweights
00775     */
00776     float FirstPlayUrgency() const;
00777 
00778     /** See FirstPlayUrgency() */
00779     void SetFirstPlayUrgency(float firstPlayUrgency);
00780 
00781     /** Log one-line summary for each game during Search() to a file.
00782         @todo File name still is hard-coded to "uctsearch.log"
00783     */
00784     bool LogGames() const;
00785 
00786     /** See LogGames() */
00787     void SetLogGames(bool enable);
00788 
00789     /** Maximum game length.
00790         If the number of moves in a game exceed this length, it will be
00791         counted as a loss.
00792         The default is @c numeric_limits<size_t>::max()
00793     */
00794     std::size_t MaxGameLength() const;
00795 
00796     /** See MaxGameLength() */
00797     void SetMaxGameLength(std::size_t maxGameLength);
00798 
00799     /** Required number of simulations to expand a node in the tree.
00800         The default is 2, which means a node will be expanded on the second
00801         visit.
00802     */
00803     std::size_t ExpandThreshold() const;
00804 
00805     /** See ExpandThreshold() */
00806     void SetExpandThreshold(std::size_t expandThreshold);
00807 
00808     /** The number of playouts per simulated game.
00809         Useful for multi-threading to increase the workload of the threads.
00810         Default is 1.
00811     */
00812     std::size_t NumberPlayouts() const;
00813 
00814     void SetNumberPlayouts(std::size_t n);
00815 
00816     /** Use the RAVE algorithm (Rapid Action Value Estimation).
00817         See Gelly, Silver 2007 in the references in the class description.
00818         In difference to the original description of the RAVE algorithm,
00819         no "RAVE bias term" is used. The estimated value of a move is the
00820         weighted mean of the move value and the RAVE value and then a
00821         single UCT-like bias term is added.
00822         @see RaveWeightFunc
00823     */
00824     bool Rave() const;
00825 
00826     /** See Rave() */
00827     void SetRave(bool enable);
00828 
00829     /** See SgUctMoveSelect */
00830     SgUctMoveSelect MoveSelect() const;
00831 
00832     /** See SgUctMoveSelect */
00833     void SetMoveSelect(SgUctMoveSelect moveSelect);
00834 
00835     /** See @ref sguctsearchweights. */
00836     float RaveWeightInitial() const;
00837 
00838     /** See @ref sguctsearchweights. */
00839     void SetRaveWeightInitial(float value);
00840 
00841     /** See @ref sguctsearchweights. */
00842     float RaveWeightFinal() const;
00843 
00844     /** See @ref sguctsearchweights. */
00845     void SetRaveWeightFinal(float value);
00846 
00847     /** Weight RAVE updates.
00848         Gives more weight to moves that are closer to the position for which
00849         the RAVE statistics are stored. The weighting function is linearly
00850         decreasing from 2 to 0 with the move number from the position for
00851         which the RAVE statistics are stored to the end of the simulated game.
00852     */
00853     bool WeightRaveUpdates() const;
00854 
00855     /** See WeightRaveUpdates() */
00856     void SetWeightRaveUpdates(bool enable);
00857 
00858     /** Whether search uses virtual loss. */
00859     bool VirtualLoss() const;
00860 
00861     /** See VirtualLoss() */
00862     void SetVirtualLoss(bool enable);
00863 
00864     /** Prune nodes with low counts if tree is full.
00865         This will prune nodes below a minimum count, if the tree gets full
00866         during a search. The minimum count is PruneMinCount() at the beginning
00867         of the search and is doubled every time a pruning operation does not
00868         reduce the tree by at least a factor of 2. The creation of the pruned
00869         tree uses the temporary tree (see GetTempTree()).
00870     */
00871     bool PruneFullTree() const;
00872 
00873     /** See PruneFullTree() */
00874     void SetPruneFullTree(bool enable);
00875 
00876     /** See PruneFullTree() */
00877     std::size_t PruneMinCount() const;
00878 
00879     /** See PruneFullTree() */
00880     void SetPruneMinCount(std::size_t n);
00881 
00882 
00883     void SetMpiSynchronizer(const SgMpiSynchronizerHandle &synchronizerHandle);
00884 
00885     SgMpiSynchronizerHandle MpiSynchronizer();
00886 
00887     const SgMpiSynchronizerHandle MpiSynchronizer() const;
00888 
00889     // @} // name
00890 
00891 
00892     /** @name Statistics */
00893     // @{
00894 
00895     const SgUctSearchStat& Statistics() const;
00896 
00897     void WriteStatistics(std::ostream& out) const;
00898 
00899     // @} // name
00900 
00901     /** Get state of one of the threads.
00902         Requires: ThreadsCreated()
00903     */
00904     SgUctThreadState& ThreadState(int i) const;
00905 
00906     /** Check if threads are already created.
00907         The threads are created at the beginning of the first search
00908         (to allow multi-step construction with setting the policy after
00909         the constructor call).
00910     */
00911     bool ThreadsCreated() const;
00912 
00913     /** Create threads.
00914         The threads are created at the beginning of the first search
00915         (to allow multi-step construction with setting the policy after
00916         the constructor call). This function needs to be called explicitely
00917         only, if a thread state is going to be used before the first search.
00918     */
00919     void CreateThreads();
00920 
00921 private:
00922     typedef boost::recursive_mutex::scoped_lock GlobalLock;
00923 
00924     friend class Thread;
00925 
00926     class Thread
00927     {
00928     public:
00929         std::auto_ptr<SgUctThreadState> m_state;
00930 
00931         Thread(SgUctSearch& search, std::auto_ptr<SgUctThreadState> state);
00932 
00933         ~Thread();
00934 
00935         void StartPlay();
00936 
00937         void WaitPlayFinished();
00938 
00939     private:
00940         /** Copyable function object that invokes Thread::operator().
00941             Needed because the the constructor of boost::thread copies the
00942             function object argument.
00943         */
00944         class Function
00945         {
00946         public:
00947             Function(Thread& thread);
00948 
00949             void operator()();
00950 
00951         private:
00952             Thread& m_thread;
00953         };
00954 
00955         friend class Thread::Function;
00956 
00957         SgUctSearch& m_search;
00958 
00959         bool m_quit;
00960 
00961         boost::barrier m_threadReady;
00962 
00963         boost::mutex m_startPlayMutex;
00964 
00965         boost::mutex m_playFinishedMutex;
00966 
00967         boost::condition m_startPlay;
00968 
00969         boost::condition m_playFinished;
00970 
00971         boost::mutex::scoped_lock m_playFinishedLock;
00972 
00973         GlobalLock m_globalLock;
00974 
00975         /** The thread.
00976             Order dependency: must be constructed as the last member, because
00977             the constructor starts the thread.
00978         */
00979         boost::thread m_thread;
00980 
00981         void operator()();
00982 
00983         void PlayGames();
00984     };
00985 
00986     std::auto_ptr<SgUctThreadStateFactory> m_threadStateFactory;
00987 
00988     /** See LogGames() */
00989     bool m_logGames;
00990 
00991     /** See Rave() */
00992     bool m_rave;
00993    
00994     /** See KnowledgeThreshold() */
00995     std::vector<std::size_t> m_knowledgeThreshold;
00996 
00997     /** Flag indicating that the search was terminated because the maximum
00998         time or number of games was reached.
00999     */
01000     volatile bool m_aborted;
01001     
01002     volatile bool m_isTreeOutOfMemory;
01003 
01004     std::auto_ptr<boost::barrier> m_searchLoopFinished;
01005 
01006     /** See SgUctEarlyAbortParam. */
01007     bool m_wasEarlyAbort;
01008 
01009     /** See SgUctEarlyAbortParam.
01010         The auto pointer is empty, if no early abort is used.
01011     */
01012     std::auto_ptr<SgUctEarlyAbortParam> m_earlyAbort;
01013 
01014     /** See SgUctMoveSelect */
01015     SgUctMoveSelect m_moveSelect;
01016 
01017     /** See RaveCheckSame() */
01018     bool m_raveCheckSame;
01019 
01020     /** See SetRandomizeRaveFrequency() */
01021     int m_randomizeRaveFrequency;
01022 
01023     /** See LockFree() */
01024     bool m_lockFree;
01025 
01026     /** See WeightRaveUpdates() */
01027     bool m_weightRaveUpdates;
01028 
01029     /** See PruneFullTree() */
01030     bool m_pruneFullTree;
01031 
01032     /** See NumberThreads() */
01033     std::size_t m_numberThreads;
01034 
01035     /** See NumberPlayouts() */
01036     std::size_t m_numberPlayouts;
01037 
01038     /** See MaxNodes() */
01039     std::size_t m_maxNodes;
01040 
01041     /** See PruneMinCount() */
01042     std::size_t m_pruneMinCount;
01043 
01044     /** See parameter moveRange in constructor */
01045     const int m_moveRange;
01046 
01047     /** See MaxGameLength() */
01048     std::size_t m_maxGameLength;
01049 
01050     /** See ExpandThreshold() */
01051     std::size_t m_expandThreshold;
01052 
01053     /** Number of games limit for the current search. */
01054     std::size_t m_maxGames;
01055 
01056     /** Number of games played in the current search. */
01057     std::size_t m_numberGames;
01058 
01059     std::size_t m_startRootMoveCount;
01060 
01061     /** Interval in number of games in which to check time abort.
01062         Avoids that the potentially expensive SgTime::Get() is called after
01063         every game. The interval is updated dynamically according to the
01064         current games/sec, such that it is called ten times per second
01065         (if the total search time is at least one second, otherwise ten times
01066         per total maximum search time)
01067     */
01068     std::size_t m_checkTimeInterval;
01069 
01070     double m_lastScoreDisplayTime;
01071 
01072     /** See BiasTermConstant() */
01073     float m_biasTermConstant;
01074 
01075     /** See FirstPlayUrgency() */
01076     float m_firstPlayUrgency;
01077 
01078     /** See @ref sguctsearchweights. */
01079     float m_raveWeightInitial;
01080 
01081     /** See @ref sguctsearchweights. */
01082     float m_raveWeightFinal;
01083 
01084     /** 1 / m_raveWeightInitial precomputed for efficiency */
01085     double m_raveWeightParam1;
01086 
01087     /** m_raveWeightInitial / m_raveWeightFinal precomputed for efficiency */
01088     double m_raveWeightParam2;
01089 
01090     /** Time limit for current search. */
01091     double m_maxTime;
01092 
01093     /** See VirtualLoss() */
01094     bool m_virtualLoss;
01095 
01096     std::string m_logFileName;
01097 
01098     SgTimer m_timer;
01099 
01100     SgUctTree m_tree;
01101 
01102     /** See GetTempTree() */
01103     SgUctTree m_tempTree;
01104 
01105     /** See parameter rootFilter in function Search() */
01106     std::vector<SgMove> m_rootFilter;
01107 
01108     std::ofstream m_log;
01109 
01110     /** Mutex for protecting global variables during multi-threading.
01111         Currently, only the play-out phase of games is thread safe, therefore
01112         this lock is always locked elsewhere (in-tree phase, updating of
01113         values and statistics, etc.)
01114     */
01115     boost::recursive_mutex m_globalMutex;
01116 
01117     SgUctSearchStat m_statistics;
01118 
01119     /** List of threads.
01120         The elements are owned by the vector (shared_ptr is only used because
01121         auto_ptr should not be used with standard containers)
01122     */
01123     std::vector<boost::shared_ptr<Thread> > m_threads;
01124 
01125 #if SG_UCTFASTLOG
01126     SgFastLog m_fastLog;
01127 #endif
01128 
01129     boost::shared_ptr<SgMpiSynchronizer> m_mpiSynchronizer;
01130 
01131 
01132     void ApplyRootFilter(std::vector<SgMoveInfo>& moves);
01133 
01134     bool CheckAbortSearch(SgUctThreadState& state);
01135 
01136     bool CheckEarlyAbort() const;
01137 
01138     bool CheckCountAbort(SgUctThreadState& state,
01139                          std::size_t remainingGames) const;
01140 
01141     void Debug(const SgUctThreadState& state, const std::string& textLine);
01142 
01143     void DeleteThreads();
01144 
01145     void ExpandNode(SgUctThreadState& state, const SgUctNode& node);
01146 
01147     void CreateChildren(SgUctThreadState& state, const SgUctNode& node,
01148                         bool deleteChildTrees);
01149 
01150     float GetBound(bool useRave, float logPosCount, 
01151                    const SgUctNode& child) const;
01152 
01153     float GetValueEstimate(bool useRave, const SgUctNode& child) const;
01154 
01155     float GetValueEstimateRave(const SgUctNode& child) const;
01156 
01157     float Log(float x) const;
01158 
01159     bool NeedToComputeKnowledge(const SgUctNode* current);
01160 
01161     void PlayGame(SgUctThreadState& state, GlobalLock* lock);
01162 
01163     bool PlayInTree(SgUctThreadState& state, bool& isTerminal);
01164 
01165     bool PlayoutGame(SgUctThreadState& state, std::size_t playout);
01166 
01167     void PrintSearchProgress(double currTime) const;
01168     
01169     void SearchLoop(SgUctThreadState& state, GlobalLock* lock);
01170 
01171     const SgUctNode& SelectChild(int& randomizeCounter, const SgUctNode& node);
01172 
01173     std::string SummaryLine(const SgUctGameInfo& info) const;
01174 
01175     void UpdateCheckTimeInterval(double time);
01176 
01177     void UpdateDynRaveBias();
01178 
01179     void UpdateRaveValues(SgUctThreadState& state);
01180 
01181     void UpdateRaveValues(SgUctThreadState& state, std::size_t playout);
01182 
01183     void UpdateRaveValues(SgUctThreadState& state, std::size_t playout,
01184                           float eval, std::size_t i,
01185                           const std::size_t firstPlay[],
01186                           const std::size_t firstPlayOpp[]);
01187 
01188     void UpdateStatistics(const SgUctGameInfo& info);
01189 
01190     void UpdateTree(const SgUctGameInfo& info);
01191 };
01192 
01193 inline float SgUctSearch::BiasTermConstant() const
01194 {
01195     return m_biasTermConstant;
01196 }
01197 
01198 inline std::size_t SgUctSearch::ExpandThreshold() const
01199 {
01200     return m_expandThreshold;
01201 }
01202 
01203 inline float SgUctSearch::FirstPlayUrgency() const
01204 {
01205     return m_firstPlayUrgency;
01206 }
01207 
01208 inline float SgUctSearch::InverseEval(float eval)
01209 {
01210     return (1 - eval);
01211 }
01212 
01213 inline bool SgUctSearch::LockFree() const
01214 {
01215     return m_lockFree;
01216 }
01217 
01218 inline const SgUctGameInfo& SgUctSearch::LastGameInfo() const
01219 {
01220     return ThreadState(0).m_gameInfo;
01221 }
01222 
01223 inline bool SgUctSearch::LogGames() const
01224 {
01225     return m_logGames;
01226 }
01227 
01228 inline std::size_t SgUctSearch::MaxGameLength() const
01229 {
01230     return m_maxGameLength;
01231 }
01232 
01233 inline std::size_t SgUctSearch::MaxNodes() const
01234 {
01235     return m_maxNodes;
01236 }
01237 
01238 inline SgUctMoveSelect SgUctSearch::MoveSelect() const
01239 {
01240     return m_moveSelect;
01241 }
01242 
01243 inline std::size_t SgUctSearch::NumberThreads() const
01244 {
01245     return m_numberThreads;
01246 }
01247 
01248 inline std::size_t SgUctSearch::NumberPlayouts() const
01249 {
01250     return m_numberPlayouts;
01251 }
01252 
01253 inline void SgUctSearch::PlayGame()
01254 {
01255     PlayGame(ThreadState(0), 0);
01256 }
01257 
01258 inline bool SgUctSearch::PruneFullTree() const
01259 {
01260     return m_pruneFullTree;
01261 }
01262 
01263 inline std::size_t SgUctSearch::PruneMinCount() const
01264 {
01265     return m_pruneMinCount;
01266 }
01267 
01268 inline bool SgUctSearch::Rave() const
01269 {
01270     return m_rave;
01271 }
01272 
01273 inline bool SgUctSearch::RaveCheckSame() const
01274 {
01275     return m_raveCheckSame;
01276 }
01277 
01278 inline float SgUctSearch::RaveWeightInitial() const
01279 {
01280     return m_raveWeightInitial;
01281 }
01282 
01283 inline float SgUctSearch::RaveWeightFinal() const
01284 {
01285     return m_raveWeightFinal;
01286 }
01287 
01288 inline void SgUctSearch::SetBiasTermConstant(float biasTermConstant)
01289 {
01290     m_biasTermConstant = biasTermConstant;
01291 }
01292 
01293 inline void SgUctSearch::SetExpandThreshold(std::size_t expandThreshold)
01294 {
01295     SG_ASSERT(expandThreshold >= 1);
01296     m_expandThreshold = expandThreshold;
01297 }
01298 
01299 inline void SgUctSearch::SetFirstPlayUrgency(float firstPlayUrgency)
01300 {
01301     m_firstPlayUrgency = firstPlayUrgency;
01302 }
01303 
01304 inline void SgUctSearch::SetLockFree(bool enable)
01305 {
01306     m_lockFree = enable;
01307 }
01308 
01309 inline void SgUctSearch::SetLogGames(bool enable)
01310 {
01311     m_logGames = enable;
01312 }
01313 
01314 inline void SgUctSearch::SetMaxGameLength(std::size_t maxGameLength)
01315 {
01316     m_maxGameLength = maxGameLength;
01317 }
01318 
01319 inline void SgUctSearch::SetMaxNodes(std::size_t maxNodes)
01320 {
01321     m_maxNodes = maxNodes;
01322     if (m_threads.size() > 0) // Threads already created
01323         m_tree.SetMaxNodes(m_maxNodes);
01324 }
01325 
01326 inline void SgUctSearch::SetMoveSelect(SgUctMoveSelect moveSelect)
01327 {
01328     m_moveSelect = moveSelect;
01329 }
01330 
01331 inline std::vector<std::size_t> SgUctSearch::KnowledgeThreshold() const
01332 {
01333     return m_knowledgeThreshold;
01334 }
01335 
01336 inline void 
01337 SgUctSearch::SetKnowledgeThreshold(const std::vector<std::size_t>& t)
01338 {
01339     m_knowledgeThreshold = t;
01340 }
01341 
01342 inline void SgUctSearch::SetNumberPlayouts(std::size_t n)
01343 {
01344     SG_ASSERT(n >= 1);
01345     m_numberPlayouts = n;
01346 }
01347 
01348 inline void SgUctSearch::SetPruneFullTree(bool enable)
01349 {
01350     m_pruneFullTree = enable;
01351 }
01352 
01353 inline void SgUctSearch::SetPruneMinCount(std::size_t n)
01354 {
01355     m_pruneMinCount = n;
01356 }
01357 
01358 inline void SgUctSearch::SetMpiSynchronizer(const SgMpiSynchronizerHandle 
01359                                             &synchronizerHandle)
01360 {
01361     m_mpiSynchronizer = SgMpiSynchronizerHandle(synchronizerHandle);
01362 }
01363 
01364 inline SgMpiSynchronizerHandle SgUctSearch::MpiSynchronizer()
01365 {
01366     return SgMpiSynchronizerHandle(m_mpiSynchronizer);
01367 }
01368 
01369 inline const SgMpiSynchronizerHandle SgUctSearch::MpiSynchronizer() const
01370 {
01371     return SgMpiSynchronizerHandle(m_mpiSynchronizer);
01372 }
01373 
01374 inline int SgUctSearch::RandomizeRaveFrequency() const
01375 {
01376     return m_randomizeRaveFrequency;
01377 }
01378 
01379 inline void SgUctSearch::SetRandomizeRaveFrequency(int frequency)
01380 {
01381     m_randomizeRaveFrequency = frequency;    
01382 }
01383 
01384 inline void SgUctSearch::SetRaveCheckSame(bool enable)
01385 {
01386     m_raveCheckSame = enable;
01387 }
01388 
01389 inline void SgUctSearch::SetRaveWeightFinal(float value)
01390 {
01391     m_raveWeightFinal = value;
01392 }
01393 
01394 inline void SgUctSearch::SetRaveWeightInitial(float value)
01395 {
01396     m_raveWeightInitial = value;
01397 }
01398 
01399 inline void SgUctSearch::SetWeightRaveUpdates(bool enable)
01400 {
01401     m_weightRaveUpdates = enable;
01402 }
01403 
01404 inline bool SgUctSearch::VirtualLoss() const
01405 {
01406     return m_virtualLoss;
01407 }
01408 
01409 inline void SgUctSearch::SetVirtualLoss(bool enable)
01410 {
01411     m_virtualLoss = enable;
01412 }
01413 
01414 inline const SgUctSearchStat& SgUctSearch::Statistics() const
01415 {
01416     return m_statistics;
01417 }
01418 
01419 inline bool SgUctSearch::ThreadsCreated() const
01420 {
01421     return (m_threads.size() > 0);
01422 }
01423 
01424 inline SgUctThreadState& SgUctSearch::ThreadState(int i) const
01425 {
01426     SG_ASSERT(static_cast<std::size_t>(i) < m_threads.size());
01427     return *m_threads[i]->m_state;
01428 }
01429 
01430 inline const SgUctTree& SgUctSearch::Tree() const
01431 {
01432     return m_tree;
01433 }
01434 
01435 inline bool SgUctSearch::WasEarlyAbort() const
01436 {
01437     return m_wasEarlyAbort;
01438 }
01439 
01440 inline bool SgUctSearch::WeightRaveUpdates() const
01441 {
01442     return m_weightRaveUpdates;
01443 }
01444 
01445 //----------------------------------------------------------------------------
01446 
01447 #endif // SG_UCTSEARCH_H


17 Jun 2010 Doxygen 1.4.7