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 #include "SgSystem.h"
00006 #include "GoUctUtil.h"
00007 
00008 #include <iomanip>
00009 #include <iostream>
00010 #include <boost/io/ios_state.hpp>
00011 #include <boost/format.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::format;
00019 using boost::io::ios_all_saver;
00020 using SgPointUtil::PointToString;
00021 using SgPointUtil::Pt;
00022 using SgPropUtil::PointToSgfString;
00023 
00024 //----------------------------------------------------------------------------
00025 
00026 namespace {
00027 
00028 bool IsRectEmpty(const GoBoard& bd, int left, int right, int top, int bottom)
00029 {
00030     for (SgRectIterator it(SgRect(left, right, top, bottom)); it; ++it)
00031         if (! bd.IsEmpty(*it))
00032             return false;
00033     return true;
00034 }
00035 
00036 /** Recursive function to save the UCT tree in SGF format. */
00037 void SaveNode(ostream& out, const SgUctTree& tree, const SgUctNode& node,
00038               SgBlackWhite toPlay, int boardSize, int maxDepth, int depth)
00039 {
00040     out << "C[MoveCount " << node.MoveCount()
00041         << "\nPosCount " << node.PosCount()
00042         << "\nMean " << fixed << setprecision(2) << node.Mean();
00043     if (! node.HasChildren())
00044     {
00045         out << "]\n";
00046         return;
00047     }
00048     out << "\n\nRave:";
00049     for (SgUctChildIterator it(tree, node); it; ++it)
00050     {
00051         const SgUctNode& child = *it;
00052         SgPoint move = child.Move();
00053         if (child.HasRaveValue())
00054         {
00055             out << '\n' << SgWritePoint(move) << ' '
00056                 << fixed << setprecision(2) << child.RaveValue()
00057                 << " (" << child.RaveCount() << ')';
00058         }
00059     }
00060     out << "]\nLB";
00061     for (SgUctChildIterator it(tree, node); it; ++it)
00062     {
00063         const SgUctNode& child = *it;
00064         if (! child.HasMean())
00065             continue;
00066         out << "["
00067             << PointToSgfString(child.Move(), boardSize, SG_PROPPOINTFMT_GO)
00068             << ':' << child.MoveCount() << ']';
00069     }
00070     out << '\n';
00071     if (maxDepth >= 0 && depth >= maxDepth)
00072         return;
00073     for (SgUctChildIterator it(tree, node); it; ++it)
00074     {
00075         const SgUctNode& child = *it;
00076         if (! child.HasMean())
00077             continue;
00078         SgPoint move = child.Move();
00079         out << "(;" << (toPlay == SG_BLACK ? 'B' : 'W') << '['
00080             << PointToSgfString(move, boardSize, SG_PROPPOINTFMT_GO) << ']';
00081         SaveNode(out, tree, child, SgOppBW(toPlay), boardSize, maxDepth,
00082                  depth + 1);
00083         out << ")\n";
00084     }
00085 }
00086 
00087 } // namespace
00088 
00089 //----------------------------------------------------------------------------
00090 
00091 void GoUctUtil::ClearStatistics(SgPointArray<SgUctStatistics>& stats)
00092 {
00093     for (SgPointArray<SgUctStatistics>::NonConstIterator
00094              it(stats); it; ++it)
00095         (*it).Clear();
00096 }
00097 
00098 SgPoint GoUctUtil::GenForcedOpeningMove(const GoBoard& bd)
00099 {
00100     int sz = bd.Size();
00101     if (sz < 13 || bd.TotalNumStones(SG_BLACK) > 5
00102         || bd.TotalNumStones(SG_WHITE) > 5)
00103         return SG_NULLMOVE;
00104     SgArrayList<SgPoint,4> moves;
00105     if (IsRectEmpty(bd, 1, 5, 1, 5))
00106         moves.PushBack(Pt(4, 4));
00107     if (IsRectEmpty(bd, 1, 5, sz - 4, sz))
00108         moves.PushBack(Pt(4, sz - 3));
00109     if (IsRectEmpty(bd, sz - 4, sz, 1, 5))
00110         moves.PushBack(Pt(sz - 3, 4));
00111     if (IsRectEmpty(bd, sz - 4, sz, sz - 4, sz))
00112         moves.PushBack(Pt(sz - 3, sz - 3));
00113     if (moves.IsEmpty())
00114         return SG_NULLMOVE;
00115     return moves[SgRandom::Global().SmallInt(moves.Length())];
00116 }
00117 
00118 void GoUctUtil::GfxBestMove(const SgUctSearch& search, SgBlackWhite toPlay,
00119                             ostream& out)
00120 {
00121     const SgUctTree& tree = search.Tree();
00122     const SgUctNode& root = tree.Root();
00123     out << "VAR";
00124     const SgUctNode* bestValueChild = search.FindBestChild(root);
00125     if (bestValueChild != 0)
00126     {
00127         SgPoint move = bestValueChild->Move();
00128         out << ' ' << (toPlay == SG_BLACK ? 'B' : 'W') << ' '
00129             << SgWritePoint(move);
00130     }
00131     out << '\n';
00132 }
00133 
00134 void GoUctUtil::GfxCounts(const SgUctTree& tree, ostream& out)
00135 {
00136     const SgUctNode& root = tree.Root();
00137     out << "LABEL";
00138     if (root.HasChildren())
00139         for (SgUctChildIterator it(tree, root); it; ++it)
00140         {
00141             const SgUctNode& child = *it;
00142             if (child.HasMean())
00143                 out << (format(" %s %.0f")
00144                         % PointToString(child.Move()) % child.MoveCount());
00145         }
00146     out << '\n';
00147 }
00148 
00149 void GoUctUtil::GfxMoveValues(const SgUctSearch& search, SgBlackWhite toPlay,
00150                               ostream& out)
00151 {
00152     const SgUctTree& tree = search.Tree();
00153     const SgUctNode& root = tree.Root();
00154     out << "INFLUENCE";
00155     if (root.HasChildren())
00156         for (SgUctChildIterator it(tree, root); it; ++it)
00157         {
00158             const SgUctNode& child = *it;
00159             if (! child.HasMean())
00160                 continue;
00161             SgUctValue value = SgUctSearch::InverseEval(child.Mean());
00162             // Scale to [-1,+1], black positive
00163             SgUctValue influence = value * 2 - 1;
00164             if (toPlay == SG_WHITE)
00165                 influence *= -1;
00166             SgPoint move = child.Move();
00167             out << ' ' << SgWritePoint(move) << ' ' << fixed
00168                 << setprecision(2) << influence;
00169         }
00170     out << '\n';
00171 }
00172 \
00173 void GoUctUtil::GfxSequence(const SgUctSearch& search, SgBlackWhite toPlay,
00174                             ostream& out)
00175 {
00176     vector<SgMove> sequence;
00177     search.FindBestSequence(sequence);
00178     out << "VAR";
00179     for (size_t i = 0; i < sequence.size(); ++i)
00180     {
00181         out << (toPlay == SG_BLACK ? " B ": " W ")
00182             << SgWritePoint(sequence[i]);
00183         toPlay = SgOppBW(toPlay);
00184     }
00185     out << '\n';
00186 }
00187 
00188 void GoUctUtil::GfxStatus(const SgUctSearch& search, ostream& out)
00189 {
00190     const SgUctTree& tree = search.Tree();
00191     const SgUctNode& root = tree.Root();
00192     const SgUctSearchStat& stat = search.Statistics();
00193     SgUctValue abortPercent = stat.m_aborted.Mean() * SgUctValue(100);
00194     out << (format(
00195           "TEXT N=%.0f V=%.2f Len=%.0f Tree=%.1f/%.1f Abrt=%.0f%% Gm/s=%.0f\n")
00196             % root.MoveCount() % root.Mean() % stat.m_gameLength.Mean()
00197             % stat.m_movesInTree.Mean() % stat.m_movesInTree.Max()
00198             % abortPercent % stat.m_gamesPerSecond);
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 //----------------------------------------------------------------------------


Sun Mar 13 2011 Doxygen 1.7.1