test: pin the invariants that make filtered estimates trustworthy
The bracket test proves the feature works on one fixture. These pin the bug class: - Invariance to converge(). This is the one that matters. Reading skill.forward instead of the carried message makes it fail immediately, because converge() alternates sweeps and contaminates skill.forward with backward information from the second iteration onward. That is the property a stored field cannot have, and the reason issue #19's proposed fix would not have worked. - Invariance to ingestion order, the crate's standing invariant. - One slice has no future to propagate back, so filtered equals smoothed. - Empty history yields zero and empty maps. Agreement is to 1e-8 under tight convergence rather than bit-identity: iteration recomputes the colour partition only when from == 0, so an incrementally built slice keeps insertion order until the first converge() reorders it, and the scratch clone inherits whichever order it finds. Same fixed point, different path to it.
This commit is contained in:
@@ -245,3 +245,14 @@ fn log_evidence_finite_for_near_certain_outcome() {
|
||||
upset.log_evidence()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_history_has_no_filtered_estimates() {
|
||||
let history: History = History::builder().build();
|
||||
|
||||
assert_eq!(history.filtered_log_evidence(), 0.0);
|
||||
|
||||
assert!(history.filtered_learning_curves().is_empty());
|
||||
|
||||
assert!(history.filtered_learning_curve("nobody").is_empty());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user