//! Basic NMF usage example //! //! This example demonstrates the basic usage of the RTX-NMF crate //! for matrix decomposition with both synthetic data and image-like data. use rtx_nmf::{Device, NMFConfig, NMFDecomposer, Tensor, demo::NMFDemo}; fn main() -> Result<(), Box> { println!("šŸš€ RTX-NMF Basic Usage Example"); println!("==============================\n"); // Initialize device (GPU if available, CPU fallback) let device = Device::cuda(0).unwrap_or_else(|_| { println!("āš ļø CUDA not available, using CPU"); Device::cpu() }); println!("šŸ”§ Using device: {:?}\n", device); // Example 1: Basic matrix decomposition basic_matrix_example(&device)?; // Example 2: Image decomposition demo image_decomposition_demo(&device)?; // Example 3: Faces decomposition demo faces_decomposition_demo(&device)?; println!("\nšŸŽ‰ All examples completed successfully!"); Ok(()) } fn basic_matrix_example(device: &Device) -> Result<(), Box> { println!("šŸ“Š Example 1: Basic Matrix Decomposition"); println!("-----------------------------------------"); // Create a simple non-negative matrix let matrix_data = vec![ 1.0, 2.0, 3.0, 4.0, 2.0, 4.0, 6.0, 8.0, 3.0, 6.0, 9.0, 12.0, 1.0, 3.0, 5.0, 7.0, 2.0, 5.0, 8.0, 11.0, ]; let matrix = Tensor::from_data(matrix_data, [5, 4], device)?; println!("Input matrix shape: {:?}", matrix.shape()); // Configure NMF let config = NMFConfig::new() .with_components(2) .with_max_iterations(100) .with_tolerance(1e-5); println!("NMF configuration:"); println!(" Components: {}", config.components()); println!(" Max iterations: {}", config.max_iterations()); println!(" Tolerance: {:.0e}", config.tolerance()); // Run decomposition let mut decomposer = NMFDecomposer::new(config); println!("\n⚔ Running NMF decomposition..."); let result = decomposer.fit_transform_detailed(&matrix)?; println!("āœ… Decomposition completed!"); println!(" W matrix shape: {:?}", result.w.shape()); println!(" H matrix shape: {:?}", result.h.shape()); println!(" Iterations: {}", result.iterations); println!(" Converged: {}", result.converged); println!(" Reconstruction error: {:.6}", result.reconstruction_error); println!(" Computation time: {:.3}s", result.computation_time); // Verify reconstruction let reconstruction = result.reconstruct()?; let reconstruction_error = result.calculate_error(&matrix)?; println!(" Verification error: {:.6}\n", reconstruction_error); Ok(()) } fn image_decomposition_demo(device: &Device) -> Result<(), Box> { println!("šŸ–¼ļø Example 2: Image Decomposition Demo"); println!("---------------------------------------"); let mut demo = NMFDemo::new(device.clone()); // Run image demo with a small image let result = demo.run_image_demo(32, 24)?; println!("Demo summary: {}", result.format_summary()); // Show performance metrics println!("Performance metrics:"); let metrics = demo.get_performance_metrics(); for (key, value) in metrics { println!(" {}: {}", key, value); } println!(); Ok(()) } fn faces_decomposition_demo(device: &Device) -> Result<(), Box> { println!("šŸ‘„ Example 3: Faces Decomposition Demo"); println!("---------------------------------------"); let mut demo = NMFDemo::new(device.clone()); // Run faces demo with small face images let result = demo.run_faces_demo(8, 16, 16)?; println!("Faces demo summary: {}", result.format_summary()); println!("Face basis components found:"); println!(" Original faces: {:?}", result.original_image.shape); println!(" Basis matrix W: {:?}", result.w_matrix.shape); println!(" Coefficients H: {:?}", result.h_matrix.shape); println!( " Each face can be reconstructed as a linear combination of {} basis faces", result.components ); println!(); Ok(()) } #[cfg(test)] mod tests { use super::*; #[test] fn test_basic_example() { let device = Device::cpu(); assert!(basic_matrix_example(&device).is_ok()); } #[test] fn test_image_demo() { let device = Device::cpu(); assert!(image_decomposition_demo(&device).is_ok()); } #[test] fn test_faces_demo() { let device = Device::cpu(); assert!(faces_decomposition_demo(&device).is_ok()); } }