1use std::collections::{HashMap, VecDeque};
18use std::sync::{Arc, Mutex, RwLock};
19use std::time::{Duration, Instant, SystemTime};
20
21use quantrs2_circuit::prelude::*;
22use quantrs2_core::{
23 error::{QuantRS2Error, QuantRS2Result},
24 quantum_universal_framework::{
25 ErrorRecovery, ExecutionStrategy, FeedbackControl, PerformanceTuning, RuntimeOptimization,
26 },
27 qubit::QubitId,
28};
29use scirs2_core::ndarray::{Array1, Array2, ArrayView1, ArrayView2};
30
31use crate::{job_scheduling::*, translation::HardwareBackend, DeviceError, DeviceResult};
32
33#[path = "advanced_scheduling_priority.rs"]
38pub(crate) mod priority;
39
40#[path = "advanced_scheduling_analytics.rs"]
45mod analytics;
46
47type AnomalyDetector = String;
49type CapacityPlanner = String;
50type CostPredictor = String;
51type ROIOptimizer = String;
52type MarketAnalyzer = String;
53type ObjectiveFunction = String;
54type NeuralNetwork = String;
55type ResourceManager = String;
56type ExecutionEngine = String;
57type MonitoringSystem = String;
58type AlertingSystem = String;
59type ComplianceMonitor = String;
60type SLAMonitor = String;
61type FairnessAnalyzer = String;
62type EnergyConsumptionModel = String;
63type EnergyEfficiencyOptimizer = String;
64
65#[derive(Debug, Clone, PartialEq, Eq)]
67pub enum MitigationUrgency {
68 Immediate,
69 High,
70 Medium,
71 Low,
72}
73type GreenComputingMetrics = String;
74type SLAConfiguration = String;
75type MitigationStrategyEngine = String;
76type ComplianceTracker = String;
77type PenaltyManager = String;
78type PlatformMonitor = String;
79type LoadBalancingEngine = String;
80type AutoScalingSystem = String;
81
82type AdaptationStrategy = String;
84type AllocationFairnessManager = String;
85type AllocationOptimization = String;
86type AllocationResults = String;
87type AuctionBasedScheduler = String;
88type AuctionMechanism = String;
89type BasePricingModel = String;
90type BudgetAlert = String;
91type CarbonOffsetProgram = String;
92type CircuitMigrator = String;
93type CoalitionFormation = String;
94type ConceptDriftDetector = String;
95type ConstraintManager = String;
96type DemandPredictor = String;
97type DemandResponseProgram = String;
98type DistributionType = String;
99type DiversityMetrics = String;
100type EarlyWarningSystem = String;
101type EmergencyResponseSystem = String;
102
103type PredictionModel = String;
105type ProjectBudget = String;
106type RenewableForecast = String;
107type RenewableSchedule = String;
108type RewardFunction = String;
109type RiskAssessment = String;
110type SocialWelfareOptimizer = String;
111type SolutionArchive = String;
112type SpendingForecast = String;
113type StreamingModel = String;
114type SustainabilityGoals = String;
115type TrainingEpoch = String;
116type UserBehaviorAnalyzer = String;
117type UserBudget = String;
118type UserPreferences = String;
119type UtilizationPricingModel = String;
120type ValueNetwork = String;
121type ViolationRecord = String;
122type ViolationType = String;
123
124type BaselineMetric = String;
126type CharacterizationProtocol = String;
127type EnsembleStrategy = String;
128type ExperienceBuffer = String;
129type ExplorationStrategy = String;
130type FeatureExtractor = String;
131type FeatureScaler = String;
132type FeatureSelector = String;
133type FeatureTransformer = String;
134type ForecastingModel = String;
135type ModelPerformanceMetrics = String;
136type OnlinePerformanceMonitor = String;
137type OrganizationalBudget = String;
138type PolicyNetwork = String;
139type IncentiveMechanism = String;
140type EmissionFactor = String;
141type EmissionRecord = String;
142type MLAlgorithm = String;
143type EnergyStorageSystem = String;
144type MechanismDesign = String;
145type NashEquilibriumSolver = String;
146type PredictedViolation = String;
147#[derive(Debug, Clone)]
148pub struct MitigationStrategy {
149 pub strategy_type: String,
150 pub urgency: MitigationUrgency,
151 pub description: String,
152 pub estimated_effectiveness: f64,
153}
154type EnergyMetrics = String;
155type FairnessMetrics = String;
156type NSGAOptimizer = String;
157type PerformancePredictor = String;
158
159#[cfg(feature = "scirs2")]
161use scirs2_graph::{
162 betweenness_centrality, closeness_centrality, dijkstra_path, louvain_communities_result,
163 minimum_spanning_tree, pagerank, strongly_connected_components, Graph,
164};
165#[cfg(feature = "scirs2")]
166use scirs2_linalg::{eig, matrix_norm, svd, trace, LinalgResult};
167#[cfg(feature = "scirs2")]
168use scirs2_optimize::{
169 differential_evolution, dual_annealing, least_squares, minimize, OptimizeResult,
170};
171#[cfg(feature = "scirs2")]
172use scirs2_stats::{
173 corrcoef,
174 distributions::{chi2, gamma, norm},
175 ks_2samp, mean, pearsonr, spearmanr, std, var,
176};
177
178#[cfg(not(feature = "scirs2"))]
180mod fallback_scirs2 {
181 use scirs2_core::ndarray::{Array1, Array2, ArrayView1, ArrayView2};
182
183 pub fn mean(_data: &ArrayView1<f64>) -> f64 {
184 0.0
185 }
186 pub fn std(_data: &ArrayView1<f64>, _ddof: i32) -> f64 {
187 1.0
188 }
189 pub fn pearsonr(_x: &ArrayView1<f64>, _y: &ArrayView1<f64>) -> (f64, f64) {
190 (0.0, 0.5)
191 }
192
193 pub struct OptimizeResult {
194 pub x: Array1<f64>,
195 pub fun: f64,
196 pub success: bool,
197 }
198
199 pub fn minimize<F>(_func: F, _x0: &Array1<f64>) -> OptimizeResult
200 where
201 F: Fn(&Array1<f64>) -> f64,
202 {
203 OptimizeResult {
204 x: Array1::zeros(2),
205 fun: 0.0,
206 success: false,
207 }
208 }
209}
210
211#[cfg(not(feature = "scirs2"))]
212use fallback_scirs2::*;
213
214pub struct AdvancedQuantumScheduler {
216 core_scheduler: Arc<QuantumJobScheduler>,
218 decision_engine: Arc<Mutex<DecisionEngine>>,
220 multi_objective_optimizer: Arc<Mutex<MultiObjectiveScheduler>>,
222 predictive_engine: Arc<Mutex<PredictiveSchedulingEngine>>,
224 cost_optimizer: Arc<Mutex<AdvancedCostOptimizer>>,
226 energy_optimizer: Arc<Mutex<AdvancedEnergyOptimizer>>,
228 sla_manager: Arc<Mutex<AdvancedSLAManager>>,
230 adaptation_engine: Arc<Mutex<RealTimeAdaptationEngine>>,
232 fairness_engine: Arc<Mutex<FairnessEngine>>,
234}
235
236struct DecisionEngine {
238 models: HashMap<String, MLModel>,
240 feature_pipeline: FeaturePipeline,
242 ensemble: ModelEnsemble,
244 rl_agent: ReinforcementLearningAgent,
246 online_learner: OnlineLearningSystem,
248}
249
250#[derive(Debug, Clone)]
252struct JobAssignment {
253 job_id: String,
254 backend: String,
255 priority: f64,
256 estimated_runtime: Duration,
257}
258
259#[derive(Debug, Clone)]
261struct ParetoSolution {
262 objectives: Vec<f64>,
263 schedule: HashMap<String, JobAssignment>,
264 quality_score: f64,
265}
266
267struct MultiObjectiveScheduler {
269 objectives: Vec<ObjectiveFunction>,
271 pareto_solutions: Vec<ParetoSolution>,
273 nsga_optimizer: Option<String>,
275 constraint_manager: Option<String>,
277 solution_archive: Vec<ParetoSolution>,
279}
280
281struct PredictiveSchedulingEngine {
283 forecasting_models: HashMap<HardwareBackend, String>,
285 demand_predictor: Option<String>,
287 performance_predictor: Option<String>,
289 anomaly_detector: AnomalyDetector,
291 capacity_planner: CapacityPlanner,
293}
294
295struct AdvancedCostOptimizer {
297 pricing_models: HashMap<HardwareBackend, DynamicPricingModel>,
299 budget_manager: BudgetManager,
301 cost_predictors: HashMap<String, CostPredictor>,
303 roi_optimizer: ROIOptimizer,
305 market_analyzer: MarketAnalyzer,
307}
308
309struct AdvancedEnergyOptimizer {
311 energy_models: HashMap<HardwareBackend, EnergyConsumptionModel>,
313 carbon_tracker: CarbonFootprintTracker,
315 renewable_scheduler: RenewableEnergyScheduler,
317 efficiency_optimizer: EnergyEfficiencyOptimizer,
319 green_metrics: GreenComputingMetrics,
321}
322
323struct AdvancedSLAManager {
325 sla_configs: HashMap<String, SLAConfiguration>,
327 violation_predictor: ViolationPredictor,
329 mitigation_engine: MitigationStrategyEngine,
331 compliance_tracker: ComplianceTracker,
333 penalty_manager: PenaltyManager,
335}
336
337struct RealTimeAdaptationEngine {
339 platform_monitor: PlatformMonitor,
341 load_balancer: LoadBalancingEngine,
343 auto_scaler: AutoScalingSystem,
345 circuit_migrator: CircuitMigrator,
347 emergency_responder: EmergencyResponseSystem,
349}
350
351struct FairnessEngine {
353 game_scheduler: GameTheoreticScheduler,
355 allocation_fairness: AllocationFairnessManager,
357 behavior_analyzer: UserBehaviorAnalyzer,
359 incentive_designer: IncentiveMechanism,
361 welfare_optimizer: SocialWelfareOptimizer,
363}
364
365#[derive(Debug, Clone)]
367struct MLModel {
368 model_id: String,
369 algorithm: MLAlgorithm,
370 parameters: HashMap<String, f64>,
371 feature_importance: HashMap<String, f64>,
372 performance_metrics: ModelPerformanceMetrics,
373 training_history: Vec<TrainingEpoch>,
374 last_updated: SystemTime,
375}
376
377#[derive(Debug, Clone, Default)]
379struct FeaturePipeline {
380 extractors: Vec<FeatureExtractor>,
381 transformers: Vec<FeatureTransformer>,
382 selectors: Vec<FeatureSelector>,
383 scalers: Vec<FeatureScaler>,
384}
385
386#[derive(Debug, Clone, Default)]
388struct ModelEnsemble {
389 base_models: Vec<String>,
390 meta_learner: Option<String>,
391 combination_strategy: EnsembleStrategy,
392 weights: Vec<f64>,
393 diversity_metrics: DiversityMetrics,
394}
395
396#[derive(Debug, Clone, Default)]
398struct ReinforcementLearningAgent {
399 policy_network: PolicyNetwork,
400 value_network: ValueNetwork,
401 experience_buffer: ExperienceBuffer,
402 exploration_strategy: ExplorationStrategy,
403 reward_function: RewardFunction,
404}
405
406#[derive(Debug, Clone, Default)]
408struct OnlineLearningSystem {
409 streaming_models: HashMap<String, StreamingModel>,
410 concept_drift_detector: ConceptDriftDetector,
411 adaptation_strategies: Vec<AdaptationStrategy>,
412 performance_monitor: OnlinePerformanceMonitor,
413}
414
415#[derive(Debug, Clone)]
417struct DynamicPricingModel {
418 base_pricing: BasePricingModel,
419 demand_elasticity: f64,
420 time_based_multipliers: HashMap<u8, f64>, utilization_pricing: UtilizationPricingModel,
422 auction_mechanism: Option<AuctionMechanism>,
423}
424
425#[derive(Debug, Clone, Default)]
427struct BudgetManager {
428 user_budgets: HashMap<String, UserBudget>,
429 project_budgets: HashMap<String, ProjectBudget>,
430 organizational_budget: OrganizationalBudget,
431 budget_alerts: Vec<BudgetAlert>,
432 spending_forecasts: HashMap<String, SpendingForecast>,
433}
434
435#[derive(Debug, Clone, Default)]
437struct CarbonFootprintTracker {
438 emission_factors: HashMap<HardwareBackend, EmissionFactor>,
439 total_emissions: f64,
440 emission_history: VecDeque<EmissionRecord>,
441 carbon_offset_programs: Vec<CarbonOffsetProgram>,
442 sustainability_goals: SustainabilityGoals,
443}
444
445#[derive(Debug, Clone, Default)]
447struct RenewableEnergyScheduler {
448 renewable_forecasts: HashMap<String, RenewableForecast>,
449 grid_carbon_intensity: HashMap<String, f64>,
450 energy_storage_systems: Vec<EnergyStorageSystem>,
451 demand_response_programs: Vec<DemandResponseProgram>,
452}
453
454#[derive(Debug, Clone, Default)]
456struct ViolationPredictor {
457 prediction_models: HashMap<ViolationType, PredictionModel>,
458 early_warning_system: EarlyWarningSystem,
459 risk_assessment: RiskAssessment,
460 historical_violations: VecDeque<ViolationRecord>,
461}
462
463#[derive(Debug, Clone, Default)]
465struct GameTheoreticScheduler {
466 mechanism_design: MechanismDesign,
467 auction_scheduler: AuctionBasedScheduler,
468 coalition_formation: CoalitionFormation,
469 nash_equilibrium_solver: NashEquilibriumSolver,
470}
471
472impl AdvancedQuantumScheduler {
473 pub fn new(params: SchedulingParams) -> Self {
475 let core_scheduler = Arc::new(QuantumJobScheduler::new(params));
476
477 Self {
478 core_scheduler,
479 decision_engine: Arc::new(Mutex::new(DecisionEngine::new())),
480 multi_objective_optimizer: Arc::new(Mutex::new(MultiObjectiveScheduler::new())),
481 predictive_engine: Arc::new(Mutex::new(PredictiveSchedulingEngine::new())),
482 cost_optimizer: Arc::new(Mutex::new(AdvancedCostOptimizer::new())),
483 energy_optimizer: Arc::new(Mutex::new(AdvancedEnergyOptimizer::new())),
484 sla_manager: Arc::new(Mutex::new(AdvancedSLAManager::new())),
485 adaptation_engine: Arc::new(Mutex::new(RealTimeAdaptationEngine::new())),
486 fairness_engine: Arc::new(Mutex::new(FairnessEngine::new())),
487 }
488 }
489
490 pub async fn submit_intelligent_job<const N: usize>(
492 &self,
493 circuit: Circuit<N>,
494 shots: usize,
495 config: JobConfig,
496 user_id: String,
497 ) -> DeviceResult<JobId> {
498 let features = self
500 .extract_job_features(&circuit, shots, &config, &user_id)
501 .await?;
502
503 let optimized_config = self.optimize_job_config(config, &features).await?;
505
506 let execution_strategy = self.predict_execution_strategy(&features).await?;
508
509 let job_id = self
511 .core_scheduler
512 .submit_job(circuit, shots, optimized_config, user_id)
513 .await?;
514
515 self.register_for_advanced_monitoring(&job_id.to_string(), execution_strategy)
517 .await?;
518
519 Ok(job_id)
520 }
521
522 pub async fn select_optimal_backend(
524 &self,
525 job_requirements: &JobRequirements,
526 user_preferences: &UserPreferences,
527 ) -> DeviceResult<HardwareBackend> {
528 let multi_obj = self
529 .multi_objective_optimizer
530 .lock()
531 .unwrap_or_else(std::sync::PoisonError::into_inner);
532
533 let objectives = vec![
535 ("performance".to_string(), 0.3),
536 ("cost".to_string(), 0.25),
537 ("energy".to_string(), 0.2),
538 ("availability".to_string(), 0.15),
539 ("fairness".to_string(), 0.1),
540 ];
541
542 #[cfg(feature = "scirs2")]
544 {
545 let backend_scores = self.evaluate_backends(job_requirements).await?;
546 let optimal_backend = self
547 .scirs2_backend_optimization(&backend_scores, &objectives)
548 .await?;
549 Ok(optimal_backend)
550 }
551
552 #[cfg(not(feature = "scirs2"))]
553 {
554 self.simple_backend_selection(job_requirements).await
556 }
557 }
558
559 pub async fn predict_queue_times(&self) -> DeviceResult<HashMap<HardwareBackend, Duration>> {
561 let predictive_engine = self
562 .predictive_engine
563 .lock()
564 .unwrap_or_else(std::sync::PoisonError::into_inner);
565
566 #[cfg(feature = "scirs2")]
567 {
568 let mut predictions = HashMap::new();
569
570 for backend in self.get_available_backends().await? {
571 let historical_data = self.get_historical_queue_data(&backend).await?;
573 let forecast = self.scirs2_time_series_forecast(&historical_data).await?;
574 predictions.insert(backend, forecast);
575 }
576
577 Ok(predictions)
578 }
579
580 #[cfg(not(feature = "scirs2"))]
581 {
582 let mut predictions = HashMap::new();
584 for backend in self.get_available_backends().await? {
585 predictions.insert(backend, Duration::from_secs(300)); }
587 Ok(predictions)
588 }
589 }
590
591 pub async fn dynamic_load_balance(&self) -> DeviceResult<()> {
593 let adaptation_engine = self
594 .adaptation_engine
595 .lock()
596 .unwrap_or_else(std::sync::PoisonError::into_inner);
597
598 let platform_metrics = self.collect_platform_metrics().await?;
600
601 let anomalies = self.detect_performance_anomalies(&platform_metrics).await?;
603
604 if !anomalies.is_empty() {
605 self.apply_load_balancing_strategies(&anomalies).await?;
607
608 self.migrate_circuits_if_needed(&anomalies).await?;
610
611 self.update_routing_policies(&platform_metrics).await?;
613 }
614
615 Ok(())
616 }
617
618 pub async fn monitor_sla_compliance(&self) -> DeviceResult<SLAComplianceReport> {
620 let sla_manager = self
621 .sla_manager
622 .lock()
623 .unwrap_or_else(std::sync::PoisonError::into_inner);
624
625 let job_metrics = self.collect_job_metrics().await?;
627
628 let predicted_violations = self.predict_sla_violations(&job_metrics).await?;
630
631 let mitigation_strategies = self
633 .generate_mitigation_strategies(&predicted_violations)
634 .await?;
635
636 for strategy in &mitigation_strategies {
638 if strategy.urgency == MitigationUrgency::Immediate {
639 self.execute_mitigation_strategy(strategy).await?;
640 }
641 }
642
643 Ok(SLAComplianceReport {
644 current_compliance: self.calculate_current_compliance().await?,
645 predicted_violations,
646 mitigation_strategies,
647 recommendations: self.generate_sla_recommendations().await?,
648 })
649 }
650
651 pub async fn optimize_costs(&self) -> DeviceResult<CostOptimizationReport> {
653 let cost_optimizer = self
654 .cost_optimizer
655 .lock()
656 .unwrap_or_else(std::sync::PoisonError::into_inner);
657
658 let spending_analysis = self.analyze_spending_patterns().await?;
660
661 self.update_dynamic_pricing().await?;
663
664 let allocation_optimizations = self.optimize_cost_allocations().await?;
666
667 let budget_recommendations = self
669 .generate_budget_recommendations(&spending_analysis)
670 .await?;
671
672 Ok(CostOptimizationReport {
673 current_costs: spending_analysis,
674 optimizations: allocation_optimizations,
675 savings_potential: self.calculate_savings_potential().await?,
676 recommendations: budget_recommendations,
677 })
678 }
679
680 pub async fn optimize_energy_consumption(&self) -> DeviceResult<EnergyOptimizationReport> {
682 let energy_optimizer = self
683 .energy_optimizer
684 .lock()
685 .unwrap_or_else(std::sync::PoisonError::into_inner);
686
687 let energy_metrics = self.collect_energy_metrics().await?;
689
690 let renewable_schedule = self.optimize_renewable_schedule().await?;
692
693 let carbon_reduction = self.calculate_carbon_reduction_opportunities().await?;
695
696 let efficiency_recommendations = self.generate_energy_recommendations().await?;
698
699 Ok(EnergyOptimizationReport {
700 current_consumption: energy_metrics,
701 renewable_optimization: renewable_schedule,
702 carbon_reduction_potential: carbon_reduction,
703 efficiency_recommendations,
704 sustainability_score: self.calculate_sustainability_score().await?,
705 })
706 }
707
708 pub async fn apply_fair_scheduling(&self) -> DeviceResult<FairnessReport> {
710 let fairness_engine = self
711 .fairness_engine
712 .lock()
713 .unwrap_or_else(std::sync::PoisonError::into_inner);
714
715 let user_analysis = self.analyze_user_behavior().await?;
717
718 let allocation_results = self.apply_game_theoretic_allocation(&user_analysis).await?;
720
721 let fairness_metrics = self.calculate_fairness_metrics(&allocation_results).await?;
723
724 let incentive_mechanisms = self.design_incentive_mechanisms(&user_analysis).await?;
726
727 Ok(FairnessReport {
728 fairness_metrics,
729 allocation_results,
730 incentive_mechanisms,
731 user_satisfaction_scores: self.calculate_user_satisfaction().await?,
732 recommendations: self.generate_fairness_recommendations().await?,
733 })
734 }
735
736 async fn extract_job_features<const N: usize>(
739 &self,
740 circuit: &Circuit<N>,
741 shots: usize,
742 config: &JobConfig,
743 user_id: &str,
744 ) -> DeviceResult<JobFeatures> {
745 Ok(JobFeatures {
747 circuit_depth: circuit.gates().len(), gate_count: circuit.gates().len(),
749 qubit_count: N,
750 shots,
751 priority: config.priority as i32,
752 user_historical_behavior: self.get_user_behavior_features(user_id).await?,
753 time_features: self.extract_temporal_features().await?,
754 platform_features: self.extract_platform_features().await?,
755 })
756 }
757
758 async fn optimize_job_config(
759 &self,
760 mut config: JobConfig,
761 features: &JobFeatures,
762 ) -> DeviceResult<JobConfig> {
763 let decision_engine = self
765 .decision_engine
766 .lock()
767 .unwrap_or_else(std::sync::PoisonError::into_inner);
768
769 config.resource_requirements = self.predict_optimal_resources(features).await?;
771
772 config.retry_attempts = self.predict_optimal_retries(features).await?;
774
775 config.max_execution_time = self.predict_optimal_timeout(features).await?;
777
778 Ok(config)
779 }
780
781 #[cfg(feature = "scirs2")]
782 async fn scirs2_time_series_forecast(
783 &self,
784 historical_data: &Array1<f64>,
785 ) -> DeviceResult<Duration> {
786 let forecast = mean(&historical_data.view());
789 let forecast_value = forecast.unwrap_or(0.0);
790 Ok(Duration::from_secs(forecast_value as u64))
791 }
792
793 #[cfg(feature = "scirs2")]
794 async fn scirs2_backend_optimization(
795 &self,
796 backend_scores: &Vec<BackendScore>,
797 objectives: &[(String, f64)],
798 ) -> DeviceResult<HardwareBackend> {
799 backend_scores
804 .first()
805 .map(|_| HardwareBackend::IBMQuantum)
806 .ok_or_else(|| DeviceError::APIError("No backends available".to_string()))
807 }
808
809 async fn predict_execution_strategy(
820 &self,
821 _features: &JobFeatures,
822 ) -> DeviceResult<ExecutionStrategy> {
823 Ok(ExecutionStrategy)
824 }
825
826 async fn register_for_advanced_monitoring(
833 &self,
834 job_id: &str,
835 _execution_strategy: ExecutionStrategy,
836 ) -> DeviceResult<()> {
837 if job_id.trim().is_empty() {
838 return Err(DeviceError::InvalidInput(
839 "register_for_advanced_monitoring: job_id must not be empty".to_string(),
840 ));
841 }
842 let _ = self.get_available_backends().await?;
846 Ok(())
847 }
848
849 async fn evaluate_backends(
851 &self,
852 job_requirements: &JobRequirements,
853 ) -> DeviceResult<Vec<BackendScore>> {
854 let backends = self.get_available_backends().await?;
855 let mut backend_scores = Vec::new();
856
857 for backend in backends {
858 let mut factors = HashMap::new();
860 factors.insert("performance".to_string(), 0.8);
861 factors.insert("cost".to_string(), 0.7);
862 factors.insert("energy".to_string(), 0.6);
863 factors.insert("availability".to_string(), 0.9);
864 factors.insert("fairness".to_string(), 0.8);
865
866 let score = BackendScore {
867 backend_name: format!("{backend:?}"),
868 score: 0.76, factors,
870 };
871 backend_scores.push(score);
872 }
873
874 Ok(backend_scores)
875 }
876
877 async fn get_available_backends(&self) -> DeviceResult<Vec<HardwareBackend>> {
879 let backends = self.core_scheduler.get_available_backends();
880 if backends.is_empty() {
881 Err(DeviceError::APIError("No backends available".to_string()))
882 } else {
883 Ok(backends)
884 }
885 }
886
887 async fn get_historical_queue_data(
889 &self,
890 backend: &HardwareBackend,
891 ) -> DeviceResult<Array1<f64>> {
892 Ok(Array1::zeros(10))
894 }
895
896 async fn collect_platform_metrics(&self) -> DeviceResult<PlatformMetrics> {
898 Ok(PlatformMetrics::default())
900 }
901
902 async fn detect_performance_anomalies(
911 &self,
912 metrics: &PlatformMetrics,
913 ) -> DeviceResult<Vec<PerformanceAnomaly>> {
914 let mut anomalies: Vec<PerformanceAnomaly> = Vec::new();
915
916 const CPU_HIGH: f64 = 0.85;
919 const MEM_HIGH: f64 = 0.85;
920 const QUEUE_LONG: usize = 50;
921 const EXEC_LONG_SECS: f64 = 30.0;
922
923 if metrics.cpu_usage > CPU_HIGH {
924 let severity = ((metrics.cpu_usage - CPU_HIGH) / (1.0 - CPU_HIGH)).clamp(0.0, 1.0);
925 anomalies.push(PerformanceAnomaly {
926 anomaly_type: "high_cpu_usage".to_string(),
927 severity,
928 description: format!(
929 "CPU usage {:.3} exceeds threshold {:.2}",
930 metrics.cpu_usage, CPU_HIGH
931 ),
932 recommendations: vec![
933 "Throttle or migrate compute-intensive jobs".to_string(),
934 "Scale out execution workers".to_string(),
935 ],
936 });
937 }
938
939 if metrics.memory_usage > MEM_HIGH {
940 let severity = ((metrics.memory_usage - MEM_HIGH) / (1.0 - MEM_HIGH)).clamp(0.0, 1.0);
941 anomalies.push(PerformanceAnomaly {
942 anomaly_type: "high_memory_usage".to_string(),
943 severity,
944 description: format!(
945 "Memory usage {:.3} exceeds threshold {:.2}",
946 metrics.memory_usage, MEM_HIGH
947 ),
948 recommendations: vec![
949 "Trigger garbage collection of cached state".to_string(),
950 "Reduce concurrent job parallelism".to_string(),
951 ],
952 });
953 }
954
955 if metrics.queue_length > QUEUE_LONG {
956 let severity =
957 ((metrics.queue_length as f64 - QUEUE_LONG as f64) / QUEUE_LONG as f64).min(1.0);
958 anomalies.push(PerformanceAnomaly {
959 anomaly_type: "queue_backlog".to_string(),
960 severity,
961 description: format!(
962 "Queue length {} exceeds threshold {QUEUE_LONG}",
963 metrics.queue_length
964 ),
965 recommendations: vec![
966 "Re-route jobs to backends with shorter queues".to_string(),
967 "Apply backpressure on submission".to_string(),
968 ],
969 });
970 }
971
972 let exec_secs = metrics.average_execution_time.as_secs_f64();
973 if exec_secs > EXEC_LONG_SECS {
974 let severity = ((exec_secs - EXEC_LONG_SECS) / EXEC_LONG_SECS).min(1.0);
975 anomalies.push(PerformanceAnomaly {
976 anomaly_type: "slow_execution".to_string(),
977 severity,
978 description: format!(
979 "Average execution time {exec_secs:.2}s exceeds threshold {EXEC_LONG_SECS:.2}s"
980 ),
981 recommendations: vec![
982 "Apply circuit transpilation passes".to_string(),
983 "Consider migrating workload to a faster backend".to_string(),
984 ],
985 });
986 }
987
988 anomalies.sort_by(|a, b| {
991 b.severity
992 .partial_cmp(&a.severity)
993 .unwrap_or(std::cmp::Ordering::Equal)
994 });
995
996 Ok(anomalies)
997 }
998
999 async fn apply_load_balancing_strategies(
1001 &self,
1002 anomalies: &[PerformanceAnomaly],
1003 ) -> DeviceResult<()> {
1004 if anomalies.is_empty() {
1005 return Ok(());
1006 }
1007 self.core_scheduler.sort_queues_by_duration().await
1010 }
1011
1012 async fn migrate_circuits_if_needed(
1016 &self,
1017 anomalies: &[PerformanceAnomaly],
1018 ) -> DeviceResult<()> {
1019 let needs_migration = anomalies
1020 .iter()
1021 .any(|a| a.anomaly_type == "queue_backlog" && a.severity > 0.5);
1022 if needs_migration {
1023 self.core_scheduler.bin_pack_jobs().await?;
1024 }
1025 Ok(())
1026 }
1027
1028 async fn update_routing_policies(&self, metrics: &PlatformMetrics) -> DeviceResult<()> {
1032 if metrics.queue_length > 0 {
1033 self.core_scheduler.sort_queues_by_duration().await?;
1034 }
1035 Ok(())
1036 }
1037
1038 async fn design_incentive_mechanisms(
1040 &self,
1041 analysis: &UserAnalysis,
1042 ) -> DeviceResult<Vec<IncentiveMechanism>> {
1043 Ok(vec![])
1045 }
1046
1047 async fn calculate_user_satisfaction(&self) -> DeviceResult<HashMap<String, f64>> {
1049 Ok(HashMap::new())
1051 }
1052
1053 async fn generate_fairness_recommendations(&self) -> DeviceResult<Vec<String>> {
1055 Ok(vec!["Maintain fair resource allocation".to_string()])
1057 }
1058
1059 #[cfg(not(feature = "scirs2"))]
1061 async fn simple_backend_selection(
1062 &self,
1063 requirements: &crate::job_scheduling::ResourceRequirements,
1064 ) -> DeviceResult<HardwareBackend> {
1065 Ok(HardwareBackend::Custom(0))
1067 }
1068
1069 async fn get_user_behavior_features(
1071 &self,
1072 user_id: &str,
1073 ) -> DeviceResult<UserBehaviorFeatures> {
1074 Ok(UserBehaviorFeatures {
1075 avg_job_complexity: 1.0,
1076 submission_frequency: 0.5,
1077 resource_utilization_efficiency: 0.8,
1078 sla_compliance_history: 0.95,
1079 })
1080 }
1081
1082 async fn extract_temporal_features(&self) -> DeviceResult<TemporalFeatures> {
1084 Ok(TemporalFeatures {
1085 hour_of_day: 12,
1086 day_of_week: 3,
1087 is_weekend: false,
1088 is_holiday: false,
1089 time_since_last_job: Duration::from_secs(300),
1090 })
1091 }
1092
1093 async fn extract_platform_features(&self) -> DeviceResult<PlatformFeatures> {
1095 Ok(PlatformFeatures {
1096 average_queue_length: 5.0,
1097 platform_utilization: 0.7,
1098 recent_performance_metrics: HashMap::new(),
1099 error_rates: HashMap::new(),
1100 })
1101 }
1102
1103 async fn predict_optimal_resources(
1105 &self,
1106 features: &JobFeatures,
1107 ) -> DeviceResult<crate::job_scheduling::ResourceRequirements> {
1108 Ok(crate::job_scheduling::ResourceRequirements {
1109 min_qubits: features.qubit_count,
1110 max_depth: None,
1111 min_fidelity: None,
1112 required_connectivity: None,
1113 cpu_cores: Some(1),
1114 memory_mb: Some(1024),
1115 required_features: Vec::new(),
1116 })
1117 }
1118
1119 async fn predict_optimal_retries(&self, features: &JobFeatures) -> DeviceResult<u32> {
1127 let retries = match features.priority {
1130 x if x <= JobPriority::Critical as i32 => 5,
1131 x if x == JobPriority::High as i32 => 4,
1132 x if x == JobPriority::Normal as i32 => 3,
1133 x if x == JobPriority::Low as i32 => 2,
1134 _ => 1, };
1136 Ok(retries)
1137 }
1138
1139 async fn predict_optimal_timeout(&self, features: &JobFeatures) -> DeviceResult<Duration> {
1147 const BASELINE_SECS: f64 = 60.0;
1148 const PER_GATE_SHOT_SECS: f64 = 1.0e-3;
1149 const MAX_TIMEOUT_SECS: f64 = 6.0 * 3600.0;
1150
1151 let gate_shot_secs =
1152 (features.gate_count as f64) * (features.shots as f64) * PER_GATE_SHOT_SECS;
1153 let total = (BASELINE_SECS + gate_shot_secs).clamp(BASELINE_SECS, MAX_TIMEOUT_SECS);
1154 Ok(Duration::from_secs_f64(total))
1155 }
1156
1157 pub async fn register_backend(&self, backend: HardwareBackend) -> DeviceResult<()> {
1159 self.core_scheduler.register_backend(backend).await
1160 }
1161
1162 pub fn get_available_backends_debug(&self) -> Vec<HardwareBackend> {
1164 self.core_scheduler.get_available_backends()
1165 }
1166}
1167
1168#[derive(Debug, Clone, Default)]
1170pub struct JobRequirements {
1171 pub min_qubits: usize,
1172 pub max_execution_time: Duration,
1173 pub priority: JobPriority,
1174}
1175
1176#[derive(Debug, Clone, Default)]
1177pub struct JobMetrics {
1178 pub job_id: String,
1179 pub execution_time: Duration,
1180 pub success_rate: f64,
1181 pub resource_usage: f64,
1182}
1183
1184#[derive(Debug, Clone, Default)]
1185pub struct UserAnalysis {
1186 pub user_patterns: HashMap<String, f64>,
1187 pub resource_preferences: HashMap<String, f64>,
1188}
1189
1190#[derive(Debug, Clone, Default)]
1191pub struct SpendingAnalysis {
1192 pub total_cost: f64,
1193 pub cost_breakdown: HashMap<String, f64>,
1194 pub trends: Vec<f64>,
1195}
1196
1197#[derive(Debug, Clone)]
1198pub struct BackendScore {
1199 pub backend_name: String,
1200 pub score: f64,
1201 pub factors: HashMap<String, f64>,
1202}
1203
1204#[derive(Debug, Clone, Default)]
1205pub struct PlatformMetrics {
1206 pub cpu_usage: f64,
1207 pub memory_usage: f64,
1208 pub queue_length: usize,
1209 pub average_execution_time: Duration,
1210}
1211
1212#[derive(Debug, Clone)]
1213pub struct PerformanceAnomaly {
1214 pub anomaly_type: String,
1215 pub severity: f64,
1216 pub description: String,
1217 pub recommendations: Vec<String>,
1218}
1219
1220#[derive(Debug, Clone)]
1223struct JobFeatures {
1224 circuit_depth: usize,
1225 gate_count: usize,
1226 qubit_count: usize,
1227 shots: usize,
1228 priority: i32,
1229 user_historical_behavior: UserBehaviorFeatures,
1230 time_features: TemporalFeatures,
1231 platform_features: PlatformFeatures,
1232}
1233
1234#[derive(Debug, Clone)]
1235struct UserBehaviorFeatures {
1236 avg_job_complexity: f64,
1237 submission_frequency: f64,
1238 resource_utilization_efficiency: f64,
1239 sla_compliance_history: f64,
1240}
1241
1242#[derive(Debug, Clone)]
1243struct TemporalFeatures {
1244 hour_of_day: u8,
1245 day_of_week: u8,
1246 is_weekend: bool,
1247 is_holiday: bool,
1248 time_since_last_job: Duration,
1249}
1250
1251#[derive(Debug, Clone)]
1252struct PlatformFeatures {
1253 average_queue_length: f64,
1254 platform_utilization: f64,
1255 recent_performance_metrics: HashMap<HardwareBackend, f64>,
1256 error_rates: HashMap<HardwareBackend, f64>,
1257}
1258
1259#[derive(Debug, Clone)]
1260pub struct SLAComplianceReport {
1261 pub current_compliance: f64,
1262 pub predicted_violations: Vec<PredictedViolation>,
1263 pub mitigation_strategies: Vec<MitigationStrategy>,
1264 pub recommendations: Vec<String>,
1265}
1266
1267#[derive(Debug, Clone)]
1268pub struct CostOptimizationReport {
1269 pub current_costs: SpendingAnalysis,
1270 pub optimizations: Vec<AllocationOptimization>,
1271 pub savings_potential: f64,
1272 pub recommendations: Vec<String>,
1273}
1274
1275#[derive(Debug, Clone)]
1276pub struct EnergyOptimizationReport {
1277 pub current_consumption: EnergyMetrics,
1278 pub renewable_optimization: RenewableSchedule,
1279 pub carbon_reduction_potential: f64,
1280 pub efficiency_recommendations: Vec<String>,
1281 pub sustainability_score: f64,
1282}
1283
1284#[derive(Debug, Clone)]
1285pub struct FairnessReport {
1286 pub fairness_metrics: FairnessMetrics,
1287 pub allocation_results: AllocationResults,
1288 pub incentive_mechanisms: Vec<IncentiveMechanism>,
1289 pub user_satisfaction_scores: HashMap<String, f64>,
1290 pub recommendations: Vec<String>,
1291}
1292
1293impl DecisionEngine {
1297 fn new() -> Self {
1298 Self {
1299 models: HashMap::new(),
1300 feature_pipeline: FeaturePipeline::default(),
1301 ensemble: ModelEnsemble::default(),
1302 rl_agent: ReinforcementLearningAgent::default(),
1303 online_learner: OnlineLearningSystem::default(),
1304 }
1305 }
1306}
1307
1308impl MultiObjectiveScheduler {
1309 fn new() -> Self {
1310 Self {
1311 objectives: Vec::new(),
1312 pareto_solutions: Vec::new(),
1313 nsga_optimizer: Some(NSGAOptimizer::default()),
1314 constraint_manager: Some(ConstraintManager::default()),
1315 solution_archive: Vec::new(),
1316 }
1317 }
1318}
1319
1320impl PredictiveSchedulingEngine {
1321 fn new() -> Self {
1322 Self {
1323 forecasting_models: HashMap::new(),
1324 demand_predictor: None,
1325 performance_predictor: None,
1326 anomaly_detector: AnomalyDetector::default(),
1327 capacity_planner: CapacityPlanner::default(),
1328 }
1329 }
1330}
1331
1332impl AdvancedCostOptimizer {
1333 fn new() -> Self {
1334 Self {
1335 pricing_models: HashMap::new(),
1336 budget_manager: BudgetManager::default(),
1337 cost_predictors: HashMap::new(),
1338 roi_optimizer: ROIOptimizer::default(),
1339 market_analyzer: MarketAnalyzer::default(),
1340 }
1341 }
1342}
1343
1344impl AdvancedEnergyOptimizer {
1345 fn new() -> Self {
1346 Self {
1347 energy_models: HashMap::new(),
1348 carbon_tracker: CarbonFootprintTracker::default(),
1349 renewable_scheduler: RenewableEnergyScheduler::default(),
1350 efficiency_optimizer: EnergyEfficiencyOptimizer::default(),
1351 green_metrics: GreenComputingMetrics::default(),
1352 }
1353 }
1354}
1355
1356impl AdvancedSLAManager {
1357 fn new() -> Self {
1358 Self {
1359 sla_configs: HashMap::new(),
1360 violation_predictor: ViolationPredictor::default(),
1361 mitigation_engine: MitigationStrategyEngine::default(),
1362 compliance_tracker: ComplianceTracker::default(),
1363 penalty_manager: PenaltyManager::default(),
1364 }
1365 }
1366}
1367
1368impl RealTimeAdaptationEngine {
1369 fn new() -> Self {
1370 Self {
1371 platform_monitor: PlatformMonitor::default(),
1372 load_balancer: LoadBalancingEngine::default(),
1373 auto_scaler: AutoScalingSystem::default(),
1374 circuit_migrator: CircuitMigrator::default(),
1375 emergency_responder: EmergencyResponseSystem::default(),
1376 }
1377 }
1378}
1379
1380impl FairnessEngine {
1381 fn new() -> Self {
1382 Self {
1383 game_scheduler: GameTheoreticScheduler::default(),
1384 allocation_fairness: AllocationFairnessManager::default(),
1385 behavior_analyzer: UserBehaviorAnalyzer::default(),
1386 incentive_designer: IncentiveMechanism::default(),
1387 welfare_optimizer: SocialWelfareOptimizer::default(),
1388 }
1389 }
1390}
1391
1392#[cfg(test)]
1410mod tests {
1411 use super::*;
1412
1413 #[tokio::test]
1414 async fn test_advanced_scheduler_creation() {
1415 let params = SchedulingParams::default();
1416 let scheduler = AdvancedQuantumScheduler::new(params);
1417 }
1420
1421 #[tokio::test]
1422 async fn test_intelligent_job_submission() {
1423 let params = SchedulingParams::default();
1424 let scheduler = AdvancedQuantumScheduler::new(params);
1425
1426 }
1429
1430 #[tokio::test]
1431 async fn test_multi_objective_optimization() {
1432 let params = SchedulingParams::default();
1433 let scheduler = AdvancedQuantumScheduler::new(params);
1434
1435 }
1438
1439 #[tokio::test]
1440 async fn test_detect_performance_anomalies_no_breach() {
1441 let params = SchedulingParams::default();
1443 let scheduler = AdvancedQuantumScheduler::new(params);
1444
1445 let metrics = PlatformMetrics {
1446 cpu_usage: 0.5,
1447 memory_usage: 0.4,
1448 queue_length: 3,
1449 average_execution_time: Duration::from_secs(2),
1450 };
1451 let anomalies = scheduler
1452 .detect_performance_anomalies(&metrics)
1453 .await
1454 .expect("anomaly detection should succeed");
1455 assert!(
1456 anomalies.is_empty(),
1457 "expected no anomalies but got {anomalies:?}"
1458 );
1459 }
1460
1461 #[tokio::test]
1462 async fn test_detect_performance_anomalies_breach() {
1463 let params = SchedulingParams::default();
1466 let scheduler = AdvancedQuantumScheduler::new(params);
1467
1468 let metrics = PlatformMetrics {
1469 cpu_usage: 0.99,
1470 memory_usage: 0.99,
1471 queue_length: 200,
1472 average_execution_time: Duration::from_secs(120),
1473 };
1474 let anomalies = scheduler
1475 .detect_performance_anomalies(&metrics)
1476 .await
1477 .expect("anomaly detection should succeed");
1478 assert_eq!(
1479 anomalies.len(),
1480 4,
1481 "expected all four thresholds to fire, got {anomalies:?}"
1482 );
1483 for w in anomalies.windows(2) {
1485 assert!(
1486 w[0].severity >= w[1].severity,
1487 "anomalies not sorted by severity: {anomalies:?}"
1488 );
1489 }
1490 for a in &anomalies {
1492 assert!(
1493 a.severity >= 0.0 && a.severity <= 1.0,
1494 "severity out of range: {a:?}"
1495 );
1496 }
1497 }
1498
1499 use super::priority::{
1504 edf_sort_key, is_overdue, priority_weight, slack_seconds, sort_by_edf, sort_by_wsjf,
1505 throughput, time_to_deadline, wsjf_priority,
1506 };
1507
1508 #[derive(Debug, Clone, PartialEq)]
1511 struct TestJob {
1512 id: &'static str,
1513 weight: f64,
1514 runtime: Duration,
1515 deadline: Option<SystemTime>,
1516 }
1517
1518 #[test]
1519 fn test_wsjf_priority_orders_correctly() {
1520 let mut jobs = vec![
1525 TestJob {
1526 id: "long",
1527 weight: 1.0,
1528 runtime: Duration::from_secs(100),
1529 deadline: None,
1530 },
1531 TestJob {
1532 id: "short",
1533 weight: 1.0,
1534 runtime: Duration::from_secs(10),
1535 deadline: None,
1536 },
1537 TestJob {
1538 id: "medium",
1539 weight: 1.0,
1540 runtime: Duration::from_secs(50),
1541 deadline: None,
1542 },
1543 ];
1544 sort_by_wsjf(&mut jobs, |j| j.weight, |j| j.runtime);
1545 assert_eq!(
1546 jobs.iter().map(|j| j.id).collect::<Vec<_>>(),
1547 vec!["short", "medium", "long"],
1548 "WSJF should put shortest job first when weights are equal"
1549 );
1550
1551 let short_p = wsjf_priority(1.0, Duration::from_secs(10));
1553 let long_p = wsjf_priority(1.0, Duration::from_secs(100));
1554 assert!(short_p > long_p);
1555
1556 let zero_p = wsjf_priority(1.0, Duration::ZERO);
1558 assert!(zero_p.is_finite() && zero_p > 0.0);
1559
1560 assert!(priority_weight(JobPriority::Critical) > priority_weight(JobPriority::High));
1562 assert!(priority_weight(JobPriority::High) > priority_weight(JobPriority::Normal));
1563 assert!(priority_weight(JobPriority::Normal) > priority_weight(JobPriority::Low));
1564 assert!(priority_weight(JobPriority::Low) > priority_weight(JobPriority::BestEffort));
1565 }
1566
1567 #[test]
1568 fn test_edf_schedules_earliest_deadline_first() {
1569 let now = SystemTime::now();
1570 let mut jobs = vec![
1571 TestJob {
1572 id: "late",
1573 weight: 1.0,
1574 runtime: Duration::from_secs(10),
1575 deadline: Some(now + Duration::from_secs(3600)),
1576 },
1577 TestJob {
1578 id: "soonest",
1579 weight: 1.0,
1580 runtime: Duration::from_secs(10),
1581 deadline: Some(now + Duration::from_secs(60)),
1582 },
1583 TestJob {
1584 id: "no_deadline",
1585 weight: 1.0,
1586 runtime: Duration::from_secs(10),
1587 deadline: None,
1588 },
1589 TestJob {
1590 id: "middle",
1591 weight: 1.0,
1592 runtime: Duration::from_secs(10),
1593 deadline: Some(now + Duration::from_secs(600)),
1594 },
1595 ];
1596 sort_by_edf(&mut jobs, now, |j| j.deadline);
1597 assert_eq!(
1598 jobs.iter().map(|j| j.id).collect::<Vec<_>>(),
1599 vec!["soonest", "middle", "late", "no_deadline"],
1600 "EDF should sort by ascending time-to-deadline; jobs without deadlines must sort last"
1601 );
1602
1603 assert_eq!(edf_sort_key(None, now), Duration::MAX);
1605 assert_eq!(
1607 edf_sort_key(Some(now - Duration::from_secs(60)), now),
1608 Duration::ZERO
1609 );
1610 }
1611
1612 #[test]
1613 fn test_overdue_returns_true_after_deadline() {
1614 let now = SystemTime::now();
1615 let past = now - Duration::from_secs(60);
1616 let future = now + Duration::from_secs(60);
1617 assert!(is_overdue(past, now));
1618 assert!(!is_overdue(future, now));
1619 assert!(!is_overdue(now, now));
1621
1622 assert!(time_to_deadline(past, now).is_none());
1624 assert_eq!(
1625 time_to_deadline(future, now)
1626 .expect("time_to_deadline should be Some for a future deadline")
1627 .as_secs(),
1628 60
1629 );
1630 }
1631
1632 #[test]
1633 fn test_slack_negative_for_late_job() {
1634 let now = SystemTime::now();
1635 let deadline = now + Duration::from_secs(10);
1637 let slack = slack_seconds(deadline, now, Duration::from_secs(60));
1638 assert!(
1639 slack < 0,
1640 "expected negative slack for late job, got {slack}"
1641 );
1642 assert_eq!(slack, -50);
1643
1644 let comfortable_deadline = now + Duration::from_secs(120);
1646 let comfortable_slack = slack_seconds(comfortable_deadline, now, Duration::from_secs(60));
1647 assert_eq!(comfortable_slack, 60);
1648
1649 let past = now - Duration::from_secs(30);
1651 let overdue_slack = slack_seconds(past, now, Duration::from_secs(10));
1652 assert!(overdue_slack <= -40);
1653 }
1654
1655 #[test]
1656 fn test_throughput_zero_for_empty_window() {
1657 assert_eq!(throughput(0, Duration::ZERO), 0.0);
1659 assert_eq!(throughput(10, Duration::ZERO), 0.0);
1660 assert!((throughput(60, Duration::from_secs(60)) - 1.0).abs() < 1.0e-9);
1662 assert_eq!(throughput(0, Duration::from_secs(1)), 0.0);
1664 }
1665
1666 #[test]
1667 fn test_device_compatible_checks_all_constraints() {
1668 use super::priority::device_compatible;
1669 use crate::job_scheduling::ResourceRequirements as JobResourceRequirements;
1670 use std::collections::HashSet;
1671
1672 let mut features: HashSet<String> = HashSet::new();
1673 features.insert("parametric_gates".to_string());
1674
1675 let req = JobResourceRequirements {
1676 min_qubits: 5,
1677 max_depth: Some(100),
1678 min_fidelity: None,
1679 required_connectivity: None,
1680 memory_mb: Some(1024),
1681 cpu_cores: Some(2),
1682 required_features: vec!["parametric_gates".to_string()],
1683 };
1684
1685 assert!(device_compatible(
1687 &req,
1688 10,
1689 Some(200),
1690 Some(2048),
1691 Some(4),
1692 &features
1693 ));
1694 assert!(!device_compatible(
1696 &req,
1697 3,
1698 Some(200),
1699 Some(2048),
1700 Some(4),
1701 &features
1702 ));
1703 assert!(!device_compatible(
1705 &req,
1706 10,
1707 Some(50),
1708 Some(2048),
1709 Some(4),
1710 &features
1711 ));
1712 let empty_features: HashSet<String> = HashSet::new();
1714 assert!(!device_compatible(
1715 &req,
1716 10,
1717 Some(200),
1718 Some(2048),
1719 Some(4),
1720 &empty_features
1721 ));
1722 assert!(device_compatible(&req, 10, None, None, None, &features));
1724 }
1725
1726 #[test]
1727 fn test_available_qubits_saturates() {
1728 use super::priority::available_qubits;
1729 assert_eq!(available_qubits(10, 4), 6);
1730 assert_eq!(available_qubits(10, 10), 0);
1731 assert_eq!(available_qubits(10, 20), 0);
1733 }
1734
1735 #[tokio::test]
1736 async fn test_predict_optimal_retries_branches_on_priority() {
1737 let params = SchedulingParams::default();
1738 let scheduler = AdvancedQuantumScheduler::new(params);
1739
1740 fn features_with(priority: JobPriority) -> JobFeatures {
1742 JobFeatures {
1743 circuit_depth: 1,
1744 gate_count: 1,
1745 qubit_count: 1,
1746 shots: 100,
1747 priority: priority as i32,
1748 user_historical_behavior: UserBehaviorFeatures {
1749 avg_job_complexity: 0.0,
1750 submission_frequency: 0.0,
1751 resource_utilization_efficiency: 0.0,
1752 sla_compliance_history: 1.0,
1753 },
1754 time_features: TemporalFeatures {
1755 hour_of_day: 0,
1756 day_of_week: 0,
1757 is_weekend: false,
1758 is_holiday: false,
1759 time_since_last_job: Duration::ZERO,
1760 },
1761 platform_features: PlatformFeatures {
1762 average_queue_length: 0.0,
1763 platform_utilization: 0.0,
1764 recent_performance_metrics: HashMap::new(),
1765 error_rates: HashMap::new(),
1766 },
1767 }
1768 }
1769
1770 let critical = scheduler
1771 .predict_optimal_retries(&features_with(JobPriority::Critical))
1772 .await
1773 .expect("retry prediction must succeed");
1774 let normal = scheduler
1775 .predict_optimal_retries(&features_with(JobPriority::Normal))
1776 .await
1777 .expect("retry prediction must succeed");
1778 let best_effort = scheduler
1779 .predict_optimal_retries(&features_with(JobPriority::BestEffort))
1780 .await
1781 .expect("retry prediction must succeed");
1782 assert!(critical > normal);
1783 assert!(normal > best_effort);
1784 }
1785
1786 #[tokio::test]
1787 async fn test_predict_optimal_timeout_grows_with_complexity() {
1788 let params = SchedulingParams::default();
1789 let scheduler = AdvancedQuantumScheduler::new(params);
1790
1791 let mut tiny = JobFeatures {
1792 circuit_depth: 1,
1793 gate_count: 1,
1794 qubit_count: 1,
1795 shots: 1,
1796 priority: JobPriority::Normal as i32,
1797 user_historical_behavior: UserBehaviorFeatures {
1798 avg_job_complexity: 0.0,
1799 submission_frequency: 0.0,
1800 resource_utilization_efficiency: 0.0,
1801 sla_compliance_history: 1.0,
1802 },
1803 time_features: TemporalFeatures {
1804 hour_of_day: 0,
1805 day_of_week: 0,
1806 is_weekend: false,
1807 is_holiday: false,
1808 time_since_last_job: Duration::ZERO,
1809 },
1810 platform_features: PlatformFeatures {
1811 average_queue_length: 0.0,
1812 platform_utilization: 0.0,
1813 recent_performance_metrics: HashMap::new(),
1814 error_rates: HashMap::new(),
1815 },
1816 };
1817 let small = scheduler
1818 .predict_optimal_timeout(&tiny)
1819 .await
1820 .expect("timeout prediction must succeed");
1821
1822 tiny.gate_count = 100_000;
1823 tiny.shots = 10_000;
1824 let large = scheduler
1825 .predict_optimal_timeout(&tiny)
1826 .await
1827 .expect("timeout prediction must succeed");
1828 assert!(large > small);
1829
1830 assert!(small >= Duration::from_secs(60));
1832 assert!(large <= Duration::from_secs(6 * 3600));
1834 }
1835
1836 #[tokio::test]
1837 async fn test_sla_compliance_reflects_real_scheduler_state_not_fixed_constant() {
1838 let params = SchedulingParams::default();
1839 let scheduler = AdvancedQuantumScheduler::new(params);
1840
1841 let job_metrics = scheduler
1846 .collect_job_metrics()
1847 .await
1848 .expect("collect_job_metrics should succeed");
1849 assert!(job_metrics.is_empty());
1850
1851 let compliance = scheduler
1852 .calculate_current_compliance()
1853 .await
1854 .expect("compliance calculation should succeed");
1855 assert_eq!(compliance, 1.0);
1856
1857 let violations = scheduler
1858 .predict_sla_violations(&job_metrics)
1859 .await
1860 .expect("violation prediction should succeed");
1861 assert!(violations.is_empty());
1862
1863 scheduler
1866 .register_backend(HardwareBackend::IBMQuantum)
1867 .await
1868 .expect("register_backend should succeed");
1869 let job_metrics_after = scheduler
1870 .collect_job_metrics()
1871 .await
1872 .expect("collect_job_metrics should succeed");
1873 assert_eq!(job_metrics_after.len(), 1);
1874 assert!(job_metrics_after[0].job_id.contains("IBMQuantum"));
1875 }
1876
1877 #[tokio::test]
1878 async fn test_cost_and_energy_metrics_vary_with_real_backend_state() {
1879 let params = SchedulingParams::default();
1880 let scheduler = AdvancedQuantumScheduler::new(params);
1881
1882 let savings_before = scheduler
1886 .calculate_savings_potential()
1887 .await
1888 .expect("savings potential should succeed");
1889 assert_eq!(savings_before, 0.0);
1890
1891 scheduler
1892 .register_backend(HardwareBackend::IBMQuantum)
1893 .await
1894 .expect("register_backend should succeed");
1895
1896 let savings_after = scheduler
1900 .calculate_savings_potential()
1901 .await
1902 .expect("savings potential should succeed");
1903 assert_eq!(savings_after, 1.0);
1904
1905 let sustainability = scheduler
1906 .calculate_sustainability_score()
1907 .await
1908 .expect("sustainability score should succeed");
1909 assert!((0.0..=1.0).contains(&sustainability));
1910
1911 let carbon_reduction = scheduler
1912 .calculate_carbon_reduction_opportunities()
1913 .await
1914 .expect("carbon reduction estimate should succeed");
1915 assert!((0.0..=1.0).contains(&carbon_reduction));
1916 }
1917
1918 #[tokio::test]
1919 async fn test_execute_mitigation_strategy_and_public_reports_still_succeed() {
1920 let params = SchedulingParams::default();
1924 let scheduler = AdvancedQuantumScheduler::new(params);
1925
1926 let compliance_report = scheduler
1927 .monitor_sla_compliance()
1928 .await
1929 .expect("monitor_sla_compliance should succeed");
1930 assert!(
1931 compliance_report.current_compliance >= 0.0
1932 && compliance_report.current_compliance <= 1.0
1933 );
1934
1935 let cost_report = scheduler
1936 .optimize_costs()
1937 .await
1938 .expect("optimize_costs should succeed");
1939 assert!(cost_report.savings_potential >= 0.0);
1940
1941 let energy_report = scheduler
1942 .optimize_energy_consumption()
1943 .await
1944 .expect("optimize_energy_consumption should succeed");
1945 assert!(
1946 energy_report.sustainability_score >= 0.0 && energy_report.sustainability_score <= 1.0
1947 );
1948
1949 let fairness_report = scheduler
1950 .apply_fair_scheduling()
1951 .await
1952 .expect("apply_fair_scheduling should succeed");
1953 assert!(fairness_report.user_satisfaction_scores.is_empty());
1956 }
1957}