#[cfg(test)]
mod tests {
use super::*;
use torsh_core::device::DeviceType;
use torsh_tensor::creation::*;
#[test]
fn test_gradient_descent_quadratic() {
let objective = |x: &Tensor| -> TorshResult<f32> {
let data = x.data()?;
let val = data[0];
Ok((val - 2.0).powi(2) + 1.0)
};
let gradient = |x: &Tensor| -> TorshResult<Tensor> {
let data = x.data()?;
let val = data[0];
let grad_val = 2.0 * (val - 2.0);
Ok(from_vec(vec![grad_val], &[1], DeviceType::Cpu)?)
};
let x0 = from_vec(vec![0.0], &[1], DeviceType::Cpu).expect("from vec should succeed");
let params = GradientDescentParams {
learning_rate: 0.1,
max_iter: 100,
tolerance: 1e-6,
line_search: None,
};
let (x_opt, _) = gradient_descent(objective, gradient, &x0, Some(params)).expect("operation should succeed");
let result = x_opt.data().expect("tensor data should be accessible")[0];
assert!(
(result - 2.0).abs() < 1e-3,
"Expected result to be close to 2.0, got {}",
result
);
}
#[test]
fn test_backtracking_line_search() {
let objective = |x: &Tensor| -> TorshResult<f32> {
let data = x.data()?;
Ok(data[0].powi(2))
};
let gradient = |x: &Tensor| -> TorshResult<Tensor> {
let data = x.data()?;
Ok(from_vec(vec![2.0 * data[0]], &[1], DeviceType::Cpu)?)
};
let x = from_vec(vec![1.0], &[1], DeviceType::Cpu).expect("from vec should succeed");
let p = from_vec(vec![-1.0], &[1], DeviceType::Cpu).expect("from vec should succeed");
let alpha = backtracking_line_search(objective, gradient, &x, &p, None).expect("backtracking line search should succeed");
assert!(alpha > 0.0 && alpha <= 1.0);
}
#[test]
fn test_momentum_gradient_descent() {
let objective = |x: &Tensor| -> TorshResult<f32> {
let data = x.data()?;
let val = data[0];
Ok(val.powi(2))
};
let gradient = |x: &Tensor| -> TorshResult<Tensor> {
let data = x.data()?;
Ok(from_vec(vec![2.0 * data[0]], &[1], DeviceType::Cpu)?)
};
let x0 = from_vec(vec![1.0], &[1], DeviceType::Cpu).expect("from vec should succeed");
let params = MomentumParams {
learning_rate: 0.1,
momentum: 0.9,
max_iter: 50,
tolerance: 1e-6,
};
let (x_opt, _) = momentum_gradient_descent(objective, gradient, &x0, Some(params)).expect("operation should succeed");
let result = x_opt.data().expect("tensor data should be accessible")[0];
assert!(
(result - 0.0).abs() < 1e-1,
"Expected result to be close to 0.0, got {}",
result
);
}
#[test]
fn test_tensor_characteristics_analysis() {
let tensor = from_vec(vec![1.0, 0.0, 3.0, 0.0, 5.0], &[5], DeviceType::Cpu).expect("from vec should succeed");
let characteristics = TensorCharacteristics::analyze(&tensor).expect("Tensor Characteristics should succeed");
assert_eq!(characteristics.size, 5);
assert_eq!(characteristics.sparsity, 0.4); assert!(characteristics.condition_number > 1.0);
}
#[test]
fn test_adaptive_algorithm_selector() {
let selector = AdaptiveAlgorithmSelector::new();
let sparse_characteristics = TensorCharacteristics {
size: 1000,
condition_number: 100.0,
sparsity: 0.9,
numerical_precision: 0.5,
memory_layout_score: 0.8,
computational_complexity: 1000.0,
};
let algorithm = selector.select_algorithm(&sparse_characteristics);
assert!(matches!(
algorithm,
OptimizationAlgorithm::ConjugateGradient
));
let large_characteristics = TensorCharacteristics {
size: 2_000_000,
condition_number: 50.0,
sparsity: 0.1,
numerical_precision: 1.0,
memory_layout_score: 0.8,
computational_complexity: 2_000_000.0,
};
let algorithm = selector.select_algorithm(&large_characteristics);
assert!(matches!(algorithm, OptimizationAlgorithm::LBFGS));
}
#[test]
fn test_adaptive_selector_learning() {
let mut selector = AdaptiveAlgorithmSelector::new();
selector.record_performance(&OptimizationAlgorithm::Adam, 0.2);
selector.record_performance(&OptimizationAlgorithm::Adam, 0.1);
selector.record_performance(&OptimizationAlgorithm::MomentumGradientDescent, 0.8);
selector.record_performance(&OptimizationAlgorithm::MomentumGradientDescent, 0.9);
let adam_score = selector.get_algorithm_score(&OptimizationAlgorithm::Adam);
let momentum_score =
selector.get_algorithm_score(&OptimizationAlgorithm::MomentumGradientDescent);
assert!(momentum_score > adam_score);
}
#[test]
fn test_optimization_problem_analysis() {
let objective_values = vec![10.0, 9.0, 8.5, 8.3, 8.29, 8.289];
let gradient_norms = vec![1.0, 0.8, 0.6, 0.4, 0.2, 0.1];
let characteristics = TensorCharacteristics {
size: 1000,
condition_number: 200.0,
sparsity: 0.1,
numerical_precision: 0.8,
memory_layout_score: 0.8,
computational_complexity: 1000.0,
};
let (algorithm, recommendation) =
analyze_optimization_problem(&objective_values, &gradient_norms, &characteristics);
assert!(matches!(
algorithm,
OptimizationAlgorithm::MomentumGradientDescent
));
assert!(recommendation.contains("MomentumGradientDescent"));
}
#[test]
fn test_auto_configure_optimization() {
let characteristics = TensorCharacteristics {
size: 10_000,
condition_number: 50.0,
sparsity: 0.1,
numerical_precision: 1.0,
memory_layout_score: 0.8,
computational_complexity: 10_000.0,
};
let config =
auto_configure_optimization(&characteristics, &OptimizationAlgorithm::Adam).expect("auto configure optimization should succeed");
assert!(config.contains("AdamParams"));
assert!(config.contains("learning_rate"));
let momentum_config = auto_configure_optimization(
&characteristics,
&OptimizationAlgorithm::MomentumGradientDescent,
)
.expect("operation should succeed");
assert!(momentum_config.contains("MomentumParams"));
assert!(momentum_config.contains("momentum"));
}
}