fixes
This commit is contained in:
10
src/elo.rs
10
src/elo.rs
@@ -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;
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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()
|
||||||
.filter(|x| x.state == Some(MVSGameState::Win))
|
.map(|x| x.wins + (x.state == Some(MVSGameState::Win)) as u16)
|
||||||
.count() as u16;
|
.sum::<u16>();
|
||||||
self.losses = others.iter().map(|x| x.losses).sum::<u16>()
|
self.losses = others
|
||||||
+ others
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|x| x.state == Some(MVSGameState::Loss))
|
.map(|x| x.losses + (x.state == Some(MVSGameState::Loss)) as u16)
|
||||||
.count() as u16;
|
.sum::<u16>();
|
||||||
self.ties = others.iter().map(|x| x.ties).sum::<u16>()
|
self.ties = others
|
||||||
+ others
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|x| x.state == Some(MVSGameState::Tie))
|
.map(|x| x.ties + (x.state == Some(MVSGameState::Tie)) as u16)
|
||||||
.count() as u16;
|
.sum::<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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
Reference in New Issue
Block a user