fix: deterministic fusion tie-order + seeded random eval sampling
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -29,3 +29,42 @@ fn cross_segment_keeps_max_score_and_all_sources() {
|
||||
assert_eq!(merged[0].1, 0.9); // max
|
||||
assert_eq!(merged[0].0.source_segments, vec![0, 2]); // all sources
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fusion_is_deterministic_across_runs() {
|
||||
// Build inputs with deliberate score ties so HashMap iteration order would
|
||||
// matter without the deterministic tiebreaker.
|
||||
// rrf_merge: entries 5 and 10 appear at symmetric positions in both lists,
|
||||
// so their RRF scores are identical. The tiebreaker must put 5 before 10.
|
||||
let lex = vec![5usize, 10, 20];
|
||||
let sem = vec![10usize, 5, 30];
|
||||
let first = rrf_merge(&lex, &sem, 60);
|
||||
for _ in 0..4 {
|
||||
let run = rrf_merge(&lex, &sem, 60);
|
||||
assert_eq!(first, run, "rrf_merge output changed between runs");
|
||||
}
|
||||
// Verify the tiebreaker: 5 and 10 have equal scores (symmetric positions);
|
||||
// ascending id means 5 should come before 10.
|
||||
let pos5 = first.iter().position(|&x| x == 5).expect("5 missing");
|
||||
let pos10 = first.iter().position(|&x| x == 10).expect("10 missing");
|
||||
assert!(pos5 < pos10, "tiebreaker should put smaller id first: got pos5={pos5} pos10={pos10}");
|
||||
|
||||
// cross_segment_dedupe: two codes with equal score — lexicographic tiebreaker.
|
||||
let cands = vec![
|
||||
cand("Z99.89", 0, Some(0.7)),
|
||||
cand("A00.0", 1, Some(0.7)),
|
||||
cand("M50.00", 2, Some(0.5)),
|
||||
];
|
||||
let first_dedup = cross_segment_dedupe(cands.clone());
|
||||
for _ in 0..4 {
|
||||
let run = cross_segment_dedupe(cands.clone());
|
||||
let ids: Vec<&str> = run.iter().map(|(d, _)| d.icd_code.as_str()).collect();
|
||||
let first_ids: Vec<&str> = first_dedup.iter().map(|(d, _)| d.icd_code.as_str()).collect();
|
||||
assert_eq!(first_ids, ids, "cross_segment_dedupe output changed between runs");
|
||||
}
|
||||
// Verify tiebreaker: A00.0 < Z99.89 lexicographically, so A00.0 first among ties.
|
||||
assert_eq!(first_dedup[0].0.icd_code, "A00.0",
|
||||
"tiebreaker should put A00.0 before Z99.89 (both score 0.7)");
|
||||
assert_eq!(first_dedup[1].0.icd_code, "Z99.89");
|
||||
assert_eq!(first_dedup[2].0.icd_code, "M50.00");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user