1use crate::advisor::config::*;
4use crate::JitResult;
5use std::collections::{HashMap, VecDeque};
6use std::time::{Duration, SystemTime};
7
8pub struct LearningSystem {
10 knowledge_base: KnowledgeBase,
11 historical_data: HistoricalDataStore,
12 recommendation_feedback: FeedbackTracker,
13 adaptation_engine: AdaptationEngine,
14 config: LearningConfig,
15}
16
17#[derive(Debug, Clone)]
19pub struct LearningConfig {
20 pub max_history_size: usize,
21 pub learning_rate: f64,
22 pub adaptation_threshold: f64,
23 pub min_feedback_samples: usize,
24 pub enable_pattern_learning: bool,
25 pub enable_performance_prediction: bool,
26}
27
28impl Default for LearningConfig {
29 fn default() -> Self {
30 Self {
31 max_history_size: 10000,
32 learning_rate: 0.01,
33 adaptation_threshold: 0.1,
34 min_feedback_samples: 10,
35 enable_pattern_learning: true,
36 enable_performance_prediction: true,
37 }
38 }
39}
40
41#[derive(Debug)]
43pub struct KnowledgeBase {
44 optimization_patterns: HashMap<String, OptimizationPattern>,
45 performance_models: HashMap<String, PerformanceModel>,
46 best_practices: Vec<BestPractice>,
47 failure_cases: Vec<FailureCase>,
48}
49
50#[derive(Debug)]
52pub struct HistoricalDataStore {
53 analysis_history: VecDeque<AnalysisRecord>,
54 performance_history: VecDeque<PerformanceRecord>,
55 recommendation_history: VecDeque<RecommendationRecord>,
56 max_size: usize,
57}
58
59#[derive(Debug)]
61pub struct FeedbackTracker {
62 recommendation_feedback: HashMap<String, Vec<FeedbackEntry>>,
63 success_rates: HashMap<String, f64>,
64 improvement_metrics: HashMap<String, Vec<f64>>,
65}
66
67#[derive(Debug)]
69pub struct AdaptationEngine {
70 pattern_weights: HashMap<String, f64>,
71 confidence_adjustments: HashMap<String, f64>,
72 learning_rate: f64,
73}
74
75impl LearningSystem {
76 pub fn new(config: LearningConfig) -> Self {
77 Self {
78 knowledge_base: KnowledgeBase::new(),
79 historical_data: HistoricalDataStore::new(config.max_history_size),
80 recommendation_feedback: FeedbackTracker::new(),
81 adaptation_engine: AdaptationEngine::new(config.learning_rate),
82 config,
83 }
84 }
85
86 pub fn record_analysis(
87 &mut self,
88 input: &AnalysisInput,
89 recommendations: &[OptimizationRecommendation],
90 ) {
91 let record = AnalysisRecord {
92 timestamp: SystemTime::now(),
93 input_characteristics: self.extract_input_characteristics(input),
94 recommendations_generated: recommendations.len(),
95 complexity_score: self.calculate_complexity_score(input),
96 };
97
98 self.historical_data.add_analysis_record(record);
99
100 for recommendation in recommendations {
101 let rec_record = RecommendationRecord {
102 id: recommendation.id.clone(),
103 timestamp: SystemTime::now(),
104 optimization_type: recommendation.optimization_type.clone(),
105 confidence: recommendation.confidence,
106 expected_benefit: recommendation.expected_speedup,
107 complexity: recommendation.implementation_complexity,
108 };
109 self.historical_data.add_recommendation_record(rec_record);
110 }
111 }
112
113 pub fn record_performance(
114 &mut self,
115 input: &AnalysisInput,
116 actual_performance: &ActualPerformanceResult,
117 ) {
118 let record = PerformanceRecord {
119 timestamp: SystemTime::now(),
120 input_hash: self.hash_input(input),
121 execution_time: actual_performance.execution_time,
122 memory_usage: actual_performance.memory_usage,
123 throughput: actual_performance.throughput,
124 actual_improvement: 1.0, };
126
127 self.historical_data.add_performance_record(record);
128 }
129
130 pub fn record_feedback(&mut self, recommendation_id: &str, feedback: RecommendationFeedback) {
131 let entry = FeedbackEntry {
132 timestamp: SystemTime::now(),
133 feedback: feedback.clone(),
134 implementation_success: true, actual_improvement: 0.0, };
137
138 self.recommendation_feedback
139 .add_feedback(recommendation_id, entry);
140 self.update_adaptation_weights(recommendation_id, &feedback);
141 }
142
143 pub fn suggest_optimizations(
144 &self,
145 input: &AnalysisInput,
146 ) -> JitResult<Vec<OptimizationSuggestion>> {
147 let mut suggestions = Vec::new();
148
149 for pattern in &self.knowledge_base.optimization_patterns {
151 if self.pattern_matches_input(pattern.1, input) {
152 suggestions.push(OptimizationSuggestion {
153 pattern_name: pattern.0.clone(),
154 confidence: pattern.1.success_rate * self.get_pattern_weight(&pattern.0),
155 estimated_benefit: pattern.1.average_benefit,
156 description: pattern.1.description.clone(),
157 });
158 }
159 }
160
161 suggestions.sort_by(|a, b| {
163 b.confidence
164 .partial_cmp(&a.confidence)
165 .unwrap_or(std::cmp::Ordering::Equal)
166 });
167 suggestions.truncate(5);
168
169 Ok(suggestions)
170 }
171
172 pub fn predict_performance(
173 &self,
174 input: &AnalysisInput,
175 optimization_type: &OptimizationType,
176 ) -> JitResult<PerformancePrediction> {
177 if !self.config.enable_performance_prediction {
178 return Ok(PerformancePrediction::default());
179 }
180
181 let similar_cases = self.find_similar_historical_cases(input);
182 if similar_cases.is_empty() {
183 return Ok(PerformancePrediction::default());
184 }
185
186 let avg_improvement = similar_cases
187 .iter()
188 .map(|case| case.actual_improvement)
189 .sum::<f64>()
190 / similar_cases.len() as f64;
191
192 let confidence =
193 (similar_cases.len() as f64 / self.config.min_feedback_samples as f64).min(1.0);
194
195 Ok(PerformancePrediction {
196 expected_improvement: avg_improvement,
197 confidence,
198 similar_cases_count: similar_cases.len(),
199 })
200 }
201
202 pub fn learn_from_outcomes(&mut self) -> JitResult<()> {
203 if !self.config.enable_pattern_learning {
204 return Ok(());
205 }
206
207 for (pattern_name, pattern) in &mut self.knowledge_base.optimization_patterns {
209 if let Some(feedback_entries) = self
210 .recommendation_feedback
211 .recommendation_feedback
212 .get(pattern_name)
213 {
214 if feedback_entries.len() >= self.config.min_feedback_samples {
215 let success_rate = feedback_entries
216 .iter()
217 .map(|entry| {
218 if entry.implementation_success {
219 1.0
220 } else {
221 0.0
222 }
223 })
224 .sum::<f64>()
225 / feedback_entries.len() as f64;
226
227 pattern.success_rate = pattern.success_rate * 0.9 + success_rate * 0.1;
228 }
229 }
230 }
231
232 self.update_performance_models()?;
234
235 Ok(())
236 }
237
238 pub fn get_knowledge_summary(&self) -> KnowledgeSummary {
239 KnowledgeSummary {
240 total_patterns: self.knowledge_base.optimization_patterns.len(),
241 total_analysis_records: self.historical_data.analysis_history.len(),
242 total_feedback_entries: self
243 .recommendation_feedback
244 .recommendation_feedback
245 .values()
246 .map(|entries| entries.len())
247 .sum(),
248 average_success_rate: self.calculate_average_success_rate(),
249 most_successful_pattern: self.find_most_successful_pattern(),
250 }
251 }
252
253 pub fn calculate_confidence(&self) -> f64 {
254 if self.historical_data.analysis_history.is_empty() {
255 return 0.3; }
257
258 let base_confidence = 0.6;
259 let history_factor = (self.historical_data.analysis_history.len() as f64 / 100.0).min(0.3);
260 let feedback_factor = if self.has_sufficient_feedback() {
261 0.1
262 } else {
263 0.0
264 };
265
266 base_confidence + history_factor + feedback_factor
267 }
268
269 fn extract_input_characteristics(&self, input: &AnalysisInput) -> InputCharacteristics {
271 InputCharacteristics {
272 graph_size: input
273 .computation_graph
274 .as_ref()
275 .map(|g| g.node_count())
276 .unwrap_or(0),
277 has_gpu: input.system_constraints.has_gpu,
278 cpu_cores: input.system_constraints.cpu_cores,
279 memory_gb: input.system_constraints.memory_gb,
280 target_platform: input.system_constraints.target_platform.clone(),
281 }
282 }
283
284 fn calculate_complexity_score(&self, input: &AnalysisInput) -> f64 {
285 let mut score: f64 = 0.0;
286
287 if let Some(graph) = &input.computation_graph {
288 score += (graph.node_count() as f64).log10() * 0.3;
289 }
290
291 score += match input.system_constraints.target_platform {
292 TargetPlatform::Desktop => 0.0,
293 TargetPlatform::Server => 0.1,
294 TargetPlatform::Mobile => 0.3,
295 TargetPlatform::Embedded => 0.5,
296 };
297
298 score.min(1.0)
299 }
300
301 fn hash_input(&self, input: &AnalysisInput) -> u64 {
302 let mut hash = 0u64;
304
305 if let Some(graph) = &input.computation_graph {
306 hash ^= graph.node_count() as u64;
307 }
308
309 hash ^= input.system_constraints.cpu_cores as u64;
310 hash ^= if input.system_constraints.has_gpu {
311 1
312 } else {
313 0
314 };
315
316 hash
317 }
318
319 fn pattern_matches_input(&self, pattern: &OptimizationPattern, input: &AnalysisInput) -> bool {
320 if let Some(graph) = &input.computation_graph {
322 if pattern.min_graph_size > 0 && graph.node_count() < pattern.min_graph_size {
323 return false;
324 }
325 }
326
327 if pattern.requires_gpu && !input.system_constraints.has_gpu {
328 return false;
329 }
330
331 true
332 }
333
334 fn get_pattern_weight(&self, pattern_name: &str) -> f64 {
335 self.adaptation_engine
336 .pattern_weights
337 .get(pattern_name)
338 .cloned()
339 .unwrap_or(1.0)
340 }
341
342 fn find_similar_historical_cases(&self, _input: &AnalysisInput) -> Vec<&PerformanceRecord> {
343 self.historical_data
345 .performance_history
346 .iter()
347 .take(5)
348 .collect()
349 }
350
351 fn update_adaptation_weights(
352 &mut self,
353 recommendation_id: &str,
354 feedback: &RecommendationFeedback,
355 ) {
356 let adjustment = match feedback {
357 RecommendationFeedback::Excellent => 0.1,
358 RecommendationFeedback::Good => 0.05,
359 RecommendationFeedback::Fair => 0.0,
360 RecommendationFeedback::Poor => -0.05,
361 RecommendationFeedback::Failed => -0.1,
362 };
363
364 *self
365 .adaptation_engine
366 .confidence_adjustments
367 .entry(recommendation_id.to_string())
368 .or_insert(0.0) += adjustment;
369 }
370
371 fn update_performance_models(&mut self) -> JitResult<()> {
372 let model_names: Vec<String> = self
374 .knowledge_base
375 .performance_models
376 .keys()
377 .cloned()
378 .collect();
379
380 for model_name in model_names {
381 let recent_data = self
383 .historical_data
384 .performance_history
385 .iter()
386 .take(100)
387 .cloned()
388 .collect::<Vec<_>>();
389 if !recent_data.is_empty() {
390 if let Some(model) = self.knowledge_base.performance_models.get_mut(&model_name) {
391 let recent_data_refs = recent_data.iter().collect::<Vec<&PerformanceRecord>>();
393 model.update_with_data(&recent_data_refs)?;
394 }
395 }
396 }
397 Ok(())
398 }
399
400 fn get_recent_performance_data(&self, _model_name: &str) -> Option<Vec<&PerformanceRecord>> {
401 Some(
402 self.historical_data
403 .performance_history
404 .iter()
405 .take(100)
406 .collect(),
407 )
408 }
409
410 fn calculate_average_success_rate(&self) -> f64 {
411 if self.knowledge_base.optimization_patterns.is_empty() {
412 return 0.0;
413 }
414
415 let total_rate = self
416 .knowledge_base
417 .optimization_patterns
418 .values()
419 .map(|pattern| pattern.success_rate)
420 .sum::<f64>();
421
422 total_rate / self.knowledge_base.optimization_patterns.len() as f64
423 }
424
425 fn find_most_successful_pattern(&self) -> Option<String> {
426 self.knowledge_base
427 .optimization_patterns
428 .iter()
429 .max_by(|a, b| {
430 a.1.success_rate
431 .partial_cmp(&b.1.success_rate)
432 .unwrap_or(std::cmp::Ordering::Equal)
433 })
434 .map(|(name, _)| name.clone())
435 }
436
437 fn has_sufficient_feedback(&self) -> bool {
438 self.recommendation_feedback
439 .recommendation_feedback
440 .values()
441 .map(|entries| entries.len())
442 .sum::<usize>()
443 >= self.config.min_feedback_samples
444 }
445}
446
447impl KnowledgeBase {
448 pub fn new() -> Self {
449 Self {
450 optimization_patterns: HashMap::new(),
451 performance_models: HashMap::new(),
452 best_practices: Vec::new(),
453 failure_cases: Vec::new(),
454 }
455 }
456
457 pub fn add_pattern(&mut self, name: String, pattern: OptimizationPattern) {
458 self.optimization_patterns.insert(name, pattern);
459 }
460
461 pub fn add_performance_model(&mut self, name: String, model: PerformanceModel) {
462 self.performance_models.insert(name, model);
463 }
464}
465
466impl HistoricalDataStore {
467 pub fn new(max_size: usize) -> Self {
468 Self {
469 analysis_history: VecDeque::new(),
470 performance_history: VecDeque::new(),
471 recommendation_history: VecDeque::new(),
472 max_size,
473 }
474 }
475
476 pub fn add_analysis_record(&mut self, record: AnalysisRecord) {
477 self.analysis_history.push_back(record);
478 if self.analysis_history.len() > self.max_size {
479 self.analysis_history.pop_front();
480 }
481 }
482
483 pub fn add_performance_record(&mut self, record: PerformanceRecord) {
484 self.performance_history.push_back(record);
485 if self.performance_history.len() > self.max_size {
486 self.performance_history.pop_front();
487 }
488 }
489
490 pub fn add_recommendation_record(&mut self, record: RecommendationRecord) {
491 self.recommendation_history.push_back(record);
492 if self.recommendation_history.len() > self.max_size {
493 self.recommendation_history.pop_front();
494 }
495 }
496}
497
498impl FeedbackTracker {
499 pub fn new() -> Self {
500 Self {
501 recommendation_feedback: HashMap::new(),
502 success_rates: HashMap::new(),
503 improvement_metrics: HashMap::new(),
504 }
505 }
506
507 pub fn add_feedback(&mut self, recommendation_id: &str, feedback: FeedbackEntry) {
508 self.recommendation_feedback
509 .entry(recommendation_id.to_string())
510 .or_insert_with(Vec::new)
511 .push(feedback);
512 }
513}
514
515impl AdaptationEngine {
516 pub fn new(learning_rate: f64) -> Self {
517 Self {
518 pattern_weights: HashMap::new(),
519 confidence_adjustments: HashMap::new(),
520 learning_rate,
521 }
522 }
523}
524
525#[derive(Debug, Clone)]
527pub struct OptimizationPattern {
528 pub description: String,
529 pub success_rate: f64,
530 pub average_benefit: f64,
531 pub min_graph_size: usize,
532 pub requires_gpu: bool,
533 pub applicable_platforms: Vec<TargetPlatform>,
534}
535
536#[derive(Debug, Clone)]
537pub struct PerformanceModel {
538 pub name: String,
539 pub accuracy: f64,
540 pub last_updated: SystemTime,
541}
542
543impl PerformanceModel {
544 pub fn update_with_data(&mut self, _data: &[&PerformanceRecord]) -> JitResult<()> {
545 self.last_updated = SystemTime::now();
546 Ok(())
547 }
548}
549
550#[derive(Debug, Clone)]
551pub struct BestPractice {
552 pub title: String,
553 pub description: String,
554 pub category: String,
555 pub effectiveness: f64,
556}
557
558#[derive(Debug, Clone)]
559pub struct FailureCase {
560 pub description: String,
561 pub root_cause: String,
562 pub prevention_strategy: String,
563}
564
565#[derive(Debug, Clone)]
566pub struct AnalysisRecord {
567 pub timestamp: SystemTime,
568 pub input_characteristics: InputCharacteristics,
569 pub recommendations_generated: usize,
570 pub complexity_score: f64,
571}
572
573#[derive(Debug, Clone)]
574pub struct PerformanceRecord {
575 pub timestamp: SystemTime,
576 pub input_hash: u64,
577 pub execution_time: Duration,
578 pub memory_usage: usize,
579 pub throughput: f64,
580 pub actual_improvement: f64,
581}
582
583#[derive(Debug, Clone)]
584pub struct RecommendationRecord {
585 pub id: String,
586 pub timestamp: SystemTime,
587 pub optimization_type: OptimizationType,
588 pub confidence: f64,
589 pub expected_benefit: f64,
590 pub complexity: f64,
591}
592
593#[derive(Debug, Clone)]
594pub struct FeedbackEntry {
595 pub timestamp: SystemTime,
596 pub feedback: RecommendationFeedback,
597 pub implementation_success: bool,
598 pub actual_improvement: f64,
599}
600
601#[derive(Debug, Clone)]
602pub struct InputCharacteristics {
603 pub graph_size: usize,
604 pub has_gpu: bool,
605 pub cpu_cores: usize,
606 pub memory_gb: usize,
607 pub target_platform: TargetPlatform,
608}
609
610#[derive(Debug, Clone)]
611pub struct OptimizationSuggestion {
612 pub pattern_name: String,
613 pub confidence: f64,
614 pub estimated_benefit: f64,
615 pub description: String,
616}
617
618#[derive(Debug, Clone)]
619pub struct PerformancePrediction {
620 pub expected_improvement: f64,
621 pub confidence: f64,
622 pub similar_cases_count: usize,
623}
624
625impl Default for PerformancePrediction {
626 fn default() -> Self {
627 Self {
628 expected_improvement: 0.0,
629 confidence: 0.0,
630 similar_cases_count: 0,
631 }
632 }
633}
634
635#[derive(Debug, Clone)]
636pub struct KnowledgeSummary {
637 pub total_patterns: usize,
638 pub total_analysis_records: usize,
639 pub total_feedback_entries: usize,
640 pub average_success_rate: f64,
641 pub most_successful_pattern: Option<String>,
642}
643
644#[derive(Debug, Clone)]
645pub enum RecommendationFeedback {
646 Excellent,
647 Good,
648 Fair,
649 Poor,
650 Failed,
651}
652
653#[derive(Debug, Clone)]
654pub struct ActualPerformanceResult {
655 pub execution_time: Duration,
656 pub memory_usage: usize,
657 pub throughput: f64,
658}