void UCTSearch::dump_stats(FastState & state, UCTNode & parent) { if (cfg_quiet || !parent.has_children()) { return; } const int color = state.get_to_move(); // sort children, put best move on top parent.sort_children(color); if (parent.get_first_child()->first_visit()) { return; } int movecount = 0; for (const auto& node : parent.get_children()) { // Always display at least two moves. In the case there is // only one move searched the user could get an idea why. if (++movecount > 2 && !node->get_visits()) break; std::string move = state.move_to_text(node->get_move()); FastState tmpstate = state; tmpstate.play_move(node->get_move()); std::string pv = move + " " + get_pv(tmpstate, *node); myprintf("%4s -> %7d (V: %5.2f%%) (N: %5.2f%%) PV: %s\n", move.c_str(), node->get_visits(), node->get_visits() ? node->get_eval(color)*100.0f : 0.0f, node->get_score() * 100.0f, pv.c_str()); } tree_stats(parent); }
void tree_stats_helper(const UCTNode& node, size_t depth, size_t& nodes, size_t& non_leaf_nodes, size_t& depth_sum, size_t& max_depth, size_t& children_count) { nodes += 1; non_leaf_nodes += node.get_visits() > 1; depth_sum += depth; if (depth > max_depth) max_depth = depth; for (const auto& child : node.get_children()) { if (!child->first_visit()) children_count += 1; tree_stats_helper(*(child.get()), depth+1, nodes, non_leaf_nodes, depth_sum, max_depth, children_count); } }
void UCTSearch::dump_stats(BoardHistory& state, UCTNode& parent) { if (cfg_quiet || !parent.has_children()) { return; } myprintf("\n"); const Color color = state.cur().side_to_move(); // sort children, put best move on top m_root->sort_root_children(color); if (parent.get_first_child()->first_visit()) { return; } auto root_temperature = get_root_temperature(); auto accum_vector = m_root->calc_proportional(root_temperature, color); for (const auto& node : boost::adaptors::reverse(parent.get_children())) { std::string tmp = state.cur().move_to_san(node->get_move()); std::string pvstring(tmp); std::string moveprob(10, '\0'); if (cfg_randomize) { auto move_probability = accum_vector.back(); accum_vector.pop_back(); if (accum_vector.size() > 0) { move_probability -= accum_vector.back(); } move_probability *= 100.0f; // The following code expects percentage. if (move_probability > 0.01f) { std::snprintf(&moveprob[0], moveprob.size(), "(%6.2f%%)", move_probability); } else if (move_probability > 0.00001f) { std::snprintf(&moveprob[0], moveprob.size(), "%s", "(> 0.00%)"); } else { std::snprintf(&moveprob[0], moveprob.size(), "%s", "( 0.00%)"); } } else { auto needed = std::snprintf(&moveprob[0], moveprob.size(), "%s", " "); moveprob.resize(needed+1); } myprintf_so("info string %5s -> %7d %s (V: %5.2f%%) (N: %5.2f%%) PV: ", tmp.c_str(), node->get_visits(), moveprob.c_str(), node->get_eval(color)*100.0f, node->get_score() * 100.0f); StateInfo si; state.cur().do_move(node->get_move(), si); // Since this is just a string, set use_san=true pvstring += " " + get_pv(state, *node, true); state.cur().undo_move(node->get_move()); myprintf_so("%s\n", pvstring.c_str()); } // winrate separate info string since it's not UCI spec float feval = m_root->get_eval(color); myprintf_so("info string stm %s winrate %5.2f%%\n", color == Color::WHITE ? "White" : "Black", feval * 100.f); myprintf("\n"); }