This commit is contained in:
Anders Olsson
2023-10-24 09:44:42 +02:00
parent aea3df285a
commit efa235be59
2 changed files with 24 additions and 191 deletions

View File

@@ -82,30 +82,6 @@ impl Game {
}
fn likelihoods(&mut self) {
let m_t_ft = self.likelihood_teams();
self.likelihoods = self
.teams
.iter()
.zip(self.weights.iter())
.zip(m_t_ft)
.map(|((p, w), m)| {
let performance = p.iter().zip(w.iter()).fold(N00, |p, (player, &weight)| {
p + (player.performance() * weight)
});
p.iter()
.zip(w.iter())
.map(|(p, &w)| {
((m - performance.exclude(p.performance() * w)) * (1.0 / w))
.forget(p.beta, 1)
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
}
fn likelihood_teams(&mut self) -> Vec<Gaussian> {
let o = sort_perm(&self.result, true);
let mut team = o
@@ -143,14 +119,10 @@ impl Game {
} else {
o.windows(2)
.map(|w| {
if self.p_draw == 0.0 {
0.0
} else {
let a: f64 = self.teams[w[0]].iter().map(|a| a.beta.powi(2)).sum();
let b: f64 = self.teams[w[1]].iter().map(|a| a.beta.powi(2)).sum();
let a: f64 = self.teams[w[0]].iter().map(|a| a.beta.powi(2)).sum();
let b: f64 = self.teams[w[1]].iter().map(|a| a.beta.powi(2)).sum();
compute_margin(self.p_draw, (a + b).sqrt())
}
compute_margin(self.p_draw, (a + b).sqrt())
})
.collect::<Vec<_>>()
};
@@ -205,7 +177,27 @@ impl Game {
team[0].likelihood_win = team[1].posterior_lose() + diff[0].likelihood;
team[t_end].likelihood_lose = team[t_end - 1].posterior_win() - diff[d_end].likelihood;
o.iter().map(|&e| team[e].likelihood()).collect::<Vec<_>>()
let m_t_ft = o.into_iter().map(|e| team[e].likelihood());
self.likelihoods = self
.teams
.iter()
.zip(self.weights.iter())
.zip(m_t_ft)
.map(|((p, w), m)| {
let performance = p.iter().zip(w.iter()).fold(N00, |p, (player, &weight)| {
p + (player.performance() * weight)
});
p.iter()
.zip(w.iter())
.map(|(p, &w)| {
((m - performance.exclude(p.performance() * w)) * (1.0 / w))
.forget(p.beta, 1)
})
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
}
pub fn posteriors(&self) -> Vec<Vec<Gaussian>> {

View File

@@ -1,159 +0,0 @@
use std::ops;
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct Gaussian {
mu: f64,
sigma: f64,
}
impl Gaussian {
#[inline(always)]
pub const fn from_ms(mu: f64, sigma: f64) -> Self {
Self { mu, sigma }
}
#[inline(always)]
pub fn from_pt(pi: f64, tau: f64) -> Self {
Self::from_ms(tau / pi, (1.0 / pi).sqrt())
}
#[inline(always)]
pub fn mu(&self) -> f64 {
self.mu
}
#[inline(always)]
pub fn sigma(&self) -> f64 {
self.sigma
}
#[inline(always)]
pub fn pi(&self) -> f64 {
if self.sigma > 0.0 {
self.sigma.powi(-2)
} else {
f64::INFINITY
}
}
#[inline(always)]
pub fn tau(&self) -> f64 {
if self.sigma > 0.0 {
self.mu * self.pi()
} else {
f64::INFINITY
}
}
}
impl ops::Add<Gaussian> for Gaussian {
type Output = Gaussian;
fn add(self, rhs: Gaussian) -> Self::Output {
Self {
mu: self.mu + rhs.mu,
sigma: (self.sigma.powi(2) + rhs.sigma.powi(2)).sqrt(),
}
}
}
impl ops::Sub<Gaussian> for Gaussian {
type Output = Gaussian;
fn sub(self, rhs: Gaussian) -> Self::Output {
Self {
mu: self.mu - rhs.mu,
sigma: (self.sigma.powi(2) + rhs.sigma.powi(2)).sqrt(),
}
}
}
impl ops::Mul<Gaussian> for Gaussian {
type Output = Gaussian;
fn mul(self, rhs: Gaussian) -> Self::Output {
/*
if self.sigma == 0.0 || rhs.sigma == 0.0 {
let mu = self.mu / (self.sigma.powi(2) / rhs.sigma.powi(2) + 1.0)
+ rhs.mu / (rhs.sigma.powi(2) / self.sigma.powi(2) + 1.0);
let sigma = (1.0 / ((1.0 / self.sigma.powi(2)) + (1.0 / rhs.sigma.powi(2)))).sqrt();
Self::from_ms(mu, sigma)
} else {
Self::from_pt(self.pi() + rhs.pi(), self.tau() + rhs.tau())
}
*/
Self::from_pt(self.pi() + rhs.pi(), self.tau() + rhs.tau())
}
}
impl ops::Div<Gaussian> for Gaussian {
type Output = Gaussian;
fn div(self, rhs: Gaussian) -> Self::Output {
/*
let (mu, sigma) = if self.sigma == 0.0 || rhs.sigma == 0.0 {
let mu = self.mu / (1.0 - self.sigma.powi(2) / rhs.sigma.powi(2))
+ rhs.mu / (rhs.sigma.powi(2) / self.sigma.powi(2) - 1.0);
let sigma = (1.0 / ((1.0 / self.sigma.powi(2)) - (1.0 / rhs.sigma.powi(2)))).sqrt();
Self::from_ms(mu, sigma)
} else {
Self::from_pt(self.pi() - rhs.pi(), self.tau() - rhs.tau())
}
*/
Self::from_pt(self.pi() - rhs.pi(), self.tau() - rhs.tau())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
let n = Gaussian::from_ms(25.0, 25.0 / 3.0);
let m = Gaussian::from_ms(0.0, 1.0);
assert_eq!(n + m, Gaussian::from_ms(25.0, 8.393118874676116));
}
#[test]
fn test_sub() {
let n = Gaussian::from_ms(25.0, 25.0 / 3.0);
let m = Gaussian::from_ms(1.0, 1.0);
assert_eq!(n - m, Gaussian::from_ms(24.0, 8.393118874676116));
}
#[test]
fn test_mul() {
let n = Gaussian::from_ms(25.0, 25.0 / 3.0);
let m = Gaussian::from_ms(0.0, 1.0);
assert_eq!(
n * m,
Gaussian::from_ms(0.35488958990536273, 0.992876838486922)
);
}
#[test]
fn test_div() {
let n = Gaussian::from_ms(25.0, 25.0 / 3.0);
let m = Gaussian::from_ms(0.0, 1.0);
assert_eq!(
m / n,
Gaussian::from_ms(-0.3652597402597402, 1.0072787050317253)
);
assert_eq!(
n / m,
Gaussian::from_ms(-0.3652597402597402, 1.0072787050317253)
);
}
}