T0 + T1 + T2: engine redesign through new API surface #1

Merged
logaritmisk merged 45 commits from t2-new-api-surface into main 2026-04-24 11:20:04 +00:00
2 changed files with 50 additions and 0 deletions
Showing only changes of commit 726896a2ba - Show all commits

View File

@@ -19,6 +19,7 @@ pub mod gaussian;
mod history; mod history;
mod key_table; mod key_table;
mod matrix; mod matrix;
mod observer;
mod outcome; mod outcome;
mod rating; mod rating;
pub(crate) mod schedule; pub(crate) mod schedule;
@@ -33,6 +34,7 @@ pub use gaussian::Gaussian;
pub use history::History; pub use history::History;
pub use key_table::KeyTable; pub use key_table::KeyTable;
use matrix::Matrix; use matrix::Matrix;
pub use observer::{NullObserver, Observer};
pub use outcome::Outcome; pub use outcome::Outcome;
pub use rating::Rating; pub use rating::Rating;
pub use schedule::ScheduleReport; pub use schedule::ScheduleReport;

48
src/observer.rs Normal file
View File

@@ -0,0 +1,48 @@
//! Observer trait for progress reporting during convergence.
//!
//! Replaces the old `verbose: bool` + `println!` path. Callers wire in any
//! observer that implements the trait; default methods are no-ops so users
//! override only what they need.
use crate::time::Time;
/// Receives progress callbacks during `History::converge`.
///
/// All methods have default no-op implementations; implement only what's
/// interesting. Send/Sync is NOT required in T2 (added in T3 along with
/// Rayon support).
pub trait Observer<T: Time> {
/// Called after each convergence iteration across the whole history.
fn on_iteration_end(&self, _iter: usize, _max_step: (f64, f64)) {}
/// Called after each time slice is processed within an iteration.
fn on_batch_processed(&self, _time: &T, _slice_idx: usize, _n_events: usize) {}
/// Called once when convergence completes (or max iters is reached).
fn on_converged(&self, _iters: usize, _final_step: (f64, f64), _converged: bool) {}
}
/// ZST no-op observer; the default when none is configured.
#[derive(Copy, Clone, Debug, Default)]
pub struct NullObserver;
impl<T: Time> Observer<T> for NullObserver {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn null_observer_compiles_for_i64() {
let o = NullObserver;
<NullObserver as Observer<i64>>::on_iteration_end(&o, 1, (0.0, 0.0));
<NullObserver as Observer<i64>>::on_converged(&o, 5, (1e-6, 1e-6), true);
}
#[test]
fn null_observer_compiles_for_untimed() {
use crate::Untimed;
let o = NullObserver;
<NullObserver as Observer<Untimed>>::on_iteration_end(&o, 1, (0.0, 0.0));
}
}