use super::*;
use solverforge_core::score::SoftScore;
#[derive(Clone)]
struct TestSolution;
impl PlanningSolution for TestSolution {
type Score = SoftScore;
fn score(&self) -> Option<Self::Score> {
None
}
fn set_score(&mut self, _: Option<Self::Score>) {}
}
fn dlas(size: usize) -> DiversifiedLateAcceptanceAcceptor<TestSolution> {
let mut acceptor = DiversifiedLateAcceptanceAcceptor::new(size);
acceptor.phase_started(&SoftScore::of(-100));
acceptor
}
#[test]
fn repeated_minimum_scores_count_every_occurrence() {
let mut acceptor = dlas(2);
for _ in 0..2 {
assert!(acceptor.is_accepted(&SoftScore::of(-110), &SoftScore::of(-110), None));
}
assert_eq!(acceptor.late_worse_occurrences, 2);
assert_eq!(acceptor.late_worse_score, SoftScore::of(-110));
}
#[test]
fn replacing_non_minimum_with_non_minimum_keeps_occurrence_count() {
let mut acceptor = dlas(3);
acceptor.previous_scores = vec![
SoftScore::of(-120),
SoftScore::of(-100),
SoftScore::of(-100),
];
acceptor.late_worse_score = SoftScore::of(-120);
acceptor.late_worse_occurrences = 1;
acceptor.late_score_index = 1;
assert!(acceptor.is_accepted(&SoftScore::of(-100), &SoftScore::of(-90), None));
assert_eq!(acceptor.late_worse_occurrences, 1);
}
#[test]
fn cached_minimum_and_count_match_ring_after_each_candidate() {
for size in 1..=8 {
let mut acceptor = dlas(size);
let mut draw = 0x5a17_u64;
for _ in 0..2_000 {
draw = draw.wrapping_mul(6364136223846793005).wrapping_add(1);
let current = SoftScore::of(-100 - ((draw >> 32) % 80) as i64);
draw = draw.wrapping_mul(6364136223846793005).wrapping_add(1);
let candidate = SoftScore::of(-100 - ((draw >> 32) % 80) as i64);
let minimum = *acceptor.previous_scores.iter().min().unwrap();
let expected_acceptance = candidate == current || candidate > minimum;
assert_eq!(
acceptor.is_accepted(¤t, &candidate, None),
expected_acceptance
);
let minimum = *acceptor.previous_scores.iter().min().unwrap();
let count = acceptor
.previous_scores
.iter()
.filter(|score| **score == minimum)
.count();
assert_eq!(acceptor.late_worse_score, minimum);
assert_eq!(acceptor.late_worse_occurrences, count);
}
}
}
#[test]
fn accepts_improvement_over_current() {
let mut acceptor = dlas(5);
assert!(acceptor.is_accepted(&SoftScore::of(-100), &SoftScore::of(-90), None));
}
#[test]
fn accepts_equality_with_current() {
let mut acceptor = dlas(3);
assert!(acceptor.is_accepted(&SoftScore::of(-100), &SoftScore::of(-100), None));
}
#[test]
fn rejects_worse_than_late_worse() {
let mut acceptor = dlas(5);
assert!(!acceptor.is_accepted(&SoftScore::of(-90), &SoftScore::of(-110), None));
}
#[test]
fn accepts_better_than_late_worse_after_worsening() {
let mut acceptor = dlas(3);
assert!(acceptor.is_accepted(&SoftScore::of(-110), &SoftScore::of(-110), None));
assert!(acceptor.is_accepted(&SoftScore::of(-110), &SoftScore::of(-105), None));
}
#[test]
fn diversification_slot_update_on_worsening() {
let mut acceptor = dlas(1);
assert!(acceptor.is_accepted(&SoftScore::of(-95), &SoftScore::of(-95), None));
let mut acceptor = dlas(1);
assert!(acceptor.is_accepted(&SoftScore::of(-120), &SoftScore::of(-120), None));
assert!(acceptor.is_accepted(&SoftScore::of(-120), &SoftScore::of(-115), None));
}
#[test]
fn ring_advances_per_candidate_even_on_reject() {
let mut acceptor = dlas(2);
assert!(!acceptor.is_accepted(&SoftScore::of(-90), &SoftScore::of(-110), None));
assert!(acceptor.is_accepted(&SoftScore::of(-110), &SoftScore::of(-110), None));
assert!(acceptor.is_accepted(&SoftScore::of(-120), &SoftScore::of(-120), None));
assert!(acceptor.is_accepted(&SoftScore::of(-110), &SoftScore::of(-110), None));
assert!(!acceptor.is_accepted(&SoftScore::of(-110), &SoftScore::of(-130), None));
}
#[test]
fn late_worse_recount_when_occurrences_exhaust() {
let mut acceptor = dlas(2);
for _ in 0..2 {
assert!(acceptor.is_accepted(&SoftScore::of(-110), &SoftScore::of(-110), None));
}
assert!(acceptor.is_accepted(&SoftScore::of(-110), &SoftScore::of(-100), None));
assert_eq!(acceptor.late_worse_score, SoftScore::of(-110));
assert_eq!(acceptor.late_worse_occurrences, 1);
assert!(acceptor.is_accepted(&SoftScore::of(-110), &SoftScore::of(-100), None));
assert_eq!(acceptor.late_worse_score, SoftScore::of(-100));
assert_eq!(acceptor.late_worse_occurrences, 2);
assert!(!acceptor.is_accepted(&SoftScore::of(-100), &SoftScore::of(-105), None));
}