1pub mod config;
8pub mod features;
9pub mod multi_objective;
10pub mod nas;
11pub mod portfolio;
12pub mod transfer_learning;
13
14use std::collections::{HashMap, VecDeque};
15use std::sync::{Arc, Mutex, RwLock};
16use std::time::{Duration, Instant};
17
18use crate::applications::{ApplicationError, ApplicationResult};
19use crate::ising::IsingModel;
20use crate::simulator::{AnnealingParams, AnnealingResult, QuantumAnnealingSimulator};
21
22pub use config::{
24 ActivationFunction, AlgorithmType, ArchitectureSpec, ConnectionPattern,
25 FeatureExtractionConfig, LayerSpec, LayerType, MetaLearningConfig, MultiObjectiveConfig,
26 NeuralArchitectureSearchConfig, OptimizationConfiguration, OptimizationSettings, OptimizerType,
27 PortfolioManagementConfig, ProblemDomain, RegularizationConfig, ResourceAllocation,
28};
29pub use features::{
30 CorrelationFeatures, FeatureExtractor, GraphFeatures, ProblemFeatures, SpectralFeatures,
31 StatisticalFeatures,
32};
33pub use multi_objective::{MultiObjectiveOptimizer, MultiObjectiveSolution, ParetoFrontier};
34pub use nas::{NeuralArchitectureSearch, PerformancePredictor};
35pub use portfolio::{Algorithm, AlgorithmPortfolio, GuaranteeType, ResourceRequirements};
36pub use transfer_learning::{SourceDomain, TransferLearner, TransferResult, TransferStrategy};
37
38pub struct MetaLearningOptimizer {
40 pub config: MetaLearningConfig,
42 pub experience_db: Arc<RwLock<ExperienceDatabase>>,
44 pub feature_extractor: Arc<Mutex<FeatureExtractor>>,
46 pub meta_learner: Arc<Mutex<MetaLearner>>,
48 pub nas_engine: Arc<Mutex<NeuralArchitectureSearch>>,
50 pub portfolio_manager: Arc<Mutex<AlgorithmPortfolio>>,
52 pub multi_objective_optimizer: Arc<Mutex<MultiObjectiveOptimizer>>,
54 pub transfer_learner: Arc<Mutex<TransferLearner>>,
56}
57
58#[derive(Debug, Clone)]
60pub struct OptimizationExperience {
61 pub id: String,
63 pub problem_features: ProblemFeatures,
65 pub configuration: OptimizationConfiguration,
67 pub results: OptimizationResults,
69 pub timestamp: Instant,
71 pub domain: ProblemDomain,
73 pub success_metrics: SuccessMetrics,
75}
76
77#[derive(Debug, Clone)]
79pub struct OptimizationResults {
80 pub objective_values: Vec<f64>,
82 pub execution_time: Duration,
84 pub resource_usage: ResourceUsage,
86 pub convergence: ConvergenceMetrics,
88 pub quality_metrics: QualityMetrics,
90}
91
92#[derive(Debug, Clone)]
94pub struct ResourceUsage {
95 pub peak_cpu: f64,
97 pub peak_memory: usize,
99 pub gpu_utilization: f64,
101 pub energy_consumption: f64,
103}
104
105#[derive(Debug, Clone)]
107pub struct ConvergenceMetrics {
108 pub iterations: usize,
110 pub convergence_rate: f64,
112 pub plateau_detected: bool,
114 pub confidence: f64,
116}
117
118#[derive(Debug, Clone)]
120pub struct QualityMetrics {
121 pub objective_value: f64,
123 pub constraint_violation: f64,
125 pub robustness: f64,
127 pub diversity: f64,
129}
130
131#[derive(Debug, Clone)]
133pub struct SuccessMetrics {
134 pub success_score: f64,
136 pub relative_performance: f64,
138 pub user_satisfaction: f64,
140 pub recommendation_confidence: f64,
142}
143
144pub struct ExperienceDatabase {
146 pub experiences: VecDeque<OptimizationExperience>,
148 pub index: ExperienceIndex,
150 pub similarity_cache: HashMap<String, Vec<(String, f64)>>,
152 pub statistics: DatabaseStatistics,
154}
155
156#[derive(Debug)]
158pub struct ExperienceIndex {
159 pub domain_index: HashMap<ProblemDomain, Vec<String>>,
161 pub size_index: std::collections::BTreeMap<usize, Vec<String>>,
163 pub performance_index: std::collections::BTreeMap<String, Vec<String>>,
165 pub feature_index: HashMap<String, Vec<String>>,
167}
168
169#[derive(Debug, Clone)]
171pub struct DatabaseStatistics {
172 pub total_experiences: usize,
174 pub domain_distribution: HashMap<ProblemDomain, usize>,
176 pub avg_performance: f64,
178 pub coverage_stats: CoverageStatistics,
180}
181
182#[derive(Debug, Clone)]
184pub struct CoverageStatistics {
185 pub feature_coverage: f64,
187 pub size_coverage: (usize, usize),
189 pub domain_coverage: f64,
191 pub performance_range: (f64, f64),
193}
194
195pub struct MetaLearner {
197 pub algorithm: MetaLearningAlgorithm,
199 pub parameters: Vec<f64>,
201 pub training_history: VecDeque<TrainingEpisode>,
203 pub evaluator: PerformanceEvaluator,
205}
206
207#[derive(Debug, Clone, PartialEq, Eq)]
209pub enum MetaLearningAlgorithm {
210 MAML,
212 PrototypicalNetworks,
214 MatchingNetworks,
216 RelationNetworks,
218 MemoryAugmented,
220 GradientBased,
222}
223
224#[derive(Debug, Clone)]
226pub struct TrainingEpisode {
227 pub id: String,
229 pub support_set: Vec<OptimizationExperience>,
231 pub query_set: Vec<OptimizationExperience>,
233 pub loss: f64,
235 pub accuracy: f64,
237 pub timestamp: Instant,
239}
240
241#[derive(Debug)]
243pub struct PerformanceEvaluator {
244 pub metrics: Vec<EvaluationMetric>,
246 pub cv_strategy: CrossValidationStrategy,
248 pub statistical_tests: Vec<StatisticalTest>,
250}
251
252#[derive(Debug, Clone, PartialEq, Eq)]
254pub enum EvaluationMetric {
255 MeanSquaredError,
257 MeanAbsoluteError,
259 RSquared,
261 Accuracy,
263 Precision,
265 Recall,
267 F1Score,
269 Custom(String),
271}
272
273#[derive(Debug, Clone, PartialEq, Eq)]
275pub enum CrossValidationStrategy {
276 KFold(usize),
278 LeaveOneOut,
280 TimeSeriesSplit,
282 StratifiedKFold(usize),
284 Custom(String),
286}
287
288#[derive(Debug, Clone, PartialEq, Eq)]
290pub enum StatisticalTest {
291 TTest,
293 WilcoxonSignedRank,
295 MannWhitneyU,
297 KolmogorovSmirnov,
299 ChiSquare,
301}
302
303#[derive(Debug, Clone)]
305pub struct RecommendedStrategy {
306 pub confidence: f64,
308 pub configuration: OptimizationConfiguration,
310 pub expected_performance: f64,
312 pub reasoning: String,
314 pub alternatives: Vec<AlternativeStrategy>,
316}
317
318#[derive(Debug, Clone)]
320pub struct AlternativeStrategy {
321 pub configuration: OptimizationConfiguration,
323 pub confidence: f64,
325 pub trade_offs: String,
327}
328
329#[derive(Debug, Clone)]
331pub struct MetaOptimizationResult {
332 pub problem_features: ProblemFeatures,
334 pub recommended_strategy: RecommendedStrategy,
336 pub optimization_result: OptimizationResults,
338 pub similar_experiences: usize,
340 pub architecture_used: Option<ArchitectureSpec>,
342 pub meta_learning_overhead: Duration,
344 pub confidence: f64,
346}
347
348#[derive(Debug, Clone)]
350pub struct MetaLearningStatistics {
351 pub total_experiences: usize,
353 pub average_performance: f64,
355 pub domain_coverage: usize,
357 pub feature_coverage: f64,
359 pub meta_learning_accuracy: f64,
361 pub transfer_learning_success_rate: f64,
363}
364
365impl MetaLearningOptimizer {
366 #[must_use]
368 pub fn new(config: MetaLearningConfig) -> Self {
369 Self {
370 config: config.clone(),
371 experience_db: Arc::new(RwLock::new(ExperienceDatabase::new())),
372 feature_extractor: Arc::new(Mutex::new(FeatureExtractor::new(
373 config.feature_config.clone(),
374 ))),
375 meta_learner: Arc::new(Mutex::new(MetaLearner::new())),
376 nas_engine: Arc::new(Mutex::new(NeuralArchitectureSearch::new(
377 config.nas_config.clone(),
378 ))),
379 portfolio_manager: Arc::new(Mutex::new(AlgorithmPortfolio::new(
380 config.portfolio_config.clone(),
381 ))),
382 multi_objective_optimizer: Arc::new(Mutex::new(MultiObjectiveOptimizer::new(
383 config.multi_objective_config,
384 ))),
385 transfer_learner: Arc::new(Mutex::new(TransferLearner::new())),
386 }
387 }
388
389 pub fn optimize(&self, problem: &IsingModel) -> ApplicationResult<MetaOptimizationResult> {
391 println!(
392 "Starting meta-learning optimization for problem with {} qubits",
393 problem.num_qubits
394 );
395
396 let start_time = Instant::now();
397
398 let problem_features = self.extract_problem_features(problem)?;
400
401 let similar_experiences = self.find_similar_experiences(&problem_features)?;
403
404 let recommended_strategy =
406 self.recommend_strategy(&problem_features, &similar_experiences)?;
407
408 let optimized_architecture = if self.config.nas_config.enable_nas {
410 Some(self.search_optimal_architecture(&problem_features)?)
411 } else {
412 None
413 };
414
415 let optimization_result = self.execute_optimization(
417 problem,
418 &recommended_strategy,
419 optimized_architecture.as_ref(),
420 )?;
421
422 self.store_experience(
424 problem,
425 &problem_features,
426 &recommended_strategy,
427 &optimization_result,
428 )?;
429
430 self.update_meta_learner(&problem_features, &optimization_result)?;
432
433 let total_time = start_time.elapsed();
434
435 println!("Meta-learning optimization completed in {total_time:?}");
436
437 Ok(MetaOptimizationResult {
438 problem_features,
439 recommended_strategy,
440 optimization_result,
441 similar_experiences: similar_experiences.len(),
442 architecture_used: optimized_architecture,
443 meta_learning_overhead: total_time,
444 confidence: 0.85,
445 })
446 }
447
448 fn extract_problem_features(&self, problem: &IsingModel) -> ApplicationResult<ProblemFeatures> {
450 let mut feature_extractor = self.feature_extractor.lock().map_err(|_| {
451 ApplicationError::OptimizationError(
452 "Failed to acquire feature extractor lock".to_string(),
453 )
454 })?;
455
456 feature_extractor.extract_features(problem)
457 }
458
459 fn find_similar_experiences(
461 &self,
462 features: &ProblemFeatures,
463 ) -> ApplicationResult<Vec<OptimizationExperience>> {
464 let experience_db = self.experience_db.read().map_err(|_| {
465 ApplicationError::OptimizationError(
466 "Failed to acquire experience database lock".to_string(),
467 )
468 })?;
469
470 experience_db.find_similar_experiences(features, 10)
471 }
472
473 fn recommend_strategy(
475 &self,
476 features: &ProblemFeatures,
477 experiences: &[OptimizationExperience],
478 ) -> ApplicationResult<RecommendedStrategy> {
479 let mut meta_learner = self.meta_learner.lock().map_err(|_| {
480 ApplicationError::OptimizationError("Failed to acquire meta-learner lock".to_string())
481 })?;
482
483 meta_learner.recommend_strategy(features, experiences)
484 }
485
486 fn search_optimal_architecture(
488 &self,
489 features: &ProblemFeatures,
490 ) -> ApplicationResult<ArchitectureSpec> {
491 let mut nas_engine = self.nas_engine.lock().map_err(|_| {
492 ApplicationError::OptimizationError("Failed to acquire NAS engine lock".to_string())
493 })?;
494
495 nas_engine.search_architecture(features)
496 }
497
498 fn execute_optimization(
500 &self,
501 problem: &IsingModel,
502 strategy: &RecommendedStrategy,
503 architecture: Option<&ArchitectureSpec>,
504 ) -> ApplicationResult<OptimizationResults> {
505 let mut params = AnnealingParams::new();
507
508 if let Some(temp) = strategy
510 .configuration
511 .hyperparameters
512 .get("initial_temperature")
513 {
514 params.initial_temperature = *temp;
515 }
516 if let Some(temp) = strategy
517 .configuration
518 .hyperparameters
519 .get("final_temperature")
520 {
521 params.final_temperature = *temp;
522 }
523 if let Some(sweeps) = strategy.configuration.hyperparameters.get("num_sweeps") {
524 params.num_sweeps = *sweeps as usize;
525 }
526
527 params.seed = Some(42);
528
529 let start_time = Instant::now();
530
531 let mut simulator = QuantumAnnealingSimulator::new(params)?;
533 let result = simulator.solve(problem)?;
534
535 let execution_time = start_time.elapsed();
536
537 let objective_value = result.best_energy;
539 let quality_score = 1.0 / (1.0 + objective_value.abs());
540
541 Ok(OptimizationResults {
542 objective_values: vec![objective_value],
543 execution_time,
544 resource_usage: ResourceUsage {
545 peak_cpu: 0.8,
546 peak_memory: 512,
547 gpu_utilization: 0.0,
548 energy_consumption: execution_time.as_secs_f64() * 100.0,
549 },
550 convergence: ConvergenceMetrics {
551 iterations: 1000,
552 convergence_rate: 0.95,
553 plateau_detected: false,
554 confidence: 0.9,
555 },
556 quality_metrics: QualityMetrics {
557 objective_value,
558 constraint_violation: 0.0,
559 robustness: 0.85,
560 diversity: 0.7,
561 },
562 })
563 }
564
565 fn store_experience(
567 &self,
568 problem: &IsingModel,
569 features: &ProblemFeatures,
570 strategy: &RecommendedStrategy,
571 result: &OptimizationResults,
572 ) -> ApplicationResult<()> {
573 let mut experience_db = self.experience_db.write().map_err(|_| {
574 ApplicationError::OptimizationError(
575 "Failed to acquire experience database lock".to_string(),
576 )
577 })?;
578
579 let experience = OptimizationExperience {
580 id: format!("exp_{}", Instant::now().elapsed().as_nanos()),
581 problem_features: features.clone(),
582 configuration: strategy.configuration.clone(),
583 results: result.clone(),
584 timestamp: Instant::now(),
585 domain: ProblemDomain::Combinatorial,
586 success_metrics: SuccessMetrics {
587 success_score: result.quality_metrics.objective_value,
588 relative_performance: 1.0,
589 user_satisfaction: 0.8,
590 recommendation_confidence: strategy.confidence,
591 },
592 };
593
594 experience_db.add_experience(experience);
595 Ok(())
596 }
597
598 fn update_meta_learner(
600 &self,
601 features: &ProblemFeatures,
602 result: &OptimizationResults,
603 ) -> ApplicationResult<()> {
604 let mut meta_learner = self.meta_learner.lock().map_err(|_| {
605 ApplicationError::OptimizationError("Failed to acquire meta-learner lock".to_string())
606 })?;
607
608 meta_learner.update_with_experience(features, result);
609 Ok(())
610 }
611
612 pub fn get_statistics(&self) -> ApplicationResult<MetaLearningStatistics> {
614 let experience_db = self.experience_db.read().map_err(|_| {
615 ApplicationError::OptimizationError(
616 "Failed to acquire experience database lock".to_string(),
617 )
618 })?;
619
620 Ok(MetaLearningStatistics {
621 total_experiences: experience_db.statistics.total_experiences,
622 average_performance: experience_db.statistics.avg_performance,
623 domain_coverage: experience_db.statistics.domain_distribution.len(),
624 feature_coverage: experience_db.statistics.coverage_stats.feature_coverage,
625 meta_learning_accuracy: 0.85,
626 transfer_learning_success_rate: 0.75,
627 })
628 }
629}
630
631impl ExperienceDatabase {
634 fn new() -> Self {
635 Self {
636 experiences: VecDeque::new(),
637 index: ExperienceIndex {
638 domain_index: HashMap::new(),
639 size_index: std::collections::BTreeMap::new(),
640 performance_index: std::collections::BTreeMap::new(),
641 feature_index: HashMap::new(),
642 },
643 similarity_cache: HashMap::new(),
644 statistics: DatabaseStatistics {
645 total_experiences: 0,
646 domain_distribution: HashMap::new(),
647 avg_performance: 0.0,
648 coverage_stats: CoverageStatistics {
649 feature_coverage: 0.0,
650 size_coverage: (0, 0),
651 domain_coverage: 0.0,
652 performance_range: (0.0, 1.0),
653 },
654 },
655 }
656 }
657
658 fn add_experience(&mut self, experience: OptimizationExperience) {
659 self.experiences.push_back(experience.clone());
660 self.update_index(&experience);
661 self.update_statistics();
662
663 if self.experiences.len() > 10_000 {
665 if let Some(removed) = self.experiences.pop_front() {
666 self.remove_from_index(&removed);
667 }
668 }
669 }
670
671 fn update_index(&mut self, experience: &OptimizationExperience) {
672 self.index
674 .domain_index
675 .entry(experience.domain.clone())
676 .or_insert_with(Vec::new)
677 .push(experience.id.clone());
678
679 self.index
681 .size_index
682 .entry(experience.problem_features.size)
683 .or_insert_with(Vec::new)
684 .push(experience.id.clone());
685 }
686
687 fn remove_from_index(&mut self, experience: &OptimizationExperience) {
688 if let Some(ids) = self.index.domain_index.get_mut(&experience.domain) {
690 ids.retain(|id| id != &experience.id);
691 }
692
693 if let Some(ids) = self
695 .index
696 .size_index
697 .get_mut(&experience.problem_features.size)
698 {
699 ids.retain(|id| id != &experience.id);
700 }
701 }
702
703 fn update_statistics(&mut self) {
704 self.statistics.total_experiences = self.experiences.len();
705
706 if !self.experiences.is_empty() {
707 let total_performance: f64 = self
708 .experiences
709 .iter()
710 .map(|exp| exp.results.quality_metrics.objective_value)
711 .sum();
712 self.statistics.avg_performance = total_performance / self.experiences.len() as f64;
713 }
714
715 self.statistics.domain_distribution.clear();
717 for experience in &self.experiences {
718 *self
719 .statistics
720 .domain_distribution
721 .entry(experience.domain.clone())
722 .or_insert(0) += 1;
723 }
724 }
725
726 fn find_similar_experiences(
727 &self,
728 features: &ProblemFeatures,
729 limit: usize,
730 ) -> ApplicationResult<Vec<OptimizationExperience>> {
731 let mut similarities = Vec::new();
732
733 for experience in &self.experiences {
734 let similarity = self.calculate_similarity(features, &experience.problem_features);
735 similarities.push((experience.clone(), similarity));
736 }
737
738 similarities.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
740
741 Ok(similarities
742 .into_iter()
743 .take(limit)
744 .map(|(exp, _)| exp)
745 .collect())
746 }
747
748 fn calculate_similarity(
749 &self,
750 features1: &ProblemFeatures,
751 features2: &ProblemFeatures,
752 ) -> f64 {
753 let size_diff = (features1.size as f64 - features2.size as f64).abs()
755 / features1.size.max(features2.size) as f64;
756 let density_diff = (features1.density - features2.density).abs();
757
758 let size_similarity = 1.0 - size_diff;
759 let density_similarity = 1.0 - density_diff;
760
761 f64::midpoint(size_similarity, density_similarity)
762 }
763}
764
765impl MetaLearner {
766 fn new() -> Self {
767 Self {
768 algorithm: MetaLearningAlgorithm::MAML,
769 parameters: Vec::new(),
770 training_history: VecDeque::new(),
771 evaluator: PerformanceEvaluator {
772 metrics: vec![
773 EvaluationMetric::MeanSquaredError,
774 EvaluationMetric::Accuracy,
775 ],
776 cv_strategy: CrossValidationStrategy::KFold(5),
777 statistical_tests: vec![StatisticalTest::TTest],
778 },
779 }
780 }
781
782 fn recommend_strategy(
783 &self,
784 features: &ProblemFeatures,
785 experiences: &[OptimizationExperience],
786 ) -> ApplicationResult<RecommendedStrategy> {
787 let algorithm = if features.size < 100 {
789 AlgorithmType::SimulatedAnnealing
790 } else if features.size < 500 {
791 AlgorithmType::QuantumAnnealing
792 } else {
793 AlgorithmType::Hybrid(vec![
794 AlgorithmType::QuantumAnnealing,
795 AlgorithmType::TabuSearch,
796 ])
797 };
798
799 let mut hyperparameters = HashMap::new();
800
801 if experiences.is_empty() {
803 hyperparameters.insert("initial_temperature".to_string(), 10.0);
805 hyperparameters.insert("final_temperature".to_string(), 0.1);
806 } else {
807 let avg_initial_temp = experiences
808 .iter()
809 .filter_map(|exp| exp.configuration.hyperparameters.get("initial_temperature"))
810 .sum::<f64>()
811 / experiences.len() as f64;
812 hyperparameters.insert("initial_temperature".to_string(), avg_initial_temp.max(1.0));
813
814 let avg_final_temp = experiences
815 .iter()
816 .filter_map(|exp| exp.configuration.hyperparameters.get("final_temperature"))
817 .sum::<f64>()
818 / experiences.len() as f64;
819 hyperparameters.insert("final_temperature".to_string(), avg_final_temp.max(0.01));
820 }
821
822 hyperparameters.insert(
823 "num_sweeps".to_string(),
824 (features.size as f64 * 10.0).min(10_000.0),
825 );
826
827 let configuration = OptimizationConfiguration {
828 algorithm,
829 hyperparameters,
830 architecture: None,
831 resources: ResourceAllocation {
832 cpu: 1.0,
833 memory: 512,
834 gpu: 0.0,
835 time: Duration::from_secs(60),
836 },
837 };
838
839 let confidence = if experiences.len() >= 5 { 0.9 } else { 0.6 };
840
841 Ok(RecommendedStrategy {
842 confidence,
843 configuration,
844 expected_performance: 0.8,
845 reasoning: format!(
846 "Recommendation based on {} similar experiences",
847 experiences.len()
848 ),
849 alternatives: Vec::new(),
850 })
851 }
852
853 const fn update_with_experience(
854 &self,
855 _features: &ProblemFeatures,
856 _result: &OptimizationResults,
857 ) {
858 }
861}
862
863pub fn create_example_meta_learning_optimizer() -> ApplicationResult<MetaLearningOptimizer> {
865 let config = MetaLearningConfig::default();
866 let optimizer = MetaLearningOptimizer::new(config);
867
868 println!("Created meta-learning optimizer with comprehensive capabilities");
869 Ok(optimizer)
870}
871
872#[cfg(test)]
873mod tests {
874 use super::*;
875
876 #[test]
877 fn test_meta_learning_optimizer_creation() {
878 let config = MetaLearningConfig::default();
879 let optimizer = MetaLearningOptimizer::new(config);
880
881 assert!(optimizer.config.enable_transfer_learning);
882 assert!(optimizer.config.enable_few_shot_learning);
883 assert_eq!(optimizer.config.experience_buffer_size, 10_000);
884 }
885
886 #[test]
887 fn test_experience_database() {
888 let mut db = ExperienceDatabase::new();
889
890 let experience = OptimizationExperience {
891 id: "test_exp".to_string(),
892 problem_features: ProblemFeatures {
893 size: 10,
894 density: 0.5,
895 graph_features: GraphFeatures::default(),
896 statistical_features: StatisticalFeatures::default(),
897 spectral_features: SpectralFeatures::default(),
898 domain_features: HashMap::new(),
899 },
900 configuration: OptimizationConfiguration {
901 algorithm: AlgorithmType::SimulatedAnnealing,
902 hyperparameters: HashMap::new(),
903 architecture: None,
904 resources: ResourceAllocation {
905 cpu: 1.0,
906 memory: 512,
907 gpu: 0.0,
908 time: Duration::from_secs(60),
909 },
910 },
911 results: OptimizationResults {
912 objective_values: vec![1.0],
913 execution_time: Duration::from_secs(10),
914 resource_usage: ResourceUsage {
915 peak_cpu: 0.8,
916 peak_memory: 256,
917 gpu_utilization: 0.0,
918 energy_consumption: 100.0,
919 },
920 convergence: ConvergenceMetrics {
921 iterations: 1000,
922 convergence_rate: 0.95,
923 plateau_detected: false,
924 confidence: 0.9,
925 },
926 quality_metrics: QualityMetrics {
927 objective_value: 1.0,
928 constraint_violation: 0.0,
929 robustness: 0.8,
930 diversity: 0.7,
931 },
932 },
933 timestamp: Instant::now(),
934 domain: ProblemDomain::Combinatorial,
935 success_metrics: SuccessMetrics {
936 success_score: 0.9,
937 relative_performance: 1.1,
938 user_satisfaction: 0.8,
939 recommendation_confidence: 0.9,
940 },
941 };
942
943 db.add_experience(experience);
944 assert_eq!(db.statistics.total_experiences, 1);
945 }
946
947 #[test]
948 fn test_meta_learner_recommendation() {
949 let mut meta_learner = MetaLearner::new();
950
951 let features = ProblemFeatures {
952 size: 50,
953 density: 0.3,
954 graph_features: GraphFeatures::default(),
955 statistical_features: StatisticalFeatures::default(),
956 spectral_features: SpectralFeatures::default(),
957 domain_features: HashMap::new(),
958 };
959
960 let experiences = vec![];
961 let recommendation = meta_learner
962 .recommend_strategy(&features, &experiences)
963 .expect("Strategy recommendation should succeed");
964
965 assert!(recommendation.confidence > 0.0);
966 assert!(recommendation.confidence <= 1.0);
967 assert!(!recommendation.configuration.hyperparameters.is_empty());
968 }
969}