refactor(game): rebuild Game::likelihoods on factor-graph machinery

Game::likelihoods now uses VarStore (for diff vars) and TruncFactor
(for EP truncation + evidence caching) instead of TeamMessage and
DiffMessage. The EP loop structure is preserved exactly; VarId-keyed
diff vars live in the arena's VarStore (capacity reused per batch).

ScratchArena loses teams/diffs/ties/margins; gains VarStore and
sort_buf (sort_perm allocation eliminated). message.rs deleted.

Public API of Game (new, posteriors, likelihoods, evidence) unchanged.
This commit is contained in:
2026-04-24 08:51:18 +02:00
parent da69f02ff7
commit cb07a874e8
4 changed files with 142 additions and 229 deletions

View File

@@ -18,7 +18,6 @@ mod game;
pub mod gaussian;
mod history;
mod matrix;
mod message;
pub mod player;
pub(crate) mod schedule;
pub mod storage;
@@ -29,7 +28,6 @@ pub use game::Game;
pub use gaussian::Gaussian;
pub use history::History;
use matrix::Matrix;
use message::DiffMessage;
pub use player::Player;
pub use schedule::ScheduleReport;
@@ -226,18 +224,6 @@ pub(crate) fn tuple_gt(t: (f64, f64), e: f64) -> bool {
t.0 > e || t.1 > e
}
pub(crate) fn sort_perm(x: &[f64], reverse: bool) -> Vec<usize> {
let mut v = x.iter().enumerate().collect::<Vec<_>>();
if reverse {
v.sort_by(|(_, a), (_, b)| b.partial_cmp(a).unwrap());
} else {
v.sort_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap());
}
v.into_iter().map(|(i, _)| i).collect()
}
pub(crate) fn sort_time(xs: &[i64], reverse: bool) -> Vec<usize> {
let mut x = xs.iter().enumerate().collect::<Vec<_>>();
@@ -250,15 +236,6 @@ pub(crate) fn sort_time(xs: &[i64], reverse: bool) -> Vec<usize> {
x.into_iter().map(|(i, _)| i).collect()
}
pub(crate) fn evidence(d: &[DiffMessage], margin: &[f64], tie: &[bool], e: usize) -> f64 {
if tie[e] {
cdf(margin[e], d[e].prior.mu(), d[e].prior.sigma())
- cdf(-margin[e], d[e].prior.mu(), d[e].prior.sigma())
} else {
1.0 - cdf(margin[e], d[e].prior.mu(), d[e].prior.sigma())
}
}
/// Calculates the match quality of the given rating groups. A result is the draw probability in the association
pub fn quality(rating_groups: &[&[Gaussian]], beta: f64) -> f64 {
let flatten_ratings = rating_groups
@@ -327,11 +304,6 @@ mod tests {
use super::*;
#[test]
fn test_sort_perm() {
assert_eq!(sort_perm(&[0.0, 1.0, 2.0, 0.0], true), vec![2, 1, 0, 3]);
}
#[test]
fn test_sort_time() {
assert_eq!(sort_time(&[0, 1, 2, 0], true), vec![2, 1, 0, 3]);