use std::time::Duration;
use solverforge_core::domain::PlanningSolution;
use solverforge_core::score::SoftScore;
use solverforge_scoring::ScoreDirector;
use crate::scope::SolverScope;
use super::*;
#[derive(Clone, Debug)]
struct TestSolution {
value: i64,
score: Option<SoftScore>,
}
impl PlanningSolution for TestSolution {
type Score = SoftScore;
fn score(&self) -> Option<Self::Score> {
self.score
}
fn set_score(&mut self, score: Option<Self::Score>) {
self.score = score;
}
}
type TestDirector = ScoreDirector<TestSolution, ()>;
#[test]
fn test_solver_factory_builder_creation() {
let _builder = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
});
}
#[test]
fn test_solver_factory_builder_builds_successfully() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
})
.build()
.expect("Failed to build factory");
let solution = TestSolution {
value: 10,
score: None,
};
let score = factory.calculate_score(&solution);
assert_eq!(score, SoftScore::of(-10));
}
#[test]
fn test_solver_factory_builder_with_time_limit() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
})
.with_time_limit(Duration::from_secs(30))
.build()
.expect("Failed to build factory");
let solution = TestSolution {
value: 5,
score: None,
};
let score = factory.calculate_score(&solution);
assert_eq!(score, SoftScore::of(-5));
}
#[test]
fn test_solver_factory_builder_with_step_limit() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
})
.with_step_limit(100)
.build()
.expect("Failed to build factory");
let solution = TestSolution {
value: 7,
score: None,
};
let score = factory.calculate_score(&solution);
assert_eq!(score, SoftScore::of(-7));
}
#[derive(Debug, Clone)]
struct NoOpPhase;
impl<S: PlanningSolution, D: solverforge_scoring::Director<S>> crate::phase::Phase<S, D>
for NoOpPhase
{
fn solve(&mut self, solver_scope: &mut SolverScope<S, D>) {
solver_scope.update_best_solution();
}
fn phase_type_name(&self) -> &'static str {
"NoOpPhase"
}
}
#[test]
fn test_solver_factory_with_phase() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
})
.with_phase(NoOpPhase)
.build()
.expect("Failed to build factory");
let solution = TestSolution {
value: 5,
score: None,
};
let score = factory.calculate_score(&solution);
assert_eq!(score, SoftScore::of(-5));
}
#[test]
fn test_solver_factory_with_multiple_phases() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
})
.with_phase(NoOpPhase)
.with_phase(NoOpPhase)
.build()
.expect("Failed to build factory");
let solution = TestSolution {
value: 3,
score: None,
};
let score = factory.calculate_score(&solution);
assert_eq!(score, SoftScore::of(-3));
}
#[test]
fn test_solver_factory_with_phase_and_step_limit() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
})
.with_phase(NoOpPhase)
.with_step_limit(50)
.build()
.expect("Failed to build factory");
let solution = TestSolution {
value: 8,
score: None,
};
let score = factory.calculate_score(&solution);
assert_eq!(score, SoftScore::of(-8));
}
#[test]
fn test_score_calculator_returns_reference() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
})
.build()
.expect("Failed to build factory");
let calculator = factory.score_calculator();
let solution = TestSolution {
value: 15,
score: None,
};
let score = calculator(&solution);
assert_eq!(score, SoftScore::of(-15));
}
#[test]
fn test_calculate_score_basic() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
})
.build()
.expect("Failed to build factory");
let solution = TestSolution {
value: 10,
score: None,
};
let score = factory.calculate_score(&solution);
assert_eq!(score, SoftScore::of(-10));
}
#[test]
fn test_calculate_score_zero() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
})
.build()
.expect("Failed to build factory");
let solution = TestSolution {
value: 0,
score: None,
};
let score = factory.calculate_score(&solution);
assert_eq!(score, SoftScore::of(0));
}
#[test]
fn test_calculate_score_negative_value() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
})
.build()
.expect("Failed to build factory");
let solution = TestSolution {
value: -5,
score: None,
};
let score = factory.calculate_score(&solution);
assert_eq!(score, SoftScore::of(5)); }
#[test]
fn test_calculate_score_multiple_solutions() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value)
})
.build()
.expect("Failed to build factory");
let solutions = [
TestSolution {
value: 1,
score: None,
},
TestSolution {
value: 2,
score: None,
},
TestSolution {
value: 3,
score: None,
},
];
for (i, solution) in solutions.iter().enumerate() {
let score = factory.calculate_score(solution);
assert_eq!(score, SoftScore::of(-((i + 1) as i64)));
}
}
#[test]
fn test_calculate_score_complex_calculator() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-(s.value * s.value))
})
.build()
.expect("Failed to build factory");
let solution = TestSolution {
value: 4,
score: None,
};
let score = factory.calculate_score(&solution);
assert_eq!(score, SoftScore::of(-16)); }
#[test]
fn test_score_calculator_and_calculate_score_consistent() {
let factory = solver_factory_builder::<TestSolution, TestDirector, _>(|s: &TestSolution| {
SoftScore::of(-s.value * 2)
})
.build()
.expect("Failed to build factory");
let solution = TestSolution {
value: 7,
score: None,
};
let calculator = factory.score_calculator();
let score_via_calculator = calculator(&solution);
let score_via_method = factory.calculate_score(&solution);
assert_eq!(score_via_calculator, score_via_method);
assert_eq!(score_via_method, SoftScore::of(-14));
}