Revert back.

This commit is contained in:
2018-10-24 07:11:38 +02:00
parent 9cf91fbdf8
commit b39c446b37
5 changed files with 112 additions and 137 deletions

View File

@@ -3,7 +3,7 @@ use std::collections::HashMap;
use gaussian::Gaussian;
use math;
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct VariableId {
index: usize,
}
@@ -23,7 +23,7 @@ impl VariableArena {
let index = self.variables.len();
self.variables.push(Variable {
value: Gaussian::with_pi_tau(0.0, 0.0),
value: Gaussian::from_precision(0.0, 0.0),
factors: HashMap::new(),
});
@@ -46,16 +46,23 @@ pub struct Variable {
impl Variable {
pub fn attach_factor(&mut self, factor: usize) {
self.factors.insert(factor, Gaussian::new());
self.factors.insert(factor, Gaussian::from_precision(0.0, 0.0));
}
pub fn update_value(&mut self, factor: usize, value: Gaussian) {
let old = self.factors[&factor];
let intermediate = value * old;
let value = intermediate / self.value;
let new = intermediate / self.value;
self.value = value;
/*
println!("update_value: old={}, value={:?}, new={:?}, self.value={:?}",
render_g(old),
value,
new,
self.value);
*/
self.value = new;
}
pub fn get_value(&self) -> Gaussian {
@@ -70,6 +77,8 @@ impl Variable {
self.value = value;
println!("update_message: old={:?} msg={:?}, new={:?}", old, message, value);
self.factors.insert(factor, message);
}
@@ -91,9 +100,7 @@ impl PriorFactor {
variable: VariableId,
gaussian: Gaussian,
) -> PriorFactor {
if let Some(variable) = variable_arena.get_mut(variable) {
variable.attach_factor(id);
}
variable_arena.get_mut(variable).unwrap().attach_factor(id);
PriorFactor {
id,
@@ -103,9 +110,9 @@ impl PriorFactor {
}
pub fn start(&self, variable_arena: &mut VariableArena) {
if let Some(variable) = variable_arena.get_mut(self.variable) {
variable.update_value(self.id, self.gaussian);
}
println!("PriorFactor: variable.id={}, msg={:?}", self.variable.index, self.gaussian);
variable_arena.get_mut(self.variable).unwrap().update_value(self.id, self.gaussian);
}
}
@@ -124,13 +131,8 @@ impl LikelihoodFactor {
value: VariableId,
variance: f64,
) -> LikelihoodFactor {
if let Some(variable) = variable_arena.get_mut(mean) {
variable.attach_factor(id);
}
if let Some(variable) = variable_arena.get_mut(value) {
variable.attach_factor(id);
}
variable_arena.get_mut(mean).unwrap().attach_factor(id);
variable_arena.get_mut(value).unwrap().attach_factor(id);
LikelihoodFactor {
id,
@@ -151,13 +153,13 @@ impl LikelihoodFactor {
.map(|variable| variable.get_message(self.id))
.unwrap();
let a = 1.0 / (1.0 + self.variance * (x.pi - fx.pi));
let a = 1.0 / (1.0 + self.variance * (x.precision_mean() - fx.precision_mean()));
let gaussian = Gaussian::with_pi_tau(a * (x.pi - fx.pi), a * (x.tau - fx.tau));
let gaussian = Gaussian::from_precision(a * (x.precision_mean() - fx.precision_mean()), a * (x.precision() - fx.precision()));
if let Some(variable) = variable_arena.get_mut(self.mean) {
variable.update_message(self.id, gaussian);
}
println!("LikelihoodFactor: mean.id={}, msg={:?}", self.mean.index, gaussian);
variable_arena.get_mut(self.mean).unwrap().update_message(self.id, gaussian);
}
pub fn update_value(&self, variable_arena: &mut VariableArena) {
@@ -165,18 +167,20 @@ impl LikelihoodFactor {
.get(self.mean)
.map(|variable| variable.get_value())
.unwrap();
let fy = variable_arena
.get(self.mean)
.map(|variable| variable.get_message(self.id))
.unwrap();
let a = 1.0 / (1.0 + self.variance * (y.pi - fy.pi));
let a = 1.0 / (1.0 + self.variance * (y.precision_mean() - fy.precision_mean()));
let gaussian = Gaussian::with_pi_tau(a * (y.pi - fy.pi), a * (y.tau - fy.tau));
let gaussian = Gaussian::from_precision(a * (y.precision_mean() - fy.precision_mean()), a * (y.precision() - fy.precision()));
if let Some(variable) = variable_arena.get_mut(self.value) {
variable.update_message(self.id, gaussian);
}
println!("LikelihoodFactor: value.id={}, msg={:?}", self.value.index, gaussian);
variable_arena.get_mut(self.value).unwrap().update_message(self.id, gaussian);
}
}
@@ -195,14 +199,10 @@ impl SumFactor {
terms: Vec<VariableId>,
coeffs: Vec<f64>,
) -> SumFactor {
if let Some(variable) = variable_arena.get_mut(sum) {
variable.attach_factor(id);
}
variable_arena.get_mut(sum).unwrap().attach_factor(id);
for term in &terms {
if let Some(variable) = variable_arena.get_mut(*term) {
variable.attach_factor(id);
}
variable_arena.get_mut(*term).unwrap().attach_factor(id);
}
SumFactor {
@@ -231,18 +231,22 @@ impl SumFactor {
let gy = y[i];
let gfy = fy[i];
sum_pi += da.powi(2) / (gy.pi - gfy.pi);
sum_tau += da * (gy.tau - gfy.tau) / (gy.pi - gfy.pi);
sum_pi += da.powi(2) / (gy.pi() - gfy.pi());
sum_tau += da * (gy.tau() - gfy.tau()) / (gy.pi() - gfy.pi());
}
let new_pi = 1.0 / sum_pi;
let new_tau = new_pi * sum_tau;
let gaussian = Gaussian::with_pi_tau(new_pi, new_tau);
let gaussian = Gaussian::from_pi_tau(new_pi, new_tau);
if let Some(variable) = variable_arena.get_mut(variable) {
variable.update_value(self.id, gaussian);
if variable == self.sum {
println!("SumFactor: sum.id={}, msg={:?}", variable.index, gaussian);
} else {
println!("SumFactor: term.id={}, msg={:?}", variable.index, gaussian);
}
variable_arena.get_mut(variable).unwrap().update_value(self.id, gaussian);
}
pub fn update_sum(&self, variable_arena: &mut VariableArena) {
@@ -351,9 +355,7 @@ impl TruncateFactor {
epsilon: f64,
draw: bool,
) -> TruncateFactor {
if let Some(variable) = variable_arena.get_mut(variable) {
variable.attach_factor(id);
}
variable_arena.get_mut(variable).unwrap().attach_factor(id);
TruncateFactor {
id,
@@ -368,13 +370,15 @@ impl TruncateFactor {
.get(self.variable)
.map(|variable| variable.get_value())
.unwrap();
let fx = variable_arena
.get_mut(self.variable)
.map(|variable| variable.get_message(self.id))
.unwrap();
let c = x.pi - fx.pi;
let d = x.tau - fx.tau;
let c = x.pi() - fx.pi();
let d = x.tau() - fx.tau();
let sqrt_c = c.sqrt();
let t = d / sqrt_c;
@@ -388,10 +392,8 @@ impl TruncateFactor {
let m_w = 1.0 - w;
let gaussian = Gaussian::with_pi_tau(c / m_w, (d + sqrt_c * v) / m_w);
let gaussian = Gaussian::from_pi_tau(c / m_w, (d + sqrt_c * v) / m_w);
if let Some(variable) = variable_arena.get_mut(self.variable) {
variable.update_value(self.id, gaussian);
}
variable_arena.get_mut(self.variable).unwrap().update_value(self.id, gaussian);
}
}

View File

@@ -1,29 +1,33 @@
use std::ops;
#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
pub struct Gaussian {
pub pi: f64,
pub tau: f64,
pi: f64,
tau: f64,
}
impl Gaussian {
pub fn new() -> Gaussian {
Gaussian::with_pi_tau(0.0, 0.0)
}
pub fn with_pi_tau(pi: f64, tau: f64) -> Gaussian {
pub fn from_pi_tau(pi: f64, tau: f64) -> Gaussian {
Gaussian { pi, tau }
}
pub fn with_mu_sigma(mu: f64, sigma: f64) -> Gaussian {
let pi = 1.0 / sigma.powi(2);
pub fn from_mu_sigma(mu: f64, sigma: f64) -> Gaussian {
let pi = 1.0 / (sigma * sigma);
Gaussian::with_pi_tau(pi, pi * mu)
Self::from_pi_tau(pi, pi * mu)
}
pub fn pi(&self) -> f64 {
self.pi
}
pub fn tau(&self) -> f64 {
self.tau
}
pub fn mu(&self) -> f64 {
if self.pi == 0.0 {
0.0
return 0.0;
} else {
self.tau / self.pi
}
@@ -38,7 +42,7 @@ impl ops::Mul<Gaussian> for Gaussian {
type Output = Gaussian;
fn mul(self, rhs: Gaussian) -> Gaussian {
Gaussian::with_pi_tau(self.pi + rhs.pi, self.tau + rhs.tau)
Gaussian::from_pi_tau(self.pi + rhs.pi, self.tau + rhs.tau)
}
}
@@ -46,6 +50,6 @@ impl ops::Div<Gaussian> for Gaussian {
type Output = Gaussian;
fn div(self, rhs: Gaussian) -> Gaussian {
Gaussian::with_pi_tau(self.pi - rhs.pi, self.tau - rhs.tau)
Gaussian::from_pi_tau(self.pi - rhs.pi, self.tau - rhs.tau)
}
}

View File

@@ -1,3 +1,6 @@
extern crate statrs;
extern crate noisy_float;
mod factor_graph;
mod gaussian;
mod math;
@@ -25,22 +28,7 @@ const DRAW_PROBABILITY: f64 = 0.10;
/// A basis to check reliability of the result.
const DELTA: f64 = 0.0001;
#[derive(Debug, PartialEq)]
pub struct Rating {
pub mu: f64,
pub sigma: f64,
}
impl Default for Rating {
fn default() -> Rating {
Rating {
mu: MU,
sigma: SIGMA,
}
}
}
fn rate(rating_groups: &[&[Rating]]) {
pub fn rate(rating_groups: &[&[Gaussian]]) {
let flatten_ratings = rating_groups
.iter()
.flat_map(|group| group.iter())
@@ -74,7 +62,7 @@ fn rate(rating_groups: &[&[Rating]]) {
for (i, rating) in flatten_ratings.iter().enumerate() {
let variable = ss[i];
let gaussian = Gaussian::with_mu_sigma(rating.mu, (rating.sigma.powi(2) + tau_sqr).sqrt());
let gaussian = Gaussian::from_mean_variance(rating.mean(), (rating.variance() + tau_sqr).sqrt());
skill.push(PriorFactor::new(
&mut variable_arena,
@@ -89,14 +77,11 @@ fn rate(rating_groups: &[&[Rating]]) {
let mut skill_to_perf = Vec::new();;
for i in 0..size {
let mean = ss[i];
let value = ps[i];
skill_to_perf.push(LikelihoodFactor::new(
&mut variable_arena,
factor_id,
mean,
value,
ss[i],
ps[i],
beta_sqr,
));
@@ -149,6 +134,7 @@ fn rate(rating_groups: &[&[Rating]]) {
factor.start(&mut variable_arena);
}
/*
println!("before:");
for i in 0..size {
@@ -157,11 +143,12 @@ fn rate(rating_groups: &[&[Rating]]) {
.map(|variable| variable.get_value())
.unwrap();
let mu = value.mu();
let sigma = value.sigma();
let mu = value.mean();
let sigma = value.std_dev();
println!("* player={}, mu={}, sigma={}", i, mu, sigma);
}
*/
for factor in &skill_to_perf {
factor.update_value(&mut variable_arena);
@@ -194,6 +181,7 @@ fn rate(rating_groups: &[&[Rating]]) {
factor.update_mean(&mut variable_arena);
}
/*
println!("after:");
for i in 0..size {
@@ -202,14 +190,15 @@ fn rate(rating_groups: &[&[Rating]]) {
.map(|variable| variable.get_value())
.unwrap();
let mu = value.mu();
let sigma = value.sigma();
let mu = value.mean();
let sigma = value.std_dev();
println!("* player={}, mu={}, sigma={}", i, mu, sigma);
}
*/
}
fn quality(rating_groups: &[&[Rating]]) -> f64 {
pub fn quality(rating_groups: &[&[Gaussian]]) -> f64 {
let flatten_ratings = rating_groups
.iter()
.flat_map(|group| group.iter())
@@ -222,13 +211,13 @@ fn quality(rating_groups: &[&[Rating]]) -> f64 {
let mut mean_matrix = Matrix::new(length, 1);
for (i, rating) in flatten_ratings.iter().enumerate() {
mean_matrix[(i, 0)] = rating.mu;
mean_matrix[(i, 0)] = rating.mean();
}
let mut variance_matrix = Matrix::new(length, length);
for (i, rating) in flatten_ratings.iter().enumerate() {
variance_matrix[(i, i)] = rating.sigma.powi(2);
variance_matrix[(i, i)] = rating.std_dev().powi(2);
}
let mut rotated_a_matrix = Matrix::new(rating_groups.len() - 1, length);
@@ -272,35 +261,23 @@ mod tests {
#[test]
fn test_quality_1vs1() {
let alice = Rating {
mu: 25.0,
sigma: SIGMA,
};
let alice = Gaussian::from_mean_std_dev(MU, SIGMA);
let bob = Gaussian::from_mean_std_dev(MU, SIGMA);
let bob = Rating {
mu: 30.0,
sigma: SIGMA,
};
assert_eq!(quality(&[&[alice], &[bob]]), 0.41614606763952605);
assert_eq!(quality(&[&[alice], &[bob]]), 0.4472135954999579);
}
#[test]
fn test_rate_1vs1() {
let alice = Rating {
mu: 25.0,
sigma: SIGMA,
};
let alice = Gaussian::from_mean_std_dev(MU, SIGMA);
let bob = Gaussian::from_mean_std_dev(MU, SIGMA);
let chris = Gaussian::from_mean_std_dev(MU, SIGMA);
let darren = Gaussian::from_mean_std_dev(MU, SIGMA);
let bob = Rating {
mu: 30.0,
sigma: SIGMA,
};
// println!("alice: {:?}", alice);
// println!("bob: {:?}", alice);
// alice: mu=27.175, sigma=7.112
// bob: mu=23.141, sigma=6.859
rate(&[&[alice], &[bob]]);
rate(&[&[alice], &[bob], &[chris], &[darren]]);
assert_eq!(true, false);
}

View File

@@ -1,30 +1,20 @@
use std::f64;
fn erfc(x: f64) -> f64 {
let z = x.abs();
let t = 1.0 / (1.0 + z / 2.0);
let r = t
* (-z * z - 1.26551223
+ t * (1.00002368
+ t * (0.37409196
+ t * (0.09678418
+ t * (-0.18628806
+ t * (0.27886807
+ t * (-1.13520398
+ t * (1.48851587 + t * (-0.82215223 + t * 0.17087277)))))))))
.exp();
if x < 0.0 {
2.0 - r
} else {
r
}
}
use statrs::distribution::{Normal, Univariate, Continuous};
pub fn cdf(x: f64) -> f64 {
0.5 * erfc(-x / 2.0f64.sqrt())
Normal::new(0.0, 1.0).unwrap().cdf(x)
}
pub fn pdf(x: f64) -> f64 {
1.0 / (2.0 * f64::consts::PI).sqrt() * (-((x / 1.0).powi(2) / 2.0)).exp()
Normal::new(0.0, 1.0).unwrap().pdf(x)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cdf() {
assert_eq!(cdf(0.5), 0.6914624612740131);
}
}