Port from julia version instead
This commit is contained in:
500
src/batch.rs
500
src/batch.rs
@@ -1,13 +1,15 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use crate::{Game, Gaussian, Player, PlayerIndex, N_INF};
|
||||
use crate::{
|
||||
agent::Agent, game::Game, gaussian::Gaussian, player::Player, tuple_gt, tuple_max, N_INF,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Skill {
|
||||
pub forward: Gaussian,
|
||||
pub backward: Gaussian,
|
||||
pub likelihood: Gaussian,
|
||||
pub elapsed: f64,
|
||||
pub(crate) struct Skill {
|
||||
pub(crate) forward: Gaussian,
|
||||
backward: Gaussian,
|
||||
likelihood: Gaussian,
|
||||
pub(crate) elapsed: u64,
|
||||
pub(crate) online: Gaussian,
|
||||
}
|
||||
|
||||
impl Default for Skill {
|
||||
@@ -16,67 +18,30 @@ impl Default for Skill {
|
||||
forward: N_INF,
|
||||
backward: N_INF,
|
||||
likelihood: N_INF,
|
||||
elapsed: 0.0,
|
||||
elapsed: 0,
|
||||
online: N_INF,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Agent {
|
||||
pub player: Player,
|
||||
pub message: Gaussian,
|
||||
pub last_time: f64,
|
||||
}
|
||||
|
||||
impl Agent {
|
||||
pub fn new(player: Player, message: Gaussian, last_time: f64) -> Self {
|
||||
Self {
|
||||
player,
|
||||
message,
|
||||
last_time,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn receive(&self, elapsed: f64) -> Gaussian {
|
||||
if self.message != N_INF {
|
||||
self.message.forget(self.player.gamma, elapsed)
|
||||
} else {
|
||||
self.player.prior
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Item {
|
||||
index: PlayerIndex,
|
||||
struct Item {
|
||||
agent: String,
|
||||
likelihood: Gaussian,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Team {
|
||||
struct Team {
|
||||
items: Vec<Item>,
|
||||
output: u16,
|
||||
output: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Event {
|
||||
struct Event {
|
||||
teams: Vec<Team>,
|
||||
pub evidence: f64,
|
||||
evidence: f64,
|
||||
weights: Vec<Vec<f64>>,
|
||||
}
|
||||
|
||||
impl Event {
|
||||
/*
|
||||
pub fn names(&self) -> Vec<&str> {
|
||||
self.teams
|
||||
.iter()
|
||||
.flat_map(|team| team.items.iter())
|
||||
.map(|item| item.name.as_str())
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn result(&self) -> Vec<u16> {
|
||||
fn outputs(&self) -> Vec<f64> {
|
||||
self.teams
|
||||
.iter()
|
||||
.map(|team| team.output)
|
||||
@@ -84,75 +49,126 @@ impl Event {
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_elapsed(last_time: f64, actual_time: f64) -> f64 {
|
||||
if last_time == f64::NEG_INFINITY {
|
||||
0.0
|
||||
} else if last_time == f64::INFINITY {
|
||||
1.0
|
||||
} else {
|
||||
actual_time - last_time
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Batch {
|
||||
pub skills: HashMap<PlayerIndex, Skill>,
|
||||
pub events: Vec<Event>,
|
||||
pub time: f64,
|
||||
pub(crate) struct Batch {
|
||||
events: Vec<Event>,
|
||||
pub(crate) skills: HashMap<String, Skill>,
|
||||
pub(crate) time: u64,
|
||||
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(
|
||||
composition: Vec<Vec<Vec<PlayerIndex>>>,
|
||||
results: Vec<Vec<u16>>,
|
||||
time: f64,
|
||||
agents: &mut HashMap<PlayerIndex, Agent>,
|
||||
pub(crate) fn new(
|
||||
composition: Vec<Vec<Vec<&str>>>,
|
||||
results: Vec<Vec<f64>>,
|
||||
weights: Vec<Vec<Vec<f64>>>,
|
||||
time: u64,
|
||||
p_draw: f64,
|
||||
agents: &mut HashMap<String, Agent>,
|
||||
) -> Self {
|
||||
assert!(
|
||||
results.is_empty() || results.len() == composition.len(),
|
||||
"TODO: Add a comment here"
|
||||
);
|
||||
assert!(
|
||||
weights.is_empty() || weights.len() == composition.len(),
|
||||
"TODO: Add a comment here"
|
||||
);
|
||||
|
||||
let this_agent = composition
|
||||
.iter()
|
||||
.flatten()
|
||||
.flatten()
|
||||
.cloned()
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
let elapsed = this_agent
|
||||
.iter()
|
||||
.map(|&a| (a, compute_elapsed(agents[a].last_time, time)))
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
let skills = this_agent
|
||||
.iter()
|
||||
.map(|&a| {
|
||||
(
|
||||
a.to_string(),
|
||||
Skill {
|
||||
forward: agents[a].receive(elapsed[a]),
|
||||
elapsed: elapsed[a],
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
let events = (0..composition.len())
|
||||
.map(|e| {
|
||||
let teams = (0..composition[e].len())
|
||||
.map(|t| {
|
||||
let items = (0..composition[e][t].len())
|
||||
.map(|a| Item {
|
||||
agent: composition[e][t][a].to_string(),
|
||||
likelihood: N_INF,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Team {
|
||||
items,
|
||||
output: if results.is_empty() {
|
||||
(composition[e].len() - (t + 1)) as f64
|
||||
} else {
|
||||
results[e][t]
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Event {
|
||||
teams,
|
||||
evidence: 0.0,
|
||||
weights: if weights.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
weights[e].clone()
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut this = Self {
|
||||
skills: HashMap::new(),
|
||||
events: Vec::new(),
|
||||
time,
|
||||
events,
|
||||
skills,
|
||||
p_draw,
|
||||
};
|
||||
|
||||
this.add_events(composition, results, agents);
|
||||
this.iteration(0, agents);
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
pub fn add_events(
|
||||
pub(crate) fn add_events(
|
||||
&mut self,
|
||||
composition: Vec<Vec<Vec<PlayerIndex>>>,
|
||||
results: Vec<Vec<u16>>,
|
||||
agents: &mut HashMap<PlayerIndex, Agent>,
|
||||
composition: Vec<Vec<Vec<&str>>>,
|
||||
results: Vec<Vec<f64>>,
|
||||
weights: Vec<Vec<Vec<f64>>>,
|
||||
agents: &mut HashMap<String, Agent>,
|
||||
) {
|
||||
let this_agent = composition
|
||||
.iter()
|
||||
.flatten()
|
||||
.flatten()
|
||||
.cloned()
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
for a in this_agent {
|
||||
let elapsed = compute_elapsed(agents[a].last_time, self.time);
|
||||
|
||||
if let Some(skill) = self.skills.get_mut(a) {
|
||||
skill.forward = agents[a].receive(elapsed);
|
||||
skill.elapsed = elapsed;
|
||||
skill.forward = agents[a].receive(elapsed);
|
||||
} else {
|
||||
self.skills.insert(
|
||||
*a,
|
||||
a.to_string(),
|
||||
Skill {
|
||||
forward: agents[a].receive(elapsed),
|
||||
elapsed,
|
||||
@@ -169,14 +185,18 @@ impl Batch {
|
||||
.map(|t| {
|
||||
let items = (0..composition[e][t].len())
|
||||
.map(|a| Item {
|
||||
index: composition[e][t][a],
|
||||
agent: composition[e][t][a].to_string(),
|
||||
likelihood: N_INF,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Team {
|
||||
items,
|
||||
output: results[e][t],
|
||||
output: if results.is_empty() {
|
||||
(composition[e].len() - (t + 1)) as f64
|
||||
} else {
|
||||
results[e][t]
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
@@ -184,6 +204,11 @@ impl Batch {
|
||||
let event = Event {
|
||||
teams,
|
||||
evidence: 0.0,
|
||||
weights: if weights.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
weights[e].clone()
|
||||
},
|
||||
};
|
||||
|
||||
self.events.push(event);
|
||||
@@ -192,33 +217,45 @@ impl Batch {
|
||||
self.iteration(from, agents);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn posterior(&self, agent: &PlayerIndex) -> Gaussian {
|
||||
pub(crate) fn posterior(&self, agent: &str) -> Gaussian {
|
||||
let skill = &self.skills[agent];
|
||||
|
||||
skill.likelihood * skill.backward * skill.forward
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn posteriors(&self) -> HashMap<PlayerIndex, Gaussian> {
|
||||
pub(crate) fn posteriors(&self) -> HashMap<String, Gaussian> {
|
||||
self.skills
|
||||
.keys()
|
||||
.map(|a| (*a, self.posterior(a)))
|
||||
.map(|a| (a.to_string(), self.posterior(a)))
|
||||
.collect::<HashMap<_, _>>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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;
|
||||
fn within_prior(
|
||||
&self,
|
||||
item: &Item,
|
||||
online: bool,
|
||||
forward: bool,
|
||||
agents: &mut HashMap<String, Agent>,
|
||||
) -> Player {
|
||||
let r = &agents[&item.agent].player;
|
||||
|
||||
Player::new(g, r.beta, r.gamma, N_INF)
|
||||
if online {
|
||||
Player::new(self.skills[&item.agent].online, r.beta, r.gamma)
|
||||
} else if forward {
|
||||
Player::new(self.skills[&item.agent].forward, r.beta, r.gamma)
|
||||
} else {
|
||||
let wp = self.posterior(&item.agent) / item.likelihood;
|
||||
|
||||
Player::new(wp, r.beta, r.gamma)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn within_priors(
|
||||
pub(crate) fn within_priors(
|
||||
&self,
|
||||
event: usize,
|
||||
agents: &mut HashMap<PlayerIndex, Agent>,
|
||||
online: bool,
|
||||
forward: bool,
|
||||
agents: &mut HashMap<String, Agent>,
|
||||
) -> Vec<Vec<Player>> {
|
||||
self.events[event]
|
||||
.teams
|
||||
@@ -226,23 +263,23 @@ impl Batch {
|
||||
.map(|team| {
|
||||
team.items
|
||||
.iter()
|
||||
.map(|item| self.within_prior(item, agents))
|
||||
.map(|item| self.within_prior(item, online, forward, agents))
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn iteration(&mut self, from: usize, agents: &mut HashMap<PlayerIndex, Agent>) {
|
||||
pub(crate) fn iteration(&mut self, from: usize, agents: &mut HashMap<String, Agent>) {
|
||||
for e in from..self.events.len() {
|
||||
let teams = self.within_priors(e, agents);
|
||||
let result = self.events[e].result();
|
||||
let teams = self.within_priors(e, false, false, agents);
|
||||
let result = self.events[e].outputs();
|
||||
|
||||
let g = Game::new(teams, result, self.p_draw);
|
||||
let g = Game::new(teams, result, self.events[e].weights.clone(), self.p_draw);
|
||||
|
||||
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.index).unwrap().likelihood =
|
||||
(self.skills[&item.index].likelihood / item.likelihood)
|
||||
self.skills.get_mut(&item.agent).unwrap().likelihood =
|
||||
(self.skills[&item.agent].likelihood / item.likelihood)
|
||||
* g.likelihoods[t][i];
|
||||
|
||||
item.likelihood = g.likelihoods[t][i];
|
||||
@@ -253,27 +290,22 @@ impl Batch {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convergence(&mut self, agents: &mut HashMap<PlayerIndex, Agent>) -> usize {
|
||||
pub(crate) fn convergence(&mut self, agents: &mut HashMap<String, Agent>) -> usize {
|
||||
let epsilon = 1e-6;
|
||||
let iterations = 20;
|
||||
|
||||
let mut step = (f64::INFINITY, f64::INFINITY);
|
||||
let mut i = 0;
|
||||
|
||||
while (step.0 > epsilon || step.1 > epsilon) && i < iterations {
|
||||
while tuple_gt(step, epsilon) && i < iterations {
|
||||
let old = self.posteriors();
|
||||
|
||||
self.iteration(0, agents);
|
||||
|
||||
let new = self.posteriors();
|
||||
|
||||
step = old.iter().fold((0.0, 0.0), |(o_l, o_r), (a, old)| {
|
||||
let (n_l, n_r) = old.delta(new[a]);
|
||||
|
||||
(
|
||||
if n_l > o_l { n_l } else { o_l },
|
||||
if n_r > o_r { n_r } else { o_r },
|
||||
)
|
||||
step = old.iter().fold((0.0, 0.0), |step, (a, old)| {
|
||||
tuple_max(step, old.delta(new[a]))
|
||||
});
|
||||
|
||||
i += 1;
|
||||
@@ -282,18 +314,16 @@ impl Batch {
|
||||
i
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn forward_prior_out(&self, agent: &PlayerIndex) -> Gaussian {
|
||||
pub(crate) fn forward_prior_out(&self, agent: &str) -> Gaussian {
|
||||
let skill = &self.skills[agent];
|
||||
|
||||
skill.forward * skill.likelihood
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn backward_prior_out(
|
||||
pub(crate) fn backward_prior_out(
|
||||
&self,
|
||||
agent: &PlayerIndex,
|
||||
agents: &mut HashMap<PlayerIndex, Agent>,
|
||||
agent: &str,
|
||||
agents: &mut HashMap<String, Agent>,
|
||||
) -> Gaussian {
|
||||
let skill = &self.skills[agent];
|
||||
let n = skill.likelihood * skill.backward;
|
||||
@@ -301,8 +331,7 @@ impl Batch {
|
||||
n.forget(agents[agent].player.gamma, skill.elapsed)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_backward_info(&mut self, agents: &mut HashMap<PlayerIndex, Agent>) {
|
||||
pub(crate) fn new_backward_info(&mut self, agents: &mut HashMap<String, Agent>) {
|
||||
for (agent, skill) in self.skills.iter_mut() {
|
||||
skill.backward = agents[agent].message;
|
||||
}
|
||||
@@ -310,8 +339,7 @@ impl Batch {
|
||||
self.iteration(0, agents);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_forward_info(&mut self, agents: &mut HashMap<PlayerIndex, Agent>) {
|
||||
pub(crate) fn new_forward_info(&mut self, agents: &mut HashMap<String, Agent>) {
|
||||
for (agent, skill) in self.skills.iter_mut() {
|
||||
skill.forward = agents[agent].receive(skill.elapsed);
|
||||
}
|
||||
@@ -320,60 +348,69 @@ impl Batch {
|
||||
}
|
||||
}
|
||||
|
||||
fn compute_elapsed(last_time: u64, actual_time: u64) -> u64 {
|
||||
if last_time == u64::MIN {
|
||||
0
|
||||
} else if last_time == u64::MAX {
|
||||
1
|
||||
} else {
|
||||
actual_time - last_time
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use approx::assert_ulps_eq;
|
||||
|
||||
use crate::{agent::Agent, player::Player};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_one_event_each() {
|
||||
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,
|
||||
for agent in ["a", "b", "c", "d", "e", "f"] {
|
||||
agents.insert(
|
||||
agent.to_string(),
|
||||
Agent {
|
||||
player: Player::new(Gaussian::new(25.0, 25.0 / 3.0), 25.0 / 6.0, 25.0 / 300.0),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
agents.insert(k, agent);
|
||||
}
|
||||
|
||||
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]],
|
||||
vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]],
|
||||
vec![],
|
||||
0,
|
||||
0.0,
|
||||
&mut agents,
|
||||
0.0,
|
||||
);
|
||||
|
||||
let post = batch.posteriors();
|
||||
|
||||
assert_eq!(post[&a].mu(), 29.205220743876975);
|
||||
assert_eq!(post[&a].sigma(), 7.194481422570443);
|
||||
assert_ulps_eq!(post["a"].mu, 29.205220743876975, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["a"].sigma, 7.194481422570443, epsilon = 0.000001);
|
||||
|
||||
assert_eq!(post[&b].mu(), 20.79477925612302);
|
||||
assert_eq!(post[&b].sigma(), 7.194481422570443);
|
||||
assert_ulps_eq!(post["b"].mu, 20.79477925612302, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["b"].sigma, 7.194481422570443, epsilon = 0.000001);
|
||||
|
||||
assert_eq!(post[&c].mu(), 20.79477925612302);
|
||||
assert_eq!(post[&c].sigma(), 7.194481422570443);
|
||||
assert_ulps_eq!(post["c"].mu, 20.79477925612302, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["c"].sigma, 7.194481422570443, epsilon = 0.000001);
|
||||
|
||||
assert_ulps_eq!(post["d"].mu, 29.205220743876975, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["d"].sigma, 7.194481422570443, epsilon = 0.000001);
|
||||
|
||||
assert_ulps_eq!(post["e"].mu, 29.205220743876975, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["e"].sigma, 7.194481422570443, epsilon = 0.000001);
|
||||
|
||||
assert_ulps_eq!(post["f"].mu, 20.79477925612302, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["f"].sigma, 7.194481422570443, epsilon = 0.000001);
|
||||
|
||||
assert_eq!(batch.convergence(&mut agents), 1);
|
||||
}
|
||||
@@ -382,123 +419,102 @@ mod tests {
|
||||
fn test_same_strength() {
|
||||
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,
|
||||
for agent in ["a", "b", "c", "d", "e", "f"] {
|
||||
agents.insert(
|
||||
agent.to_string(),
|
||||
Agent {
|
||||
player: Player::new(Gaussian::new(25.0, 25.0 / 3.0), 25.0 / 6.0, 25.0 / 300.0),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
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!["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,
|
||||
&mut agents,
|
||||
vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]],
|
||||
vec![],
|
||||
0,
|
||||
0.0,
|
||||
&mut agents,
|
||||
);
|
||||
|
||||
let post = batch.posteriors();
|
||||
|
||||
assert_eq!(post[&a].mu(), 24.96097857478182);
|
||||
assert_eq!(post[&a].sigma(), 6.298544763358269);
|
||||
assert_ulps_eq!(post["a"].mu, 24.96097857478182, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["a"].sigma, 6.298544763358269, epsilon = 0.000001);
|
||||
|
||||
assert_eq!(post[&b].mu(), 27.095590669107086);
|
||||
assert_eq!(post[&b].sigma(), 6.010330439043099);
|
||||
assert_ulps_eq!(post["b"].mu, 27.095590669107086, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["b"].sigma, 6.010330439043099, epsilon = 0.000001);
|
||||
|
||||
assert_eq!(post[&c].mu(), 24.88968178743119);
|
||||
assert_eq!(post[&c].sigma(), 5.866311348102562);
|
||||
assert_ulps_eq!(post["c"].mu, 24.88968178743119, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["c"].sigma, 5.866311348102562, epsilon = 0.000001);
|
||||
|
||||
assert!(batch.convergence(&mut agents) > 1);
|
||||
|
||||
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,
|
||||
for agent in ["a", "b", "c", "d", "e", "f"] {
|
||||
agents.insert(
|
||||
agent.to_string(),
|
||||
Agent {
|
||||
player: Player::new(Gaussian::new(25.0, 25.0 / 3.0), 25.0 / 6.0, 25.0 / 300.0),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
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!["a"], vec!["b"]],
|
||||
vec![vec!["a"], vec!["c"]],
|
||||
vec![vec!["b"], vec!["c"]],
|
||||
],
|
||||
vec![vec![1, 0], vec![0, 1], vec![1, 0]],
|
||||
vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]],
|
||||
vec![],
|
||||
0,
|
||||
0.0,
|
||||
&mut agents,
|
||||
0.0,
|
||||
);
|
||||
|
||||
batch.convergence(&mut agents);
|
||||
|
||||
let p = batch.posteriors();
|
||||
let post = 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!(post["a"].mu, 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["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!(post["b"].mu, 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["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);
|
||||
assert_ulps_eq!(post["c"].mu, 25.000000, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["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!["a"], vec!["b"]],
|
||||
vec![vec!["a"], vec!["c"]],
|
||||
vec![vec!["b"], vec!["c"]],
|
||||
],
|
||||
vec![vec![1, 0], vec![0, 1], vec![1, 0]],
|
||||
vec![vec![1.0, 0.0], vec![0.0, 1.0], vec![1.0, 0.0]],
|
||||
vec![],
|
||||
&mut agents,
|
||||
);
|
||||
|
||||
@@ -506,15 +522,15 @@ mod tests {
|
||||
|
||||
batch.convergence(&mut agents);
|
||||
|
||||
let p = batch.posteriors();
|
||||
let post = 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!(post["a"].mu, 25.00000315330858, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["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!(post["b"].mu, 25.00000315330858, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["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);
|
||||
assert_ulps_eq!(post["c"].mu, 25.00000315330858, epsilon = 0.000001);
|
||||
assert_ulps_eq!(post["c"].sigma, 3.880150268080797, epsilon = 0.000001);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user