refactor(time_slice): add convergence field, rename iterate_to_convergence

TimeSlice<T> gains a pub(crate) convergence: ConvergenceOptions field
set at construction. TimeSlice::new now takes it as a third parameter
(breaking change to the pub constructor, acceptable in 0.1.x).
History::add_events_with_prior passes self.convergence so the propagated
value reaches every TimeSlice. The pre-existing convergence-the-method
is renamed to iterate_to_convergence to disambiguate from the new
convergence-the-field.

The field is wired but not yet read by inference -- the three
Game::*_with_arena callsites in time_slice.rs still hardcode
ConvergenceOptions::default(). Task 2 changes that. Bit-equal because
the propagated value equals the hardcoded value end-to-end.

Also updated benches/batch.rs which has a fourth TimeSlice::new
callsite (not enumerated in the plan -- only src/ files were).
This commit is contained in:
2026-05-08 15:29:39 +02:00
parent 6e453b6845
commit 872f91797d
3 changed files with 20 additions and 14 deletions
+3 -3
View File
@@ -1,7 +1,7 @@
use criterion::{Criterion, criterion_group, criterion_main};
use trueskill_tt::{
BETA, Competitor, EventKind, GAMMA, KeyTable, MU, P_DRAW, Rating, SIGMA, TimeSlice,
drift::ConstantDrift, gaussian::Gaussian, storage::CompetitorStore,
BETA, Competitor, ConvergenceOptions, EventKind, GAMMA, KeyTable, MU, P_DRAW, Rating, SIGMA,
TimeSlice, drift::ConstantDrift, gaussian::Gaussian, storage::CompetitorStore,
};
fn criterion_benchmark(criterion: &mut Criterion) {
@@ -35,7 +35,7 @@ fn criterion_benchmark(criterion: &mut Criterion) {
let kinds = vec![EventKind::Ranked; composition.len()];
let mut time_slice = TimeSlice::new(1, P_DRAW);
let mut time_slice = TimeSlice::new(1, P_DRAW, ConvergenceOptions::default());
time_slice.add_events(composition, results, weights, kinds, &agents);
criterion.bench_function("Batch::iteration", |b| {
+1 -1
View File
@@ -594,7 +594,7 @@ impl<T: Time, D: Drift<T>, O: Observer<T>, K: Eq + Hash + Clone> History<T, D, O
agent.message = time_slice.forward_prior_out(&agent_idx);
}
} else {
let mut time_slice = TimeSlice::new(t, self.p_draw);
let mut time_slice = TimeSlice::new(t, self.p_draw, self.convergence);
time_slice.add_events(composition, results, weights, kinds_chunk, &self.agents);
self.time_slices.insert(k, time_slice);
+16 -10
View File
@@ -175,17 +175,20 @@ pub struct TimeSlice<T: Time = i64> {
pub(crate) skills: SkillStore,
pub(crate) time: T,
p_draw: f64,
#[allow(dead_code)]
pub(crate) convergence: crate::ConvergenceOptions,
arena: ScratchArena,
pub(crate) color_groups: ColorGroups,
}
impl<T: Time> TimeSlice<T> {
pub fn new(time: T, p_draw: f64) -> Self {
pub fn new(time: T, p_draw: f64, convergence: crate::ConvergenceOptions) -> Self {
Self {
events: Vec::new(),
skills: SkillStore::new(),
time,
p_draw,
convergence,
arena: ScratchArena::new(),
color_groups: ColorGroups::new(),
}
@@ -444,7 +447,10 @@ impl<T: Time> TimeSlice<T> {
}
#[allow(dead_code)]
pub(crate) fn convergence<D: Drift<T>>(&mut self, agents: &CompetitorStore<T, D>) -> usize {
pub(crate) fn iterate_to_convergence<D: Drift<T>>(
&mut self,
agents: &CompetitorStore<T, D>,
) -> usize {
let epsilon = 1e-6;
let iterations = 20;
@@ -643,7 +649,7 @@ mod tests {
);
}
let mut time_slice = TimeSlice::new(0i64, 0.0);
let mut time_slice = TimeSlice::new(0i64, 0.0, crate::ConvergenceOptions::default());
time_slice.add_events(
vec![
@@ -690,7 +696,7 @@ mod tests {
epsilon = 1e-6
);
assert_eq!(time_slice.convergence(&agents), 1);
assert_eq!(time_slice.iterate_to_convergence(&agents), 1);
}
#[test]
@@ -720,7 +726,7 @@ mod tests {
);
}
let mut time_slice = TimeSlice::new(0i64, 0.0);
let mut time_slice = TimeSlice::new(0i64, 0.0, crate::ConvergenceOptions::default());
time_slice.add_events(
vec![
@@ -752,7 +758,7 @@ mod tests {
epsilon = 1e-6
);
assert!(time_slice.convergence(&agents) > 1);
assert!(time_slice.iterate_to_convergence(&agents) > 1);
let post = time_slice.posteriors();
@@ -800,7 +806,7 @@ mod tests {
);
}
let mut time_slice = TimeSlice::new(0i64, 0.0);
let mut time_slice = TimeSlice::new(0i64, 0.0, crate::ConvergenceOptions::default());
time_slice.add_events(
vec![
@@ -814,7 +820,7 @@ mod tests {
&agents,
);
time_slice.convergence(&agents);
time_slice.iterate_to_convergence(&agents);
let post = time_slice.posteriors();
@@ -848,7 +854,7 @@ mod tests {
assert_eq!(time_slice.events.len(), 6);
time_slice.convergence(&agents);
time_slice.iterate_to_convergence(&agents);
let post = time_slice.posteriors();
@@ -898,7 +904,7 @@ mod tests {
);
}
let mut ts = TimeSlice::new(0i64, 0.0);
let mut ts = TimeSlice::new(0i64, 0.0, crate::ConvergenceOptions::default());
ts.add_events(
vec![