Remove unnecessary allocations

This commit is contained in:
Anders Olsson
2023-10-24 16:10:40 +02:00
parent 59c256edad
commit d152e356f1
4 changed files with 108 additions and 83 deletions

View File

@@ -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);