This commit is contained in:
2025-04-28 01:42:29 -04:00
parent 189a5aef58
commit eedc80e46a
4 changed files with 62 additions and 35 deletions

View File

@@ -9,7 +9,7 @@ use indicatif::{ProgressBar, ProgressStyle};
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
use skillratings::{ use skillratings::{
elo::{elo, EloConfig, EloRating}, glicko2::{glicko2, Glicko2Rating},
Outcomes, Rating, Outcomes, Rating,
}; };
use std::num::NonZero; use std::num::NonZero;
@@ -136,7 +136,7 @@ pub fn run() {
pub struct PlayerArena { pub struct PlayerArena {
/// Name, Creator Function, Elo /// Name, Creator Function, Elo
players: Vec<(String, AgentMaker, EloRating)>, players: Vec<(String, AgentMaker, Glicko2Rating)>,
} }
impl std::fmt::Display for PlayerArena { impl std::fmt::Display for PlayerArena {
@@ -162,7 +162,7 @@ impl PlayerArena {
Self { Self {
players: players players: players
.into_iter() .into_iter()
.zip([EloRating::new()].into_iter().cycle()) .zip([Default::default()].into_iter().cycle())
// flatten tuple // flatten tuple
.map(|((a, b), c)| (a, b, c)) .map(|((a, b), c)| (a, b, c))
.collect(), .collect(),
@@ -263,11 +263,11 @@ impl PlayerArena {
} }
fn process_outcome(&mut self, player1: usize, player2: usize, outcome: &Outcomes) { 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[player1].2,
&self.players[player2].2, &self.players[player2].2,
outcome, outcome,
&EloConfig { k: 10.0 }, &Default::default(),
); );
self.players[player1].2 = np1; self.players[player1].2 = np1;
self.players[player2].2 = np2; self.players[player2].2 = np2;

View File

@@ -87,21 +87,17 @@ impl std::fmt::Display for FutureMoveConfig {
} }
} }
#[derive(Debug, Clone, Copy, Allocative)] #[derive(Debug, Clone, Copy, Allocative, Default)]
#[allow(dead_code)] #[allow(dead_code)]
pub enum ChildrenEvalMethod { pub enum ChildrenEvalMethod {
/// Best so far? /// Best so far?
// #[default]
MinMax, MinMax,
#[default]
MinMaxProb, MinMaxProb,
} }
impl Default for ChildrenEvalMethod {
fn default() -> Self {
Self::MinMax
}
}
impl FutureMoves { impl FutureMoves {
pub const fn new(agent_color: Piece, config: FutureMoveConfig) -> Self { pub const fn new(agent_color: Piece, config: FutureMoveConfig) -> Self {
Self { Self {

View File

@@ -19,10 +19,11 @@ pub struct MoveValueStats {
impl MoveValueStats { impl MoveValueStats {
#[cfg(test)] #[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 { Self {
wins, wins,
losses, losses,
ties,
..Default::default() ..Default::default()
} }
} }
@@ -56,21 +57,18 @@ impl MoveValueStats {
} }
pub fn populate_self_from_children(&mut self, others: &[Self]) { pub fn populate_self_from_children(&mut self, others: &[Self]) {
self.wins = others.iter().map(|x| x.wins).sum::<u16>() self.wins = others
+ others .iter()
.iter() .map(|x| x.wins + (x.state == Some(MVSGameState::Win)) as u16)
.filter(|x| x.state == Some(MVSGameState::Win)) .sum::<u16>();
.count() as u16; self.losses = others
self.losses = others.iter().map(|x| x.losses).sum::<u16>() .iter()
+ others .map(|x| x.losses + (x.state == Some(MVSGameState::Loss)) as u16)
.iter() .sum::<u16>();
.filter(|x| x.state == Some(MVSGameState::Loss)) self.ties = others
.count() as u16; .iter()
self.ties = others.iter().map(|x| x.ties).sum::<u16>() .map(|x| x.ties + (x.state == Some(MVSGameState::Tie)) as u16)
+ others .sum::<u16>();
.iter()
.filter(|x| x.state == Some(MVSGameState::Tie))
.count() as u16;
} }
} }
@@ -105,29 +103,62 @@ mod tests {
#[test] #[test]
fn two_prob() { fn two_prob() {
let one = MoveValueStats::new_from_wins_losses(10, 4); let one = MoveValueStats::new_from_outcomes(100, 40, 0);
let two = MoveValueStats::new_from_wins_losses(4, 6);
let two = MoveValueStats::new_from_outcomes(40, 60, 0);
assert!(one > two); assert!(one > two);
} }
#[test] #[test]
fn one_prob_one_non() { 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); let two = MoveValueStats::new_from_value(10);
assert!(one > two); assert!(one > two);
} }
#[test] #[test]
fn one_prob_one_win() { 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)); let two = MoveValueStats::new_from_state(Some(MVSGameState::Win));
assert!(one < two); assert!(one < two);
} }
#[test] #[test]
fn two_prob_zero() { fn two_prob_zero() {
let one = MoveValueStats::new_from_wins_losses(10, 0); let one = MoveValueStats::new_from_outcomes(100, 0, 0);
let two = MoveValueStats::new_from_wins_losses(0, 6); let two = MoveValueStats::new_from_outcomes(0, 60, 0);
assert!(one > two); 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");
}
} }

View File

@@ -39,7 +39,7 @@ fn main() {
min_arena_depth: 14, min_arena_depth: 14,
top_k_children: 2, top_k_children: 2,
up_to_minus: 10, up_to_minus: 10,
max_arena_size: 200_000_000, max_arena_size: 50_000_000,
do_prune: false, do_prune: false,
print: true, print: true,
children_eval_method: Default::default(), children_eval_method: Default::default(),