Skip to main content

swarm_engine_core/exploration/selection/
stats.rs

1//! Selection Statistics - 探索ノード選択の統計管理
2//!
3//! ノード選択に必要な統計情報を管理する。
4//!
5//! # 設計
6//!
7//! 統計情報は `SwarmStats`(collector/stats.rs)が Single Source of Truth。
8//! このモジュールの `NodeStats` は後方互換のために残しているが、
9//! 実際には `SwarmStats::ActionStats` を使用する。
10//!
11//! - `NodeStats`: 個別ノードの成功/失敗統計(後方互換)
12
13// ============================================================================
14// Node Statistics - ノードの実行統計
15// ============================================================================
16
17/// ノードの実行統計
18///
19/// UCB1/Thompson で使用する成功/失敗カウント。
20#[derive(Debug, Clone, Default)]
21pub struct NodeStats {
22    /// 訪問回数
23    pub visits: u32,
24    /// 成功回数
25    pub successes: u32,
26    /// 失敗回数
27    pub failures: u32,
28    /// 発見した子ノード数の合計
29    pub discoveries: u32,
30}
31
32impl NodeStats {
33    pub fn new() -> Self {
34        Self::default()
35    }
36
37    /// 成功を記録
38    pub fn record_success(&mut self) {
39        self.visits += 1;
40        self.successes += 1;
41    }
42
43    /// 失敗を記録
44    pub fn record_failure(&mut self) {
45        self.visits += 1;
46        self.failures += 1;
47    }
48
49    /// 発見を記録
50    pub fn record_discovery(&mut self, count: u32) {
51        self.visits += 1;
52        self.successes += 1;
53        self.discoveries += count;
54    }
55
56    /// 成功率(訪問なしの場合は 0.5)
57    pub fn success_rate(&self) -> f64 {
58        if self.visits == 0 {
59            0.5 // 事前確率
60        } else {
61            self.successes as f64 / self.visits as f64
62        }
63    }
64}
65
66// ============================================================================
67// Tests
68// ============================================================================
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn test_node_stats_success_rate() {
76        let mut stats = NodeStats::new();
77        assert_eq!(stats.success_rate(), 0.5); // 事前確率
78
79        stats.record_success();
80        stats.record_success();
81        stats.record_failure();
82        assert!((stats.success_rate() - 0.666).abs() < 0.01);
83    }
84}