File: Util.cpp

package info (click to toggle)
pentobi 29.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,892 kB
  • sloc: cpp: 25,719; javascript: 875; xml: 40; makefile: 13; sh: 6
file content (112 lines) | stat: -rw-r--r-- 3,908 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//-----------------------------------------------------------------------------
/** @file libpentobi_mcts/Util.cpp
    @author Markus Enzenberger
    @copyright GNU General Public License version 3 or later */
//-----------------------------------------------------------------------------

#include "Util.h"

#include <thread>
#include "libboardgame_base/Writer.h"
#include "libpentobi_base/BoardUtil.h"
#include "libpentobi_base/PentobiSgfUtil.h"

namespace libpentobi_mcts {

using libboardgame_base::Writer;

//-----------------------------------------------------------------------------

namespace {

void dump_tree_recurse(Writer& writer, Variant variant,
                       const Search::Tree& tree, const Search::Node& node,
                       Color to_play)
{
    ostringstream comment;
    comment << "Visits: " << node.get_visit_count()
            << "\nPrior: " << node.get_move_prior()
            << "\nVal:   " << node.get_value()
            << "\nCnt:   " << node.get_value_count();
    writer.write_property("C", comment.str());
    writer.end_node();
    auto children = tree.get_children(node);
    if (children.empty())
        return;
    Color next_to_play = to_play.get_next(get_nu_colors(variant));    
    vector<const Search::Node*> sorted_children;
    sorted_children.reserve(children.size());
    for (auto& i : tree.get_children(node))
        sorted_children.push_back(&i);
    sort(sorted_children.begin(), sorted_children.end(), compare_node);
    for (const auto i : sorted_children)
    {
        writer.begin_tree();
        writer.begin_node();
        auto mv =  i->get_move();
        if (! mv.is_null())
        {
            auto& board_const = BoardConst::get(variant);
            auto id = get_color_id(variant, to_play);
            if (! mv.is_null())
                writer.write_property(id, board_const.to_string(mv, false));
        }
        dump_tree_recurse(writer, variant, tree, *i, next_to_play);
        writer.end_tree();
    }
}

} // namespace

//-----------------------------------------------------------------------------

bool compare_node(const Search::Node* n1, const Search::Node* n2)
{
    Float count1 = n1->get_visit_count();
    Float count2 = n2->get_visit_count();
    if (count1 != count2)
        return count1 > count2;
    return n1->get_value() > n2->get_value();
}

void dump_tree(ostream& out, const Search& search)
{
    Variant variant;
    Setup setup;
    search.get_root_position(variant, setup);
    Writer writer(out);
    writer.begin_tree();
    writer.begin_node();
    writer.write_property("GM", to_string(variant));
    write_setup(writer, variant, setup);
    writer.write_property("PL", get_color_id(variant, setup.to_play));
    auto& tree = search.get_tree();
    dump_tree_recurse(writer, variant, tree, tree.get_root(), setup.to_play);
    writer.end_tree();
}

unsigned get_nu_threads()
{
    unsigned nu_threads = thread::hardware_concurrency();
    if (nu_threads == 0)
    {
        LIBBOARDGAME_LOG("Could not determine the number of hardware threads");
        nu_threads = 1;
    }
    // The lock-free search probably scales up to 16-32 threads, but we
    // haven't tested more than 8 threads, we still use single precision
    // float for LIBBOARDGAME_MCTS_FLOAT_TYPE (which limits the maximum number
    // of simulations per search) and CPUs with more than 8 cores are
    // currently not very common anyway. Also, the loss of playing strength
    // of a multi-threaded search with the same count as a single-threaded
    // search will become larger with many threads, so there would need to be
    // a correction factor in the number of simulations per level to take this
    // into account.
    if (nu_threads > 8)
        nu_threads = 8;
    return nu_threads;
}

//-----------------------------------------------------------------------------

} // namespace libpentobi_mcts