use vecstore::autotuning::{AutoTuner, PerformanceConstraints, TuningGoal};
fn main() {
println!("🎯 HNSW Auto-tuning Example\n");
println!("📊 Basic Auto-tuning:");
println!("═══════════════════════\n");
let dimension = 384; let num_vectors = 100_000;
let tuner = AutoTuner::new(dimension, num_vectors);
println!("Dataset characteristics:");
println!(" - Dimension: {}", dimension);
println!(" - Number of vectors: {}\n", num_vectors);
println!("\n🎯 Tuning Goals:");
println!("═══════════════\n");
println!("1. FAST (Minimize Latency):");
let fast = tuner.tune_heuristic(TuningGoal::MinLatency, None).unwrap();
println!(" M: {}", fast.m);
println!(" ef_construction: {}", fast.ef_construction);
println!(" ef_search: {}", fast.ef_search);
if let Some(recall) = fast.estimated_recall {
println!(" Estimated recall: {:.1}%", recall * 100.0);
}
if let Some(latency) = fast.estimated_latency_ms {
println!(" Estimated latency: {:.2}ms", latency);
}
if let Some(memory) = fast.estimated_memory_mb {
println!(" Estimated memory: {:.1} MB", memory);
}
println!("\n2. BALANCED:");
let balanced = tuner.tune_heuristic(TuningGoal::Balanced, None).unwrap();
println!(" M: {}", balanced.m);
println!(" ef_construction: {}", balanced.ef_construction);
println!(" ef_search: {}", balanced.ef_search);
if let Some(recall) = balanced.estimated_recall {
println!(" Estimated recall: {:.1}%", recall * 100.0);
}
if let Some(latency) = balanced.estimated_latency_ms {
println!(" Estimated latency: {:.2}ms", latency);
}
if let Some(memory) = balanced.estimated_memory_mb {
println!(" Estimated memory: {:.1} MB", memory);
}
println!("\n3. ACCURATE (Maximize Recall):");
let accurate = tuner.tune_heuristic(TuningGoal::MaxRecall, None).unwrap();
println!(" M: {}", accurate.m);
println!(" ef_construction: {}", accurate.ef_construction);
println!(" ef_search: {}", accurate.ef_search);
if let Some(recall) = accurate.estimated_recall {
println!(" Estimated recall: {:.1}%", recall * 100.0);
}
if let Some(latency) = accurate.estimated_latency_ms {
println!(" Estimated latency: {:.2}ms", latency);
}
if let Some(memory) = accurate.estimated_memory_mb {
println!(" Estimated memory: {:.1} MB", memory);
}
println!("\n4. MEMORY-EFFICIENT:");
let memory_efficient = tuner.tune_heuristic(TuningGoal::MinMemory, None).unwrap();
println!(" M: {}", memory_efficient.m);
println!(" ef_construction: {}", memory_efficient.ef_construction);
println!(" ef_search: {}", memory_efficient.ef_search);
if let Some(recall) = memory_efficient.estimated_recall {
println!(" Estimated recall: {:.1}%", recall * 100.0);
}
if let Some(latency) = memory_efficient.estimated_latency_ms {
println!(" Estimated latency: {:.2}ms", latency);
}
if let Some(memory) = memory_efficient.estimated_memory_mb {
println!(" Estimated memory: {:.1} MB", memory);
}
println!("\n\n⚖️ Tuning with Constraints:");
println!("═══════════════════════════\n");
let constraints = PerformanceConstraints {
min_recall: 0.95, max_latency_ms: 5.0, max_memory_mb: 500.0, };
println!("Constraints:");
println!(" - Minimum recall: {:.0}%", constraints.min_recall * 100.0);
println!(" - Maximum latency: {:.1}ms", constraints.max_latency_ms);
println!(" - Maximum memory: {:.0} MB\n", constraints.max_memory_mb);
let constrained = tuner
.tune_heuristic(TuningGoal::Balanced, Some(constraints))
.unwrap();
println!("Constrained parameters:");
println!(" M: {}", constrained.m);
println!(" ef_construction: {}", constrained.ef_construction);
println!(" ef_search: {}", constrained.ef_search);
if let Some(recall) = constrained.estimated_recall {
println!(" Estimated recall: {:.1}% ✓", recall * 100.0);
}
if let Some(latency) = constrained.estimated_latency_ms {
let status = if latency <= 5.0 { "✓" } else { "✗" };
println!(" Estimated latency: {:.2}ms {}", latency, status);
}
if let Some(memory) = constrained.estimated_memory_mb {
let status = if memory <= 500.0 { "✓" } else { "✗" };
println!(" Estimated memory: {:.1} MB {}", memory, status);
}
println!("\n\n📏 Dataset Size Impact:");
println!("═══════════════════════\n");
let datasets = vec![
("Small (1K vectors)", 1_000),
("Medium (50K vectors)", 50_000),
("Large (500K vectors)", 500_000),
("Very Large (5M vectors)", 5_000_000),
];
for (name, count) in datasets {
println!("{}:", name);
let dataset_tuner = AutoTuner::new(384, count);
let params = dataset_tuner
.tune_heuristic(TuningGoal::Balanced, None)
.unwrap();
println!(
" M={}, ef_construction={}, ef_search={}",
params.m, params.ef_construction, params.ef_search
);
if let (Some(latency), Some(memory)) =
(params.estimated_latency_ms, params.estimated_memory_mb)
{
println!(" ~{:.2}ms latency, ~{:.0} MB memory", latency, memory);
}
println!();
}
println!("\n📐 Dimension Impact:");
println!("══════════════════\n");
let dimensions = vec![
("Small (128-dim)", 128),
("Medium (384-dim)", 384),
("Large (768-dim)", 768),
("Very Large (1536-dim)", 1536),
];
for (name, dim) in dimensions {
println!("{}:", name);
let dim_tuner = AutoTuner::new(dim, 100_000);
let params = dim_tuner
.tune_heuristic(TuningGoal::Balanced, None)
.unwrap();
if let (Some(latency), Some(memory)) =
(params.estimated_latency_ms, params.estimated_memory_mb)
{
println!(" ~{:.2}ms latency, ~{:.0} MB memory", latency, memory);
}
println!();
}
println!("\n💡 All Recommendations:");
println!("═══════════════════════\n");
let recommendations = tuner.recommend_all();
for (name, params) in &recommendations {
println!("{}:", name);
println!(
" M={}, ef_construction={}, ef_search={}",
params.m, params.ef_construction, params.ef_search
);
if let Some(recall) = params.estimated_recall {
println!(" Recall: {:.1}%", recall * 100.0);
}
if let Some(latency) = params.estimated_latency_ms {
println!(" Latency: {:.2}ms", latency);
}
if let Some(memory) = params.estimated_memory_mb {
println!(" Memory: {:.1} MB", memory);
}
println!();
}
println!("\n📖 Parameter Explanation:");
println!("═════════════════════════\n");
let params = tuner.tune_heuristic(TuningGoal::Balanced, None).unwrap();
let explanation = tuner.explain_params(¶ms);
println!("{}", explanation);
println!("\n🌍 Real-world Scenarios:");
println!("═══════════════════════\n");
println!("1. E-commerce Product Search (1M products, fast search required):");
let ecommerce_tuner = AutoTuner::new(384, 1_000_000);
let ecommerce_constraints = PerformanceConstraints {
min_recall: 0.90, max_latency_ms: 20.0, max_memory_mb: 2000.0, };
let ecommerce = ecommerce_tuner
.tune_heuristic(TuningGoal::MinLatency, Some(ecommerce_constraints))
.unwrap();
println!(
" Recommended: M={}, ef_construction={}, ef_search={}",
ecommerce.m, ecommerce.ef_construction, ecommerce.ef_search
);
if let Some(latency) = ecommerce.estimated_latency_ms {
println!(" Expected latency: {:.2}ms", latency);
}
println!("\n2. Medical Document Search (100K docs, high accuracy required):");
let medical_tuner = AutoTuner::new(768, 100_000);
let medical_constraints = PerformanceConstraints {
min_recall: 0.98, max_latency_ms: 50.0, max_memory_mb: 1000.0,
};
let medical = medical_tuner
.tune_heuristic(TuningGoal::MaxRecall, Some(medical_constraints))
.unwrap();
println!(
" Recommended: M={}, ef_construction={}, ef_search={}",
medical.m, medical.ef_construction, medical.ef_search
);
if let Some(recall) = medical.estimated_recall {
println!(" Expected recall: {:.1}%", recall * 100.0);
}
println!("\n3. Mobile App Vector Search (10K items, memory constrained):");
let mobile_tuner = AutoTuner::new(128, 10_000);
let mobile_constraints = PerformanceConstraints {
min_recall: 0.92,
max_latency_ms: 10.0,
max_memory_mb: 50.0, };
let mobile = mobile_tuner
.tune_heuristic(TuningGoal::MinMemory, Some(mobile_constraints))
.unwrap();
println!(
" Recommended: M={}, ef_construction={}, ef_search={}",
mobile.m, mobile.ef_construction, mobile.ef_search
);
if let Some(memory) = mobile.estimated_memory_mb {
println!(" Expected memory: {:.1} MB", memory);
}
println!("\n\n🔧 Integration with VecStore:");
println!("═════════════════════════════\n");
println!("Example code:");
println!(
r#"
use vecstore::{{VecStoreBuilder, autotuning::{{AutoTuner, TuningGoal}}}};
// Auto-tune parameters
let tuner = AutoTuner::new(384, 100_000);
let params = tuner.tune_heuristic(TuningGoal::Balanced, None)?;
// Build VecStore with tuned parameters
let store = VecStoreBuilder::new()
.dimension(384)
.hnsw_m(params.m)
.hnsw_ef_construction(params.ef_construction)
.hnsw_ef_search(params.ef_search)
.build("vectors.db")?;
"#
);
println!("\n✅ Auto-tuning example complete!\n");
println!("💡 Key Takeaways:");
println!(" - Use MinLatency for real-time search");
println!(" - Use MaxRecall for high-precision applications");
println!(" - Use MinMemory for resource-constrained environments");
println!(" - Use Balanced for general-purpose search");
println!(" - Always specify constraints for production use");
println!(" - Larger datasets need lower M to save memory");
println!(" - Higher dimensions increase latency and memory");
}