1use crate::error::Result;
6use crate::transformer_based_optimizer::{
7 ArchitectureUpdate, TransformerOptimizer, TransformerOptimizerConfig,
8};
9
10use super::architecture_adapter::DynamicArchitectureAdapter;
11use super::landscape::LandscapeStatistics;
12use super::performance_predictor::TransformerPerformancePredictor;
13use super::predictor::{PredictorFitReport, PredictorSample};
14use crate::common::cast_scalar;
15use scirs2_core::ndarray::{Array1, Array3};
16use scirs2_core::numeric::Float;
17use std::collections::{HashMap, VecDeque};
18use std::fmt::Debug;
19
20#[derive(Debug)]
22pub struct ArchitectureAdaptation<
23 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
24> {
25 pub adapted_config: TransformerOptimizerConfig<T>,
27 pub changes: Vec<ArchitectureChange>,
29 pub expected_improvement: T,
31 pub confidence: T,
33}
34#[derive(Debug)]
36pub struct MemoryEfficientAttentionManager<
37 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
38> {
39 pattern_cache: AttentionPatternCache<T>,
41 memory_tracker: MemoryUsageTracker,
43 sparsity_floor: T,
45 allow_head_pruning: bool,
48 min_span: usize,
51 max_span: usize,
54}
55impl<T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static>
56 MemoryEfficientAttentionManager<T>
57{
58 fn new(config: &AdaptiveConfig<T>) -> Result<Self> {
67 if config.min_sequence_length == 0
68 || config.min_sequence_length > config.max_sequence_length
69 {
70 return Err(crate::error::OptimError::InvalidConfig(format!(
71 "sequence length bounds must satisfy 0 < min ({}) <= max ({})",
72 config.min_sequence_length, config.max_sequence_length
73 )));
74 }
75 Ok(Self {
76 pattern_cache: AttentionPatternCache::new(),
77 memory_tracker: MemoryUsageTracker::with_budget(config.memory_budget),
78 sparsity_floor: config.attention_sparsity_threshold,
79 allow_head_pruning: config.dynamic_head_pruning,
80 min_span: config.min_sequence_length,
81 max_span: config.max_sequence_length,
82 })
83 }
84 fn optimize_attention(
85 &mut self,
86 analysis: &LandscapeAnalysis<T>,
87 ) -> Result<AttentionOptimization<T>> {
88 let complexity = analysis.complexity.to_f64().unwrap_or(0.5);
89 let difficulty = analysis.difficulty.to_f64().unwrap_or(0.3);
90 let (num_heads, seq_len) = self.determine_attention_dimensions(complexity, difficulty)?;
91 let mut attention_patterns = Array3::zeros((num_heads, seq_len, seq_len));
92 self.generate_attention_patterns(&mut attention_patterns, analysis)?;
93 let requested: T =
96 scirs2_core::numeric::NumCast::from(if complexity > 0.7 { 0.05 } else { 0.15 })
97 .unwrap_or_else(|| T::zero());
98 let sparsitylevel = if requested > self.sparsity_floor {
99 requested
100 } else {
101 self.sparsity_floor
102 };
103 self.apply_sparsity_mask(&mut attention_patterns, sparsitylevel)?;
104 let pattern_key = format!("pattern_{}_{}", num_heads, seq_len);
105 self.pattern_cache
106 .patterns
107 .insert(pattern_key.clone(), attention_patterns.clone());
108 *self
109 .pattern_cache
110 .usage_frequency
111 .entry(pattern_key)
112 .or_insert(0) += 1;
113 let original_size = 8 * 512 * 512 * std::mem::size_of::<f32>();
114 let optimized_size = num_heads * seq_len * seq_len * std::mem::size_of::<f32>();
115 let memory_savings = original_size.saturating_sub(optimized_size);
116 let speedup_from_sparsity = T::one() / sparsitylevel;
117 let speedup_from_dimensions: T =
120 cast_scalar(512.0 * 512.0 / (seq_len.max(1) * seq_len.max(1)) as f64)?;
121 let computational_speedup = (speedup_from_sparsity + speedup_from_dimensions)
122 / scirs2_core::numeric::NumCast::from(2.0).unwrap_or_else(|| T::zero());
123 self.memory_tracker.current_usage += optimized_size;
124 if self.memory_tracker.current_usage > self.memory_tracker.peak_usage {
125 self.memory_tracker.peak_usage = self.memory_tracker.current_usage;
126 }
127 Ok(AttentionOptimization {
128 attention_patterns,
129 sparsitylevel,
130 memory_savings,
131 computational_speedup,
132 })
133 }
134 fn determine_attention_dimensions(
142 &self,
143 complexity: f64,
144 difficulty: f64,
145 ) -> Result<(usize, usize)> {
146 let base_heads = 8;
147 let scaled_heads = if complexity > 0.8 {
148 (base_heads as f64 * 1.5) as usize
149 } else if complexity < 0.3 && self.allow_head_pruning {
150 (base_heads as f64 * 0.75) as usize
151 } else {
152 base_heads
153 };
154 let heads = scaled_heads.clamp(4, 16);
155
156 let base_span = (self.min_span + self.max_span) / 2;
159 let scaled_span = if difficulty > 0.7 {
160 (base_span as f64 * 1.2) as usize
161 } else if difficulty < 0.3 {
162 (base_span as f64 * 0.8) as usize
163 } else {
164 base_span
165 };
166 let seq_len = scaled_span.clamp(self.min_span, self.max_span).max(1);
167 Ok((heads, seq_len))
168 }
169 fn generate_attention_patterns(
170 &self,
171 patterns: &mut Array3<T>,
172 analysis: &LandscapeAnalysis<T>,
173 ) -> Result<()> {
174 let (num_heads, seq_len, _) = patterns.dim();
175 for head in 0..num_heads {
176 for i in 0..seq_len {
177 for j in 0..seq_len {
178 let distance = ((i as i32 - j as i32).abs() as f64).sqrt();
179 let base_attention = (-scirs2_core::numeric::NumCast::from(distance)
180 .unwrap_or_else(|| T::zero())
181 / (scirs2_core::numeric::NumCast::from(seq_len)
182 .unwrap_or_else(|| T::zero())
183 * scirs2_core::numeric::NumCast::from(0.1)
184 .unwrap_or_else(|| T::zero())))
185 .exp();
186 let complexity_factor = analysis.complexity.to_f64().unwrap_or(0.5);
187 let modulated_attention = base_attention
188 * (T::one()
189 + scirs2_core::numeric::NumCast::from(complexity_factor)
190 .unwrap_or_else(|| T::zero())
191 * scirs2_core::numeric::NumCast::from(0.3)
192 .unwrap_or_else(|| T::zero()));
193 patterns[[head, i, j]] =
194 scirs2_core::numeric::NumCast::from(modulated_attention)
195 .unwrap_or_else(|| T::zero());
196 }
197 }
198 }
199 Ok(())
200 }
201 fn apply_sparsity_mask(&self, patterns: &mut Array3<T>, sparsitylevel: T) -> Result<()> {
202 let sparsity_threshold = sparsitylevel.to_f64().unwrap_or(0.1);
203 patterns.map_inplace(|x| {
204 if x.to_f64().unwrap_or(0.0) < sparsity_threshold {
205 *x = T::zero();
206 }
207 });
208 Ok(())
209 }
210}
211#[derive(Debug)]
213pub struct AdaptiveSequenceProcessor<
214 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
215> {
216 current_length: usize,
218 importance_scores: VecDeque<T>,
220 compression_ratio: T,
222 min_length: usize,
224 max_length: usize,
226 length_adaptation_enabled: bool,
228}
229impl<T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static>
230 AdaptiveSequenceProcessor<T>
231{
232 fn new(config: &AdaptiveConfig<T>) -> Result<Self> {
240 if config.min_sequence_length == 0
241 || config.min_sequence_length > config.max_sequence_length
242 {
243 return Err(crate::error::OptimError::InvalidConfig(format!(
244 "sequence length bounds must satisfy 0 < min ({}) <= max ({})",
245 config.min_sequence_length, config.max_sequence_length
246 )));
247 }
248 Ok(Self {
249 current_length: (config.min_sequence_length + config.max_sequence_length) / 2,
250 importance_scores: VecDeque::new(),
251 compression_ratio: scirs2_core::numeric::NumCast::from(0.8)
252 .unwrap_or_else(|| T::zero()),
253 min_length: config.min_sequence_length,
254 max_length: config.max_sequence_length,
255 length_adaptation_enabled: config.adaptive_sequence_length,
256 })
257 }
258 fn adapt_to_landscape(
259 &mut self,
260 analysis: &LandscapeAnalysis<T>,
261 ) -> Result<SequenceAdaptation<T>> {
262 let complexity_factor = analysis.complexity.to_f64().unwrap_or(0.5);
263 let difficulty_factor = analysis.difficulty.to_f64().unwrap_or(0.3);
264 let new_length = if !self.length_adaptation_enabled {
265 self.current_length
266 } else if complexity_factor > 0.7 {
267 ((self.current_length as f64 * 1.2) as usize).min(self.max_length)
268 } else if complexity_factor < 0.3 {
269 ((self.current_length as f64 * 0.8) as usize).max(self.min_length)
270 } else {
271 self.current_length
272 };
273 let new_compression_ratio = if difficulty_factor > 0.6 {
274 self.compression_ratio
275 * scirs2_core::numeric::NumCast::from(0.9).unwrap_or_else(|| T::zero())
276 } else {
277 self.compression_ratio
278 * scirs2_core::numeric::NumCast::from(1.1).unwrap_or_else(|| T::zero())
279 }
280 .min(scirs2_core::numeric::NumCast::from(0.95).unwrap_or_else(|| T::zero()))
281 .max(scirs2_core::numeric::NumCast::from(0.5).unwrap_or_else(|| T::zero()));
282 self.current_length = new_length;
283 self.compression_ratio = new_compression_ratio;
284 let information_preservation = T::one()
285 - (T::one() - new_compression_ratio)
286 * scirs2_core::numeric::NumCast::from(0.5).unwrap_or_else(|| T::zero());
287 let length_efficiency =
288 scirs2_core::numeric::NumCast::from(self.current_length as f64 / new_length as f64)
289 .unwrap_or_else(|| T::zero());
290 let compression_efficiency = T::one() / new_compression_ratio;
291 let efficiency_gain = (length_efficiency + compression_efficiency)
292 / scirs2_core::numeric::NumCast::from(2.0).unwrap_or_else(|| T::zero());
293 self.update_importance_scores(analysis)?;
294 Ok(SequenceAdaptation {
295 new_length,
296 compression_ratio: new_compression_ratio,
297 information_preservation,
298 efficiency_gain,
299 })
300 }
301 fn update_importance_scores(&mut self, analysis: &LandscapeAnalysis<T>) -> Result<()> {
302 let base_importance = scirs2_core::numeric::NumCast::from(0.5).unwrap_or_else(|| T::zero());
303 let complexity_boost = analysis.complexity
304 * scirs2_core::numeric::NumCast::from(0.3).unwrap_or_else(|| T::zero());
305 let difficulty_boost = analysis.difficulty
306 * scirs2_core::numeric::NumCast::from(0.2).unwrap_or_else(|| T::zero());
307 let new_importance = base_importance + complexity_boost + difficulty_boost;
308 self.importance_scores.push_back(new_importance);
309 if self.importance_scores.len() > 100 {
310 self.importance_scores.pop_front();
311 }
312 Ok(())
313 }
314}
315#[derive(Debug, Clone)]
317pub struct LandscapeFeatures<
318 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
319> {
320 pub(super) smoothness: T,
322 pub(super) multimodality: T,
324 pub(super) noise_level: T,
326}
327#[derive(Debug)]
329pub struct SequenceAdaptation<
330 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
331> {
332 pub new_length: usize,
334 pub compression_ratio: T,
336 pub information_preservation: T,
338 pub efficiency_gain: T,
340}
341#[derive(Debug)]
343pub struct LandscapeAnalysis<
344 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
345> {
346 pub complexity: T,
348 pub difficulty: T,
350 pub recommended_strategies: Vec<OptimizationStrategy>,
352 pub confidence: T,
354}
355#[derive(Debug, Clone, Copy)]
356pub enum PositionalEncodingType {
357 Sinusoidal,
358 Learned,
359 Rotary,
360 Relative,
361}
362#[derive(Debug)]
364pub struct ComplexityEstimator<
365 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
366> {
367 computational_complexity: T,
369 generalization_complexity: T,
371}
372impl<T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static>
373 ComplexityEstimator<T>
374{
375 fn new() -> Self {
376 Self {
377 computational_complexity: scirs2_core::numeric::NumCast::from(0.5)
378 .unwrap_or_else(|| T::zero()),
379 generalization_complexity: scirs2_core::numeric::NumCast::from(0.5)
380 .unwrap_or_else(|| T::zero()),
381 }
382 }
383}
384#[derive(Debug, Clone)]
386pub struct ArchitecturePerformance<
387 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
388> {
389 final_performance: T,
391}
392#[derive(Debug)]
394pub struct EnhancementResult<
395 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
396> {
397 pub sequence_adaptation: SequenceAdaptation<T>,
399 pub attention_optimization: AttentionOptimization<T>,
401 pub architecture_adaptation: ArchitectureAdaptation<T>,
403 pub performance_prediction: PerformancePrediction<T>,
405 pub landscape_analysis: LandscapeAnalysis<T>,
407 pub convergence_metrics: ConvergenceMetrics<T>,
409 pub architecture_update: ArchitectureUpdate,
416}
417#[derive(Debug, Clone)]
419pub struct EnhancementStatistics<
420 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
421> {
422 pub total_enhancements: usize,
424 pub average_complexity: T,
426 pub average_performance: T,
428 pub memory_efficiency: T,
430 pub adaptation_success_rate: T,
432}
433#[derive(Debug, Clone)]
435pub enum ArchitectureChange {
436 LayerCountChange(usize),
437 HiddenSizeChange(usize),
438 AttentionHeadChange(usize),
439 ActivationChange(ActivationType),
440 DropoutChange(f64),
441}
442#[derive(Debug, Clone)]
444pub struct ResourceConstraints {
445 pub(super) max_memory: usize,
447}
448#[derive(Debug)]
450pub struct AttentionPatternCache<
451 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
452> {
453 patterns: HashMap<String, Array3<T>>,
455 usage_frequency: HashMap<String, usize>,
457}
458impl<T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static>
459 AttentionPatternCache<T>
460{
461 fn new() -> Self {
462 Self {
463 patterns: HashMap::new(),
464 usage_frequency: HashMap::new(),
465 }
466 }
467}
468#[derive(Debug)]
470pub struct OptimizationLandscapeAnalyzer<
471 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
472> {
473 landscape_features: LandscapeFeatures<T>,
475 complexity_estimator: ComplexityEstimator<T>,
477 analysis_cache: HashMap<String, AnalysisResult<T>>,
479 confidence_horizon: usize,
482 last_statistics: LandscapeStatistics,
484}
485impl<T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static>
486 OptimizationLandscapeAnalyzer<T>
487{
488 fn new(config: &AdaptiveConfig<T>) -> Result<Self> {
489 Ok(Self {
490 landscape_features: LandscapeFeatures::default(),
491 complexity_estimator: ComplexityEstimator::new(),
492 analysis_cache: HashMap::new(),
493 confidence_horizon: config.prediction_horizon.max(2),
494 last_statistics: LandscapeStatistics::empty(),
495 })
496 }
497
498 fn analyze(
521 &mut self,
522 gradient_history: &[Array1<T>],
523 loss_history: &[T],
524 ) -> Result<LandscapeAnalysis<T>> {
525 if gradient_history.is_empty() && loss_history.is_empty() {
526 return Err(crate::error::OptimError::InsufficientData(
527 "landscape analysis needs at least one gradient or loss sample".to_string(),
528 ));
529 }
530
531 let stats = LandscapeStatistics::from_history(gradient_history, loss_history);
532 let complexity = stats.complexity();
533 let difficulty = stats.difficulty();
534 let confidence = stats.analysis_confidence(self.confidence_horizon);
535
536 self.landscape_features.smoothness =
539 scirs2_core::numeric::NumCast::from(1.0 - stats.loss_roughness)
540 .unwrap_or_else(|| T::zero());
541 self.landscape_features.multimodality =
542 scirs2_core::numeric::NumCast::from(stats.reversal_rate).unwrap_or_else(|| T::zero());
543 self.landscape_features.noise_level =
544 scirs2_core::numeric::NumCast::from(stats.gradient_norm_cv)
545 .unwrap_or_else(|| T::zero());
546 self.complexity_estimator.computational_complexity =
547 scirs2_core::numeric::NumCast::from(complexity).unwrap_or_else(|| T::zero());
548 self.complexity_estimator.generalization_complexity =
549 scirs2_core::numeric::NumCast::from(difficulty).unwrap_or_else(|| T::zero());
550
551 let high = 0.6;
552 let low = 0.4;
553 let strategy = match (difficulty >= high, complexity >= high) {
554 (true, true) => OptimizationStrategy::Exploratory,
555 (true, false) if complexity <= low => OptimizationStrategy::Aggressive,
556 (false, true) if difficulty <= low => OptimizationStrategy::Conservative,
557 _ if difficulty <= low && complexity <= low => OptimizationStrategy::Exploitative,
558 _ => OptimizationStrategy::Adaptive,
559 };
560
561 self.last_statistics = stats;
562
563 Ok(LandscapeAnalysis {
564 complexity: scirs2_core::numeric::NumCast::from(complexity)
565 .unwrap_or_else(|| T::zero()),
566 difficulty: scirs2_core::numeric::NumCast::from(difficulty)
567 .unwrap_or_else(|| T::zero()),
568 recommended_strategies: vec![strategy],
569 confidence: scirs2_core::numeric::NumCast::from(confidence)
570 .unwrap_or_else(|| T::zero()),
571 })
572 }
573
574 pub fn last_statistics(&self) -> &LandscapeStatistics {
576 &self.last_statistics
577 }
578}
579#[derive(Debug, Clone)]
581pub struct AnalysisResult<
582 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
583> {
584 complexity_score: T,
586}
587#[derive(Debug, Clone, Copy)]
589pub enum AdaptationStrategy {
590 Gradual,
592 Rapid,
594 Conservative,
596 Aggressive,
598 Learned,
600}
601#[derive(Debug, Clone)]
603pub struct AdaptiveConfig<
604 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
605> {
606 pub adaptive_sequence_length: bool,
608 pub max_sequence_length: usize,
610 pub min_sequence_length: usize,
612 pub attention_sparsity_threshold: T,
614 pub memory_budget: usize,
616 pub dynamic_head_pruning: bool,
618 pub layer_adaptation: bool,
620 pub landscape_analysis_frequency: usize,
622 pub prediction_horizon: usize,
624 pub adaptation_lr: T,
626}
627#[derive(Debug, Clone)]
634pub struct AttentionOptimization<
635 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
636> {
637 pub attention_patterns: Array3<T>,
639 pub sparsitylevel: T,
641 pub memory_savings: usize,
643 pub computational_speedup: T,
645}
646#[derive(Debug)]
648pub struct PerformancePrediction<
649 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
650> {
651 pub convergence_improvement: T,
653 pub final_performance: T,
655 pub confidence: T,
657 pub uncertainty: T,
659}
660#[derive(Debug, Clone, Copy)]
662pub enum UncertaintyMethod {
663 MonteCarloDropout,
665 BayesianNN,
667 Ensemble,
669 VariationalInference,
671}
672#[derive(Debug, Clone, Copy)]
674pub enum OptimizationStrategy {
675 Conservative,
676 Aggressive,
677 Adaptive,
678 Exploratory,
679 Exploitative,
680}
681#[derive(Debug)]
683pub struct MemoryUsageTracker {
684 current_usage: usize,
686 peak_usage: usize,
688 budget: usize,
690}
691impl MemoryUsageTracker {
692 fn with_budget(budget: usize) -> Self {
695 Self {
696 current_usage: 0,
697 peak_usage: 0,
698 budget: if budget == 0 { 8192 } else { budget },
699 }
700 }
701
702 pub fn budget(&self) -> usize {
704 self.budget
705 }
706
707 pub fn peak_usage(&self) -> usize {
709 self.peak_usage
710 }
711}
712#[derive(Debug, Clone)]
714pub struct ArchitectureSearchSpace {
715 pub(super) layer_count_range: (usize, usize),
717 pub(super) attention_head_options: Vec<usize>,
719}
720#[derive(Debug, Clone)]
722pub struct ConvergenceMetrics<
723 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
724> {
725 pub convergence_rate: T,
727 pub stability_measure: T,
729 pub plateau_detection: bool,
731 pub oscillation_measure: T,
733}
734pub struct AdaptiveTransformerEnhancement<
736 T: Float + Debug + scirs2_core::ndarray::ScalarOperand + Send + Sync + 'static,
737> {
738 sequence_processor: AdaptiveSequenceProcessor<T>,
740 attention_manager: MemoryEfficientAttentionManager<T>,
742 architecture_adapter: DynamicArchitectureAdapter<T>,
744 landscape_analyzer: OptimizationLandscapeAnalyzer<T>,
746 performance_predictor: TransformerPerformancePredictor<T>,
748 adaptive_config: AdaptiveConfig<T>,
750 grad_second_moment: Array1<T>,
757 step_count: usize,
761 cached_landscape: Option<LandscapeAnalysis<T>>,
763}
764impl<
765 T: Float
766 + Debug
767 + scirs2_core::ndarray::ScalarOperand
768 + Send
769 + Sync
770 + 'static
771 + std::iter::Sum
772 + scirs2_core::numeric::FromPrimitive,
773 > AdaptiveTransformerEnhancement<T>
774{
775 pub fn enhance_optimizer(
791 &mut self,
792 transformer: &mut TransformerOptimizer<T>,
793 gradient_history: &[Array1<T>],
794 losshistory: &[T],
795 ) -> Result<EnhancementResult<T>> {
796 self.architecture_adapter.sync_with(transformer.config());
798
799 let landscape_analysis = self
800 .landscape_analyzer
801 .analyze(gradient_history, losshistory)?;
802 let sequence_adaptation = self
803 .sequence_processor
804 .adapt_to_landscape(&landscape_analysis)?;
805 let attention_optimization = self
806 .attention_manager
807 .optimize_attention(&landscape_analysis)?;
808 let architecture_adaptation = self.architecture_adapter.adapt_architecture(
809 &landscape_analysis,
810 &sequence_adaptation,
811 &attention_optimization,
812 )?;
813 let performance_prediction = self
814 .performance_predictor
815 .predict_improvement(&landscape_analysis, &architecture_adaptation)?;
816
817 let architecture_update =
822 transformer.apply_architecture_config(&architecture_adaptation.adapted_config)?;
823
824 let convergence_metrics = self.calculate_convergence_metrics(losshistory);
825 Ok(EnhancementResult {
826 architecture_update,
827 sequence_adaptation,
828 attention_optimization,
829 architecture_adaptation,
830 performance_prediction,
831 landscape_analysis,
832 convergence_metrics,
833 })
834 }
835}
836impl<
837 T: Float
838 + Debug
839 + scirs2_core::ndarray::ScalarOperand
840 + Send
841 + Sync
842 + 'static
843 + std::iter::Sum,
844 > AdaptiveTransformerEnhancement<T>
845{
846 pub fn new(config: AdaptiveConfig<T>) -> Result<Self> {
847 Ok(Self {
848 sequence_processor: AdaptiveSequenceProcessor::new(&config)?,
849 attention_manager: MemoryEfficientAttentionManager::new(&config)?,
850 architecture_adapter: DynamicArchitectureAdapter::new(&config)?,
851 landscape_analyzer: OptimizationLandscapeAnalyzer::new(&config)?,
852 performance_predictor: TransformerPerformancePredictor::new(&config)?,
853 adaptive_config: config,
854 grad_second_moment: Array1::zeros(0),
855 step_count: 0,
856 cached_landscape: None,
857 })
858 }
859
860 pub fn config(&self) -> &AdaptiveConfig<T> {
862 &self.adaptive_config
863 }
864
865 pub fn train_performance_predictor(
871 &mut self,
872 samples: &[PredictorSample],
873 ) -> Result<PredictorFitReport> {
874 self.performance_predictor.train(samples)
875 }
876
877 pub fn predictor_is_trained(&self) -> bool {
879 self.performance_predictor.is_trained()
880 }
881
882 pub fn gradient_second_moment(&self) -> &Array1<T> {
885 &self.grad_second_moment
886 }
887 pub fn enhanced_optimize_step(
894 &mut self,
895 parameters: &mut Array1<T>,
896 gradients: &Array1<T>,
897 losshistory: &[T],
898 gradient_history: &[Array1<T>],
899 ) -> Result<EnhancementResult<T>> {
900 let frequency = self.adaptive_config.landscape_analysis_frequency.max(1);
901 let refresh = self.cached_landscape.is_none() || self.step_count.is_multiple_of(frequency);
902 let landscape = if refresh {
903 let fresh = self
904 .landscape_analyzer
905 .analyze(gradient_history, losshistory)?;
906 self.cached_landscape = Some(LandscapeAnalysis {
907 complexity: fresh.complexity,
908 difficulty: fresh.difficulty,
909 recommended_strategies: fresh.recommended_strategies.clone(),
910 confidence: fresh.confidence,
911 });
912 fresh
913 } else {
914 match &self.cached_landscape {
915 Some(cached) => LandscapeAnalysis {
916 complexity: cached.complexity,
917 difficulty: cached.difficulty,
918 recommended_strategies: cached.recommended_strategies.clone(),
919 confidence: cached.confidence,
920 },
921 None => self
922 .landscape_analyzer
923 .analyze(gradient_history, losshistory)?,
924 }
925 };
926 let sequence_adaptation = self.sequence_processor.adapt_to_landscape(&landscape)?;
927 let attention_optimization = self.attention_manager.optimize_attention(&landscape)?;
928 let architecture_adaptation = self.architecture_adapter.adapt_architecture(
929 &landscape,
930 &sequence_adaptation,
931 &attention_optimization,
932 )?;
933 let performance_prediction = self
934 .performance_predictor
935 .predict_improvement(&landscape, &architecture_adaptation)?;
936 self.apply_adaptive_updates(
937 parameters,
938 gradients,
939 &sequence_adaptation,
940 &attention_optimization,
941 &architecture_adaptation,
942 )?;
943 Ok(EnhancementResult {
944 landscape_analysis: landscape,
945 sequence_adaptation,
946 attention_optimization,
947 architecture_adaptation,
948 performance_prediction,
949 convergence_metrics: self.calculate_convergence_metrics(losshistory),
950 architecture_update: ArchitectureUpdate::Unchanged,
953 })
954 }
955 fn apply_adaptive_updates(
970 &mut self,
971 parameters: &mut Array1<T>,
972 gradients: &Array1<T>,
973 sequence_adaptation: &SequenceAdaptation<T>,
974 attention_optimization: &AttentionOptimization<T>,
975 architecture_adaptation: &ArchitectureAdaptation<T>,
976 ) -> Result<()> {
977 if parameters.len() != gradients.len() {
978 return Err(crate::error::OptimError::ComputationError(format!(
979 "parameter/gradient length mismatch: {} vs {}",
980 parameters.len(),
981 gradients.len()
982 )));
983 }
984
985 let squash = |v: T| -> T {
988 let x = v.to_f64().unwrap_or(0.0).abs();
989 scirs2_core::numeric::NumCast::from(x / (1.0 + x)).unwrap_or_else(|| T::zero())
990 };
991 let three: T = scirs2_core::numeric::NumCast::from(3.0).unwrap_or_else(|| T::one());
992 let combined_scale = (squash(sequence_adaptation.efficiency_gain)
993 + squash(attention_optimization.computational_speedup)
994 + squash(architecture_adaptation.expected_improvement))
995 / three;
996
997 if self.grad_second_moment.len() != gradients.len() {
999 self.grad_second_moment = Array1::zeros(gradients.len());
1000 }
1001 let beta: T = scirs2_core::numeric::NumCast::from(0.9).unwrap_or_else(|| T::zero());
1002 let one_minus_beta = T::one() - beta;
1003 for (slot, &g) in self.grad_second_moment.iter_mut().zip(gradients.iter()) {
1004 *slot = beta * *slot + one_minus_beta * g * g;
1005 }
1006
1007 self.step_count += 1;
1008 for (i, (param, grad)) in parameters.iter_mut().zip(gradients.iter()).enumerate() {
1009 let adaptive_lr = self.calculate_adaptive_learning_rate(i, combined_scale)?;
1010 *param = *param - adaptive_lr * *grad;
1011 }
1012 Ok(())
1013 }
1014
1015 fn calculate_adaptive_learning_rate(&self, param_index: usize, basescale: T) -> Result<T> {
1029 if param_index >= self.grad_second_moment.len() {
1030 return Err(crate::error::OptimError::ComputationError(format!(
1031 "parameter index {param_index} outside the tracked width {}",
1032 self.grad_second_moment.len()
1033 )));
1034 }
1035 let base_lr = self.adaptive_config.adaptation_lr;
1036 let epsilon: T = scirs2_core::numeric::NumCast::from(1e-8).unwrap_or_else(|| T::zero());
1037
1038 let beta = 0.9_f64;
1040 let correction = 1.0 - beta.powi(self.step_count.max(1) as i32);
1041 let correction_t: T = scirs2_core::numeric::NumCast::from(correction.max(f64::EPSILON))
1042 .unwrap_or_else(|| T::one());
1043 let v_hat = self.grad_second_moment[param_index] / correction_t;
1044
1045 Ok(base_lr * basescale / (v_hat.sqrt() + epsilon))
1046 }
1047 fn calculate_convergence_metrics(&self, losshistory: &[T]) -> ConvergenceMetrics<T> {
1049 if losshistory.len() < 2 {
1050 return ConvergenceMetrics {
1051 convergence_rate: T::zero(),
1052 stability_measure: T::zero(),
1053 plateau_detection: false,
1054 oscillation_measure: T::zero(),
1055 };
1056 }
1057 let recent_losses = &losshistory[losshistory.len().saturating_sub(10)..];
1058 let convergence_rate = if recent_losses.len() >= 2 {
1059 let initial = recent_losses[0];
1060 let final_loss = recent_losses[recent_losses.len() - 1];
1061 if initial > T::zero() {
1062 (initial - final_loss) / initial
1063 } else {
1064 T::zero()
1065 }
1066 } else {
1067 T::zero()
1068 };
1069 let sample_count: T = cast_scalar(recent_losses.len()).unwrap_or_else(|_| T::one());
1072 let mean_loss = recent_losses.iter().cloned().sum::<T>() / sample_count;
1073 let variance = recent_losses
1074 .iter()
1075 .map(|&loss| {
1076 let diff = loss - mean_loss;
1077 diff * diff
1078 })
1079 .sum::<T>()
1080 / sample_count;
1081 let stability_measure = T::one() / (T::one() + variance);
1082 let plateau_threshold =
1083 scirs2_core::numeric::NumCast::from(0.001).unwrap_or_else(|| T::zero());
1084 let plateau_detection = convergence_rate.abs() < plateau_threshold;
1085 let mut oscillation_sum = T::zero();
1086 for i in 1..recent_losses.len() {
1087 oscillation_sum = oscillation_sum + (recent_losses[i] - recent_losses[i - 1]).abs();
1088 }
1089 let oscillation_measure = match cast_scalar::<T, _>(recent_losses.len() - 1) {
1090 Ok(gaps) if gaps > T::zero() => oscillation_sum / gaps,
1091 _ => T::zero(),
1092 };
1093 ConvergenceMetrics {
1094 convergence_rate,
1095 stability_measure,
1096 plateau_detection,
1097 oscillation_measure,
1098 }
1099 }
1100 pub fn update_enhancement_state(
1102 &mut self,
1103 enhancement_result: &EnhancementResult<T>,
1104 ) -> Result<()> {
1105 let cache_key = format!(
1106 "analysis_{}",
1107 enhancement_result
1108 .landscape_analysis
1109 .complexity
1110 .to_f64()
1111 .unwrap_or(0.0)
1112 );
1113 self.landscape_analyzer.analysis_cache.insert(
1114 cache_key,
1115 AnalysisResult {
1116 complexity_score: enhancement_result.landscape_analysis.complexity,
1117 },
1118 );
1119 let performance = ArchitecturePerformance {
1120 final_performance: T::one() - enhancement_result.performance_prediction.uncertainty,
1121 };
1122 self.architecture_adapter
1123 .performance_history
1124 .push_back(performance);
1125 if self.architecture_adapter.performance_history.len() > 100 {
1126 self.architecture_adapter.performance_history.pop_front();
1127 }
1128 Ok(())
1129 }
1130 pub fn get_enhancement_statistics(&self) -> EnhancementStatistics<T> {
1132 let avg_complexity = if !self.landscape_analyzer.analysis_cache.is_empty() {
1133 let sum: T = self
1134 .landscape_analyzer
1135 .analysis_cache
1136 .values()
1137 .map(|result| result.complexity_score)
1138 .sum();
1139 match cast_scalar::<T, _>(self.landscape_analyzer.analysis_cache.len()) {
1140 Ok(count) if count > T::zero() => sum / count,
1141 _ => T::zero(),
1142 }
1143 } else {
1144 scirs2_core::numeric::NumCast::from(0.5).unwrap_or_else(|| T::zero())
1145 };
1146 let avg_performance = if !self.architecture_adapter.performance_history.is_empty() {
1147 let sum: T = self
1148 .architecture_adapter
1149 .performance_history
1150 .iter()
1151 .map(|perf| perf.final_performance)
1152 .sum();
1153 match cast_scalar::<T, _>(self.architecture_adapter.performance_history.len()) {
1154 Ok(count) if count > T::zero() => sum / count,
1155 _ => T::zero(),
1156 }
1157 } else {
1158 scirs2_core::numeric::NumCast::from(0.5).unwrap_or_else(|| T::zero())
1159 };
1160 EnhancementStatistics {
1161 total_enhancements: self.landscape_analyzer.analysis_cache.len(),
1162 average_complexity: avg_complexity,
1163 average_performance: avg_performance,
1164 memory_efficiency: scirs2_core::numeric::NumCast::from(0.8)
1165 .unwrap_or_else(|| T::zero()),
1166 adaptation_success_rate: scirs2_core::numeric::NumCast::from(0.85)
1167 .unwrap_or_else(|| T::zero()),
1168 }
1169 }
1170}
1171#[derive(Debug, Clone, Copy)]
1173pub enum ActivationType {
1174 ReLU,
1175 GELU,
1176 Swish,
1177 Mish,
1178 ELU,
1179 Tanh,
1180}