use crate::solution::{apply_bounds, finalize_scalar_solution, Solution};
pub struct RealSolutionBuilder {
variables: Vec<f64>,
quality: Option<f64>,
lower_bounds: Option<Vec<f64>>,
upper_bounds: Option<Vec<f64>>,
}
impl RealSolutionBuilder {
pub fn new(size: usize) -> Self {
Self {
variables: vec![0.0; size],
quality: None,
lower_bounds: None,
upper_bounds: None,
}
}
pub fn from_variables(variables: Vec<f64>) -> Self {
Self {
variables,
quality: None,
lower_bounds: None,
upper_bounds: None,
}
}
pub fn with_variables(mut self, variables: Vec<f64>) -> Self {
self.variables = variables;
self
}
pub fn with_quality(mut self, quality: f64) -> Self {
self.quality = Some(quality);
self
}
pub fn with_lower_bounds(mut self, bounds: Vec<f64>) -> Self {
self.lower_bounds = Some(bounds);
self
}
pub fn with_upper_bounds(mut self, bounds: Vec<f64>) -> Self {
self.upper_bounds = Some(bounds);
self
}
pub fn with_bounds(mut self, lower: f64, upper: f64) -> Self {
let size = self.variables.len();
self.lower_bounds = Some(vec![lower; size]);
self.upper_bounds = Some(vec![upper; size]);
self
}
pub fn set_variable(mut self, index: usize, value: f64) -> Self {
if index < self.variables.len() {
self.variables[index] = value;
}
self
}
pub fn fill(mut self, value: f64) -> Self {
self.variables.fill(value);
self
}
pub fn build(self) -> Solution<f64> {
let variables = apply_bounds(self.variables, &self.lower_bounds, &self.upper_bounds);
finalize_scalar_solution(variables, self.quality)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_real_solution_builder_with_bounds() {
let solution = RealSolutionBuilder::new(3)
.fill(5.0)
.with_bounds(0.0, 1.0)
.build();
assert_eq!(solution.variables(), &[1.0, 1.0, 1.0]);
}
#[test]
fn test_real_solution_builder_individual_bounds() {
let solution = RealSolutionBuilder::from_variables(vec![5.0, -5.0, 10.0])
.with_lower_bounds(vec![0.0, 0.0, 0.0])
.with_upper_bounds(vec![1.0, 1.0, 1.0])
.build();
assert_eq!(solution.variables(), &[1.0, 0.0, 1.0]);
}
}