Added more functions to History
This commit is contained in:
@@ -1,3 +1,7 @@
|
|||||||
# TrueSkill - Through Time
|
# TrueSkill - Through Time
|
||||||
|
|
||||||
Rust port of [TrueSkillThroughTime.py](https://github.com/glandfried/TrueSkillThroughTime.py).
|
Rust port of [TrueSkillThroughTime.py](https://github.com/glandfried/TrueSkillThroughTime.py).
|
||||||
|
|
||||||
|
## Todo
|
||||||
|
|
||||||
|
- [ ] Change `time` to always be a u64 (or usize)?
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ pub struct Team {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Event {
|
pub struct Event {
|
||||||
teams: Vec<Team>,
|
teams: Vec<Team>,
|
||||||
evidence: f64,
|
pub evidence: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Event {
|
impl Event {
|
||||||
@@ -94,8 +94,8 @@ fn compute_elapsed(last_time: f64, actual_time: f64) -> f64 {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Batch {
|
pub struct Batch {
|
||||||
pub skills: HashMap<String, Skill>,
|
pub skills: HashMap<String, Skill>,
|
||||||
events: Vec<Event>,
|
pub events: Vec<Event>,
|
||||||
time: f64,
|
pub time: f64,
|
||||||
p_draw: f64,
|
p_draw: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
|
|
||||||
use crate::utils;
|
use crate::{utils, MU, SIGMA};
|
||||||
|
|
||||||
pub const BETA: f64 = 1.0;
|
|
||||||
pub const MU: f64 = 0.0;
|
|
||||||
pub const SIGMA: f64 = BETA * 6.0;
|
|
||||||
pub const GAMMA: f64 = BETA * 0.03;
|
|
||||||
|
|
||||||
pub const N01: Gaussian = Gaussian::new(0.0, 1.0);
|
|
||||||
pub const N00: Gaussian = Gaussian::new(0.0, 0.0);
|
|
||||||
pub const N_INF: Gaussian = Gaussian::new(0.0, f64::INFINITY);
|
|
||||||
pub const N_MS: Gaussian = Gaussian::new(MU, SIGMA);
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||||
pub struct Gaussian {
|
pub struct Gaussian {
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ impl History {
|
|||||||
pub fn convergence(&mut self) -> ((f64, f64), usize) {
|
pub fn convergence(&mut self) -> ((f64, f64), usize) {
|
||||||
let epsilon = 1e-6;
|
let epsilon = 1e-6;
|
||||||
let iterations = 30;
|
let iterations = 30;
|
||||||
let verbose = false;
|
let verbose = true;
|
||||||
|
|
||||||
let mut step = (f64::INFINITY, f64::INFINITY);
|
let mut step = (f64::INFINITY, f64::INFINITY);
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
@@ -196,12 +196,30 @@ impl History {
|
|||||||
(step, i)
|
(step, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn learning_curves(&self) {
|
pub fn learning_curves(&self) -> HashMap<String, Vec<(f64, Gaussian)>> {
|
||||||
todo!()
|
let mut data: HashMap<String, Vec<(f64, Gaussian)>> = HashMap::new();
|
||||||
|
|
||||||
|
for b in &self.batches {
|
||||||
|
for agent in b.skills.keys() {
|
||||||
|
let point = (b.time, b.posterior(agent));
|
||||||
|
|
||||||
|
if let Some(entry) = data.get_mut(agent) {
|
||||||
|
entry.push(point);
|
||||||
|
} else {
|
||||||
|
data.insert(agent.to_string(), vec![point]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log_evidence(&self) {
|
pub fn log_evidence(&self) -> f64 {
|
||||||
todo!()
|
self.batches
|
||||||
|
.iter()
|
||||||
|
.flat_map(|batch| batch.events.iter())
|
||||||
|
.map(|event| event.evidence.ln())
|
||||||
|
.sum()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,4 +462,71 @@ mod tests {
|
|||||||
epsilon = 0.000001
|
epsilon = 0.000001
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_learning_curves() {
|
||||||
|
let composition = vec![
|
||||||
|
vec![vec!["aj"], vec!["bj"]],
|
||||||
|
vec![vec!["bj"], vec!["cj"]],
|
||||||
|
vec![vec!["cj"], vec!["aj"]],
|
||||||
|
];
|
||||||
|
let results = vec![vec![1, 0], vec![1, 0], vec![1, 0]];
|
||||||
|
let times = vec![5, 6, 7];
|
||||||
|
|
||||||
|
let mut priors = HashMap::new();
|
||||||
|
|
||||||
|
for k in ["aj", "bj", "cj"] {
|
||||||
|
let player = Player::new(
|
||||||
|
Gaussian::new(25.0, 25.0 / 3.0),
|
||||||
|
25.0 / 6.0,
|
||||||
|
25.0 / 300.0,
|
||||||
|
N_INF,
|
||||||
|
);
|
||||||
|
|
||||||
|
priors.insert(k.to_string(), player);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut h = History::new(
|
||||||
|
composition,
|
||||||
|
results,
|
||||||
|
times,
|
||||||
|
priors,
|
||||||
|
MU,
|
||||||
|
BETA,
|
||||||
|
SIGMA,
|
||||||
|
GAMMA,
|
||||||
|
P_DRAW,
|
||||||
|
);
|
||||||
|
|
||||||
|
h.convergence();
|
||||||
|
|
||||||
|
let lc = h.learning_curves();
|
||||||
|
|
||||||
|
let aj_e = lc["aj"].len();
|
||||||
|
let cj_e = lc["cj"].len();
|
||||||
|
|
||||||
|
assert_eq!(lc["aj"][0].0, 5.0);
|
||||||
|
assert_eq!(lc["aj"][aj_e - 1].0, 7.0);
|
||||||
|
|
||||||
|
assert_ulps_eq!(
|
||||||
|
lc["aj"][aj_e - 1].1.mu(),
|
||||||
|
24.99999999569006,
|
||||||
|
epsilon = 0.000001
|
||||||
|
);
|
||||||
|
assert_ulps_eq!(
|
||||||
|
lc["aj"][aj_e - 1].1.sigma(),
|
||||||
|
5.419212002171145,
|
||||||
|
epsilon = 0.000001
|
||||||
|
);
|
||||||
|
assert_ulps_eq!(
|
||||||
|
lc["cj"][cj_e - 1].1.mu(),
|
||||||
|
24.999999998686533,
|
||||||
|
epsilon = 0.000001
|
||||||
|
);
|
||||||
|
assert_ulps_eq!(
|
||||||
|
lc["cj"][cj_e - 1].1.sigma(),
|
||||||
|
5.419212002245715,
|
||||||
|
epsilon = 0.000001
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,5 +36,5 @@ fn main() {
|
|||||||
P_DRAW,
|
P_DRAW,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (step, i) = h2.convergence();
|
let (_step, _i) = h2.convergence();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user