Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

GoUctUtil.cpp

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file GoUctUtil.cpp
00003 */
00004 //----------------------------------------------------------------------------
00005 
00006 #include "SgSystem.h"
00007 #include "GoUctUtil.h"
00008 
00009 #include <iomanip>
00010 #include <iostream>
00011 #include <boost/io/ios_state.hpp>
00012 #include "SgBWSet.h"
00013 #include "SgPointSet.h"
00014 #include "SgProp.h"
00015 #include "SgUctSearch.h"
00016 
00017 using namespace std;
00018 using boost::io::ios_all_saver;
00019 using SgPointUtil::Pt;
00020 using SgPropUtil::PointToSgfString;
00021 
00022 //----------------------------------------------------------------------------
00023 
00024 namespace {
00025 
00026 bool IsRectEmpty(const GoBoard& bd, int left, int right, int top, int bottom)
00027 {
00028     for (SgRectIterator it(SgRect(left, right, top, bottom)); it; ++it)
00029         if (! bd.IsEmpty(*it))
00030             return false;
00031     return true;
00032 }
00033 
00034 /** Recursive function to save the UCT tree in SGF format. */
00035 void SaveNode(ostream& out, const SgUctTree& tree, const SgUctNode& node,
00036               SgBlackWhite toPlay, int boardSize, int maxDepth, int depth)
00037 {
00038     out << "C[MoveCount " << node.MoveCount()
00039         << "\nPosCount " << node.PosCount()
00040         << "\nMean " << fixed << setprecision(2) << node.Mean();
00041     if (! node.HasChildren())
00042     {
00043         out << "]\n";
00044         return;
00045     }
00046     out << "\n\nRave:";
00047     for (SgUctChildIterator it(tree, node); it; ++it)
00048     {
00049         const SgUctNode& child = *it;
00050         SgPoint move = child.Move();
00051         if (child.HasRaveValue())
00052         {
00053             out << '\n' << SgWritePoint(move) << ' '
00054                 << fixed << setprecision(2) << child.RaveValue()
00055                 << " (" << child.RaveCount() << ')';
00056         }
00057     }
00058     out << "]\nLB";
00059     for (SgUctChildIterator it(tree, node); it; ++it)
00060     {
00061         const SgUctNode& child = *it;
00062         if (! child.HasMean())
00063             continue;
00064         out << "["
00065             << PointToSgfString(child.Move(), boardSize, SG_PROPPOINTFMT_GO)
00066             << ':' << child.MoveCount() << ']';
00067     }
00068     out << '\n';
00069     if (maxDepth >= 0 && depth >= maxDepth)
00070         return;
00071     for (SgUctChildIterator it(tree, node); it; ++it)
00072     {
00073         const SgUctNode& child = *it;
00074         if (! child.HasMean())
00075             continue;
00076         SgPoint move = child.Move();
00077         out << "(;" << (toPlay == SG_BLACK ? 'B' : 'W') << '['
00078             << PointToSgfString(move, boardSize, SG_PROPPOINTFMT_GO) << ']';
00079         SaveNode(out, tree, child, SgOppBW(toPlay), boardSize, maxDepth,
00080                  depth + 1);
00081         out << ")\n";
00082     }
00083 }
00084 
00085 } // namespace
00086 
00087 //----------------------------------------------------------------------------
00088 
00089 void GoUctUtil::ClearStatistics(SgPointArray<SgUctStatistics>& stats)
00090 {
00091     for (SgPointArray<SgUctStatistics>::NonConstIterator
00092              it(stats); it; ++it)
00093         (*it).Clear();
00094 }
00095 
00096 SgPoint GoUctUtil::GenForcedOpeningMove(const GoBoard& bd)
00097 {
00098     int sz = bd.Size();
00099     if (sz < 15 || bd.TotalNumStones(SG_BLACK) > 5
00100         || bd.TotalNumStones(SG_WHITE) > 5)
00101         return SG_NULLMOVE;
00102     SgSList<SgPoint,4> moves;
00103     if (IsRectEmpty(bd, 1, 5, 1, 5))
00104         moves.PushBack(Pt(4, 4));
00105     if (IsRectEmpty(bd, 1, 5, sz - 4, sz))
00106         moves.PushBack(Pt(4, sz - 3));
00107     if (IsRectEmpty(bd, sz - 4, sz, 1, 5))
00108         moves.PushBack(Pt(sz - 3, 4));
00109     if (IsRectEmpty(bd, sz - 4, sz, sz - 4, sz))
00110         moves.PushBack(Pt(sz - 3, sz - 3));
00111     if (moves.IsEmpty())
00112         return SG_NULLMOVE;
00113     return moves[SgRandom::Global().Int(moves.Length())];
00114 }
00115 
00116 void GoUctUtil::GfxBestMove(const SgUctSearch& search, SgBlackWhite toPlay,
00117                             ostream& out)
00118 {
00119     const SgUctTree& tree = search.Tree();
00120     const SgUctNode& root = tree.Root();
00121     out << "VAR";
00122     const SgUctNode* bestValueChild = search.FindBestChild(root);
00123     if (bestValueChild != 0)
00124     {
00125         SgPoint move = bestValueChild->Move();
00126         out << ' ' << (toPlay == SG_BLACK ? 'B' : 'W') << ' '
00127             << SgWritePoint(move);
00128     }
00129     out << '\n';
00130 }
00131 
00132 void GoUctUtil::GfxCounts(const SgUctTree& tree, ostream& out)
00133 {
00134     const SgUctNode& root = tree.Root();
00135     out << "LABEL";
00136     if (root.HasChildren())
00137         for (SgUctChildIterator it(tree, root); it; ++it)
00138         {
00139             const SgUctNode& child = *it;
00140             if (child.HasMean())
00141                 out << ' ' << SgWritePoint(child.Move()) << ' '
00142                     << child.MoveCount();
00143         }
00144     out << '\n';
00145 }
00146 
00147 void GoUctUtil::GfxMoveValues(const SgUctSearch& search, SgBlackWhite toPlay,
00148                               ostream& out)
00149 {
00150     const SgUctTree& tree = search.Tree();
00151     const SgUctNode& root = tree.Root();
00152     out << "INFLUENCE";
00153     if (root.HasChildren())
00154         for (SgUctChildIterator it(tree, root); it; ++it)
00155         {
00156             const SgUctNode& child = *it;
00157             if (! child.HasMean())
00158                 continue;
00159             float value = SgUctSearch::InverseEval(child.Mean());
00160             // Scale to [-1,+1], black positive
00161             double influence = value * 2 - 1;
00162             if (toPlay == SG_WHITE)
00163                 influence *= -1;
00164             SgPoint move = child.Move();
00165             out << ' ' << SgWritePoint(move) << ' ' << fixed
00166                 << setprecision(2) << influence;
00167         }
00168     out << '\n';
00169 }
00170 \
00171 void GoUctUtil::GfxSequence(const SgUctSearch& search, SgBlackWhite toPlay,
00172                             ostream& out)
00173 {
00174     vector<SgMove> sequence;
00175     search.FindBestSequence(sequence);
00176     out << "VAR";
00177     for (size_t i = 0; i < sequence.size(); ++i)
00178     {
00179         out << (toPlay == SG_BLACK ? " B ": " W ")
00180             << SgWritePoint(sequence[i]);
00181         toPlay = SgOppBW(toPlay);
00182     }
00183     out << '\n';
00184 }
00185 
00186 void GoUctUtil::GfxStatus(const SgUctSearch& search, ostream& out)
00187 {
00188     const SgUctTree& tree = search.Tree();
00189     const SgUctNode& root = tree.Root();
00190     const SgUctSearchStat& stat = search.Statistics();
00191     int abortPercent = static_cast<int>(stat.m_aborted.Mean() * 100);
00192     out << "TEXT N=" << root.MoveCount()
00193         << " V=" << setprecision(2) << root.Mean()
00194         << " Len=" << static_cast<int>(stat.m_gameLength.Mean())
00195         << " Tree=" << setprecision(1) << stat.m_movesInTree.Mean()
00196         << "/" << static_cast<int>(stat.m_movesInTree.Max())
00197         << " Abrt=" << abortPercent << '%'
00198         << " Gm/s=" << static_cast<int>(stat.m_gamesPerSecond) << '\n';
00199 }
00200 
00201 void GoUctUtil::GfxTerritoryStatistics(
00202                      const SgPointArray<SgUctStatistics>& territoryStatistics,
00203                      const GoBoard& bd, std::ostream& out)
00204 {
00205     ios_all_saver saver(out);
00206     out << fixed << setprecision(3) << "INFLUENCE";
00207     for (GoBoard::Iterator it(bd); it; ++it)
00208         if (territoryStatistics[*it].Count() > 0)
00209             // Scale to [-1,+1], black positive
00210             out << ' ' << SgWritePoint(*it) << ' '
00211                 << territoryStatistics[*it].Mean() * 2 - 1;
00212     out << '\n';
00213 }
00214 
00215 void GoUctUtil::SaveTree(const SgUctTree& tree, int boardSize,
00216                          const SgBWSet& stones, SgBlackWhite toPlay,
00217                          ostream& out, int maxDepth)
00218 {
00219     out << "(;FF[4]GM[1]SZ[" << boardSize << "]\n";
00220     for (SgBWIterator itColor; itColor; ++itColor)
00221     {
00222         const SgPointSet& stonesColor = stones[*itColor];
00223         if (stonesColor.Size() == 0)
00224             continue;
00225         out << ((*itColor) == SG_BLACK ? "AB" : "AW");
00226         for (SgSetIterator it(stonesColor); it; ++it)
00227             out << '[' << PointToSgfString(*it, boardSize, SG_PROPPOINTFMT_GO)
00228                 << ']';
00229         out << '\n';
00230     }
00231     out << "PL[" << (toPlay == SG_BLACK ? "B" : "W") << "]\n";
00232     SaveNode(out, tree, tree.Root(), toPlay, boardSize, maxDepth, 0);
00233     out << ")\n";
00234 }
00235 
00236 namespace
00237 {
00238 
00239 /** Assist to sort nodes in GoUctUtil::ChildrenStatistics */
00240 bool IsMeanLess(const SgUctNode* lhs, const SgUctNode* rhs)
00241 {
00242     return (lhs->Mean() < rhs->Mean());
00243 }
00244 
00245 } // namespace
00246 
00247 string GoUctUtil::ChildrenStatistics(const SgUctSearch& search,
00248                                      bool bSort, const SgUctNode& node)
00249 {
00250     ostringstream out;
00251     vector<const SgUctNode*> vec;
00252     const SgUctTree& tree = search.Tree();
00253     for (SgUctChildIterator it(tree, node); it; ++it)
00254     {
00255         const SgUctNode& child = *it;
00256         vec.push_back(&child);
00257     }
00258     if (bSort)
00259         sort(vec.begin(), vec.end(), IsMeanLess);
00260     for (vector<const SgUctNode*>::iterator it = vec.begin(); it != vec.end();
00261          ++it)
00262     {
00263         const SgUctNode& child = **it;
00264         out << search.MoveString(child.Move()) << " -" << " value="
00265             << child.Mean() << " count=" << child.MoveCount() << '\n';
00266     }
00267     return out.str();
00268 }
00269 
00270 //----------------------------------------------------------------------------


17 Jun 2010 Doxygen 1.4.7