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 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;

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)]
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 {

View File

@@ -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::<u16>()
+ others
.iter()
.filter(|x| x.state == Some(MVSGameState::Win))
.count() as u16;
self.losses = others.iter().map(|x| x.losses).sum::<u16>()
+ others
.iter()
.filter(|x| x.state == Some(MVSGameState::Loss))
.count() as u16;
self.ties = others.iter().map(|x| x.ties).sum::<u16>()
+ 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::<u16>();
self.losses = others
.iter()
.map(|x| x.losses + (x.state == Some(MVSGameState::Loss)) as u16)
.sum::<u16>();
self.ties = others
.iter()
.map(|x| x.ties + (x.state == Some(MVSGameState::Tie)) as u16)
.sum::<u16>();
}
}
@@ -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");
}
}

View File

@@ -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(),