diff --git a/src/elo.rs b/src/elo.rs index 62a715c..3a2a6de 100644 --- a/src/elo.rs +++ b/src/elo.rs @@ -9,7 +9,7 @@ use indicatif::{ProgressBar, ProgressStyle}; use rand::seq::SliceRandom; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use skillratings::{ - elo::{elo, EloConfig, EloRating}, + glicko2::{glicko2, Glicko2Rating}, Outcomes, Rating, }; use std::num::NonZero; @@ -136,7 +136,7 @@ pub fn run() { pub struct PlayerArena { /// Name, Creator Function, Elo - players: Vec<(String, AgentMaker, EloRating)>, + players: Vec<(String, AgentMaker, Glicko2Rating)>, } impl std::fmt::Display for PlayerArena { @@ -162,7 +162,7 @@ impl PlayerArena { Self { players: players .into_iter() - .zip([EloRating::new()].into_iter().cycle()) + .zip([Default::default()].into_iter().cycle()) // flatten tuple .map(|((a, b), c)| (a, b, c)) .collect(), @@ -263,11 +263,11 @@ impl PlayerArena { } fn process_outcome(&mut self, player1: usize, player2: usize, outcome: &Outcomes) { - let (np1, np2) = elo( + let (np1, np2) = glicko2( &self.players[player1].2, &self.players[player2].2, outcome, - &EloConfig { k: 10.0 }, + &Default::default(), ); self.players[player1].2 = np1; self.players[player2].2 = np2; diff --git a/src/logic/future_moves.rs b/src/logic/future_moves.rs index 269f2d4..bf66c7f 100644 --- a/src/logic/future_moves.rs +++ b/src/logic/future_moves.rs @@ -87,21 +87,17 @@ impl std::fmt::Display for FutureMoveConfig { } } -#[derive(Debug, Clone, Copy, Allocative)] +#[derive(Debug, Clone, Copy, Allocative, Default)] #[allow(dead_code)] pub enum ChildrenEvalMethod { /// Best so far? + // #[default] MinMax, + #[default] MinMaxProb, } -impl Default for ChildrenEvalMethod { - fn default() -> Self { - Self::MinMax - } -} - impl FutureMoves { pub const fn new(agent_color: Piece, config: FutureMoveConfig) -> Self { Self { diff --git a/src/logic/mvs.rs b/src/logic/mvs.rs index 4184bc0..f0ab44d 100644 --- a/src/logic/mvs.rs +++ b/src/logic/mvs.rs @@ -19,10 +19,11 @@ pub struct MoveValueStats { impl MoveValueStats { #[cfg(test)] - pub fn new_from_wins_losses(wins: u16, losses: u16) -> Self { + pub fn new_from_outcomes(wins: u16, losses: u16, ties: u16) -> Self { Self { wins, losses, + ties, ..Default::default() } } @@ -56,21 +57,18 @@ impl MoveValueStats { } pub fn populate_self_from_children(&mut self, others: &[Self]) { - self.wins = others.iter().map(|x| x.wins).sum::() - + others - .iter() - .filter(|x| x.state == Some(MVSGameState::Win)) - .count() as u16; - self.losses = others.iter().map(|x| x.losses).sum::() - + others - .iter() - .filter(|x| x.state == Some(MVSGameState::Loss)) - .count() as u16; - self.ties = others.iter().map(|x| x.ties).sum::() - + others - .iter() - .filter(|x| x.state == Some(MVSGameState::Tie)) - .count() as u16; + self.wins = others + .iter() + .map(|x| x.wins + (x.state == Some(MVSGameState::Win)) as u16) + .sum::(); + self.losses = others + .iter() + .map(|x| x.losses + (x.state == Some(MVSGameState::Loss)) as u16) + .sum::(); + self.ties = others + .iter() + .map(|x| x.ties + (x.state == Some(MVSGameState::Tie)) as u16) + .sum::(); } } @@ -105,29 +103,62 @@ mod tests { #[test] fn two_prob() { - let one = MoveValueStats::new_from_wins_losses(10, 4); - let two = MoveValueStats::new_from_wins_losses(4, 6); + let one = MoveValueStats::new_from_outcomes(100, 40, 0); + + let two = MoveValueStats::new_from_outcomes(40, 60, 0); assert!(one > two); } #[test] fn one_prob_one_non() { - let one = MoveValueStats::new_from_wins_losses(10, 4); + let one = MoveValueStats::new_from_outcomes(100, 4, 0); let two = MoveValueStats::new_from_value(10); assert!(one > two); } #[test] fn one_prob_one_win() { - let one = MoveValueStats::new_from_wins_losses(10, 4); + let one = MoveValueStats::new_from_outcomes(100, 4, 0); let two = MoveValueStats::new_from_state(Some(MVSGameState::Win)); assert!(one < two); } #[test] fn two_prob_zero() { - let one = MoveValueStats::new_from_wins_losses(10, 0); - let two = MoveValueStats::new_from_wins_losses(0, 6); + let one = MoveValueStats::new_from_outcomes(100, 0, 0); + let two = MoveValueStats::new_from_outcomes(0, 60, 0); assert!(one > two); } + + #[test] + fn test_children_pop() { + let mut a = MoveValueStats::new_from_value(0); + + let children = vec![ + MoveValueStats::new_from_outcomes(1, 0, 0), + MoveValueStats::new_from_outcomes(0, 2, 0), + MoveValueStats::new_from_outcomes(0, 0, 3), + ]; + a.populate_self_from_children(&children); + assert_eq!(a.wins, 1, "Wins should be 1"); + assert_eq!(a.losses, 2, "Losses should be 2"); + assert_eq!(a.ties, 3, "Ties should be 3"); + } + + #[test] + fn test_children_pop_state() { + let mut a = MoveValueStats::new_from_value(0); + + let children = vec![ + MoveValueStats::new_from_state(Some(MVSGameState::Win)), + MoveValueStats::new_from_state(Some(MVSGameState::Win)), + MoveValueStats::new_from_state(Some(MVSGameState::Loss)), + MoveValueStats::new_from_state(Some(MVSGameState::Tie)), + MoveValueStats::new_from_state(Some(MVSGameState::Tie)), + ]; + a.populate_self_from_children(&children); + assert_eq!(a.wins, 2, "Wins should be 2"); + assert_eq!(a.losses, 1, "Losses should be 1"); + assert_eq!(a.ties, 2, "Ties should be 2"); + } } diff --git a/src/main.rs b/src/main.rs index 982646c..8b2330c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,7 +39,7 @@ fn main() { min_arena_depth: 14, top_k_children: 2, up_to_minus: 10, - max_arena_size: 200_000_000, + max_arena_size: 50_000_000, do_prune: false, print: true, children_eval_method: Default::default(),