From f85dbc3fe316b7c9c09d2d10098b0caa14b6552a Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Tue, 30 Mar 2021 14:56:29 +0200 Subject: [PATCH 01/11] Reorder code and add important comments. --- src/learn/stats.cpp | 64 +++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/src/learn/stats.cpp b/src/learn/stats.cpp index 9d9589c4..d8224760 100644 --- a/src/learn/stats.cpp +++ b/src/learn/stats.cpp @@ -31,34 +31,6 @@ namespace Learner::Stats [[nodiscard]] virtual std::map get_formatted_stats() const = 0; }; - struct PositionCounter : StatisticGathererBase - { - PositionCounter() : - m_num_positions(0) - { - } - - void on_position(const Position&) override - { - m_num_positions += 1; - } - - void reset() override - { - m_num_positions = 0; - } - - [[nodiscard]] std::map get_formatted_stats() const override - { - return { - { "Number of positions", std::to_string(m_num_positions) } - }; - } - - private: - std::uint64_t m_num_positions; - }; - struct StatisticGathererFactoryBase { [[nodiscard]] virtual std::unique_ptr create() const = 0; @@ -102,6 +74,42 @@ namespace Learner::Stats std::map>> m_gatherers_by_group; }; + /* + Definitions for specific statistic gatherers follow: + */ + + struct PositionCounter : StatisticGathererBase + { + PositionCounter() : + m_num_positions(0) + { + } + + void on_position(const Position&) override + { + m_num_positions += 1; + } + + void reset() override + { + m_num_positions = 0; + } + + [[nodiscard]] std::map get_formatted_stats() const override + { + return { + { "Number of positions", std::to_string(m_num_positions) } + }; + } + + private: + std::uint64_t m_num_positions; + }; + + /* + This function provides factories for all possible statistic gatherers. + Each new statistic gatherer needs to be added there. + */ const auto& get_statistics_gatherers_registry() { static StatisticGathererRegistry s_reg = [](){ From 7d74185d0be2665f9d18e959c2b77be21b1605a9 Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Tue, 30 Mar 2021 15:00:34 +0200 Subject: [PATCH 02/11] Add max_count parameter to limit the number of positions read. --- docs/stats.md | 8 ++++++++ src/learn/stats.cpp | 10 +++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/stats.md b/docs/stats.md index d5a76b61..2a2d3a07 100644 --- a/docs/stats.md +++ b/docs/stats.md @@ -4,6 +4,14 @@ Simplest usage: `stockfish.exe gather_statistics all input_file a.binpack` +Any name that doesn't designate an argument name or is not an argument will be interpreted as a group name. + +## Parameters + +`input_file` - the path to the .bin or .binpack input file to read + +`max_count` - the maximum number of positions to process. Default: no limit. + ## Groups `all` diff --git a/src/learn/stats.cpp b/src/learn/stats.cpp index d8224760..8efbeb6f 100644 --- a/src/learn/stats.cpp +++ b/src/learn/stats.cpp @@ -125,7 +125,8 @@ namespace Learner::Stats void do_gather_statistics( const std::string& filename, - std::vector>& statistic_gatherers) + std::vector>& statistic_gatherers, + std::uint64_t max_count) { Thread* th = Threads.main(); Position& pos = th->rootPos; @@ -154,7 +155,7 @@ namespace Learner::Stats } uint64_t num_processed = 0; - for (;;) + while (num_processed < max_count) { auto v = in->next(); if (!v.has_value()) @@ -196,6 +197,7 @@ namespace Learner::Stats std::vector> statistic_gatherers; std::string input_file; + std::uint64_t max_count = std::numeric_limits::max(); while(true) { @@ -207,11 +209,13 @@ namespace Learner::Stats if (token == "input_file") is >> input_file; + else if (token == "max_count") + is >> max_count; else registry.add_statistic_gatherers_by_group(statistic_gatherers, token); } - do_gather_statistics(input_file, statistic_gatherers); + do_gather_statistics(input_file, statistic_gatherers, max_count); } } From 570a0f6f3c6b012e89744657e08f34e9855b1c5f Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Mon, 5 Apr 2021 16:12:47 +0200 Subject: [PATCH 03/11] Per square stats utility --- src/learn/stats.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/learn/stats.cpp b/src/learn/stats.cpp index 8efbeb6f..ce85caa0 100644 --- a/src/learn/stats.cpp +++ b/src/learn/stats.cpp @@ -11,12 +11,15 @@ #include "nnue/evaluate_nnue.h" +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -74,6 +77,44 @@ namespace Learner::Stats std::map>> m_gatherers_by_group; }; + /* + Statistic gatherer helpers + */ + + template + struct StatPerSquare + { + StatPerSquare() + { + for (int i = 0; i < SQUARE_NB; ++i) + m_squares[i] = 0; + } + + [[nodiscard]] T& operator[](Square sq) + { + return m_squares[sq]; + } + + [[nodiscard]] const T& operator[](Square sq) const + { + return m_squares[sq]; + } + + [[nodiscard]] std::string get_formatted_stats() const + { + std::stringstream ss; + for (int i = 0; i < SQUARE_NB; ++i) + { + ss << std::setw(8) << m_squares[i] << ' '; + if ((i + 1) % 8 == 0) + ss << '\n'; + } + } + + private: + std::array m_squares; + }; + /* Definitions for specific statistic gatherers follow: */ From eda51f19a2c1c5feeb755b6877132738ce1b1771 Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Mon, 5 Apr 2021 16:15:37 +0200 Subject: [PATCH 04/11] Add king square counter --- src/learn/stats.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/learn/stats.cpp b/src/learn/stats.cpp index ce85caa0..419108d9 100644 --- a/src/learn/stats.cpp +++ b/src/learn/stats.cpp @@ -147,6 +147,32 @@ namespace Learner::Stats std::uint64_t m_num_positions; }; + struct KingSquareCounter : StatisticGathererBase + { + KingSquareCounter() : + m_white{}, + m_black{} + { + + } + + void on_position(const Position& pos) override + { + m_white[pos.square(WHITE)] += 1; + m_black[pos.square(BLACK)] += 1; + } + + void reset() override + { + m_white = StatPerSquare{}; + m_black = StatPerSquare{}; + } + + private: + StatPerSquare m_white; + StatPerSquare m_black; + }; + /* This function provides factories for all possible statistic gatherers. Each new statistic gatherer needs to be added there. @@ -158,6 +184,9 @@ namespace Learner::Stats reg.add("position_count"); + reg.add("king"); + reg.add("king_square_count"); + return reg; }(); From b2a5bf4171c943a6037eeabb49710cf726861e72 Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Mon, 5 Apr 2021 16:36:27 +0200 Subject: [PATCH 05/11] Deduplicate statistic gatherers. Fix King square counter compilation errors. --- src/learn/stats.cpp | 124 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 18 deletions(-) diff --git a/src/learn/stats.cpp b/src/learn/stats.cpp index 419108d9..0a93cc5e 100644 --- a/src/learn/stats.cpp +++ b/src/learn/stats.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -31,12 +32,14 @@ namespace Learner::Stats virtual void on_position(const Position&) {} virtual void on_move(const Move&) {} virtual void reset() = 0; + [[nodiscard]] virtual const std::string& get_name() const = 0; [[nodiscard]] virtual std::map get_formatted_stats() const = 0; }; struct StatisticGathererFactoryBase { [[nodiscard]] virtual std::unique_ptr create() const = 0; + [[nodiscard]] virtual const std::string& get_name() const = 0; }; template @@ -46,12 +49,84 @@ namespace Learner::Stats { return std::make_unique(); } + + [[nodiscard]] const std::string& get_name() const override + { + return T::name; + } + }; + + struct StatisticGathererSet : StatisticGathererBase + { + void add(const StatisticGathererFactoryBase& factory) + { + const std::string name = factory.get_name(); + if (m_gatherers_names.count(name) == 0) + { + m_gatherers_names.insert(name); + m_gatherers.emplace_back(factory.create()); + } + } + + void add(std::unique_ptr&& gatherer) + { + const std::string name = gatherer->get_name(); + if (m_gatherers_names.count(name) == 0) + { + m_gatherers_names.insert(name); + m_gatherers.emplace_back(std::move(gatherer)); + } + } + + void on_position(const Position& position) override + { + for (auto& g : m_gatherers) + { + g->on_position(position); + } + } + + void on_move(const Move& move) override + { + for (auto& g : m_gatherers) + { + g->on_move(move); + } + } + + void reset() override + { + for (auto& g : m_gatherers) + { + g->reset(); + } + } + + [[nodiscard]] virtual const std::string& get_name() const override + { + static std::string name = "SET"; + return name; + } + + [[nodiscard]] virtual std::map get_formatted_stats() const override + { + std::map parts; + for (auto&& s : m_gatherers) + { + parts.merge(s->get_formatted_stats()); + } + return parts; + } + + private: + std::vector> m_gatherers; + std::set m_gatherers_names; }; struct StatisticGathererRegistry { void add_statistic_gatherers_by_group( - std::vector>& gatherers, + StatisticGathererSet& gatherers, const std::string& group) const { auto it = m_gatherers_by_group.find(group); @@ -59,7 +134,7 @@ namespace Learner::Stats { for (auto& factory : it->second) { - gatherers.emplace_back(factory->create()); + gatherers.add(*factory); } } } @@ -109,6 +184,7 @@ namespace Learner::Stats if ((i + 1) % 8 == 0) ss << '\n'; } + return ss.str(); } private: @@ -121,6 +197,8 @@ namespace Learner::Stats struct PositionCounter : StatisticGathererBase { + static inline std::string name = "PositionCounter"; + PositionCounter() : m_num_positions(0) { @@ -136,6 +214,11 @@ namespace Learner::Stats m_num_positions = 0; } + [[nodiscard]] const std::string& get_name() const override + { + return name; + } + [[nodiscard]] std::map get_formatted_stats() const override { return { @@ -149,6 +232,8 @@ namespace Learner::Stats struct KingSquareCounter : StatisticGathererBase { + static inline std::string name = "KingSquareCounter"; + KingSquareCounter() : m_white{}, m_black{} @@ -168,6 +253,19 @@ namespace Learner::Stats m_black = StatPerSquare{}; } + [[nodiscard]] const std::string& get_name() const override + { + return name; + } + + [[nodiscard]] std::map get_formatted_stats() const override + { + return { + { "White king squares", m_white.get_formatted_stats() }, + { "Black king squares", m_black.get_formatted_stats() } + }; + } + private: StatPerSquare m_white; StatPerSquare m_black; @@ -195,7 +293,7 @@ namespace Learner::Stats void do_gather_statistics( const std::string& filename, - std::vector>& statistic_gatherers, + StatisticGathererSet& statistic_gatherers, std::uint64_t max_count) { Thread* th = Threads.main(); @@ -205,17 +303,11 @@ namespace Learner::Stats auto in = Learner::open_sfen_input_file(filename); auto on_move = [&](Move move) { - for (auto&& s : statistic_gatherers) - { - s->on_move(move); - } + statistic_gatherers.on_move(move); }; auto on_position = [&](const Position& position) { - for (auto&& s : statistic_gatherers) - { - s->on_position(position); - } + statistic_gatherers.on_position(position); }; if (in == nullptr) @@ -248,13 +340,9 @@ namespace Learner::Stats std::cout << "Finished gathering statistics.\n\n"; std::cout << "Results:\n\n"; - for (auto&& s : statistic_gatherers) + for (auto&& [name, value] : statistic_gatherers.get_formatted_stats()) { - for (auto&& [name, value] : s->get_formatted_stats()) - { - std::cout << name << ": " << value << '\n'; - } - std::cout << '\n'; + std::cout << name << ": " << value << '\n'; } } @@ -264,7 +352,7 @@ namespace Learner::Stats auto& registry = get_statistics_gatherers_registry(); - std::vector> statistic_gatherers; + StatisticGathererSet statistic_gatherers; std::string input_file; std::uint64_t max_count = std::numeric_limits::max(); From fcd53684b672a185d823338d757ae360307b21a9 Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Mon, 5 Apr 2021 16:43:25 +0200 Subject: [PATCH 06/11] To/from move stats --- src/learn/stats.cpp | 106 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 8 deletions(-) diff --git a/src/learn/stats.cpp b/src/learn/stats.cpp index 0a93cc5e..c77b61b9 100644 --- a/src/learn/stats.cpp +++ b/src/learn/stats.cpp @@ -30,7 +30,7 @@ namespace Learner::Stats struct StatisticGathererBase { virtual void on_position(const Position&) {} - virtual void on_move(const Move&) {} + virtual void on_move(const Position&, const Move&) {} virtual void reset() = 0; [[nodiscard]] virtual const std::string& get_name() const = 0; [[nodiscard]] virtual std::map get_formatted_stats() const = 0; @@ -86,11 +86,11 @@ namespace Learner::Stats } } - void on_move(const Move& move) override + void on_move(const Position& pos, const Move& move) override { for (auto& g : m_gatherers) { - g->on_move(move); + g->on_move(pos, move); } } @@ -261,8 +261,94 @@ namespace Learner::Stats [[nodiscard]] std::map get_formatted_stats() const override { return { - { "White king squares", m_white.get_formatted_stats() }, - { "Black king squares", m_black.get_formatted_stats() } + { "White king squares", '\n' + m_white.get_formatted_stats() }, + { "Black king squares", '\n' + m_black.get_formatted_stats() } + }; + } + + private: + StatPerSquare m_white; + StatPerSquare m_black; + }; + + struct MoveFromCounter : StatisticGathererBase + { + static inline std::string name = "MoveFromCounter"; + + MoveFromCounter() : + m_white{}, + m_black{} + { + + } + + void on_move(const Position& pos, const Move& move) override + { + if (pos.side_to_move() == WHITE) + m_white[from_sq(move)] += 1; + else + m_black[from_sq(move)] += 1; + } + + void reset() override + { + m_white = StatPerSquare{}; + m_black = StatPerSquare{}; + } + + [[nodiscard]] const std::string& get_name() const override + { + return name; + } + + [[nodiscard]] std::map get_formatted_stats() const override + { + return { + { "White move from squares", '\n' + m_white.get_formatted_stats() }, + { "Black move from squares", '\n' + m_black.get_formatted_stats() } + }; + } + + private: + StatPerSquare m_white; + StatPerSquare m_black; + }; + + struct MoveToCounter : StatisticGathererBase + { + static inline std::string name = "MoveToCounter"; + + MoveToCounter() : + m_white{}, + m_black{} + { + + } + + void on_move(const Position& pos, const Move& move) override + { + if (pos.side_to_move() == WHITE) + m_white[to_sq(move)] += 1; + else + m_black[to_sq(move)] += 1; + } + + void reset() override + { + m_white = StatPerSquare{}; + m_black = StatPerSquare{}; + } + + [[nodiscard]] const std::string& get_name() const override + { + return name; + } + + [[nodiscard]] std::map get_formatted_stats() const override + { + return { + { "White move to squares", '\n' + m_white.get_formatted_stats() }, + { "Black move to squares", '\n' + m_black.get_formatted_stats() } }; } @@ -285,6 +371,10 @@ namespace Learner::Stats reg.add("king"); reg.add("king_square_count"); + reg.add("move"); + reg.add("move_from_count"); + reg.add("move_to_count"); + return reg; }(); @@ -302,8 +392,8 @@ namespace Learner::Stats auto in = Learner::open_sfen_input_file(filename); - auto on_move = [&](Move move) { - statistic_gatherers.on_move(move); + auto on_move = [&](const Position& position, const Move& move) { + statistic_gatherers.on_move(position, move); }; auto on_position = [&](const Position& position) { @@ -328,7 +418,7 @@ namespace Learner::Stats pos.set_from_packed_sfen(ps.sfen, &si, th); on_position(pos); - on_move((Move)ps.move); + on_move(pos, (Move)ps.move); num_processed += 1; if (num_processed % 1'000'000 == 0) From e7b3803fd0249e21eb53736254ee1a76b3d9a50b Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Mon, 5 Apr 2021 17:00:27 +0200 Subject: [PATCH 07/11] Add more counters --- src/learn/stats.cpp | 163 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/src/learn/stats.cpp b/src/learn/stats.cpp index c77b61b9..3a8b4454 100644 --- a/src/learn/stats.cpp +++ b/src/learn/stats.cpp @@ -357,6 +357,165 @@ namespace Learner::Stats StatPerSquare m_black; }; + struct MoveTypeCounter : StatisticGathererBase + { + static inline std::string name = "MoveTypeCounter"; + + MoveTypeCounter() : + m_total(0), + m_normal(0), + m_capture(0), + m_promotion(0), + m_castling(0), + m_enpassant(0) + { + + } + + void on_move(const Position& pos, const Move& move) override + { + m_total += 1; + + if (!pos.empty(to_sq(move))) + m_capture += 1; + + if (type_of(move) == CASTLING) + m_castling += 1; + else if (type_of(move) == PROMOTION) + m_promotion += 1; + else if (type_of(move) == ENPASSANT) + m_enpassant += 1; + else if (type_of(move) == NORMAL) + m_normal += 1; + } + + void reset() override + { + m_total = 0; + m_normal = 0; + m_capture = 0; + m_promotion = 0; + m_castling = 0; + m_enpassant = 0; + } + + [[nodiscard]] const std::string& get_name() const override + { + return name; + } + + [[nodiscard]] std::map get_formatted_stats() const override + { + return { + { "Total moves", std::to_string(m_total) }, + { "Normal moves", std::to_string(m_normal) }, + { "Capture moves", std::to_string(m_capture) }, + { "Promotion moves", std::to_string(m_promotion) }, + { "Castling moves", std::to_string(m_castling) }, + { "En-passant moves", std::to_string(m_enpassant) } + }; + } + + private: + std::uint64_t m_total; + std::uint64_t m_normal; + std::uint64_t m_capture; + std::uint64_t m_promotion; + std::uint64_t m_castling; + std::uint64_t m_enpassant; + }; + + struct PieceCountCounter : StatisticGathererBase + { + static inline std::string name = "PieceCountCounter"; + + PieceCountCounter() + { + reset(); + } + + void on_position(const Position& pos) override + { + m_piece_count_hist[popcount(pos.pieces())] += 1; + } + + void reset() override + { + for (int i = 0; i < SQUARE_NB; ++i) + m_num_pieces[i] = 0; + } + + [[nodiscard]] const std::string& get_name() const override + { + return name; + } + + [[nodiscard]] std::map get_formatted_stats() const override + { + std::map result; + bool do_write = false; + for (int i = SQUARE_NB; i >= 0; --i) + { + if (m_piece_count_hist[i] != 0) + do_write = true; + + // Start writing when the first non-zero number pops up. + if (do_write) + { + result.try_emplace( + std::string("Number of positions with ") + std::to_string(i) + " pieces", + std::to_string(m_piece_count_hist[i]) + ); + } + } + return result; + } + + private: + std::uint64_t m_piece_count_hist[SQUARE_NB]; + }; + + struct MovedPieceTypeCounter : StatisticGathererBase + { + static inline std::string name = "MovedPieceTypeCounter"; + + MovedPieceTypeCounter() + { + reset(); + } + + void on_move(const Position& pos, const Move& move) override + { + m_moved_piece_type_hist[type_of(pos.piece_on(from_sq(move)))] += 1; + } + + void reset() override + { + for (int i = 0; i < PIECE_TYPE_NB; ++i) + m_moved_piece_type_hist[i] = 0; + } + + [[nodiscard]] const std::string& get_name() const override + { + return name; + } + + [[nodiscard]] std::map get_formatted_stats() const override + { + return { + { "Pawn moves", std::to_string(m_moved_piece_type_hist[PAWN]) }, + { "Knight moves", std::to_string(m_moved_piece_type_hist[KNIGHT]) }, + { "Bishop moves", std::to_string(m_moved_piece_type_hist[BISHOP]) }, + { "Rook moves", std::to_string(m_moved_piece_type_hist[ROOK]) }, + { "Queen moves", std::to_string(m_moved_piece_type_hist[QUEEN]) }, + { "King moves", std::to_string(m_moved_piece_type_hist[KING]) } + }; + } + + private: + std::uint64_t m_moved_piece_type_hist[PIECE_TYPE_NB]; + }; + /* This function provides factories for all possible statistic gatherers. Each new statistic gatherer needs to be added there. @@ -374,6 +533,10 @@ namespace Learner::Stats reg.add("move"); reg.add("move_from_count"); reg.add("move_to_count"); + reg.add("move_type"); + reg.add("moved_piece_type"); + + reg.add("piece_count") return reg; }(); From e371d133a7cbb08c0ce2cb83788f8f9145769890 Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Mon, 5 Apr 2021 17:10:16 +0200 Subject: [PATCH 08/11] Fix grouping and do dedup in registry. --- src/learn/stats.cpp | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/learn/stats.cpp b/src/learn/stats.cpp index 3a8b4454..d899090e 100644 --- a/src/learn/stats.cpp +++ b/src/learn/stats.cpp @@ -45,6 +45,8 @@ namespace Learner::Stats template struct StatisticGathererFactory : StatisticGathererFactoryBase { + static inline std::string name = T::name; + [[nodiscard]] std::unique_ptr create() const override { return std::make_unique(); @@ -52,7 +54,7 @@ namespace Learner::Stats [[nodiscard]] const std::string& get_name() const override { - return T::name; + return name; } }; @@ -139,17 +141,29 @@ namespace Learner::Stats } } - template - void add(const std::string& group) + template + void add(const ArgsTs&... group) { - m_gatherers_by_group[group].emplace_back(std::make_unique>()); - - // Always add to the special group "all". - m_gatherers_by_group["all"].emplace_back(std::make_unique>()); + auto dummy = {(add_single(group), 0)...}; + (void)dummy; + add_single("all"); } private: std::map>> m_gatherers_by_group; + std::map> m_gatherers_names_by_group; + + template + void add_single(const ArgT& group) + { + using FactoryT = StatisticGathererFactory; + + if (m_gatherers_names_by_group[group].count(FactoryT::name) == 0) + { + m_gatherers_by_group[group].emplace_back(std::make_unique()); + m_gatherers_names_by_group[group].insert(FactoryT::name); + } + } }; /* @@ -442,7 +456,7 @@ namespace Learner::Stats void reset() override { for (int i = 0; i < SQUARE_NB; ++i) - m_num_pieces[i] = 0; + m_piece_count_hist[i] = 0; } [[nodiscard]] const std::string& get_name() const override @@ -527,16 +541,14 @@ namespace Learner::Stats reg.add("position_count"); - reg.add("king"); - reg.add("king_square_count"); + reg.add("king", "king_square_count"); - reg.add("move"); - reg.add("move_from_count"); - reg.add("move_to_count"); - reg.add("move_type"); - reg.add("moved_piece_type"); + reg.add("move", "move_from_count"); + reg.add("move", "move_to_count"); + reg.add("move", "move_type"); + reg.add("move", "moved_piece_type"); - reg.add("piece_count") + reg.add("piece_count"); return reg; }(); From 1786be5553d3ee2ee4353b107e579c15709fb1fa Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Mon, 5 Apr 2021 17:25:24 +0200 Subject: [PATCH 09/11] Minor fixes --- src/learn/stats.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/learn/stats.cpp b/src/learn/stats.cpp index d899090e..4ee123da 100644 --- a/src/learn/stats.cpp +++ b/src/learn/stats.cpp @@ -194,7 +194,7 @@ namespace Learner::Stats std::stringstream ss; for (int i = 0; i < SQUARE_NB; ++i) { - ss << std::setw(8) << m_squares[i] << ' '; + ss << std::setw(8) << m_squares[i ^ (int)SQ_A8] << ' '; if ((i + 1) % 8 == 0) ss << '\n'; } From f8d9836ca363c45e7d137a5f261e23ffdb53a2a5 Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Mon, 5 Apr 2021 17:27:57 +0200 Subject: [PATCH 10/11] Use an ordered container for the results. --- src/learn/stats.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/learn/stats.cpp b/src/learn/stats.cpp index 4ee123da..c0e2c0a1 100644 --- a/src/learn/stats.cpp +++ b/src/learn/stats.cpp @@ -33,7 +33,7 @@ namespace Learner::Stats virtual void on_move(const Position&, const Move&) {} virtual void reset() = 0; [[nodiscard]] virtual const std::string& get_name() const = 0; - [[nodiscard]] virtual std::map get_formatted_stats() const = 0; + [[nodiscard]] virtual std::vector> get_formatted_stats() const = 0; }; struct StatisticGathererFactoryBase @@ -110,12 +110,13 @@ namespace Learner::Stats return name; } - [[nodiscard]] virtual std::map get_formatted_stats() const override + [[nodiscard]] virtual std::vector> get_formatted_stats() const override { - std::map parts; + std::vector> parts; for (auto&& s : m_gatherers) { - parts.merge(s->get_formatted_stats()); + auto part = s->get_formatted_stats(); + parts.insert(parts.end(), part.begin(), part.end()); } return parts; } @@ -233,7 +234,7 @@ namespace Learner::Stats return name; } - [[nodiscard]] std::map get_formatted_stats() const override + [[nodiscard]] std::vector> get_formatted_stats() const override { return { { "Number of positions", std::to_string(m_num_positions) } @@ -272,7 +273,7 @@ namespace Learner::Stats return name; } - [[nodiscard]] std::map get_formatted_stats() const override + [[nodiscard]] std::vector> get_formatted_stats() const override { return { { "White king squares", '\n' + m_white.get_formatted_stats() }, @@ -315,7 +316,7 @@ namespace Learner::Stats return name; } - [[nodiscard]] std::map get_formatted_stats() const override + [[nodiscard]] std::vector> get_formatted_stats() const override { return { { "White move from squares", '\n' + m_white.get_formatted_stats() }, @@ -358,7 +359,7 @@ namespace Learner::Stats return name; } - [[nodiscard]] std::map get_formatted_stats() const override + [[nodiscard]] std::vector> get_formatted_stats() const override { return { { "White move to squares", '\n' + m_white.get_formatted_stats() }, @@ -418,7 +419,7 @@ namespace Learner::Stats return name; } - [[nodiscard]] std::map get_formatted_stats() const override + [[nodiscard]] std::vector> get_formatted_stats() const override { return { { "Total moves", std::to_string(m_total) }, @@ -464,11 +465,11 @@ namespace Learner::Stats return name; } - [[nodiscard]] std::map get_formatted_stats() const override + [[nodiscard]] std::vector> get_formatted_stats() const override { - std::map result; + std::vector> result; bool do_write = false; - for (int i = SQUARE_NB; i >= 0; --i) + for (int i = SQUARE_NB - 1; i >= 0; --i) { if (m_piece_count_hist[i] != 0) do_write = true; @@ -476,7 +477,7 @@ namespace Learner::Stats // Start writing when the first non-zero number pops up. if (do_write) { - result.try_emplace( + result.emplace_back( std::string("Number of positions with ") + std::to_string(i) + " pieces", std::to_string(m_piece_count_hist[i]) ); @@ -514,7 +515,7 @@ namespace Learner::Stats return name; } - [[nodiscard]] std::map get_formatted_stats() const override + [[nodiscard]] std::vector> get_formatted_stats() const override { return { { "Pawn moves", std::to_string(m_moved_piece_type_hist[PAWN]) }, From 9dac979ce8d4452881dd154793611fc2522d04e8 Mon Sep 17 00:00:00 2001 From: Tomasz Sobczyk Date: Mon, 5 Apr 2021 17:37:15 +0200 Subject: [PATCH 11/11] Update docs --- docs/stats.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/stats.md b/docs/stats.md index 2a2d3a07..78fe9051 100644 --- a/docs/stats.md +++ b/docs/stats.md @@ -21,3 +21,25 @@ Any name that doesn't designate an argument name or is not an argument will be i `position_count` - `struct PositionCounter` - the total number of positions in the file. + + + reg.add("king", "king_square_count"); + + reg.add("move", "move_from_count"); + reg.add("move", "move_to_count"); + reg.add("move", "move_type"); + reg.add("move", "moved_piece_type"); + + reg.add("piece_count"); + +`king`, `king_square_count` - the number of times a king was on each square. Output is layed out as a chessboard, with the 8th rank being the topmost. Separate values for white and black kings. + +`move`, `move_from_count` - same as `king_square_count` but for from_sq(move) + +`move`, `move_to_count` - same as `king_square_count` but for to_sq(move) + +`move`, `move_type` - the number of moves with each type. Includes normal, captures, castling, promotions, enpassant. The groups are not disjoint. + +`move`, `moved_piece_type` - the number of times a piece of each type was moved + +`piece_count` - the histogram of the number of pieces on the board