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
40type AnomalyDetector = String;
42type CapacityPlanner = String;
43type CostPredictor = String;
44type ROIOptimizer = String;
45type MarketAnalyzer = String;
46type ObjectiveFunction = String;
47type NeuralNetwork = String;
48type ResourceManager = String;
49type ExecutionEngine = String;
50type MonitoringSystem = String;
51type AlertingSystem = String;
52type ComplianceMonitor = String;
53type SLAMonitor = String;
54type FairnessAnalyzer = String;
55type EnergyConsumptionModel = String;
56type EnergyEfficiencyOptimizer = String;
57
58#[derive(Debug, Clone, PartialEq, Eq)]
60pub enum MitigationUrgency {
61 Immediate,
62 High,
63 Medium,
64 Low,
65}
66type GreenComputingMetrics = String;
67type SLAConfiguration = String;
68type MitigationStrategyEngine = String;
69type ComplianceTracker = String;
70type PenaltyManager = String;
71type PlatformMonitor = String;
72type LoadBalancingEngine = String;
73type AutoScalingSystem = String;
74
75type AdaptationStrategy = String;
77type AllocationFairnessManager = String;
78type AllocationOptimization = String;
79type AllocationResults = String;
80type AuctionBasedScheduler = String;
81type AuctionMechanism = String;
82type BasePricingModel = String;
83type BudgetAlert = String;
84type CarbonOffsetProgram = String;
85type CircuitMigrator = String;
86type CoalitionFormation = String;
87type ConceptDriftDetector = String;
88type ConstraintManager = String;
89type DemandPredictor = String;
90type DemandResponseProgram = String;
91type DistributionType = String;
92type DiversityMetrics = String;
93type EarlyWarningSystem = String;
94type EmergencyResponseSystem = String;
95
96type PredictionModel = String;
98type ProjectBudget = String;
99type RenewableForecast = String;
100type RenewableSchedule = String;
101type RewardFunction = String;
102type RiskAssessment = String;
103type SocialWelfareOptimizer = String;
104type SolutionArchive = String;
105type SpendingForecast = String;
106type StreamingModel = String;
107type SustainabilityGoals = String;
108type TrainingEpoch = String;
109type UserBehaviorAnalyzer = String;
110type UserBudget = String;
111type UserPreferences = String;
112type UtilizationPricingModel = String;
113type ValueNetwork = String;
114type ViolationRecord = String;
115type ViolationType = String;
116
117type BaselineMetric = String;
119type CharacterizationProtocol = String;
120type EnsembleStrategy = String;
121type ExperienceBuffer = String;
122type ExplorationStrategy = String;
123type FeatureExtractor = String;
124type FeatureScaler = String;
125type FeatureSelector = String;
126type FeatureTransformer = String;
127type ForecastingModel = String;
128type ModelPerformanceMetrics = String;
129type OnlinePerformanceMonitor = String;
130type OrganizationalBudget = String;
131type PolicyNetwork = String;
132type IncentiveMechanism = String;
133type EmissionFactor = String;
134type EmissionRecord = String;
135type MLAlgorithm = String;
136type EnergyStorageSystem = String;
137type MechanismDesign = String;
138type NashEquilibriumSolver = String;
139type PredictedViolation = String;
140#[derive(Debug, Clone)]
141pub struct MitigationStrategy {
142 pub strategy_type: String,
143 pub urgency: MitigationUrgency,
144 pub description: String,
145 pub estimated_effectiveness: f64,
146}
147type EnergyMetrics = String;
148type FairnessMetrics = String;
149type NSGAOptimizer = String;
150type PerformancePredictor = String;
151
152#[cfg(feature = "scirs2")]
154use scirs2_graph::{
155 betweenness_centrality, closeness_centrality, dijkstra_path, louvain_communities_result,
156 minimum_spanning_tree, pagerank, strongly_connected_components, Graph,
157};
158#[cfg(feature = "scirs2")]
159use scirs2_linalg::{eig, matrix_norm, svd, trace, LinalgResult};
160#[cfg(feature = "scirs2")]
161use scirs2_optimize::{
162 differential_evolution, dual_annealing, least_squares, minimize, OptimizeResult,
163};
164#[cfg(feature = "scirs2")]
165use scirs2_stats::{
166 corrcoef,
167 distributions::{chi2, gamma, norm},
168 ks_2samp, mean, pearsonr, spearmanr, std, var,
169};
170
171#[cfg(not(feature = "scirs2"))]
173mod fallback_scirs2 {
174 use scirs2_core::ndarray::{Array1, Array2, ArrayView1, ArrayView2};
175
176 pub fn mean(_data: &ArrayView1<f64>) -> f64 {
177 0.0
178 }
179 pub fn std(_data: &ArrayView1<f64>, _ddof: i32) -> f64 {
180 1.0
181 }
182 pub fn pearsonr(_x: &ArrayView1<f64>, _y: &ArrayView1<f64>) -> (f64, f64) {
183 (0.0, 0.5)
184 }
185
186 pub struct OptimizeResult {
187 pub x: Array1<f64>,
188 pub fun: f64,
189 pub success: bool,
190 }
191
192 pub fn minimize<F>(_func: F, _x0: &Array1<f64>) -> OptimizeResult
193 where
194 F: Fn(&Array1<f64>) -> f64,
195 {
196 OptimizeResult {
197 x: Array1::zeros(2),
198 fun: 0.0,
199 success: false,
200 }
201 }
202}
203
204#[cfg(not(feature = "scirs2"))]
205use fallback_scirs2::*;
206
207pub struct AdvancedQuantumScheduler {
209 core_scheduler: Arc<QuantumJobScheduler>,
211 decision_engine: Arc<Mutex<DecisionEngine>>,
213 multi_objective_optimizer: Arc<Mutex<MultiObjectiveScheduler>>,
215 predictive_engine: Arc<Mutex<PredictiveSchedulingEngine>>,
217 cost_optimizer: Arc<Mutex<AdvancedCostOptimizer>>,
219 energy_optimizer: Arc<Mutex<AdvancedEnergyOptimizer>>,
221 sla_manager: Arc<Mutex<AdvancedSLAManager>>,
223 adaptation_engine: Arc<Mutex<RealTimeAdaptationEngine>>,
225 fairness_engine: Arc<Mutex<FairnessEngine>>,
227}
228
229struct DecisionEngine {
231 models: HashMap<String, MLModel>,
233 feature_pipeline: FeaturePipeline,
235 ensemble: ModelEnsemble,
237 rl_agent: ReinforcementLearningAgent,
239 online_learner: OnlineLearningSystem,
241}
242
243#[derive(Debug, Clone)]
245struct JobAssignment {
246 job_id: String,
247 backend: String,
248 priority: f64,
249 estimated_runtime: Duration,
250}
251
252#[derive(Debug, Clone)]
254struct ParetoSolution {
255 objectives: Vec<f64>,
256 schedule: HashMap<String, JobAssignment>,
257 quality_score: f64,
258}
259
260struct MultiObjectiveScheduler {
262 objectives: Vec<ObjectiveFunction>,
264 pareto_solutions: Vec<ParetoSolution>,
266 nsga_optimizer: Option<String>,
268 constraint_manager: Option<String>,
270 solution_archive: Vec<ParetoSolution>,
272}
273
274struct PredictiveSchedulingEngine {
276 forecasting_models: HashMap<HardwareBackend, String>,
278 demand_predictor: Option<String>,
280 performance_predictor: Option<String>,
282 anomaly_detector: AnomalyDetector,
284 capacity_planner: CapacityPlanner,
286}
287
288struct AdvancedCostOptimizer {
290 pricing_models: HashMap<HardwareBackend, DynamicPricingModel>,
292 budget_manager: BudgetManager,
294 cost_predictors: HashMap<String, CostPredictor>,
296 roi_optimizer: ROIOptimizer,
298 market_analyzer: MarketAnalyzer,
300}
301
302struct AdvancedEnergyOptimizer {
304 energy_models: HashMap<HardwareBackend, EnergyConsumptionModel>,
306 carbon_tracker: CarbonFootprintTracker,
308 renewable_scheduler: RenewableEnergyScheduler,
310 efficiency_optimizer: EnergyEfficiencyOptimizer,
312 green_metrics: GreenComputingMetrics,
314}
315
316struct AdvancedSLAManager {
318 sla_configs: HashMap<String, SLAConfiguration>,
320 violation_predictor: ViolationPredictor,
322 mitigation_engine: MitigationStrategyEngine,
324 compliance_tracker: ComplianceTracker,
326 penalty_manager: PenaltyManager,
328}
329
330struct RealTimeAdaptationEngine {
332 platform_monitor: PlatformMonitor,
334 load_balancer: LoadBalancingEngine,
336 auto_scaler: AutoScalingSystem,
338 circuit_migrator: CircuitMigrator,
340 emergency_responder: EmergencyResponseSystem,
342}
343
344struct FairnessEngine {
346 game_scheduler: GameTheoreticScheduler,
348 allocation_fairness: AllocationFairnessManager,
350 behavior_analyzer: UserBehaviorAnalyzer,
352 incentive_designer: IncentiveMechanism,
354 welfare_optimizer: SocialWelfareOptimizer,
356}
357
358#[derive(Debug, Clone)]
360struct MLModel {
361 model_id: String,
362 algorithm: MLAlgorithm,
363 parameters: HashMap<String, f64>,
364 feature_importance: HashMap<String, f64>,
365 performance_metrics: ModelPerformanceMetrics,
366 training_history: Vec<TrainingEpoch>,
367 last_updated: SystemTime,
368}
369
370#[derive(Debug, Clone, Default)]
372struct FeaturePipeline {
373 extractors: Vec<FeatureExtractor>,
374 transformers: Vec<FeatureTransformer>,
375 selectors: Vec<FeatureSelector>,
376 scalers: Vec<FeatureScaler>,
377}
378
379#[derive(Debug, Clone, Default)]
381struct ModelEnsemble {
382 base_models: Vec<String>,
383 meta_learner: Option<String>,
384 combination_strategy: EnsembleStrategy,
385 weights: Vec<f64>,
386 diversity_metrics: DiversityMetrics,
387}
388
389#[derive(Debug, Clone, Default)]
391struct ReinforcementLearningAgent {
392 policy_network: PolicyNetwork,
393 value_network: ValueNetwork,
394 experience_buffer: ExperienceBuffer,
395 exploration_strategy: ExplorationStrategy,
396 reward_function: RewardFunction,
397}
398
399#[derive(Debug, Clone, Default)]
401struct OnlineLearningSystem {
402 streaming_models: HashMap<String, StreamingModel>,
403 concept_drift_detector: ConceptDriftDetector,
404 adaptation_strategies: Vec<AdaptationStrategy>,
405 performance_monitor: OnlinePerformanceMonitor,
406}
407
408#[derive(Debug, Clone)]
410struct DynamicPricingModel {
411 base_pricing: BasePricingModel,
412 demand_elasticity: f64,
413 time_based_multipliers: HashMap<u8, f64>, utilization_pricing: UtilizationPricingModel,
415 auction_mechanism: Option<AuctionMechanism>,
416}
417
418#[derive(Debug, Clone, Default)]
420struct BudgetManager {
421 user_budgets: HashMap<String, UserBudget>,
422 project_budgets: HashMap<String, ProjectBudget>,
423 organizational_budget: OrganizationalBudget,
424 budget_alerts: Vec<BudgetAlert>,
425 spending_forecasts: HashMap<String, SpendingForecast>,
426}
427
428#[derive(Debug, Clone, Default)]
430struct CarbonFootprintTracker {
431 emission_factors: HashMap<HardwareBackend, EmissionFactor>,
432 total_emissions: f64,
433 emission_history: VecDeque<EmissionRecord>,
434 carbon_offset_programs: Vec<CarbonOffsetProgram>,
435 sustainability_goals: SustainabilityGoals,
436}
437
438#[derive(Debug, Clone, Default)]
440struct RenewableEnergyScheduler {
441 renewable_forecasts: HashMap<String, RenewableForecast>,
442 grid_carbon_intensity: HashMap<String, f64>,
443 energy_storage_systems: Vec<EnergyStorageSystem>,
444 demand_response_programs: Vec<DemandResponseProgram>,
445}
446
447#[derive(Debug, Clone, Default)]
449struct ViolationPredictor {
450 prediction_models: HashMap<ViolationType, PredictionModel>,
451 early_warning_system: EarlyWarningSystem,
452 risk_assessment: RiskAssessment,
453 historical_violations: VecDeque<ViolationRecord>,
454}
455
456#[derive(Debug, Clone, Default)]
458struct GameTheoreticScheduler {
459 mechanism_design: MechanismDesign,
460 auction_scheduler: AuctionBasedScheduler,
461 coalition_formation: CoalitionFormation,
462 nash_equilibrium_solver: NashEquilibriumSolver,
463}
464
465impl AdvancedQuantumScheduler {
466 pub fn new(params: SchedulingParams) -> Self {
468 let core_scheduler = Arc::new(QuantumJobScheduler::new(params));
469
470 Self {
471 core_scheduler,
472 decision_engine: Arc::new(Mutex::new(DecisionEngine::new())),
473 multi_objective_optimizer: Arc::new(Mutex::new(MultiObjectiveScheduler::new())),
474 predictive_engine: Arc::new(Mutex::new(PredictiveSchedulingEngine::new())),
475 cost_optimizer: Arc::new(Mutex::new(AdvancedCostOptimizer::new())),
476 energy_optimizer: Arc::new(Mutex::new(AdvancedEnergyOptimizer::new())),
477 sla_manager: Arc::new(Mutex::new(AdvancedSLAManager::new())),
478 adaptation_engine: Arc::new(Mutex::new(RealTimeAdaptationEngine::new())),
479 fairness_engine: Arc::new(Mutex::new(FairnessEngine::new())),
480 }
481 }
482
483 pub async fn submit_intelligent_job<const N: usize>(
485 &self,
486 circuit: Circuit<N>,
487 shots: usize,
488 config: JobConfig,
489 user_id: String,
490 ) -> DeviceResult<JobId> {
491 let features = self
493 .extract_job_features(&circuit, shots, &config, &user_id)
494 .await?;
495
496 let optimized_config = self.optimize_job_config(config, &features).await?;
498
499 let execution_strategy = self.predict_execution_strategy(&features).await?;
501
502 let job_id = self
504 .core_scheduler
505 .submit_job(circuit, shots, optimized_config, user_id)
506 .await?;
507
508 self.register_for_advanced_monitoring(&job_id.to_string(), execution_strategy)
510 .await?;
511
512 Ok(job_id)
513 }
514
515 pub async fn select_optimal_backend(
517 &self,
518 job_requirements: &JobRequirements,
519 user_preferences: &UserPreferences,
520 ) -> DeviceResult<HardwareBackend> {
521 let multi_obj = self
522 .multi_objective_optimizer
523 .lock()
524 .expect("Multi-objective optimizer Mutex should not be poisoned");
525
526 let objectives = vec![
528 ("performance".to_string(), 0.3),
529 ("cost".to_string(), 0.25),
530 ("energy".to_string(), 0.2),
531 ("availability".to_string(), 0.15),
532 ("fairness".to_string(), 0.1),
533 ];
534
535 #[cfg(feature = "scirs2")]
537 {
538 let backend_scores = self.evaluate_backends(job_requirements).await?;
539 let optimal_backend = self
540 .scirs2_backend_optimization(&backend_scores, &objectives)
541 .await?;
542 Ok(optimal_backend)
543 }
544
545 #[cfg(not(feature = "scirs2"))]
546 {
547 self.simple_backend_selection(job_requirements).await
549 }
550 }
551
552 pub async fn predict_queue_times(&self) -> DeviceResult<HashMap<HardwareBackend, Duration>> {
554 let predictive_engine = self
555 .predictive_engine
556 .lock()
557 .expect("Predictive engine Mutex should not be poisoned");
558
559 #[cfg(feature = "scirs2")]
560 {
561 let mut predictions = HashMap::new();
562
563 for backend in self.get_available_backends().await? {
564 let historical_data = self.get_historical_queue_data(&backend).await?;
566 let forecast = self.scirs2_time_series_forecast(&historical_data).await?;
567 predictions.insert(backend, forecast);
568 }
569
570 Ok(predictions)
571 }
572
573 #[cfg(not(feature = "scirs2"))]
574 {
575 let mut predictions = HashMap::new();
577 for backend in self.get_available_backends().await? {
578 predictions.insert(backend, Duration::from_secs(300)); }
580 Ok(predictions)
581 }
582 }
583
584 pub async fn dynamic_load_balance(&self) -> DeviceResult<()> {
586 let adaptation_engine = self
587 .adaptation_engine
588 .lock()
589 .expect("Adaptation engine Mutex should not be poisoned");
590
591 let platform_metrics = self.collect_platform_metrics().await?;
593
594 let anomalies = self.detect_performance_anomalies(&platform_metrics).await?;
596
597 if !anomalies.is_empty() {
598 self.apply_load_balancing_strategies(&anomalies).await?;
600
601 self.migrate_circuits_if_needed(&anomalies).await?;
603
604 self.update_routing_policies(&platform_metrics).await?;
606 }
607
608 Ok(())
609 }
610
611 pub async fn monitor_sla_compliance(&self) -> DeviceResult<SLAComplianceReport> {
613 let sla_manager = self
614 .sla_manager
615 .lock()
616 .expect("SLA manager Mutex should not be poisoned");
617
618 let job_metrics = self.collect_job_metrics().await?;
620
621 let predicted_violations = self.predict_sla_violations(&job_metrics).await?;
623
624 let mitigation_strategies = self
626 .generate_mitigation_strategies(&predicted_violations)
627 .await?;
628
629 for strategy in &mitigation_strategies {
631 if strategy.urgency == MitigationUrgency::Immediate {
632 self.execute_mitigation_strategy(strategy).await?;
633 }
634 }
635
636 Ok(SLAComplianceReport {
637 current_compliance: self.calculate_current_compliance().await?,
638 predicted_violations,
639 mitigation_strategies,
640 recommendations: self.generate_sla_recommendations().await?,
641 })
642 }
643
644 pub async fn optimize_costs(&self) -> DeviceResult<CostOptimizationReport> {
646 let cost_optimizer = self
647 .cost_optimizer
648 .lock()
649 .expect("Cost optimizer Mutex should not be poisoned");
650
651 let spending_analysis = self.analyze_spending_patterns().await?;
653
654 self.update_dynamic_pricing().await?;
656
657 let allocation_optimizations = self.optimize_cost_allocations().await?;
659
660 let budget_recommendations = self
662 .generate_budget_recommendations(&spending_analysis)
663 .await?;
664
665 Ok(CostOptimizationReport {
666 current_costs: spending_analysis,
667 optimizations: allocation_optimizations,
668 savings_potential: self.calculate_savings_potential().await?,
669 recommendations: budget_recommendations,
670 })
671 }
672
673 pub async fn optimize_energy_consumption(&self) -> DeviceResult<EnergyOptimizationReport> {
675 let energy_optimizer = self
676 .energy_optimizer
677 .lock()
678 .expect("Energy optimizer Mutex should not be poisoned");
679
680 let energy_metrics = self.collect_energy_metrics().await?;
682
683 let renewable_schedule = self.optimize_renewable_schedule().await?;
685
686 let carbon_reduction = self.calculate_carbon_reduction_opportunities().await?;
688
689 let efficiency_recommendations = self.generate_energy_recommendations().await?;
691
692 Ok(EnergyOptimizationReport {
693 current_consumption: energy_metrics,
694 renewable_optimization: renewable_schedule,
695 carbon_reduction_potential: carbon_reduction,
696 efficiency_recommendations,
697 sustainability_score: self.calculate_sustainability_score().await?,
698 })
699 }
700
701 pub async fn apply_fair_scheduling(&self) -> DeviceResult<FairnessReport> {
703 let fairness_engine = self
704 .fairness_engine
705 .lock()
706 .expect("Fairness engine Mutex should not be poisoned");
707
708 let user_analysis = self.analyze_user_behavior().await?;
710
711 let allocation_results = self.apply_game_theoretic_allocation(&user_analysis).await?;
713
714 let fairness_metrics = self.calculate_fairness_metrics(&allocation_results).await?;
716
717 let incentive_mechanisms = self.design_incentive_mechanisms(&user_analysis).await?;
719
720 Ok(FairnessReport {
721 fairness_metrics,
722 allocation_results,
723 incentive_mechanisms,
724 user_satisfaction_scores: self.calculate_user_satisfaction().await?,
725 recommendations: self.generate_fairness_recommendations().await?,
726 })
727 }
728
729 async fn extract_job_features<const N: usize>(
732 &self,
733 circuit: &Circuit<N>,
734 shots: usize,
735 config: &JobConfig,
736 user_id: &str,
737 ) -> DeviceResult<JobFeatures> {
738 Ok(JobFeatures {
740 circuit_depth: circuit.gates().len(), gate_count: circuit.gates().len(),
742 qubit_count: N,
743 shots,
744 priority: config.priority as i32,
745 user_historical_behavior: self.get_user_behavior_features(user_id).await?,
746 time_features: self.extract_temporal_features().await?,
747 platform_features: self.extract_platform_features().await?,
748 })
749 }
750
751 async fn optimize_job_config(
752 &self,
753 mut config: JobConfig,
754 features: &JobFeatures,
755 ) -> DeviceResult<JobConfig> {
756 let decision_engine = self
758 .decision_engine
759 .lock()
760 .expect("Decision engine Mutex should not be poisoned");
761
762 config.resource_requirements = self.predict_optimal_resources(features).await?;
764
765 config.retry_attempts = self.predict_optimal_retries(features).await?;
767
768 config.max_execution_time = self.predict_optimal_timeout(features).await?;
770
771 Ok(config)
772 }
773
774 #[cfg(feature = "scirs2")]
775 async fn scirs2_time_series_forecast(
776 &self,
777 historical_data: &Array1<f64>,
778 ) -> DeviceResult<Duration> {
779 let forecast = mean(&historical_data.view());
782 let forecast_value = forecast.unwrap_or(0.0);
783 Ok(Duration::from_secs(forecast_value as u64))
784 }
785
786 #[cfg(feature = "scirs2")]
787 async fn scirs2_backend_optimization(
788 &self,
789 backend_scores: &Vec<BackendScore>,
790 objectives: &[(String, f64)],
791 ) -> DeviceResult<HardwareBackend> {
792 backend_scores
797 .first()
798 .map(|_| HardwareBackend::IBMQuantum)
799 .ok_or_else(|| DeviceError::APIError("No backends available".to_string()))
800 }
801
802 async fn predict_execution_strategy(
806 &self,
807 features: &JobFeatures,
808 ) -> DeviceResult<ExecutionStrategy> {
809 Ok(ExecutionStrategy)
811 }
812
813 async fn register_for_advanced_monitoring(
815 &self,
816 job_id: &str,
817 execution_strategy: ExecutionStrategy,
818 ) -> DeviceResult<()> {
819 Ok(())
821 }
822
823 async fn evaluate_backends(
825 &self,
826 job_requirements: &JobRequirements,
827 ) -> DeviceResult<Vec<BackendScore>> {
828 let backends = self.get_available_backends().await?;
829 let mut backend_scores = Vec::new();
830
831 for backend in backends {
832 let mut factors = HashMap::new();
834 factors.insert("performance".to_string(), 0.8);
835 factors.insert("cost".to_string(), 0.7);
836 factors.insert("energy".to_string(), 0.6);
837 factors.insert("availability".to_string(), 0.9);
838 factors.insert("fairness".to_string(), 0.8);
839
840 let score = BackendScore {
841 backend_name: format!("{backend:?}"),
842 score: 0.76, factors,
844 };
845 backend_scores.push(score);
846 }
847
848 Ok(backend_scores)
849 }
850
851 async fn get_available_backends(&self) -> DeviceResult<Vec<HardwareBackend>> {
853 let backends = self.core_scheduler.get_available_backends();
854 if backends.is_empty() {
855 Err(DeviceError::APIError("No backends available".to_string()))
856 } else {
857 Ok(backends)
858 }
859 }
860
861 async fn get_historical_queue_data(
863 &self,
864 backend: &HardwareBackend,
865 ) -> DeviceResult<Array1<f64>> {
866 Ok(Array1::zeros(10))
868 }
869
870 async fn collect_platform_metrics(&self) -> DeviceResult<PlatformMetrics> {
872 Ok(PlatformMetrics::default())
874 }
875
876 async fn detect_performance_anomalies(
885 &self,
886 metrics: &PlatformMetrics,
887 ) -> DeviceResult<Vec<PerformanceAnomaly>> {
888 let mut anomalies: Vec<PerformanceAnomaly> = Vec::new();
889
890 const CPU_HIGH: f64 = 0.85;
893 const MEM_HIGH: f64 = 0.85;
894 const QUEUE_LONG: usize = 50;
895 const EXEC_LONG_SECS: f64 = 30.0;
896
897 if metrics.cpu_usage > CPU_HIGH {
898 let severity = ((metrics.cpu_usage - CPU_HIGH) / (1.0 - CPU_HIGH)).clamp(0.0, 1.0);
899 anomalies.push(PerformanceAnomaly {
900 anomaly_type: "high_cpu_usage".to_string(),
901 severity,
902 description: format!(
903 "CPU usage {:.3} exceeds threshold {:.2}",
904 metrics.cpu_usage, CPU_HIGH
905 ),
906 recommendations: vec![
907 "Throttle or migrate compute-intensive jobs".to_string(),
908 "Scale out execution workers".to_string(),
909 ],
910 });
911 }
912
913 if metrics.memory_usage > MEM_HIGH {
914 let severity = ((metrics.memory_usage - MEM_HIGH) / (1.0 - MEM_HIGH)).clamp(0.0, 1.0);
915 anomalies.push(PerformanceAnomaly {
916 anomaly_type: "high_memory_usage".to_string(),
917 severity,
918 description: format!(
919 "Memory usage {:.3} exceeds threshold {:.2}",
920 metrics.memory_usage, MEM_HIGH
921 ),
922 recommendations: vec![
923 "Trigger garbage collection of cached state".to_string(),
924 "Reduce concurrent job parallelism".to_string(),
925 ],
926 });
927 }
928
929 if metrics.queue_length > QUEUE_LONG {
930 let severity =
931 ((metrics.queue_length as f64 - QUEUE_LONG as f64) / QUEUE_LONG as f64).min(1.0);
932 anomalies.push(PerformanceAnomaly {
933 anomaly_type: "queue_backlog".to_string(),
934 severity,
935 description: format!(
936 "Queue length {} exceeds threshold {QUEUE_LONG}",
937 metrics.queue_length
938 ),
939 recommendations: vec![
940 "Re-route jobs to backends with shorter queues".to_string(),
941 "Apply backpressure on submission".to_string(),
942 ],
943 });
944 }
945
946 let exec_secs = metrics.average_execution_time.as_secs_f64();
947 if exec_secs > EXEC_LONG_SECS {
948 let severity = ((exec_secs - EXEC_LONG_SECS) / EXEC_LONG_SECS).min(1.0);
949 anomalies.push(PerformanceAnomaly {
950 anomaly_type: "slow_execution".to_string(),
951 severity,
952 description: format!(
953 "Average execution time {exec_secs:.2}s exceeds threshold {EXEC_LONG_SECS:.2}s"
954 ),
955 recommendations: vec![
956 "Apply circuit transpilation passes".to_string(),
957 "Consider migrating workload to a faster backend".to_string(),
958 ],
959 });
960 }
961
962 anomalies.sort_by(|a, b| {
965 b.severity
966 .partial_cmp(&a.severity)
967 .unwrap_or(std::cmp::Ordering::Equal)
968 });
969
970 Ok(anomalies)
971 }
972
973 async fn apply_load_balancing_strategies(
975 &self,
976 anomalies: &[PerformanceAnomaly],
977 ) -> DeviceResult<()> {
978 Ok(())
980 }
981
982 async fn migrate_circuits_if_needed(
984 &self,
985 anomalies: &[PerformanceAnomaly],
986 ) -> DeviceResult<()> {
987 Ok(())
989 }
990
991 async fn update_routing_policies(&self, metrics: &PlatformMetrics) -> DeviceResult<()> {
993 Ok(())
995 }
996
997 async fn collect_job_metrics(&self) -> DeviceResult<Vec<JobMetrics>> {
999 Ok(vec![])
1001 }
1002
1003 async fn predict_sla_violations(
1005 &self,
1006 job_metrics: &[JobMetrics],
1007 ) -> DeviceResult<Vec<PredictedViolation>> {
1008 Ok(vec![])
1010 }
1011
1012 async fn generate_mitigation_strategies(
1014 &self,
1015 violations: &[PredictedViolation],
1016 ) -> DeviceResult<Vec<MitigationStrategy>> {
1017 Ok(vec![])
1019 }
1020
1021 async fn execute_mitigation_strategy(&self, strategy: &MitigationStrategy) -> DeviceResult<()> {
1023 Ok(())
1025 }
1026
1027 async fn calculate_current_compliance(&self) -> DeviceResult<f64> {
1029 Ok(0.95)
1031 }
1032
1033 async fn generate_sla_recommendations(&self) -> DeviceResult<Vec<String>> {
1035 Ok(vec!["Maintain current performance levels".to_string()])
1037 }
1038
1039 async fn analyze_spending_patterns(&self) -> DeviceResult<SpendingAnalysis> {
1041 Ok(SpendingAnalysis::default())
1043 }
1044
1045 async fn update_dynamic_pricing(&self) -> DeviceResult<()> {
1047 Ok(())
1049 }
1050
1051 async fn optimize_cost_allocations(&self) -> DeviceResult<Vec<AllocationOptimization>> {
1053 Ok(vec![])
1055 }
1056
1057 async fn generate_budget_recommendations(
1059 &self,
1060 analysis: &SpendingAnalysis,
1061 ) -> DeviceResult<Vec<String>> {
1062 Ok(vec!["Consider budget optimization".to_string()])
1064 }
1065
1066 async fn calculate_savings_potential(&self) -> DeviceResult<f64> {
1068 Ok(0.15)
1070 }
1071
1072 async fn collect_energy_metrics(&self) -> DeviceResult<EnergyMetrics> {
1074 Ok(EnergyMetrics::default())
1076 }
1077
1078 async fn optimize_renewable_schedule(&self) -> DeviceResult<RenewableSchedule> {
1080 Ok(RenewableSchedule::default())
1082 }
1083
1084 async fn calculate_carbon_reduction_opportunities(&self) -> DeviceResult<f64> {
1086 Ok(0.20)
1088 }
1089
1090 async fn generate_energy_recommendations(&self) -> DeviceResult<Vec<String>> {
1092 Ok(vec!["Optimize energy usage during peak hours".to_string()])
1094 }
1095
1096 async fn calculate_sustainability_score(&self) -> DeviceResult<f64> {
1098 Ok(0.75)
1100 }
1101
1102 async fn analyze_user_behavior(&self) -> DeviceResult<UserAnalysis> {
1104 Ok(UserAnalysis::default())
1106 }
1107
1108 async fn apply_game_theoretic_allocation(
1110 &self,
1111 analysis: &UserAnalysis,
1112 ) -> DeviceResult<AllocationResults> {
1113 Ok(AllocationResults::default())
1115 }
1116
1117 async fn calculate_fairness_metrics(
1119 &self,
1120 results: &AllocationResults,
1121 ) -> DeviceResult<FairnessMetrics> {
1122 Ok(FairnessMetrics::default())
1124 }
1125
1126 async fn design_incentive_mechanisms(
1128 &self,
1129 analysis: &UserAnalysis,
1130 ) -> DeviceResult<Vec<IncentiveMechanism>> {
1131 Ok(vec![])
1133 }
1134
1135 async fn calculate_user_satisfaction(&self) -> DeviceResult<HashMap<String, f64>> {
1137 Ok(HashMap::new())
1139 }
1140
1141 async fn generate_fairness_recommendations(&self) -> DeviceResult<Vec<String>> {
1143 Ok(vec!["Maintain fair resource allocation".to_string()])
1145 }
1146
1147 #[cfg(not(feature = "scirs2"))]
1149 async fn simple_backend_selection(
1150 &self,
1151 requirements: &crate::job_scheduling::ResourceRequirements,
1152 ) -> DeviceResult<HardwareBackend> {
1153 Ok(HardwareBackend::Custom(0))
1155 }
1156
1157 async fn get_user_behavior_features(
1159 &self,
1160 user_id: &str,
1161 ) -> DeviceResult<UserBehaviorFeatures> {
1162 Ok(UserBehaviorFeatures {
1163 avg_job_complexity: 1.0,
1164 submission_frequency: 0.5,
1165 resource_utilization_efficiency: 0.8,
1166 sla_compliance_history: 0.95,
1167 })
1168 }
1169
1170 async fn extract_temporal_features(&self) -> DeviceResult<TemporalFeatures> {
1172 Ok(TemporalFeatures {
1173 hour_of_day: 12,
1174 day_of_week: 3,
1175 is_weekend: false,
1176 is_holiday: false,
1177 time_since_last_job: Duration::from_secs(300),
1178 })
1179 }
1180
1181 async fn extract_platform_features(&self) -> DeviceResult<PlatformFeatures> {
1183 Ok(PlatformFeatures {
1184 average_queue_length: 5.0,
1185 platform_utilization: 0.7,
1186 recent_performance_metrics: HashMap::new(),
1187 error_rates: HashMap::new(),
1188 })
1189 }
1190
1191 async fn predict_optimal_resources(
1193 &self,
1194 features: &JobFeatures,
1195 ) -> DeviceResult<crate::job_scheduling::ResourceRequirements> {
1196 Ok(crate::job_scheduling::ResourceRequirements {
1197 min_qubits: features.qubit_count,
1198 max_depth: None,
1199 min_fidelity: None,
1200 required_connectivity: None,
1201 cpu_cores: Some(1),
1202 memory_mb: Some(1024),
1203 required_features: Vec::new(),
1204 })
1205 }
1206
1207 async fn predict_optimal_retries(&self, features: &JobFeatures) -> DeviceResult<u32> {
1215 let retries = match features.priority {
1218 x if x <= JobPriority::Critical as i32 => 5,
1219 x if x == JobPriority::High as i32 => 4,
1220 x if x == JobPriority::Normal as i32 => 3,
1221 x if x == JobPriority::Low as i32 => 2,
1222 _ => 1, };
1224 Ok(retries)
1225 }
1226
1227 async fn predict_optimal_timeout(&self, features: &JobFeatures) -> DeviceResult<Duration> {
1235 const BASELINE_SECS: f64 = 60.0;
1236 const PER_GATE_SHOT_SECS: f64 = 1.0e-3;
1237 const MAX_TIMEOUT_SECS: f64 = 6.0 * 3600.0;
1238
1239 let gate_shot_secs =
1240 (features.gate_count as f64) * (features.shots as f64) * PER_GATE_SHOT_SECS;
1241 let total = (BASELINE_SECS + gate_shot_secs).clamp(BASELINE_SECS, MAX_TIMEOUT_SECS);
1242 Ok(Duration::from_secs_f64(total))
1243 }
1244
1245 pub async fn register_backend(&self, backend: HardwareBackend) -> DeviceResult<()> {
1247 self.core_scheduler.register_backend(backend).await
1248 }
1249
1250 pub fn get_available_backends_debug(&self) -> Vec<HardwareBackend> {
1252 self.core_scheduler.get_available_backends()
1253 }
1254}
1255
1256#[derive(Debug, Clone, Default)]
1258pub struct JobRequirements {
1259 pub min_qubits: usize,
1260 pub max_execution_time: Duration,
1261 pub priority: JobPriority,
1262}
1263
1264#[derive(Debug, Clone, Default)]
1265pub struct JobMetrics {
1266 pub job_id: String,
1267 pub execution_time: Duration,
1268 pub success_rate: f64,
1269 pub resource_usage: f64,
1270}
1271
1272#[derive(Debug, Clone, Default)]
1273pub struct UserAnalysis {
1274 pub user_patterns: HashMap<String, f64>,
1275 pub resource_preferences: HashMap<String, f64>,
1276}
1277
1278#[derive(Debug, Clone, Default)]
1279pub struct SpendingAnalysis {
1280 pub total_cost: f64,
1281 pub cost_breakdown: HashMap<String, f64>,
1282 pub trends: Vec<f64>,
1283}
1284
1285#[derive(Debug, Clone)]
1286pub struct BackendScore {
1287 pub backend_name: String,
1288 pub score: f64,
1289 pub factors: HashMap<String, f64>,
1290}
1291
1292#[derive(Debug, Clone, Default)]
1293pub struct PlatformMetrics {
1294 pub cpu_usage: f64,
1295 pub memory_usage: f64,
1296 pub queue_length: usize,
1297 pub average_execution_time: Duration,
1298}
1299
1300#[derive(Debug, Clone)]
1301pub struct PerformanceAnomaly {
1302 pub anomaly_type: String,
1303 pub severity: f64,
1304 pub description: String,
1305 pub recommendations: Vec<String>,
1306}
1307
1308#[derive(Debug, Clone)]
1311struct JobFeatures {
1312 circuit_depth: usize,
1313 gate_count: usize,
1314 qubit_count: usize,
1315 shots: usize,
1316 priority: i32,
1317 user_historical_behavior: UserBehaviorFeatures,
1318 time_features: TemporalFeatures,
1319 platform_features: PlatformFeatures,
1320}
1321
1322#[derive(Debug, Clone)]
1323struct UserBehaviorFeatures {
1324 avg_job_complexity: f64,
1325 submission_frequency: f64,
1326 resource_utilization_efficiency: f64,
1327 sla_compliance_history: f64,
1328}
1329
1330#[derive(Debug, Clone)]
1331struct TemporalFeatures {
1332 hour_of_day: u8,
1333 day_of_week: u8,
1334 is_weekend: bool,
1335 is_holiday: bool,
1336 time_since_last_job: Duration,
1337}
1338
1339#[derive(Debug, Clone)]
1340struct PlatformFeatures {
1341 average_queue_length: f64,
1342 platform_utilization: f64,
1343 recent_performance_metrics: HashMap<HardwareBackend, f64>,
1344 error_rates: HashMap<HardwareBackend, f64>,
1345}
1346
1347#[derive(Debug, Clone)]
1348pub struct SLAComplianceReport {
1349 pub current_compliance: f64,
1350 pub predicted_violations: Vec<PredictedViolation>,
1351 pub mitigation_strategies: Vec<MitigationStrategy>,
1352 pub recommendations: Vec<String>,
1353}
1354
1355#[derive(Debug, Clone)]
1356pub struct CostOptimizationReport {
1357 pub current_costs: SpendingAnalysis,
1358 pub optimizations: Vec<AllocationOptimization>,
1359 pub savings_potential: f64,
1360 pub recommendations: Vec<String>,
1361}
1362
1363#[derive(Debug, Clone)]
1364pub struct EnergyOptimizationReport {
1365 pub current_consumption: EnergyMetrics,
1366 pub renewable_optimization: RenewableSchedule,
1367 pub carbon_reduction_potential: f64,
1368 pub efficiency_recommendations: Vec<String>,
1369 pub sustainability_score: f64,
1370}
1371
1372#[derive(Debug, Clone)]
1373pub struct FairnessReport {
1374 pub fairness_metrics: FairnessMetrics,
1375 pub allocation_results: AllocationResults,
1376 pub incentive_mechanisms: Vec<IncentiveMechanism>,
1377 pub user_satisfaction_scores: HashMap<String, f64>,
1378 pub recommendations: Vec<String>,
1379}
1380
1381impl DecisionEngine {
1385 fn new() -> Self {
1386 Self {
1387 models: HashMap::new(),
1388 feature_pipeline: FeaturePipeline::default(),
1389 ensemble: ModelEnsemble::default(),
1390 rl_agent: ReinforcementLearningAgent::default(),
1391 online_learner: OnlineLearningSystem::default(),
1392 }
1393 }
1394}
1395
1396impl MultiObjectiveScheduler {
1397 fn new() -> Self {
1398 Self {
1399 objectives: Vec::new(),
1400 pareto_solutions: Vec::new(),
1401 nsga_optimizer: Some(NSGAOptimizer::default()),
1402 constraint_manager: Some(ConstraintManager::default()),
1403 solution_archive: Vec::new(),
1404 }
1405 }
1406}
1407
1408impl PredictiveSchedulingEngine {
1409 fn new() -> Self {
1410 Self {
1411 forecasting_models: HashMap::new(),
1412 demand_predictor: None,
1413 performance_predictor: None,
1414 anomaly_detector: AnomalyDetector::default(),
1415 capacity_planner: CapacityPlanner::default(),
1416 }
1417 }
1418}
1419
1420impl AdvancedCostOptimizer {
1421 fn new() -> Self {
1422 Self {
1423 pricing_models: HashMap::new(),
1424 budget_manager: BudgetManager::default(),
1425 cost_predictors: HashMap::new(),
1426 roi_optimizer: ROIOptimizer::default(),
1427 market_analyzer: MarketAnalyzer::default(),
1428 }
1429 }
1430}
1431
1432impl AdvancedEnergyOptimizer {
1433 fn new() -> Self {
1434 Self {
1435 energy_models: HashMap::new(),
1436 carbon_tracker: CarbonFootprintTracker::default(),
1437 renewable_scheduler: RenewableEnergyScheduler::default(),
1438 efficiency_optimizer: EnergyEfficiencyOptimizer::default(),
1439 green_metrics: GreenComputingMetrics::default(),
1440 }
1441 }
1442}
1443
1444impl AdvancedSLAManager {
1445 fn new() -> Self {
1446 Self {
1447 sla_configs: HashMap::new(),
1448 violation_predictor: ViolationPredictor::default(),
1449 mitigation_engine: MitigationStrategyEngine::default(),
1450 compliance_tracker: ComplianceTracker::default(),
1451 penalty_manager: PenaltyManager::default(),
1452 }
1453 }
1454}
1455
1456impl RealTimeAdaptationEngine {
1457 fn new() -> Self {
1458 Self {
1459 platform_monitor: PlatformMonitor::default(),
1460 load_balancer: LoadBalancingEngine::default(),
1461 auto_scaler: AutoScalingSystem::default(),
1462 circuit_migrator: CircuitMigrator::default(),
1463 emergency_responder: EmergencyResponseSystem::default(),
1464 }
1465 }
1466}
1467
1468impl FairnessEngine {
1469 fn new() -> Self {
1470 Self {
1471 game_scheduler: GameTheoreticScheduler::default(),
1472 allocation_fairness: AllocationFairnessManager::default(),
1473 behavior_analyzer: UserBehaviorAnalyzer::default(),
1474 incentive_designer: IncentiveMechanism::default(),
1475 welfare_optimizer: SocialWelfareOptimizer::default(),
1476 }
1477 }
1478}
1479
1480#[cfg(test)]
1498mod tests {
1499 use super::*;
1500
1501 #[tokio::test]
1502 async fn test_advanced_scheduler_creation() {
1503 let params = SchedulingParams::default();
1504 let scheduler = AdvancedQuantumScheduler::new(params);
1505 }
1508
1509 #[tokio::test]
1510 async fn test_intelligent_job_submission() {
1511 let params = SchedulingParams::default();
1512 let scheduler = AdvancedQuantumScheduler::new(params);
1513
1514 }
1517
1518 #[tokio::test]
1519 async fn test_multi_objective_optimization() {
1520 let params = SchedulingParams::default();
1521 let scheduler = AdvancedQuantumScheduler::new(params);
1522
1523 }
1526
1527 #[tokio::test]
1528 async fn test_detect_performance_anomalies_no_breach() {
1529 let params = SchedulingParams::default();
1531 let scheduler = AdvancedQuantumScheduler::new(params);
1532
1533 let metrics = PlatformMetrics {
1534 cpu_usage: 0.5,
1535 memory_usage: 0.4,
1536 queue_length: 3,
1537 average_execution_time: Duration::from_secs(2),
1538 };
1539 let anomalies = scheduler
1540 .detect_performance_anomalies(&metrics)
1541 .await
1542 .expect("anomaly detection should succeed");
1543 assert!(
1544 anomalies.is_empty(),
1545 "expected no anomalies but got {anomalies:?}"
1546 );
1547 }
1548
1549 #[tokio::test]
1550 async fn test_detect_performance_anomalies_breach() {
1551 let params = SchedulingParams::default();
1554 let scheduler = AdvancedQuantumScheduler::new(params);
1555
1556 let metrics = PlatformMetrics {
1557 cpu_usage: 0.99,
1558 memory_usage: 0.99,
1559 queue_length: 200,
1560 average_execution_time: Duration::from_secs(120),
1561 };
1562 let anomalies = scheduler
1563 .detect_performance_anomalies(&metrics)
1564 .await
1565 .expect("anomaly detection should succeed");
1566 assert_eq!(
1567 anomalies.len(),
1568 4,
1569 "expected all four thresholds to fire, got {anomalies:?}"
1570 );
1571 for w in anomalies.windows(2) {
1573 assert!(
1574 w[0].severity >= w[1].severity,
1575 "anomalies not sorted by severity: {anomalies:?}"
1576 );
1577 }
1578 for a in &anomalies {
1580 assert!(
1581 a.severity >= 0.0 && a.severity <= 1.0,
1582 "severity out of range: {a:?}"
1583 );
1584 }
1585 }
1586
1587 use super::priority::{
1592 edf_sort_key, is_overdue, priority_weight, slack_seconds, sort_by_edf, sort_by_wsjf,
1593 throughput, time_to_deadline, wsjf_priority,
1594 };
1595
1596 #[derive(Debug, Clone, PartialEq)]
1599 struct TestJob {
1600 id: &'static str,
1601 weight: f64,
1602 runtime: Duration,
1603 deadline: Option<SystemTime>,
1604 }
1605
1606 #[test]
1607 fn test_wsjf_priority_orders_correctly() {
1608 let mut jobs = vec![
1613 TestJob {
1614 id: "long",
1615 weight: 1.0,
1616 runtime: Duration::from_secs(100),
1617 deadline: None,
1618 },
1619 TestJob {
1620 id: "short",
1621 weight: 1.0,
1622 runtime: Duration::from_secs(10),
1623 deadline: None,
1624 },
1625 TestJob {
1626 id: "medium",
1627 weight: 1.0,
1628 runtime: Duration::from_secs(50),
1629 deadline: None,
1630 },
1631 ];
1632 sort_by_wsjf(&mut jobs, |j| j.weight, |j| j.runtime);
1633 assert_eq!(
1634 jobs.iter().map(|j| j.id).collect::<Vec<_>>(),
1635 vec!["short", "medium", "long"],
1636 "WSJF should put shortest job first when weights are equal"
1637 );
1638
1639 let short_p = wsjf_priority(1.0, Duration::from_secs(10));
1641 let long_p = wsjf_priority(1.0, Duration::from_secs(100));
1642 assert!(short_p > long_p);
1643
1644 let zero_p = wsjf_priority(1.0, Duration::ZERO);
1646 assert!(zero_p.is_finite() && zero_p > 0.0);
1647
1648 assert!(priority_weight(JobPriority::Critical) > priority_weight(JobPriority::High));
1650 assert!(priority_weight(JobPriority::High) > priority_weight(JobPriority::Normal));
1651 assert!(priority_weight(JobPriority::Normal) > priority_weight(JobPriority::Low));
1652 assert!(priority_weight(JobPriority::Low) > priority_weight(JobPriority::BestEffort));
1653 }
1654
1655 #[test]
1656 fn test_edf_schedules_earliest_deadline_first() {
1657 let now = SystemTime::now();
1658 let mut jobs = vec![
1659 TestJob {
1660 id: "late",
1661 weight: 1.0,
1662 runtime: Duration::from_secs(10),
1663 deadline: Some(now + Duration::from_secs(3600)),
1664 },
1665 TestJob {
1666 id: "soonest",
1667 weight: 1.0,
1668 runtime: Duration::from_secs(10),
1669 deadline: Some(now + Duration::from_secs(60)),
1670 },
1671 TestJob {
1672 id: "no_deadline",
1673 weight: 1.0,
1674 runtime: Duration::from_secs(10),
1675 deadline: None,
1676 },
1677 TestJob {
1678 id: "middle",
1679 weight: 1.0,
1680 runtime: Duration::from_secs(10),
1681 deadline: Some(now + Duration::from_secs(600)),
1682 },
1683 ];
1684 sort_by_edf(&mut jobs, now, |j| j.deadline);
1685 assert_eq!(
1686 jobs.iter().map(|j| j.id).collect::<Vec<_>>(),
1687 vec!["soonest", "middle", "late", "no_deadline"],
1688 "EDF should sort by ascending time-to-deadline; jobs without deadlines must sort last"
1689 );
1690
1691 assert_eq!(edf_sort_key(None, now), Duration::MAX);
1693 assert_eq!(
1695 edf_sort_key(Some(now - Duration::from_secs(60)), now),
1696 Duration::ZERO
1697 );
1698 }
1699
1700 #[test]
1701 fn test_overdue_returns_true_after_deadline() {
1702 let now = SystemTime::now();
1703 let past = now - Duration::from_secs(60);
1704 let future = now + Duration::from_secs(60);
1705 assert!(is_overdue(past, now));
1706 assert!(!is_overdue(future, now));
1707 assert!(!is_overdue(now, now));
1709
1710 assert!(time_to_deadline(past, now).is_none());
1712 assert_eq!(
1713 time_to_deadline(future, now)
1714 .expect("time_to_deadline should be Some for a future deadline")
1715 .as_secs(),
1716 60
1717 );
1718 }
1719
1720 #[test]
1721 fn test_slack_negative_for_late_job() {
1722 let now = SystemTime::now();
1723 let deadline = now + Duration::from_secs(10);
1725 let slack = slack_seconds(deadline, now, Duration::from_secs(60));
1726 assert!(
1727 slack < 0,
1728 "expected negative slack for late job, got {slack}"
1729 );
1730 assert_eq!(slack, -50);
1731
1732 let comfortable_deadline = now + Duration::from_secs(120);
1734 let comfortable_slack = slack_seconds(comfortable_deadline, now, Duration::from_secs(60));
1735 assert_eq!(comfortable_slack, 60);
1736
1737 let past = now - Duration::from_secs(30);
1739 let overdue_slack = slack_seconds(past, now, Duration::from_secs(10));
1740 assert!(overdue_slack <= -40);
1741 }
1742
1743 #[test]
1744 fn test_throughput_zero_for_empty_window() {
1745 assert_eq!(throughput(0, Duration::ZERO), 0.0);
1747 assert_eq!(throughput(10, Duration::ZERO), 0.0);
1748 assert!((throughput(60, Duration::from_secs(60)) - 1.0).abs() < 1.0e-9);
1750 assert_eq!(throughput(0, Duration::from_secs(1)), 0.0);
1752 }
1753
1754 #[test]
1755 fn test_device_compatible_checks_all_constraints() {
1756 use super::priority::device_compatible;
1757 use crate::job_scheduling::ResourceRequirements as JobResourceRequirements;
1758 use std::collections::HashSet;
1759
1760 let mut features: HashSet<String> = HashSet::new();
1761 features.insert("parametric_gates".to_string());
1762
1763 let req = JobResourceRequirements {
1764 min_qubits: 5,
1765 max_depth: Some(100),
1766 min_fidelity: None,
1767 required_connectivity: None,
1768 memory_mb: Some(1024),
1769 cpu_cores: Some(2),
1770 required_features: vec!["parametric_gates".to_string()],
1771 };
1772
1773 assert!(device_compatible(
1775 &req,
1776 10,
1777 Some(200),
1778 Some(2048),
1779 Some(4),
1780 &features
1781 ));
1782 assert!(!device_compatible(
1784 &req,
1785 3,
1786 Some(200),
1787 Some(2048),
1788 Some(4),
1789 &features
1790 ));
1791 assert!(!device_compatible(
1793 &req,
1794 10,
1795 Some(50),
1796 Some(2048),
1797 Some(4),
1798 &features
1799 ));
1800 let empty_features: HashSet<String> = HashSet::new();
1802 assert!(!device_compatible(
1803 &req,
1804 10,
1805 Some(200),
1806 Some(2048),
1807 Some(4),
1808 &empty_features
1809 ));
1810 assert!(device_compatible(&req, 10, None, None, None, &features));
1812 }
1813
1814 #[test]
1815 fn test_available_qubits_saturates() {
1816 use super::priority::available_qubits;
1817 assert_eq!(available_qubits(10, 4), 6);
1818 assert_eq!(available_qubits(10, 10), 0);
1819 assert_eq!(available_qubits(10, 20), 0);
1821 }
1822
1823 #[tokio::test]
1824 async fn test_predict_optimal_retries_branches_on_priority() {
1825 let params = SchedulingParams::default();
1826 let scheduler = AdvancedQuantumScheduler::new(params);
1827
1828 fn features_with(priority: JobPriority) -> JobFeatures {
1830 JobFeatures {
1831 circuit_depth: 1,
1832 gate_count: 1,
1833 qubit_count: 1,
1834 shots: 100,
1835 priority: priority as i32,
1836 user_historical_behavior: UserBehaviorFeatures {
1837 avg_job_complexity: 0.0,
1838 submission_frequency: 0.0,
1839 resource_utilization_efficiency: 0.0,
1840 sla_compliance_history: 1.0,
1841 },
1842 time_features: TemporalFeatures {
1843 hour_of_day: 0,
1844 day_of_week: 0,
1845 is_weekend: false,
1846 is_holiday: false,
1847 time_since_last_job: Duration::ZERO,
1848 },
1849 platform_features: PlatformFeatures {
1850 average_queue_length: 0.0,
1851 platform_utilization: 0.0,
1852 recent_performance_metrics: HashMap::new(),
1853 error_rates: HashMap::new(),
1854 },
1855 }
1856 }
1857
1858 let critical = scheduler
1859 .predict_optimal_retries(&features_with(JobPriority::Critical))
1860 .await
1861 .expect("retry prediction must succeed");
1862 let normal = scheduler
1863 .predict_optimal_retries(&features_with(JobPriority::Normal))
1864 .await
1865 .expect("retry prediction must succeed");
1866 let best_effort = scheduler
1867 .predict_optimal_retries(&features_with(JobPriority::BestEffort))
1868 .await
1869 .expect("retry prediction must succeed");
1870 assert!(critical > normal);
1871 assert!(normal > best_effort);
1872 }
1873
1874 #[tokio::test]
1875 async fn test_predict_optimal_timeout_grows_with_complexity() {
1876 let params = SchedulingParams::default();
1877 let scheduler = AdvancedQuantumScheduler::new(params);
1878
1879 let mut tiny = JobFeatures {
1880 circuit_depth: 1,
1881 gate_count: 1,
1882 qubit_count: 1,
1883 shots: 1,
1884 priority: JobPriority::Normal as i32,
1885 user_historical_behavior: UserBehaviorFeatures {
1886 avg_job_complexity: 0.0,
1887 submission_frequency: 0.0,
1888 resource_utilization_efficiency: 0.0,
1889 sla_compliance_history: 1.0,
1890 },
1891 time_features: TemporalFeatures {
1892 hour_of_day: 0,
1893 day_of_week: 0,
1894 is_weekend: false,
1895 is_holiday: false,
1896 time_since_last_job: Duration::ZERO,
1897 },
1898 platform_features: PlatformFeatures {
1899 average_queue_length: 0.0,
1900 platform_utilization: 0.0,
1901 recent_performance_metrics: HashMap::new(),
1902 error_rates: HashMap::new(),
1903 },
1904 };
1905 let small = scheduler
1906 .predict_optimal_timeout(&tiny)
1907 .await
1908 .expect("timeout prediction must succeed");
1909
1910 tiny.gate_count = 100_000;
1911 tiny.shots = 10_000;
1912 let large = scheduler
1913 .predict_optimal_timeout(&tiny)
1914 .await
1915 .expect("timeout prediction must succeed");
1916 assert!(large > small);
1917
1918 assert!(small >= Duration::from_secs(60));
1920 assert!(large <= Duration::from_secs(6 * 3600));
1922 }
1923}