Remove unnecessary allocations
This commit is contained in:
@@ -51,7 +51,8 @@ fn criterion_benchmark(criterion: &mut Criterion) {
|
||||
weights.push(vec![vec![1.0], vec![1.0]]);
|
||||
}
|
||||
|
||||
let mut batch = Batch::new(composition, results, weights, 1, P_DRAW, &agents);
|
||||
let mut batch = Batch::new(1, P_DRAW);
|
||||
batch.add_events(composition, results, weights, &agents);
|
||||
|
||||
criterion.bench_function("Batch::iteration", |b| {
|
||||
b.iter(|| batch.iteration(0, &agents))
|
||||
|
||||
50
src/batch.rs
50
src/batch.rs
@@ -1,4 +1,4 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
agent::Agent, game::Game, gaussian::Gaussian, player::Player, tuple_gt, tuple_max, Index, N_INF,
|
||||
@@ -116,29 +116,34 @@ impl Batch {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add_events(
|
||||
pub fn add_events(
|
||||
&mut self,
|
||||
composition: Vec<Vec<Vec<Index>>>,
|
||||
results: Vec<Vec<f64>>,
|
||||
weights: Vec<Vec<Vec<f64>>>,
|
||||
agents: &HashMap<Index, Agent>,
|
||||
) {
|
||||
let this_agent = composition
|
||||
.iter()
|
||||
.flatten()
|
||||
.flatten()
|
||||
.cloned()
|
||||
.collect::<HashSet<_>>();
|
||||
let mut unique = Vec::with_capacity(10);
|
||||
|
||||
let this_agent = composition.iter().flatten().flatten().filter(|idx| {
|
||||
if !unique.contains(idx) {
|
||||
unique.push(*idx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
});
|
||||
|
||||
for idx in this_agent {
|
||||
let elapsed = compute_elapsed(agents[&idx].last_time, self.time);
|
||||
|
||||
if let Some(skill) = self.skills.get_mut(&idx) {
|
||||
if let Some(skill) = self.skills.get_mut(idx) {
|
||||
skill.elapsed = elapsed;
|
||||
skill.forward = agents[&idx].receive(elapsed);
|
||||
} else {
|
||||
self.skills.insert(
|
||||
idx,
|
||||
*idx,
|
||||
Skill {
|
||||
forward: agents[&idx].receive(elapsed),
|
||||
elapsed,
|
||||
@@ -172,14 +177,19 @@ impl Batch {
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let weights = if weights.is_empty() {
|
||||
teams
|
||||
.iter()
|
||||
.map(|team| vec![1.0; team.items.len()])
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
weights[e].clone()
|
||||
};
|
||||
|
||||
Event {
|
||||
teams,
|
||||
evidence: 0.0,
|
||||
weights: if weights.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
weights[e].clone()
|
||||
},
|
||||
weights,
|
||||
}
|
||||
});
|
||||
|
||||
@@ -202,7 +212,7 @@ impl Batch {
|
||||
let teams = event.within_priors(false, false, &self.skills, agents);
|
||||
let result = event.outputs();
|
||||
|
||||
let g = Game::new(teams, result, event.weights.clone(), self.p_draw);
|
||||
let g = Game::new(teams, &result, &event.weights, self.p_draw);
|
||||
|
||||
for (t, team) in event.teams.iter_mut().enumerate() {
|
||||
for (i, item) in team.items.iter_mut().enumerate() {
|
||||
@@ -291,8 +301,8 @@ impl Batch {
|
||||
.map(|(_, event)| {
|
||||
Game::new(
|
||||
event.within_priors(online, forward, &self.skills, agents),
|
||||
event.outputs(),
|
||||
event.weights.clone(),
|
||||
&event.outputs(),
|
||||
&event.weights,
|
||||
self.p_draw,
|
||||
)
|
||||
.evidence
|
||||
@@ -316,8 +326,8 @@ impl Batch {
|
||||
.map(|(_, event)| {
|
||||
Game::new(
|
||||
event.within_priors(online, forward, &self.skills, agents),
|
||||
event.outputs(),
|
||||
event.weights.clone(),
|
||||
&event.outputs(),
|
||||
&event.weights,
|
||||
self.p_draw,
|
||||
)
|
||||
.evidence
|
||||
|
||||
116
src/game.rs
116
src/game.rs
@@ -7,39 +7,33 @@ use crate::{
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Game {
|
||||
pub struct Game<'a> {
|
||||
teams: Vec<Vec<Player>>,
|
||||
result: Vec<f64>,
|
||||
weights: Vec<Vec<f64>>,
|
||||
result: &'a [f64],
|
||||
weights: &'a [Vec<f64>],
|
||||
p_draw: f64,
|
||||
pub(crate) likelihoods: Vec<Vec<Gaussian>>,
|
||||
pub(crate) evidence: f64,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
impl<'a> Game<'a> {
|
||||
pub fn new(
|
||||
teams: Vec<Vec<Player>>,
|
||||
mut result: Vec<f64>,
|
||||
mut weights: Vec<Vec<f64>>,
|
||||
result: &'a [f64],
|
||||
weights: &'a [Vec<f64>],
|
||||
p_draw: f64,
|
||||
) -> Self {
|
||||
assert!(
|
||||
(result.is_empty() || result.len() == teams.len()),
|
||||
"result must be empty or the same length as teams"
|
||||
(result.len() == teams.len()),
|
||||
"result must have the same length as teams"
|
||||
);
|
||||
|
||||
assert!(
|
||||
(weights.is_empty() || weights.len() == teams.len()),
|
||||
"weights must be empty or the same length as teams"
|
||||
);
|
||||
|
||||
assert!(
|
||||
weights.is_empty()
|
||||
|| weights
|
||||
.iter()
|
||||
.zip(teams.iter())
|
||||
.all(|(w, t)| w.len() == t.len()),
|
||||
"weights must be empty or has the same dimensions as teams"
|
||||
weights
|
||||
.iter()
|
||||
.zip(teams.iter())
|
||||
.all(|(w, t)| w.len() == t.len()),
|
||||
"weights must have the same dimensions as teams"
|
||||
);
|
||||
|
||||
assert!(
|
||||
@@ -49,24 +43,13 @@ impl Game {
|
||||
|
||||
assert!(
|
||||
p_draw > 0.0 || {
|
||||
let mut r = result.clone();
|
||||
let mut r = result.to_vec();
|
||||
r.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
r.windows(2).all(|w| w[0] != w[1])
|
||||
},
|
||||
"draw must be > 0.0 if there is teams with draw"
|
||||
);
|
||||
|
||||
if result.is_empty() {
|
||||
result = (0..teams.len()).rev().map(|i| i as f64).collect::<Vec<_>>();
|
||||
}
|
||||
|
||||
if weights.is_empty() {
|
||||
weights = teams
|
||||
.iter()
|
||||
.map(|team| vec![1.0; team.len()])
|
||||
.collect::<Vec<_>>();
|
||||
}
|
||||
|
||||
let mut this = Self {
|
||||
teams,
|
||||
result,
|
||||
@@ -82,7 +65,7 @@ impl Game {
|
||||
}
|
||||
|
||||
fn likelihoods(&mut self) {
|
||||
let o = sort_perm(&self.result, true);
|
||||
let o = sort_perm(self.result, true);
|
||||
|
||||
let mut team = o
|
||||
.iter()
|
||||
@@ -235,7 +218,8 @@ mod tests {
|
||||
25.0 / 300.0,
|
||||
);
|
||||
|
||||
let g = Game::new(vec![vec![t_a], vec![t_b]], vec![0.0, 1.0], vec![], 0.0);
|
||||
let w = [vec![1.0], vec![1.0]];
|
||||
let g = Game::new(vec![vec![t_a], vec![t_b]], &[0.0, 1.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
let a = p[0][0];
|
||||
@@ -247,7 +231,8 @@ mod tests {
|
||||
let t_a = Player::new(Gaussian::from_ms(29.0, 1.0), 25.0 / 6.0, GAMMA);
|
||||
let t_b = Player::new(Gaussian::from_ms(25.0, 25.0 / 3.0), 25.0 / 6.0, GAMMA);
|
||||
|
||||
let g = Game::new(vec![vec![t_a], vec![t_b]], vec![0.0, 1.0], vec![], 0.0);
|
||||
let w = [vec![1.0], vec![1.0]];
|
||||
let g = Game::new(vec![vec![t_a], vec![t_b]], &[0.0, 1.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
let a = p[0][0];
|
||||
@@ -259,7 +244,8 @@ mod tests {
|
||||
let t_a = Player::new(Gaussian::from_ms(1.139, 0.531), 1.0, 0.2125);
|
||||
let t_b = Player::new(Gaussian::from_ms(15.568, 0.51), 1.0, 0.2125);
|
||||
|
||||
let g = Game::new(vec![vec![t_a], vec![t_b]], vec![0.0, 1.0], vec![], 0.0);
|
||||
let w = [vec![1.0], vec![1.0]];
|
||||
let g = Game::new(vec![vec![t_a], vec![t_b]], &[0.0, 1.0], &w, 0.0);
|
||||
|
||||
assert_eq!(g.likelihoods[0][0], N_INF);
|
||||
assert_eq!(g.likelihoods[1][0], N_INF);
|
||||
@@ -285,7 +271,8 @@ mod tests {
|
||||
)],
|
||||
];
|
||||
|
||||
let g = Game::new(teams.clone(), vec![1.0, 2.0, 0.0], vec![], 0.0);
|
||||
let w = [vec![1.0], vec![1.0], vec![1.0]];
|
||||
let g = Game::new(teams.clone(), &[1.0, 2.0, 0.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
let a = p[0][0];
|
||||
@@ -294,7 +281,8 @@ mod tests {
|
||||
assert_ulps_eq!(a, Gaussian::from_ms(25.000000, 6.238469), epsilon = 1e-6);
|
||||
assert_ulps_eq!(b, Gaussian::from_ms(31.311358, 6.698818), epsilon = 1e-6);
|
||||
|
||||
let g = Game::new(teams.clone(), vec![], vec![], 0.0);
|
||||
let w = [vec![1.0], vec![1.0], vec![1.0]];
|
||||
let g = Game::new(teams.clone(), &[2.0, 1.0, 0.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
let a = p[0][0];
|
||||
@@ -303,7 +291,8 @@ mod tests {
|
||||
assert_ulps_eq!(a, Gaussian::from_ms(31.311358, 6.698818), epsilon = 1e-6);
|
||||
assert_ulps_eq!(b, Gaussian::from_ms(25.000000, 6.238469), epsilon = 1e-6);
|
||||
|
||||
let g = Game::new(teams, vec![1.0, 2.0, 0.0], vec![], 0.5);
|
||||
let w = [vec![1.0], vec![1.0], vec![1.0]];
|
||||
let g = Game::new(teams, &[1.0, 2.0, 0.0], &w, 0.5);
|
||||
let p = g.posteriors();
|
||||
|
||||
let a = p[0][0];
|
||||
@@ -328,7 +317,8 @@ mod tests {
|
||||
25.0 / 300.0,
|
||||
);
|
||||
|
||||
let g = Game::new(vec![vec![t_a], vec![t_b]], vec![0.0, 0.0], vec![], 0.25);
|
||||
let w = [vec![1.0], vec![1.0]];
|
||||
let g = Game::new(vec![vec![t_a], vec![t_b]], &[0.0, 0.0], &w, 0.25);
|
||||
let p = g.posteriors();
|
||||
|
||||
let a = p[0][0];
|
||||
@@ -340,7 +330,8 @@ mod tests {
|
||||
let t_a = Player::new(Gaussian::from_ms(25.0, 3.0), 25.0 / 6.0, 25.0 / 300.0);
|
||||
let t_b = Player::new(Gaussian::from_ms(29.0, 2.0), 25.0 / 6.0, 25.0 / 300.0);
|
||||
|
||||
let g = Game::new(vec![vec![t_a], vec![t_b]], vec![0.0, 0.0], vec![], 0.25);
|
||||
let w = [vec![1.0], vec![1.0]];
|
||||
let g = Game::new(vec![vec![t_a], vec![t_b]], &[0.0, 0.0], &w, 0.25);
|
||||
let p = g.posteriors();
|
||||
|
||||
let a = p[0][0];
|
||||
@@ -368,10 +359,11 @@ mod tests {
|
||||
25.0 / 300.0,
|
||||
);
|
||||
|
||||
let w = [vec![1.0], vec![1.0], vec![1.0]];
|
||||
let g = Game::new(
|
||||
vec![vec![t_a], vec![t_b], vec![t_c]],
|
||||
vec![0.0, 0.0, 0.0],
|
||||
vec![],
|
||||
&[0.0, 0.0, 0.0],
|
||||
&w,
|
||||
0.25,
|
||||
);
|
||||
let p = g.posteriors();
|
||||
@@ -388,10 +380,11 @@ mod tests {
|
||||
let t_b = Player::new(Gaussian::from_ms(25.0, 3.0), 25.0 / 6.0, 25.0 / 300.0);
|
||||
let t_c = Player::new(Gaussian::from_ms(29.0, 2.0), 25.0 / 6.0, 25.0 / 300.0);
|
||||
|
||||
let w = [vec![1.0], vec![1.0], vec![1.0]];
|
||||
let g = Game::new(
|
||||
vec![vec![t_a], vec![t_b], vec![t_c]],
|
||||
vec![0.0, 0.0, 0.0],
|
||||
vec![],
|
||||
&[0.0, 0.0, 0.0],
|
||||
&w,
|
||||
0.25,
|
||||
);
|
||||
let p = g.posteriors();
|
||||
@@ -421,7 +414,8 @@ mod tests {
|
||||
Player::new(Gaussian::from_ms(16., 3.0), 25.0 / 6.0, 25.0 / 300.0),
|
||||
];
|
||||
|
||||
let g = Game::new(vec![t_a, t_b, t_c], vec![1.0, 0.0, 0.0], vec![], 0.25);
|
||||
let w = [vec![1.0, 1.0], vec![1.0], vec![1.0, 1.0]];
|
||||
let g = Game::new(vec![t_a, t_b, t_c], &[1.0, 0.0, 0.0], &w, 0.25);
|
||||
let p = g.posteriors();
|
||||
|
||||
assert_ulps_eq!(p[0][0], Gaussian::from_ms(13.051, 2.864), epsilon = 1e-3);
|
||||
@@ -447,7 +441,8 @@ mod tests {
|
||||
0.0,
|
||||
)];
|
||||
|
||||
let g = Game::new(vec![t_a.clone(), t_b.clone()], vec![], vec![w_a, w_b], 0.0);
|
||||
let w = [w_a, w_b];
|
||||
let g = Game::new(vec![t_a.clone(), t_b.clone()], &[1.0, 0.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
assert_ulps_eq!(
|
||||
@@ -464,7 +459,8 @@ mod tests {
|
||||
let w_a = vec![1.0];
|
||||
let w_b = vec![0.7];
|
||||
|
||||
let g = Game::new(vec![t_a.clone(), t_b.clone()], vec![], vec![w_a, w_b], 0.0);
|
||||
let w = [w_a, w_b];
|
||||
let g = Game::new(vec![t_a.clone(), t_b.clone()], &[1.0, 0.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
assert_ulps_eq!(
|
||||
@@ -481,7 +477,8 @@ mod tests {
|
||||
let w_a = vec![1.6];
|
||||
let w_b = vec![0.7];
|
||||
|
||||
let g = Game::new(vec![t_a, t_b], vec![], vec![w_a, w_b], 0.0);
|
||||
let w = [w_a, w_b];
|
||||
let g = Game::new(vec![t_a, t_b], &[1.0, 0.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
assert_ulps_eq!(
|
||||
@@ -501,7 +498,8 @@ mod tests {
|
||||
let t_a = vec![Player::new(Gaussian::from_ms(2.0, 6.0), 1.0, 0.0)];
|
||||
let t_b = vec![Player::new(Gaussian::from_ms(2.0, 6.0), 1.0, 0.0)];
|
||||
|
||||
let g = Game::new(vec![t_a, t_b], vec![], vec![w_a, w_b], 0.0);
|
||||
let w = [w_a, w_b];
|
||||
let g = Game::new(vec![t_a, t_b], &[1.0, 0.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
assert_ulps_eq!(
|
||||
@@ -521,7 +519,8 @@ mod tests {
|
||||
let t_a = vec![Player::new(Gaussian::from_ms(2.0, 6.0), 1.0, 0.0)];
|
||||
let t_b = vec![Player::new(Gaussian::from_ms(2.0, 6.0), 1.0, 0.0)];
|
||||
|
||||
let g = Game::new(vec![t_a, t_b], vec![], vec![w_a, w_b], 0.0);
|
||||
let w = [w_a, w_b];
|
||||
let g = Game::new(vec![t_a, t_b], &[1.0, 0.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
assert_ulps_eq!(p[0][0], p[1][0], epsilon = 1e-6);
|
||||
@@ -541,7 +540,8 @@ mod tests {
|
||||
];
|
||||
let w_b = vec![0.9, 0.6];
|
||||
|
||||
let g = Game::new(vec![t_a.clone(), t_b.clone()], vec![], vec![w_a, w_b], 0.0);
|
||||
let w = [w_a, w_b];
|
||||
let g = Game::new(vec![t_a.clone(), t_b.clone()], &[1.0, 0.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
assert_ulps_eq!(
|
||||
@@ -568,7 +568,8 @@ mod tests {
|
||||
let w_a = vec![1.3, 1.5];
|
||||
let w_b = vec![0.7, 0.4];
|
||||
|
||||
let g = Game::new(vec![t_a.clone(), t_b.clone()], vec![], vec![w_a, w_b], 0.0);
|
||||
let w = [w_a, w_b];
|
||||
let g = Game::new(vec![t_a.clone(), t_b.clone()], &[1.0, 0.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
assert_ulps_eq!(
|
||||
@@ -595,7 +596,8 @@ mod tests {
|
||||
let w_a = vec![1.6, 0.2];
|
||||
let w_b = vec![0.7, 2.4];
|
||||
|
||||
let g = Game::new(vec![t_a.clone(), t_b.clone()], vec![], vec![w_a, w_b], 0.0);
|
||||
let w = [w_a, w_b];
|
||||
let g = Game::new(vec![t_a.clone(), t_b.clone()], &[1.0, 0.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
assert_ulps_eq!(
|
||||
@@ -619,6 +621,7 @@ mod tests {
|
||||
epsilon = 1e-6
|
||||
);
|
||||
|
||||
let w = [vec![1.0, 1.0], vec![1.0]];
|
||||
let g = Game::new(
|
||||
vec![
|
||||
t_a.clone(),
|
||||
@@ -628,8 +631,8 @@ mod tests {
|
||||
0.0,
|
||||
)],
|
||||
],
|
||||
vec![],
|
||||
vec![],
|
||||
&[1.0, 0.0],
|
||||
&w,
|
||||
0.0,
|
||||
);
|
||||
let post_2vs1 = g.posteriors();
|
||||
@@ -637,7 +640,8 @@ mod tests {
|
||||
let w_a = vec![1.0, 1.0];
|
||||
let w_b = vec![1.0, 0.0];
|
||||
|
||||
let g = Game::new(vec![t_a, t_b.clone()], vec![], vec![w_a, w_b], 0.0);
|
||||
let w = [w_a, w_b];
|
||||
let g = Game::new(vec![t_a, t_b.clone()], &[1.0, 0.0], &w, 0.0);
|
||||
let p = g.posteriors();
|
||||
|
||||
assert_ulps_eq!(p[0][0], post_2vs1[0][0], epsilon = 1e-6);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
agent::{self, Agent},
|
||||
@@ -267,17 +267,27 @@ impl History {
|
||||
"(length(weights) > 0) & (length(composition) != length(weights))"
|
||||
);
|
||||
|
||||
let mut unique = Vec::with_capacity(10);
|
||||
|
||||
let this_agent = composition
|
||||
.iter()
|
||||
.flatten()
|
||||
.flatten()
|
||||
.cloned()
|
||||
.collect::<HashSet<_>>();
|
||||
.filter(|idx| {
|
||||
if !unique.contains(idx) {
|
||||
unique.push(*idx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
false
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for agent in &this_agent {
|
||||
if !self.agents.contains_key(agent) {
|
||||
self.agents.insert(
|
||||
*agent,
|
||||
**agent,
|
||||
Agent {
|
||||
player: priors.get(agent).cloned().unwrap_or_else(|| {
|
||||
Player::new(
|
||||
@@ -473,8 +483,8 @@ mod tests {
|
||||
|
||||
let p = Game::new(
|
||||
h.batches[1].events[0].within_priors(false, false, &h.batches[1].skills, &h.agents),
|
||||
vec![0.0, 1.0],
|
||||
vec![],
|
||||
&vec![0.0, 1.0],
|
||||
&vec![vec![1.0], vec![1.0]],
|
||||
P_DRAW,
|
||||
)
|
||||
.posteriors();
|
||||
|
||||
Reference in New Issue
Block a user