swarm-engine-core 0.1.6

Core types and orchestration for SwarmEngine
Documentation
//! FIFO Selection - 先入れ先出し選択
//!
//! 最もシンプルな選択戦略。frontiers の追加順で選択する。

use std::fmt::Debug;

use super::SelectionLogic;
use crate::exploration::map::{ExplorationMap, GraphMap, MapNodeId, MapState};
use crate::exploration::mutation::ActionExtractor;
use crate::learn::LearnedProvider;
use crate::online_stats::SwarmStats;

/// FIFO 選択(frontiers の順番)
///
/// スコアリングを行わず、単純に追加順で選択する。
/// デバッグや比較実験のベースラインとして有用。
#[derive(Debug, Clone, Default)]
pub struct Fifo;

impl Fifo {
    pub fn new() -> Self {
        Self
    }
}

impl<N, E, S> SelectionLogic<N, E, S> for Fifo
where
    N: Debug + Clone + ActionExtractor,
    E: Debug + Clone,
    S: MapState,
{
    fn next(
        &self,
        map: &GraphMap<N, E, S>,
        _stats: &SwarmStats,
        _provider: &dyn LearnedProvider,
    ) -> Option<MapNodeId> {
        map.frontiers().first().copied()
    }

    fn select(
        &self,
        map: &GraphMap<N, E, S>,
        count: usize,
        _stats: &SwarmStats,
        _provider: &dyn LearnedProvider,
    ) -> Vec<MapNodeId> {
        map.frontiers().into_iter().take(count).collect()
    }

    fn score(
        &self,
        _action: &str,
        _target: Option<&str>,
        _stats: &SwarmStats,
        _provider: &dyn LearnedProvider,
    ) -> f64 {
        0.0 // FIFO はスコアを使わない
    }

    fn name(&self) -> &str {
        "FIFO"
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::exploration::map::MapNodeState;
    use crate::exploration::mutation::ActionNodeData;
    use crate::learn::NullProvider;

    #[test]
    fn test_fifo_selection() {
        let fifo = Fifo::new();
        let mut map: GraphMap<ActionNodeData, String, MapNodeState> = GraphMap::new();
        let stats = SwarmStats::new();
        let provider = NullProvider;

        // Root を追加
        let root = map.create_root(ActionNodeData::new("root"), MapNodeState::Open);

        // 選択
        let selected = fifo.select(&map, 1, &stats, &provider);
        assert_eq!(selected.len(), 1);
        assert_eq!(selected[0], root);
    }

    #[test]
    fn test_fifo_score_always_zero() {
        use crate::exploration::map::MapNodeState;
        use crate::exploration::mutation::ActionNodeData;

        let fifo = Fifo::new();
        let stats = SwarmStats::new();
        let provider = NullProvider;

        // 型を明示的に指定
        let score = <Fifo as SelectionLogic<ActionNodeData, String, MapNodeState>>::score(
            &fifo, "any", None, &stats, &provider,
        );
        assert_eq!(score, 0.0);
    }
}