#[cfg(test)]
mod tests {
use super::super::solution_integration::*;
use super::super::subproblem_solving::*;
use super::super::variable_partitioning::*;
use crate::model::Model;
use crate::variables::{VarId, Val};
use std::collections::HashMap;
use std::time::Duration;
fn create_test_model() -> (Model, Vec<VarId>) {
let mut model = Model::with_float_precision(3);
let var0 = m.float(0.0, 10.0); let var1 = m.int(1, 5); let var2 = m.float(-1.0, 1.0); let var3 = m.int(10, 20);
(model, vec![var0, var1, var2, var3])
}
fn create_valid_combined_solution(var_ids: &[VarId]) -> CombinedSolution {
let mut all_assignments = HashMap::new();
all_assignments.insert(var_ids[0], SubproblemValue::Float(5.0)); all_assignments.insert(var_ids[1], SubproblemValue::Integer(3)); all_assignments.insert(var_ids[2], SubproblemValue::Float(0.5)); all_assignments.insert(var_ids[3], SubproblemValue::Integer(15));
let subproblem_result = SubproblemSolution {
variable_assignments: all_assignments.clone(),
solve_time: Duration::from_micros(100),
is_solved: true,
variable_count: 4,
};
CombinedSolution {
all_assignments,
subproblem_results: vec![subproblem_result],
total_time: Duration::from_micros(100),
is_complete: true,
speedup_factor: 10.0,
}
}
fn create_invalid_combined_solution(var_ids: &[VarId]) -> CombinedSolution {
let mut all_assignments = HashMap::new();
all_assignments.insert(var_ids[0], SubproblemValue::Float(15.0)); all_assignments.insert(var_ids[1], SubproblemValue::Integer(3)); all_assignments.insert(var_ids[2], SubproblemValue::Float(2.0)); all_assignments.insert(var_ids[3], SubproblemValue::Integer(25));
let subproblem_result = SubproblemSolution {
variable_assignments: all_assignments.clone(),
solve_time: Duration::from_micros(100),
is_solved: true,
variable_count: 4,
};
CombinedSolution {
all_assignments,
subproblem_results: vec![subproblem_result],
total_time: Duration::from_micros(100),
is_complete: true,
speedup_factor: 10.0,
}
}
fn create_partition_result() -> PartitionResult {
PartitionResult {
float_partition: None,
integer_partition: None,
is_separable: true,
total_variables: 4,
total_constraints: 0,
}
}
#[test]
fn test_integrator_creation() {
let integrator = SolutionIntegrator::new();
let integrator_with_config = SolutionIntegrator::new()
.with_timeout(Duration::from_millis(1000))
.with_full_validation(false);
assert!(true); }
#[test]
fn test_valid_solution_integration() {
let (model, var_ids) = create_test_model();
let combined_solution = create_valid_combined_solution(&var_ids);
let partition_result = create_partition_result();
let integrator = SolutionIntegrator::new();
let result = integrator.integrate_solution(&model, &combined_solution, &partition_result);
assert!(result.is_ok());
let integrated = result.unwrap();
assert!(integrated.is_fully_validated);
assert_eq!(integrated.variable_assignments.len(), 4);
assert_eq!(integrated.validation_issues.len(), 0);
assert!(integrated.integration_time < Duration::from_millis(100));
assert_eq!(integrated.solution[var_ids[0]], Val::ValF(5.0));
assert_eq!(integrated.solution[var_ids[1]], Val::ValI(3));
assert_eq!(integrated.solution[var_ids[2]], Val::ValF(0.5));
assert_eq!(integrated.solution[var_ids[3]], Val::ValI(15));
assert_eq!(integrated.variable_assignments[&var_ids[0]], Val::ValF(5.0));
assert_eq!(integrated.variable_assignments[&var_ids[1]], Val::ValI(3));
assert_eq!(integrated.variable_assignments[&var_ids[2]], Val::ValF(0.5));
assert_eq!(integrated.variable_assignments[&var_ids[3]], Val::ValI(15));
}
#[test]
fn test_invalid_solution_integration() {
let (model, var_ids) = create_test_model();
let combined_solution = create_invalid_combined_solution(&var_ids);
let partition_result = create_partition_result();
let integrator = SolutionIntegrator::new();
let result = integrator.integrate_solution(&model, &combined_solution, &partition_result);
assert!(result.is_ok());
let integrated = result.unwrap();
assert!(!integrated.is_fully_validated);
assert_eq!(integrated.variable_assignments.len(), 4);
assert!(integrated.validation_issues.len() > 0);
let out_of_bounds_issues: Vec<_> = integrated.validation_issues.iter()
.filter(|issue| matches!(issue, ValidationIssue::VariableOutOfBounds { .. }))
.collect();
assert_eq!(out_of_bounds_issues.len(), 3); }
#[test]
fn test_incomplete_solution_integration() {
let (model, _var_ids) = create_test_model();
let partition_result = create_partition_result();
let integrator = SolutionIntegrator::new();
let incomplete_solution = CombinedSolution {
all_assignments: HashMap::new(),
subproblem_results: vec![],
total_time: Duration::from_micros(50),
is_complete: false,
speedup_factor: 1.0,
};
let result = integrator.integrate_solution(&model, &incomplete_solution, &partition_result);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(), IntegrationError::NoSolution));
}
#[test]
fn test_missing_variable_assignment() {
let (model, var_ids) = create_test_model();
let partition_result = create_partition_result();
let integrator = SolutionIntegrator::new();
let mut all_assignments = HashMap::new();
all_assignments.insert(var_ids[0], SubproblemValue::Float(5.0));
all_assignments.insert(var_ids[1], SubproblemValue::Integer(3));
all_assignments.insert(var_ids[2], SubproblemValue::Float(0.5));
let incomplete_combined = CombinedSolution {
all_assignments,
subproblem_results: vec![],
total_time: Duration::from_micros(50),
is_complete: true, speedup_factor: 1.0,
};
let result = integrator.integrate_solution(&model, &incomplete_combined, &partition_result);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(),
IntegrationError::ConstructionFailed(
ConstructionError::MissingRequiredVariables { .. }
)));
}
#[test]
fn test_type_conversion() {
let (model, var_ids) = create_test_model();
let partition_result = create_partition_result();
let integrator = SolutionIntegrator::new();
let mut all_assignments = HashMap::new();
all_assignments.insert(var_ids[0], SubproblemValue::Integer(5)); all_assignments.insert(var_ids[1], SubproblemValue::Float(3.0)); all_assignments.insert(var_ids[2], SubproblemValue::Float(0.5)); all_assignments.insert(var_ids[3], SubproblemValue::Integer(15));
let combined_solution = CombinedSolution {
all_assignments,
subproblem_results: vec![],
total_time: Duration::from_micros(50),
is_complete: true,
speedup_factor: 1.0,
};
let result = integrator.integrate_solution(&model, &combined_solution, &partition_result);
assert!(result.is_ok());
let integrated = result.unwrap();
assert!(integrated.is_fully_validated);
assert_eq!(integrated.variable_assignments[&var_ids[0]], Val::ValF(5.0)); assert_eq!(integrated.variable_assignments[&var_ids[1]], Val::ValI(3)); }
#[test]
fn test_invalid_type_conversion() {
let (model, var_ids) = create_test_model();
let partition_result = create_partition_result();
let integrator = SolutionIntegrator::new();
let mut all_assignments = HashMap::new();
all_assignments.insert(var_ids[0], SubproblemValue::Float(5.0));
all_assignments.insert(var_ids[1], SubproblemValue::Float(3.7)); all_assignments.insert(var_ids[2], SubproblemValue::Float(0.5));
all_assignments.insert(var_ids[3], SubproblemValue::Integer(15));
let combined_solution = CombinedSolution {
all_assignments,
subproblem_results: vec![],
total_time: Duration::from_micros(50),
is_complete: true,
speedup_factor: 1.0,
};
let result = integrator.integrate_solution(&model, &combined_solution, &partition_result);
assert!(result.is_err());
assert!(matches!(result.unwrap_err(),
IntegrationError::MergingFailed(
MergingError::TypeConversionFailed { .. }
)));
}
#[test]
fn test_validation_timeout() {
let (model, var_ids) = create_test_model();
let combined_solution = create_valid_combined_solution(&var_ids);
let partition_result = create_partition_result();
let integrator = SolutionIntegrator::new()
.with_timeout(Duration::from_nanos(1));
let result = integrator.integrate_solution(&model, &combined_solution, &partition_result);
if let Err(error) = result {
assert!(matches!(error, IntegrationError::TimeoutExceeded));
}
}
#[test]
fn test_validation_disabled() {
let (model, var_ids) = create_test_model();
let combined_solution = create_invalid_combined_solution(&var_ids);
let partition_result = create_partition_result();
let integrator = SolutionIntegrator::new()
.with_full_validation(false);
let result = integrator.integrate_solution(&model, &combined_solution, &partition_result);
assert!(result.is_ok());
let integrated = result.unwrap();
assert!(!integrated.is_fully_validated);
assert_eq!(integrated.constraints_validated, 0); }
#[test]
fn test_validation_issue_display() {
let var_id = crate::optimization::model_integration::index_to_var_id(0);
let issues = vec![
ValidationIssue::VariableOutOfBounds {
var_id,
value: Val::ValF(15.0),
expected_min: Val::ValF(0.0),
expected_max: Val::ValF(10.0),
},
ValidationIssue::ConstraintViolation {
constraint_type: "equals".to_string(),
variables: vec![var_id],
},
ValidationIssue::TypeMismatch {
var_id,
expected_type: VariableType::Float,
actual_value: Val::ValI(5),
},
ValidationIssue::MissingAssignment { var_id },
ValidationIssue::ValidationTimeout,
];
for issue in issues {
let display_string = format!("{}", issue);
assert!(!display_string.is_empty());
}
}
#[test]
fn test_error_display() {
let var_id = crate::optimization::model_integration::index_to_var_id(0);
let errors = vec![
IntegrationError::MergingFailed(MergingError::ConflictingAssignments {
var_id,
value1: SubproblemValue::Float(1.0),
value2: SubproblemValue::Float(2.0),
}),
IntegrationError::ValidationFailed(ValidationError::CriticalViolation {
constraint_info: "test constraint".to_string(),
}),
IntegrationError::ConstructionFailed(ConstructionError::InvalidAssignments),
IntegrationError::TimeoutExceeded,
IntegrationError::NoSolution,
];
for error in errors {
let display_string = format!("{}", error);
assert!(!display_string.is_empty());
}
}
#[test]
fn test_convenience_function() {
let (model, var_ids) = create_test_model();
let combined_solution = create_valid_combined_solution(&var_ids);
let partition_result = create_partition_result();
let result = integrate_subproblem_solution(&model, &combined_solution, &partition_result);
assert!(result.is_ok());
let integrated = result.unwrap();
assert!(integrated.is_fully_validated);
assert_eq!(integrated.variable_assignments.len(), 4);
}
#[test]
fn test_performance_characteristics() {
let (model, var_ids) = create_test_model();
let combined_solution = create_valid_combined_solution(&var_ids);
let partition_result = create_partition_result();
let integrator = SolutionIntegrator::new();
let start_time = std::time::Instant::now();
let result = integrator.integrate_solution(&model, &combined_solution, &partition_result);
let elapsed = start_time.elapsed();
assert!(result.is_ok());
let integrated = result.unwrap();
assert!(elapsed < Duration::from_millis(50)); assert!(integrated.integration_time < Duration::from_millis(10));
println!("Step 6.4 Performance:");
println!(" Integration time: {:?}", integrated.integration_time);
println!(" Variables integrated: {}", integrated.variable_assignments.len());
println!(" Validation issues: {}", integrated.validation_issues.len());
println!(" Constraints validated: {}", integrated.constraints_validated);
println!(" Fully validated: {}", integrated.is_fully_validated);
}
#[test]
fn test_solution_object_creation() {
let (model, var_ids) = create_test_model();
let combined_solution = create_valid_combined_solution(&var_ids);
let partition_result = create_partition_result();
let integrator = SolutionIntegrator::new();
let result = integrator.integrate_solution(&model, &combined_solution, &partition_result);
assert!(result.is_ok());
let integrated = result.unwrap();
let solution = integrated.solution;
assert_eq!(solution[var_ids[0]], Val::ValF(5.0));
assert_eq!(solution[var_ids[1]], Val::ValI(3));
assert_eq!(solution[var_ids[2]], Val::ValF(0.5));
assert_eq!(solution[var_ids[3]], Val::ValI(15));
}
}