Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

Book.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file Book.cpp
00003 */
00004 //----------------------------------------------------------------------------
00005 
00006 #include <cmath>
00007 #include <boost/numeric/conversion/bounds.hpp>
00008 
00009 #include "BitsetIterator.hpp"
00010 #include "Book.hpp"
00011 #include "HexModState.hpp"
00012 #include "Time.hpp"
00013 
00014 using namespace benzene;
00015 
00016 //----------------------------------------------------------------------------
00017 
00018 /** Dump debug info. */
00019 #define OUTPUT_OB_INFO 1
00020 
00021 //----------------------------------------------------------------------------
00022 
00023 /** Current version for book databases. 
00024     Update this if BookNode changes to prevent old out-of-date books
00025     being loaded. */
00026 const std::string Book::BOOK_DB_VERSION = "BENZENE_BOOK_VER_0001";
00027 
00028 //----------------------------------------------------------------------------
00029 
00030 float BookUtil::Value(const SgBookNode& node, const HexState& state)
00031 {
00032     if (state.Position().IsLegal(SWAP_PIECES))
00033         return std::max(node.m_value, BookUtil::InverseEval(node.m_value));
00034     return node.m_value;
00035 }
00036 
00037 float BookUtil::Score(const SgBookNode& node, const HexState& state, 
00038                       float countWeight)
00039 {
00040     float score = BookUtil::InverseEval(Value(node, state));
00041     if (!node.IsTerminal())
00042         score += log(node.m_count + 1) * countWeight;
00043     return score;   
00044 }
00045 
00046 float BookUtil::InverseEval(float eval)
00047 {
00048     if (HexEvalUtil::IsWinOrLoss(eval))
00049         return -eval;
00050     if (eval < 0 || eval > 1)
00051         LogInfo() << "eval = " << eval << '\n';
00052     HexAssert(0 <= eval && eval <= 1.0);
00053     return 1.0 - eval;
00054 }
00055 
00056 //----------------------------------------------------------------------------
00057 
00058 int BookUtil::GetMainLineDepth(const Book& book, const HexState& origState)
00059 {
00060     int depth = 0;
00061     HexState state(origState);
00062     for (;;) 
00063     {
00064         HexBookNode node;
00065         if (!book.Get(state, node))
00066             break;
00067         HexPoint move = INVALID_POINT;
00068         float value = -1e9;
00069         for (BitsetIterator p(state.Position().GetEmpty()); p; ++p)
00070         {
00071             state.PlayMove(*p);
00072             HexBookNode child;
00073             if (book.Get(state, child))
00074             {
00075                 float curValue = InverseEval(BookUtil::Value(child, state));
00076                 if (curValue > value)
00077                 {
00078                     value = curValue;
00079                     move = *p;
00080                 }
00081             }
00082             state.UndoMove(*p);
00083         }
00084         if (move == INVALID_POINT)
00085             break;
00086         state.PlayMove(move);
00087         depth++;
00088     }
00089     return depth;
00090 }
00091 
00092 namespace 
00093 {
00094 
00095 std::size_t TreeSize(const Book& book, HexState& state, 
00096                      StateMap<std::size_t>& solved)
00097 {
00098     if (solved.Exists(state))
00099         return solved[state];
00100     HexBookNode node;
00101     if (!book.Get(state, node))
00102         return 0;
00103     std::size_t ret = 1;
00104     for (BitsetIterator p(state.Position().GetEmpty()); p; ++p) 
00105     {
00106         state.PlayMove(*p);
00107         ret += TreeSize(book, state, solved);
00108         state.UndoMove(*p);
00109     }
00110     solved[state] = ret;
00111     return ret;
00112 }
00113 
00114 }
00115 
00116 std::size_t BookUtil::GetTreeSize(const Book& book, const HexState& origState)
00117 {
00118     StateMap<std::size_t> solved;
00119     HexState state(origState);
00120     return TreeSize(book, state, solved);
00121 }
00122 
00123 //----------------------------------------------------------------------------
00124 
00125 HexPoint BookUtil::BestMove(const Book& book, const HexState& origState,
00126                             unsigned minCount, float countWeight)
00127 {
00128     HexBookNode node;
00129     if (!book.Get(origState, node) || node.m_count < minCount)
00130         return INVALID_POINT;
00131 
00132     float bestScore = -1e9;
00133     HexPoint bestChild = INVALID_POINT;
00134     HexState state(origState);
00135     for (BitsetIterator p(state.Position().GetEmpty()); p; ++p)
00136     {
00137         state.PlayMove(*p);
00138         HexBookNode child;
00139         if (book.Get(state, child))
00140         {
00141             float score = BookUtil::Score(child, state, countWeight);
00142             if (score > bestScore)
00143             {
00144                 bestScore = score;
00145                 bestChild = *p;
00146             }
00147         }
00148         state.UndoMove(*p);
00149     }
00150     HexAssert(bestChild != INVALID_POINT);
00151     return bestChild;
00152 }
00153 
00154 //----------------------------------------------------------------------------
00155 
00156 void BookUtil::DumpVisualizationData(const Book& book,
00157                                      const HexState& origState, int depth, 
00158                                      std::ostream& out)
00159 {
00160     HexBookNode node;
00161     if (!book.Get(origState, node))
00162         return;
00163     if (node.IsLeaf())
00164     {
00165         out << BookUtil::Value(node, origState) << " " << depth << '\n';
00166         return;
00167     }
00168     HexModState modState(origState);
00169     HexState state = modState.State();
00170     for (BitsetIterator i(state.Position().GetEmpty()); i; ++i) 
00171     {
00172     state.PlayMove( *i);
00173         DumpVisualizationData(book, state, depth + 1, out);
00174         state.UndoMove(*i);
00175     }
00176 }
00177 
00178 namespace {
00179 
00180 void DumpPolarizedLeafs(const Book& book, HexState& state,
00181                         float polarization, StateSet& seen,
00182                         PointSequence& pv, std::ostream& out,
00183                         const StateSet& ignoreSet)
00184 {
00185     if (seen.Exists(state))
00186         return;
00187     HexBookNode node;
00188     if (!book.Get(state, node))
00189         return;
00190     if (fabs(BookUtil::Value(node, state) - 0.5) >= polarization 
00191         && node.IsLeaf() && !node.IsTerminal()
00192         && ignoreSet.Exists(state))
00193     {
00194         out << HexPointUtil::ToString(pv) << '\n';
00195         seen.Insert(state);
00196     }
00197     else
00198     {
00199         if (node.IsLeaf() || node.IsTerminal())
00200             return;
00201         for (BitsetIterator i(state.Position().GetEmpty()); i; ++i) 
00202         {
00203             state.PlayMove(*i);
00204             pv.push_back(*i);
00205             DumpPolarizedLeafs(book, state, polarization, seen, pv, out, 
00206                                ignoreSet);
00207             pv.pop_back();
00208             state.UndoMove(*i);
00209         }
00210         seen.Insert(state);
00211     } 
00212 }
00213 
00214 }
00215 
00216 void BookUtil::DumpPolarizedLeafs(const Book& book, const HexState& origState,
00217                                   float polarization, PointSequence& pv, 
00218                                   std::ostream& out, 
00219                                   const StateSet& ignoreSet)
00220 {
00221     StateSet seen;
00222     HexModState modState(origState);
00223     HexState state = modState.State();
00224     ::DumpPolarizedLeafs(book, state, polarization, seen, pv, out, ignoreSet);
00225 }
00226 
00227 void BookUtil::ImportSolvedStates(Book& book, const ConstBoard& constBoard,
00228                                   std::istream& positions)
00229 {
00230     StoneBoard brd(constBoard.Width(), constBoard.Height());
00231     HexState state(brd, FIRST_TO_PLAY);
00232     std::string text;
00233     std::size_t lineNumber = 0;
00234     std::size_t numParsed = 0;
00235     std::size_t numReplaced = 0;
00236     std::size_t numNew = 0;
00237     while (std::getline(positions, text))
00238     {
00239         ++lineNumber;
00240         std::istringstream is(text);
00241         PointSequence points;
00242         HexColor winner = EMPTY;
00243         bool parsed = false;
00244         while (true)
00245         {
00246             std::string token;
00247             is >> token;
00248             if (token == "black")
00249             {
00250                 winner = BLACK;
00251                 parsed = true;
00252                 break;
00253             } 
00254             else if (token == "white")
00255             {
00256                 winner = WHITE;
00257                 parsed = true;
00258                 break;
00259             }
00260             else
00261             {
00262                 HexPoint p = HexPointUtil::FromString(token);
00263                 if (p == INVALID_POINT)
00264                     break;
00265                 points.push_back(p);
00266             }
00267         }
00268         if (!parsed)
00269         {
00270             LogInfo() << "Skipping badly formed line " << lineNumber << ".\n";
00271             continue;
00272         }
00273         HexAssert(winner != EMPTY);
00274         
00275         ++numParsed;
00276         state.Position().StartNewGame();
00277         state.SetToPlay(FIRST_TO_PLAY);
00278         for (std::size_t i = 0; i < points.size(); ++i)
00279             state.PlayMove(points[i]);
00280         HexEval ourValue = (state.ToPlay() == winner) 
00281             ? IMMEDIATE_WIN : IMMEDIATE_LOSS;
00282         HexBookNode node;
00283         if (book.Get(state, node))
00284         {
00285             HexAssert(node.IsLeaf());
00286             HexAssert(!node.IsTerminal());
00287             node.m_value = ourValue;
00288             ++numReplaced;
00289         }
00290         else 
00291         {
00292             node = HexBookNode(ourValue);
00293             ++numNew;
00294         }
00295         book.Put(state, node);
00296     }
00297     book.Flush();
00298     LogInfo() << "   Lines: " << lineNumber << '\n';
00299     LogInfo() << "  Parsed: " << numParsed << '\n';
00300     LogInfo() << "Replaced: " << numReplaced << '\n';
00301     LogInfo() << "     New: " << numNew << '\n';
00302 }
00303 
00304 //----------------------------------------------------------------------------


6 Jan 2011 Doxygen 1.6.3