Use PlayerIndex instead of String
This commit is contained in:
230
src/batch.rs
230
src/batch.rs
@@ -1,6 +1,6 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use crate::{Game, Gaussian, Player, N_INF};
|
||||
use crate::{Game, Gaussian, Player, PlayerIndex, N_INF};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Skill {
|
||||
@@ -48,7 +48,7 @@ impl Agent {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Item {
|
||||
name: String,
|
||||
index: PlayerIndex,
|
||||
likelihood: Gaussian,
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ pub struct Event {
|
||||
}
|
||||
|
||||
impl Event {
|
||||
/*
|
||||
pub fn names(&self) -> Vec<&str> {
|
||||
self.teams
|
||||
.iter()
|
||||
@@ -72,6 +73,7 @@ impl Event {
|
||||
.map(|item| item.name.as_str())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn result(&self) -> Vec<u16> {
|
||||
self.teams
|
||||
@@ -93,18 +95,28 @@ fn compute_elapsed(last_time: f64, actual_time: f64) -> f64 {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Batch {
|
||||
pub skills: HashMap<String, Skill>,
|
||||
pub skills: HashMap<PlayerIndex, Skill>,
|
||||
pub events: Vec<Event>,
|
||||
pub time: f64,
|
||||
p_draw: f64,
|
||||
}
|
||||
|
||||
/*
|
||||
fn test<S, I>(inp: S) where S: AsRef<[I]>, I: AsRef<[u8]> {
|
||||
for a in inp.as_ref().iter() {
|
||||
for b in a.as_ref().iter() {
|
||||
println!("{}", b);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
impl Batch {
|
||||
pub fn new<C: AsRef<str> + Clone>(
|
||||
composition: Vec<Vec<Vec<C>>>,
|
||||
pub fn new(
|
||||
composition: Vec<Vec<Vec<PlayerIndex>>>,
|
||||
results: Vec<Vec<u16>>,
|
||||
time: f64,
|
||||
agents: &mut HashMap<String, Agent>,
|
||||
agents: &mut HashMap<PlayerIndex, Agent>,
|
||||
p_draw: f64,
|
||||
) -> Self {
|
||||
let mut this = Self {
|
||||
@@ -119,17 +131,16 @@ impl Batch {
|
||||
this
|
||||
}
|
||||
|
||||
pub fn add_events<C: AsRef<str> + Clone>(
|
||||
pub fn add_events(
|
||||
&mut self,
|
||||
composition: Vec<Vec<Vec<C>>>,
|
||||
composition: Vec<Vec<Vec<PlayerIndex>>>,
|
||||
results: Vec<Vec<u16>>,
|
||||
agents: &mut HashMap<String, Agent>,
|
||||
agents: &mut HashMap<PlayerIndex, Agent>,
|
||||
) {
|
||||
let this_agent = composition
|
||||
.iter()
|
||||
.flatten()
|
||||
.flatten()
|
||||
.map(AsRef::as_ref)
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
for a in this_agent {
|
||||
@@ -140,7 +151,7 @@ impl Batch {
|
||||
skill.elapsed = elapsed;
|
||||
} else {
|
||||
self.skills.insert(
|
||||
a.to_string(),
|
||||
*a,
|
||||
Skill {
|
||||
forward: agents[a].receive(elapsed),
|
||||
elapsed,
|
||||
@@ -157,7 +168,7 @@ impl Batch {
|
||||
.map(|t| {
|
||||
let items = (0..composition[e][t].len())
|
||||
.map(|a| Item {
|
||||
name: composition[e][t][a].as_ref().to_string(),
|
||||
index: composition[e][t][a],
|
||||
likelihood: N_INF,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -180,22 +191,22 @@ impl Batch {
|
||||
self.iteration(from, agents);
|
||||
}
|
||||
|
||||
pub fn posterior(&self, agent: &str) -> Gaussian {
|
||||
pub fn posterior(&self, agent: &PlayerIndex) -> Gaussian {
|
||||
let skill = &self.skills[agent];
|
||||
|
||||
skill.likelihood * skill.backward * skill.forward
|
||||
}
|
||||
|
||||
pub fn posteriors(&self) -> HashMap<String, Gaussian> {
|
||||
pub fn posteriors(&self) -> HashMap<PlayerIndex, Gaussian> {
|
||||
self.skills
|
||||
.keys()
|
||||
.map(|a| (a.clone(), self.posterior(a)))
|
||||
.map(|a| (*a, self.posterior(a)))
|
||||
.collect::<HashMap<_, _>>()
|
||||
}
|
||||
|
||||
fn within_prior(&self, item: &Item, agents: &mut HashMap<String, Agent>) -> Player {
|
||||
let r = &agents[&item.name].player;
|
||||
let g = self.posterior(&item.name) / item.likelihood;
|
||||
fn within_prior(&self, item: &Item, agents: &mut HashMap<PlayerIndex, Agent>) -> Player {
|
||||
let r = &agents[&item.index].player;
|
||||
let g = self.posterior(&item.index) / item.likelihood;
|
||||
|
||||
Player::new(g, r.beta, r.gamma, N_INF)
|
||||
}
|
||||
@@ -203,7 +214,7 @@ impl Batch {
|
||||
pub fn within_priors(
|
||||
&self,
|
||||
event: usize,
|
||||
agents: &mut HashMap<String, Agent>,
|
||||
agents: &mut HashMap<PlayerIndex, Agent>,
|
||||
) -> Vec<Vec<Player>> {
|
||||
self.events[event]
|
||||
.teams
|
||||
@@ -217,7 +228,7 @@ impl Batch {
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn iteration(&mut self, from: usize, agents: &mut HashMap<String, Agent>) {
|
||||
fn iteration(&mut self, from: usize, agents: &mut HashMap<PlayerIndex, Agent>) {
|
||||
for e in from..self.events.len() {
|
||||
let teams = self.within_priors(e, agents);
|
||||
let result = self.events[e].result();
|
||||
@@ -226,8 +237,8 @@ impl Batch {
|
||||
|
||||
for (t, team) in self.events[e].teams.iter_mut().enumerate() {
|
||||
for (i, item) in team.items.iter_mut().enumerate() {
|
||||
self.skills.get_mut(&item.name).unwrap().likelihood =
|
||||
(self.skills[&item.name].likelihood / item.likelihood)
|
||||
self.skills.get_mut(&item.index).unwrap().likelihood =
|
||||
(self.skills[&item.index].likelihood / item.likelihood)
|
||||
* g.likelihoods[t][i];
|
||||
|
||||
item.likelihood = g.likelihoods[t][i];
|
||||
@@ -238,7 +249,7 @@ impl Batch {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convergence(&mut self, agents: &mut HashMap<String, Agent>) -> usize {
|
||||
pub fn convergence(&mut self, agents: &mut HashMap<PlayerIndex, Agent>) -> usize {
|
||||
let epsilon = 1e-6;
|
||||
let iterations = 20;
|
||||
|
||||
@@ -267,20 +278,24 @@ impl Batch {
|
||||
i
|
||||
}
|
||||
|
||||
pub fn forward_prior_out(&self, agent: &str) -> Gaussian {
|
||||
pub fn forward_prior_out(&self, agent: &PlayerIndex) -> Gaussian {
|
||||
let skill = &self.skills[agent];
|
||||
|
||||
skill.forward * skill.likelihood
|
||||
}
|
||||
|
||||
pub fn backward_prior_out(&self, agent: &str, agents: &mut HashMap<String, Agent>) -> Gaussian {
|
||||
pub fn backward_prior_out(
|
||||
&self,
|
||||
agent: &PlayerIndex,
|
||||
agents: &mut HashMap<PlayerIndex, Agent>,
|
||||
) -> Gaussian {
|
||||
let skill = &self.skills[agent];
|
||||
let n = skill.likelihood * skill.backward;
|
||||
|
||||
n.forget(agents[agent].player.gamma, skill.elapsed)
|
||||
}
|
||||
|
||||
pub fn new_backward_info(&mut self, agents: &mut HashMap<String, Agent>) {
|
||||
pub fn new_backward_info(&mut self, agents: &mut HashMap<PlayerIndex, Agent>) {
|
||||
for (agent, skill) in self.skills.iter_mut() {
|
||||
skill.backward = agents[agent].message;
|
||||
}
|
||||
@@ -288,7 +303,7 @@ impl Batch {
|
||||
self.iteration(0, agents);
|
||||
}
|
||||
|
||||
pub fn new_forward_info(&mut self, agents: &mut HashMap<String, Agent>) {
|
||||
pub fn new_forward_info(&mut self, agents: &mut HashMap<PlayerIndex, Agent>) {
|
||||
for (agent, skill) in self.skills.iter_mut() {
|
||||
skill.forward = agents[agent].receive(skill.elapsed);
|
||||
}
|
||||
@@ -307,7 +322,14 @@ mod tests {
|
||||
fn test_one_event_each() {
|
||||
let mut agents = HashMap::new();
|
||||
|
||||
for k in ["a", "b", "c", "d", "e", "f"] {
|
||||
let a = PlayerIndex::new(0);
|
||||
let b = PlayerIndex::new(1);
|
||||
let c = PlayerIndex::new(2);
|
||||
let d = PlayerIndex::new(3);
|
||||
let e = PlayerIndex::new(4);
|
||||
let f = PlayerIndex::new(5);
|
||||
|
||||
for k in [a, b, c, d, e, f] {
|
||||
let agent = Agent::new(
|
||||
Player::new(
|
||||
Gaussian::new(25.0, 25.0 / 3.0),
|
||||
@@ -319,14 +341,14 @@ mod tests {
|
||||
f64::NEG_INFINITY,
|
||||
);
|
||||
|
||||
agents.insert(k.to_string(), agent);
|
||||
agents.insert(k, agent);
|
||||
}
|
||||
|
||||
let mut b = Batch::new(
|
||||
let mut batch = Batch::new(
|
||||
vec![
|
||||
vec![vec!["a"], vec!["b"]],
|
||||
vec![vec!["c"], vec!["d"]],
|
||||
vec![vec!["e"], vec!["f"]],
|
||||
vec![vec![a], vec![b]],
|
||||
vec![vec![c], vec![d]],
|
||||
vec![vec![e], vec![f]],
|
||||
],
|
||||
vec![vec![1, 0], vec![0, 1], vec![1, 0]],
|
||||
0.0,
|
||||
@@ -334,25 +356,32 @@ mod tests {
|
||||
0.0,
|
||||
);
|
||||
|
||||
let post = b.posteriors();
|
||||
let post = batch.posteriors();
|
||||
|
||||
assert_eq!(post["a"].mu(), 29.205220743876975);
|
||||
assert_eq!(post["a"].sigma(), 7.194481422570443);
|
||||
assert_eq!(post[&a].mu(), 29.205220743876975);
|
||||
assert_eq!(post[&a].sigma(), 7.194481422570443);
|
||||
|
||||
assert_eq!(post["b"].mu(), 20.79477925612302);
|
||||
assert_eq!(post["b"].sigma(), 7.194481422570443);
|
||||
assert_eq!(post[&b].mu(), 20.79477925612302);
|
||||
assert_eq!(post[&b].sigma(), 7.194481422570443);
|
||||
|
||||
assert_eq!(post["c"].mu(), 20.79477925612302);
|
||||
assert_eq!(post["c"].sigma(), 7.194481422570443);
|
||||
assert_eq!(post[&c].mu(), 20.79477925612302);
|
||||
assert_eq!(post[&c].sigma(), 7.194481422570443);
|
||||
|
||||
assert_eq!(b.convergence(&mut agents), 1);
|
||||
assert_eq!(batch.convergence(&mut agents), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_same_strength() {
|
||||
let mut agents = HashMap::new();
|
||||
|
||||
for k in ["a", "b", "c", "d", "e", "f"] {
|
||||
let a = PlayerIndex::new(0);
|
||||
let b = PlayerIndex::new(1);
|
||||
let c = PlayerIndex::new(2);
|
||||
let d = PlayerIndex::new(3);
|
||||
let e = PlayerIndex::new(4);
|
||||
let f = PlayerIndex::new(5);
|
||||
|
||||
for k in [a, b, c, d, e, f] {
|
||||
let agent = Agent::new(
|
||||
Player::new(
|
||||
Gaussian::new(25.0, 25.0 / 3.0),
|
||||
@@ -364,14 +393,14 @@ mod tests {
|
||||
f64::NEG_INFINITY,
|
||||
);
|
||||
|
||||
agents.insert(k.to_string(), agent);
|
||||
agents.insert(k, agent);
|
||||
}
|
||||
|
||||
let mut b = Batch::new(
|
||||
let mut batch = Batch::new(
|
||||
vec![
|
||||
vec![vec!["a"], vec!["b"]],
|
||||
vec![vec!["a"], vec!["c"]],
|
||||
vec![vec!["b"], vec!["c"]],
|
||||
vec![vec![a], vec![b]],
|
||||
vec![vec![a], vec![c]],
|
||||
vec![vec![b], vec![c]],
|
||||
],
|
||||
vec![vec![1, 0], vec![0, 1], vec![1, 0]],
|
||||
2.0,
|
||||
@@ -379,28 +408,105 @@ mod tests {
|
||||
0.0,
|
||||
);
|
||||
|
||||
let post = b.posteriors();
|
||||
let post = batch.posteriors();
|
||||
|
||||
assert_eq!(post["a"].mu(), 24.96097857478182);
|
||||
assert_eq!(post["a"].sigma(), 6.298544763358269);
|
||||
assert_eq!(post[&a].mu(), 24.96097857478182);
|
||||
assert_eq!(post[&a].sigma(), 6.298544763358269);
|
||||
|
||||
assert_eq!(post["b"].mu(), 27.095590669107086);
|
||||
assert_eq!(post["b"].sigma(), 6.010330439043099);
|
||||
assert_eq!(post[&b].mu(), 27.095590669107086);
|
||||
assert_eq!(post[&b].sigma(), 6.010330439043099);
|
||||
|
||||
assert_eq!(post["c"].mu(), 24.88968178743119);
|
||||
assert_eq!(post["c"].sigma(), 5.866311348102562);
|
||||
assert_eq!(post[&c].mu(), 24.88968178743119);
|
||||
assert_eq!(post[&c].sigma(), 5.866311348102562);
|
||||
|
||||
assert!(b.convergence(&mut agents) > 1);
|
||||
assert!(batch.convergence(&mut agents) > 1);
|
||||
|
||||
let post = b.posteriors();
|
||||
let post = batch.posteriors();
|
||||
|
||||
assert_ulps_eq!(post["a"].mu(), 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["a"].sigma(), 5.4192120, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post[&a].mu(), 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post[&a].sigma(), 5.4192120, epsilon = 0.000001);
|
||||
|
||||
assert_ulps_eq!(post["b"].mu(), 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["b"].sigma(), 5.4192120, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post[&b].mu(), 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post[&b].sigma(), 5.4192120, epsilon = 0.000001);
|
||||
|
||||
assert_ulps_eq!(post["c"].mu(), 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["c"].sigma(), 5.4192120, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post[&c].mu(), 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post[&c].sigma(), 5.4192120, epsilon = 0.000001);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_events() {
|
||||
let mut agents = HashMap::new();
|
||||
|
||||
let a = PlayerIndex::new(0);
|
||||
let b = PlayerIndex::new(1);
|
||||
let c = PlayerIndex::new(2);
|
||||
let d = PlayerIndex::new(3);
|
||||
let e = PlayerIndex::new(4);
|
||||
let f = PlayerIndex::new(5);
|
||||
|
||||
for k in [a, b, c, d, e, f] {
|
||||
let agent = Agent::new(
|
||||
Player::new(
|
||||
Gaussian::new(25.0, 25.0 / 3.0),
|
||||
25.0 / 6.0,
|
||||
25.0 / 300.0,
|
||||
N_INF,
|
||||
),
|
||||
N_INF,
|
||||
f64::NEG_INFINITY,
|
||||
);
|
||||
|
||||
agents.insert(k, agent);
|
||||
}
|
||||
|
||||
let mut batch = Batch::new(
|
||||
vec![
|
||||
vec![vec![a], vec![b]],
|
||||
vec![vec![a], vec![c]],
|
||||
vec![vec![b], vec![c]],
|
||||
],
|
||||
vec![vec![1, 0], vec![0, 1], vec![1, 0]],
|
||||
0.0,
|
||||
&mut agents,
|
||||
0.0,
|
||||
);
|
||||
|
||||
batch.convergence(&mut agents);
|
||||
|
||||
let p = batch.posteriors();
|
||||
|
||||
assert_ulps_eq!(p[&a].mu(), 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(p[&a].sigma(), 5.4192120, epsilon = 0.000001);
|
||||
|
||||
assert_ulps_eq!(p[&b].mu(), 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(p[&b].sigma(), 5.4192120, epsilon = 0.000001);
|
||||
|
||||
assert_ulps_eq!(p[&c].mu(), 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(p[&c].sigma(), 5.4192120, epsilon = 0.000001);
|
||||
|
||||
batch.add_events(
|
||||
vec![
|
||||
vec![vec![a], vec![b]],
|
||||
vec![vec![a], vec![c]],
|
||||
vec![vec![b], vec![c]],
|
||||
],
|
||||
vec![vec![1, 0], vec![0, 1], vec![1, 0]],
|
||||
&mut agents,
|
||||
);
|
||||
|
||||
assert_eq!(batch.events.len(), 6);
|
||||
|
||||
batch.convergence(&mut agents);
|
||||
|
||||
let p = batch.posteriors();
|
||||
|
||||
assert_ulps_eq!(p[&a].mu(), 25.00000315330858, epsilon = 0.000001);
|
||||
assert_ulps_eq!(p[&a].sigma(), 3.880150268080797, epsilon = 0.000001);
|
||||
|
||||
assert_ulps_eq!(p[&b].mu(), 25.00000315330858, epsilon = 0.000001);
|
||||
assert_ulps_eq!(p[&b].sigma(), 3.880150268080797, epsilon = 0.000001);
|
||||
|
||||
assert_ulps_eq!(p[&c].mu(), 25.00000315330858, epsilon = 0.000001);
|
||||
assert_ulps_eq!(p[&c].sigma(), 3.880150268080797, epsilon = 0.000001);
|
||||
}
|
||||
}
|
||||
|
||||
161
src/history.rs
161
src/history.rs
@@ -1,11 +1,11 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use crate::{utils, Agent, Batch, Gaussian, Player, N_INF};
|
||||
use crate::{utils, Agent, Batch, Gaussian, Player, PlayerIndex, N_INF};
|
||||
|
||||
pub struct History {
|
||||
size: usize,
|
||||
pub batches: Vec<Batch>,
|
||||
pub agents: HashMap<String, Agent>,
|
||||
batches: Vec<Batch>,
|
||||
agents: HashMap<PlayerIndex, Agent>,
|
||||
mu: f64,
|
||||
sigma: f64,
|
||||
gamma: f64,
|
||||
@@ -17,11 +17,11 @@ pub struct History {
|
||||
}
|
||||
|
||||
impl History {
|
||||
pub fn new<C: AsRef<str> + Clone>(
|
||||
composition: Vec<Vec<Vec<C>>>,
|
||||
pub fn new(
|
||||
composition: Vec<Vec<Vec<PlayerIndex>>>,
|
||||
results: Vec<Vec<u16>>,
|
||||
times: Vec<f64>,
|
||||
priors: HashMap<String, Player>,
|
||||
priors: HashMap<PlayerIndex, Player>,
|
||||
mu: f64,
|
||||
sigma: f64,
|
||||
beta: f64,
|
||||
@@ -32,7 +32,6 @@ impl History {
|
||||
.iter()
|
||||
.flatten()
|
||||
.flatten()
|
||||
.map(AsRef::as_ref)
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
let agents = this_agent
|
||||
@@ -44,7 +43,7 @@ impl History {
|
||||
.unwrap_or_else(|| Player::new(Gaussian::new(mu, sigma), beta, gamma, N_INF));
|
||||
|
||||
(
|
||||
a.to_string(),
|
||||
*a,
|
||||
Agent {
|
||||
player,
|
||||
message: N_INF,
|
||||
@@ -73,9 +72,9 @@ impl History {
|
||||
this
|
||||
}
|
||||
|
||||
fn trueskill<C: AsRef<str> + Clone>(
|
||||
fn trueskill(
|
||||
&mut self,
|
||||
composition: Vec<Vec<Vec<C>>>,
|
||||
composition: Vec<Vec<Vec<PlayerIndex>>>,
|
||||
results: Vec<Vec<u16>>,
|
||||
times: Vec<f64>,
|
||||
) {
|
||||
@@ -207,8 +206,8 @@ impl History {
|
||||
(step, i)
|
||||
}
|
||||
|
||||
pub fn learning_curves(&self) -> HashMap<String, Vec<(f64, Gaussian)>> {
|
||||
let mut data: HashMap<String, Vec<(f64, Gaussian)>> = HashMap::new();
|
||||
pub fn learning_curves(&self) -> HashMap<PlayerIndex, Vec<(f64, Gaussian)>> {
|
||||
let mut data: HashMap<PlayerIndex, Vec<(f64, Gaussian)>> = HashMap::new();
|
||||
|
||||
for b in &self.batches {
|
||||
for agent in b.skills.keys() {
|
||||
@@ -217,7 +216,7 @@ impl History {
|
||||
if let Some(entry) = data.get_mut(agent) {
|
||||
entry.push(point);
|
||||
} else {
|
||||
data.insert(agent.to_string(), vec![point]);
|
||||
data.insert(*agent, vec![point]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,16 +260,20 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_init() {
|
||||
let a = PlayerIndex::new(0);
|
||||
let b = PlayerIndex::new(1);
|
||||
let c = PlayerIndex::new(2);
|
||||
|
||||
let composition = vec![
|
||||
vec![vec!["a"], vec!["b"]],
|
||||
vec![vec!["a"], vec!["c"]],
|
||||
vec![vec!["b"], vec!["c"]],
|
||||
vec![vec![a], vec![b]],
|
||||
vec![vec![a], vec![c]],
|
||||
vec![vec![b], vec![c]],
|
||||
];
|
||||
let results = vec![vec![1, 0], vec![0, 1], vec![1, 0]];
|
||||
|
||||
let mut priors = HashMap::new();
|
||||
|
||||
for k in ["a", "b", "c"] {
|
||||
for k in [a, b, c] {
|
||||
let player = Player::new(
|
||||
Gaussian::new(25.0, 25.0 / 3.0),
|
||||
25.0 / 6.0,
|
||||
@@ -278,7 +281,7 @@ mod tests {
|
||||
N_INF,
|
||||
);
|
||||
|
||||
priors.insert(k.to_string(), player);
|
||||
priors.insert(k, player);
|
||||
}
|
||||
|
||||
let mut h = History::new(
|
||||
@@ -295,16 +298,16 @@ mod tests {
|
||||
|
||||
let p0 = h.batches[0].posteriors();
|
||||
|
||||
assert_ulps_eq!(p0["a"].mu(), 29.205220743876975, epsilon = 0.000001);
|
||||
assert_ulps_eq!(p0["a"].sigma(), 7.194481422570443, epsilon = 0.000001);
|
||||
assert_ulps_eq!(p0[&a].mu(), 29.205220743876975, epsilon = 0.000001);
|
||||
assert_ulps_eq!(p0[&a].sigma(), 7.194481422570443, epsilon = 0.000001);
|
||||
|
||||
let observed = h.batches[1].skills["a"].forward.sigma();
|
||||
let observed = h.batches[1].skills[&a].forward.sigma();
|
||||
let gamma: f64 = 0.15 * 25.0 / 3.0;
|
||||
let expected = (gamma.powi(2) + h.batches[0].posterior("a").sigma().powi(2)).sqrt();
|
||||
let expected = (gamma.powi(2) + h.batches[0].posterior(&a).sigma().powi(2)).sqrt();
|
||||
|
||||
assert_ulps_eq!(observed, expected, epsilon = 0.000001);
|
||||
|
||||
let observed = h.batches[1].posterior("a");
|
||||
let observed = h.batches[1].posterior(&a);
|
||||
let p = Game::new(
|
||||
h.batches[1].within_priors(0, &mut h.agents),
|
||||
vec![0, 1],
|
||||
@@ -319,17 +322,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_one_batch() {
|
||||
let a = PlayerIndex::new(0);
|
||||
let b = PlayerIndex::new(1);
|
||||
let c = PlayerIndex::new(2);
|
||||
|
||||
let composition = vec![
|
||||
vec![vec!["aj"], vec!["bj"]],
|
||||
vec![vec!["bj"], vec!["cj"]],
|
||||
vec![vec!["cj"], vec!["aj"]],
|
||||
vec![vec![a], vec![b]],
|
||||
vec![vec![b], vec![c]],
|
||||
vec![vec![c], vec![a]],
|
||||
];
|
||||
let results = vec![vec![1, 0], vec![1, 0], vec![1, 0]];
|
||||
let times = vec![1.0, 1.0, 1.0];
|
||||
|
||||
let mut priors = HashMap::new();
|
||||
|
||||
for k in ["aj", "bj", "cj"] {
|
||||
for k in [a, b, c] {
|
||||
let player = Player::new(
|
||||
Gaussian::new(25.0, 25.0 / 3.0),
|
||||
25.0 / 6.0,
|
||||
@@ -337,7 +344,7 @@ mod tests {
|
||||
N_INF,
|
||||
);
|
||||
|
||||
priors.insert(k.to_string(), player);
|
||||
priors.insert(k, player);
|
||||
}
|
||||
|
||||
let mut h1 = History::new(
|
||||
@@ -353,22 +360,22 @@ mod tests {
|
||||
);
|
||||
|
||||
assert_ulps_eq!(
|
||||
h1.batches[0].posterior("aj").mu(),
|
||||
h1.batches[0].posterior(&a).mu(),
|
||||
22.904409330892914,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h1.batches[0].posterior("aj").sigma(),
|
||||
h1.batches[0].posterior(&a).sigma(),
|
||||
6.0103304390431,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h1.batches[0].posterior("cj").mu(),
|
||||
h1.batches[0].posterior(&c).mu(),
|
||||
25.110318212568806,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h1.batches[0].posterior("cj").sigma(),
|
||||
h1.batches[0].posterior(&c).sigma(),
|
||||
5.866311348102563,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
@@ -376,37 +383,37 @@ mod tests {
|
||||
let (_step, _i) = h1.convergence();
|
||||
|
||||
assert_ulps_eq!(
|
||||
h1.batches[0].posterior("aj").mu(),
|
||||
h1.batches[0].posterior(&a).mu(),
|
||||
25.00000000,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h1.batches[0].posterior("aj").sigma(),
|
||||
h1.batches[0].posterior(&a).sigma(),
|
||||
5.41921200,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h1.batches[0].posterior("cj").mu(),
|
||||
h1.batches[0].posterior(&c).mu(),
|
||||
25.00000000,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h1.batches[0].posterior("cj").sigma(),
|
||||
h1.batches[0].posterior(&c).sigma(),
|
||||
5.41921200,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
|
||||
let composition = vec![
|
||||
vec![vec!["aj"], vec!["bj"]],
|
||||
vec![vec!["bj"], vec!["cj"]],
|
||||
vec![vec!["cj"], vec!["aj"]],
|
||||
vec![vec![a], vec![b]],
|
||||
vec![vec![b], vec![c]],
|
||||
vec![vec![c], vec![a]],
|
||||
];
|
||||
let results = vec![vec![1, 0], vec![1, 0], vec![1, 0]];
|
||||
let times = vec![1.0, 2.0, 3.0];
|
||||
|
||||
let mut priors = HashMap::new();
|
||||
|
||||
for k in ["aj", "bj", "cj"] {
|
||||
for k in [a, b, c] {
|
||||
let player = Player::new(
|
||||
Gaussian::new(25.0, 25.0 / 3.0),
|
||||
25.0 / 6.0,
|
||||
@@ -414,7 +421,7 @@ mod tests {
|
||||
N_INF,
|
||||
);
|
||||
|
||||
priors.insert(k.to_string(), player);
|
||||
priors.insert(k, player);
|
||||
}
|
||||
|
||||
let mut h2 = History::new(
|
||||
@@ -430,22 +437,22 @@ mod tests {
|
||||
);
|
||||
|
||||
assert_ulps_eq!(
|
||||
h2.batches[2].posterior("aj").mu(),
|
||||
h2.batches[2].posterior(&a).mu(),
|
||||
22.90352227792141,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h2.batches[2].posterior("aj").sigma(),
|
||||
h2.batches[2].posterior(&a).sigma(),
|
||||
6.011017301320632,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h2.batches[2].posterior("cj").mu(),
|
||||
h2.batches[2].posterior(&c).mu(),
|
||||
25.110702468366718,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h2.batches[2].posterior("cj").sigma(),
|
||||
h2.batches[2].posterior(&c).sigma(),
|
||||
5.866811597660157,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
@@ -453,22 +460,22 @@ mod tests {
|
||||
let (_step, _i) = h2.convergence();
|
||||
|
||||
assert_ulps_eq!(
|
||||
h2.batches[2].posterior("aj").mu(),
|
||||
h2.batches[2].posterior(&a).mu(),
|
||||
24.99866831022851,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h2.batches[2].posterior("aj").sigma(),
|
||||
h2.batches[2].posterior(&a).sigma(),
|
||||
5.420053708148435,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h2.batches[2].posterior("cj").mu(),
|
||||
h2.batches[2].posterior(&c).mu(),
|
||||
25.000532179593538,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h2.batches[2].posterior("cj").sigma(),
|
||||
h2.batches[2].posterior(&c).sigma(),
|
||||
5.419827012784138,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
@@ -476,17 +483,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_learning_curves() {
|
||||
let a = PlayerIndex::new(0);
|
||||
let b = PlayerIndex::new(1);
|
||||
let c = PlayerIndex::new(2);
|
||||
|
||||
let composition = vec![
|
||||
vec![vec!["aj"], vec!["bj"]],
|
||||
vec![vec!["bj"], vec!["cj"]],
|
||||
vec![vec!["cj"], vec!["aj"]],
|
||||
vec![vec![a], vec![b]],
|
||||
vec![vec![b], vec![c]],
|
||||
vec![vec![c], vec![a]],
|
||||
];
|
||||
let results = vec![vec![1, 0], vec![1, 0], vec![1, 0]];
|
||||
let times = vec![5.0, 6.0, 7.0];
|
||||
|
||||
let mut priors = HashMap::new();
|
||||
|
||||
for k in ["aj", "bj", "cj"] {
|
||||
for k in [a, b, c] {
|
||||
let player = Player::new(
|
||||
Gaussian::new(25.0, 25.0 / 3.0),
|
||||
25.0 / 6.0,
|
||||
@@ -494,7 +505,7 @@ mod tests {
|
||||
N_INF,
|
||||
);
|
||||
|
||||
priors.insert(k.to_string(), player);
|
||||
priors.insert(k, player);
|
||||
}
|
||||
|
||||
let mut h = History::new(
|
||||
@@ -513,29 +524,29 @@ mod tests {
|
||||
|
||||
let lc = h.learning_curves();
|
||||
|
||||
let aj_e = lc["aj"].len();
|
||||
let cj_e = lc["cj"].len();
|
||||
let aj_e = lc[&a].len();
|
||||
let cj_e = lc[&c].len();
|
||||
|
||||
assert_eq!(lc["aj"][0].0, 5.0);
|
||||
assert_eq!(lc["aj"][aj_e - 1].0, 7.0);
|
||||
assert_eq!(lc[&a][0].0, 5.0);
|
||||
assert_eq!(lc[&a][aj_e - 1].0, 7.0);
|
||||
|
||||
assert_ulps_eq!(
|
||||
lc["aj"][aj_e - 1].1.mu(),
|
||||
lc[&a][aj_e - 1].1.mu(),
|
||||
24.99866831022851,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
lc["aj"][aj_e - 1].1.sigma(),
|
||||
lc[&a][aj_e - 1].1.sigma(),
|
||||
5.420053708148435,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
lc["cj"][cj_e - 1].1.mu(),
|
||||
lc[&c][cj_e - 1].1.mu(),
|
||||
25.000532179593538,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
lc["cj"][cj_e - 1].1.sigma(),
|
||||
lc[&c][cj_e - 1].1.sigma(),
|
||||
5.419827012784138,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
@@ -543,10 +554,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_env_ttt() {
|
||||
let a = PlayerIndex::new(0);
|
||||
let b = PlayerIndex::new(1);
|
||||
let c = PlayerIndex::new(2);
|
||||
|
||||
let composition = vec![
|
||||
vec![vec!["a"], vec!["b"]],
|
||||
vec![vec!["a"], vec!["c"]],
|
||||
vec![vec!["b"], vec!["c"]],
|
||||
vec![vec![a], vec![b]],
|
||||
vec![vec![a], vec![c]],
|
||||
vec![vec![b], vec![c]],
|
||||
];
|
||||
let results = vec![vec![1, 0], vec![0, 1], vec![1, 0]];
|
||||
|
||||
@@ -564,36 +579,36 @@ mod tests {
|
||||
|
||||
let (_step, _i) = h.convergence();
|
||||
|
||||
assert_eq!(h.batches[2].skills["b"].elapsed, 1.0);
|
||||
assert_eq!(h.batches[2].skills["c"].elapsed, 1.0);
|
||||
assert_eq!(h.batches[2].skills[&b].elapsed, 1.0);
|
||||
assert_eq!(h.batches[2].skills[&c].elapsed, 1.0);
|
||||
|
||||
assert_ulps_eq!(
|
||||
h.batches[0].posterior("a").mu(),
|
||||
h.batches[0].posterior(&a).mu(),
|
||||
25.0002673,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h.batches[0].posterior("a").sigma(),
|
||||
h.batches[0].posterior(&a).sigma(),
|
||||
5.41938162,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h.batches[0].posterior("b").mu(),
|
||||
h.batches[0].posterior(&b).mu(),
|
||||
24.999465,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h.batches[0].posterior("b").sigma(),
|
||||
h.batches[0].posterior(&b).sigma(),
|
||||
5.419425831,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h.batches[2].posterior("b").mu(),
|
||||
h.batches[2].posterior(&b).mu(),
|
||||
25.00053219,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
assert_ulps_eq!(
|
||||
h.batches[2].posterior("b").sigma(),
|
||||
h.batches[2].posterior(&b).sigma(),
|
||||
5.419696790,
|
||||
epsilon = 0.000001
|
||||
);
|
||||
|
||||
28
src/main.rs
28
src/main.rs
@@ -1,28 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use trueskill_tt::*;
|
||||
|
||||
fn main() {
|
||||
let composition = vec![
|
||||
vec![vec!["a"], vec!["b"]],
|
||||
vec![vec!["a"], vec!["c"]],
|
||||
vec![vec!["b"], vec!["c"]],
|
||||
];
|
||||
let results = vec![vec![1, 0], vec![0, 1], vec![1, 0]];
|
||||
|
||||
let mut h = History::new(
|
||||
composition,
|
||||
results,
|
||||
vec![],
|
||||
HashMap::new(),
|
||||
25.0,
|
||||
25.0 / 3.0,
|
||||
25.0 / 6.0,
|
||||
25.0 / 300.0,
|
||||
0.0,
|
||||
);
|
||||
|
||||
let (_step, _i) = h.convergence();
|
||||
|
||||
println!("{:#?}", h.batches);
|
||||
}
|
||||
@@ -1,5 +1,14 @@
|
||||
use crate::{Gaussian, BETA, GAMMA, N_INF};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||
pub struct PlayerIndex(usize);
|
||||
|
||||
impl PlayerIndex {
|
||||
pub fn new(index: usize) -> Self {
|
||||
Self(index)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Player {
|
||||
pub prior: Gaussian,
|
||||
|
||||
Reference in New Issue
Block a user