use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::sync::{Arc, Mutex, RwLock};
use std::time::{Duration, SystemTime};
use crate::{translation::HardwareBackend, CircuitResult};
use quantrs2_circuit::prelude::Circuit;
use serde::{Deserialize, Serialize};
use tokio::sync::mpsc;
use uuid::Uuid;
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default,
)]
pub enum JobPriority {
Critical = 0,
High = 1,
#[default]
Normal = 2,
Low = 3,
BestEffort = 4,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum JobStatus {
Pending,
Validating,
Scheduled,
Running,
Completed,
Failed,
Cancelled,
TimedOut,
Retrying,
Paused,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum SchedulingStrategy {
PriorityFIFO,
ShortestJobFirst,
ShortestRemainingTimeFirst,
FairShare,
PriorityRoundRobin,
Backfill,
EarliestDeadlineFirst,
RateMonotonic,
MLOptimized,
MultiObjectiveOptimized,
ReinforcementLearning,
GeneticAlgorithm,
GameTheoreticFair,
EnergyAware,
DeadlineAwareSLA,
Custom(String),
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum AllocationStrategy {
FirstFit,
BestFit,
WorstFit,
LeastLoaded,
MostLoaded,
RoundRobin,
WeightedRoundRobin,
CostOptimized,
PerformanceOptimized,
EnergyEfficient,
SciRS2Optimized,
MultiObjectiveOptimized,
LocalityAware,
FaultTolerant,
PredictiveAllocation,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JobConfig {
pub priority: JobPriority,
pub max_execution_time: Duration,
pub max_queue_time: Option<Duration>,
pub retry_attempts: u32,
pub retry_delay: Duration,
pub resource_requirements: ResourceRequirements,
pub preferred_backends: Vec<HardwareBackend>,
pub tags: HashMap<String, String>,
pub dependencies: Vec<JobId>,
pub deadline: Option<SystemTime>,
pub cost_limit: Option<f64>,
}
impl Default for JobConfig {
fn default() -> Self {
Self {
priority: JobPriority::Normal,
max_execution_time: Duration::from_secs(3600), max_queue_time: Some(Duration::from_secs(86400)), retry_attempts: 3,
retry_delay: Duration::from_secs(60),
resource_requirements: ResourceRequirements::default(),
preferred_backends: vec![],
tags: HashMap::new(),
dependencies: vec![],
deadline: None,
cost_limit: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceRequirements {
pub min_qubits: usize,
pub max_depth: Option<usize>,
pub min_fidelity: Option<f64>,
pub required_connectivity: Option<String>,
pub memory_mb: Option<u64>,
pub cpu_cores: Option<u32>,
pub required_features: Vec<String>,
}
impl Default for ResourceRequirements {
fn default() -> Self {
Self {
min_qubits: 1,
max_depth: None,
min_fidelity: None,
required_connectivity: None,
memory_mb: None,
cpu_cores: None,
required_features: vec![],
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct JobId(pub String);
impl Default for JobId {
fn default() -> Self {
Self::new()
}
}
impl JobId {
pub fn new() -> Self {
Self(Uuid::new_v4().to_string())
}
pub const fn from_string(s: String) -> Self {
Self(s)
}
}
impl std::fmt::Display for JobId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone)]
pub struct QuantumJob<const N: usize> {
pub id: JobId,
pub config: JobConfig,
pub circuit: Circuit<N>,
pub shots: usize,
pub submitted_at: SystemTime,
pub status: JobStatus,
pub execution_history: Vec<JobExecution>,
pub metadata: HashMap<String, String>,
pub user_id: String,
pub group_id: Option<String>,
pub estimated_duration: Option<Duration>,
pub assigned_backend: Option<HardwareBackend>,
pub estimated_cost: Option<f64>,
pub actual_cost: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JobExecution {
pub attempt: u32,
pub backend: HardwareBackend,
pub started_at: SystemTime,
pub ended_at: Option<SystemTime>,
pub result: Option<CircuitResult>,
pub error: Option<String>,
pub metrics: ExecutionMetrics,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExecutionMetrics {
pub queue_time: Duration,
pub execution_time: Option<Duration>,
pub resource_utilization: f64,
pub cost: Option<f64>,
pub quality_metrics: HashMap<String, f64>,
}
impl Default for ExecutionMetrics {
fn default() -> Self {
Self {
queue_time: Duration::from_secs(0),
execution_time: None,
resource_utilization: 0.0,
cost: None,
quality_metrics: HashMap::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct BackendPerformance {
pub backend: HardwareBackend,
pub queue_length: usize,
pub avg_queue_time: Duration,
pub avg_execution_time: Duration,
pub success_rate: f64,
pub utilization: f64,
pub avg_cost: Option<f64>,
pub last_updated: SystemTime,
pub history: VecDeque<PerformanceSnapshot>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceSnapshot {
pub timestamp: SystemTime,
pub queue_length: usize,
pub utilization: f64,
pub avg_queue_time_secs: f64,
pub success_rate: f64,
}
#[derive(Debug, Clone)]
pub struct QueueAnalytics {
pub total_queue_length: usize,
pub queue_by_priority: HashMap<JobPriority, usize>,
pub queue_by_backend: HashMap<HardwareBackend, usize>,
pub predicted_queue_times: HashMap<HardwareBackend, Duration>,
pub system_load: f64,
pub throughput: f64,
pub avg_wait_time: Duration,
}
#[derive(Debug, Clone)]
pub struct SchedulingParams {
pub strategy: SchedulingStrategy,
pub allocation_strategy: AllocationStrategy,
pub time_slice: Duration,
pub max_jobs_per_user: Option<usize>,
pub fair_share_weights: HashMap<String, f64>,
pub backfill_threshold: Duration,
pub load_balance_factor: f64,
pub scirs2_params: SciRS2SchedulingParams,
}
#[derive(Debug, Clone)]
pub struct SciRS2SchedulingParams {
pub enabled: bool,
pub objective_weights: HashMap<String, f64>,
pub learning_window: Duration,
pub optimization_frequency: Duration,
pub model_params: HashMap<String, f64>,
pub ml_algorithm: MLAlgorithm,
pub multi_objective_weights: MultiObjectiveWeights,
pub rl_params: RLParameters,
pub ga_params: GAParameters,
pub enable_prediction: bool,
pub retrain_frequency: Duration,
pub feature_params: FeatureParams,
}
impl Default for SciRS2SchedulingParams {
fn default() -> Self {
Self {
enabled: true,
objective_weights: [
("throughput".to_string(), 0.25),
("fairness".to_string(), 0.25),
("utilization".to_string(), 0.2),
("cost".to_string(), 0.15),
("energy".to_string(), 0.1),
("sla_compliance".to_string(), 0.05),
]
.into_iter()
.collect(),
learning_window: Duration::from_secs(86400), optimization_frequency: Duration::from_secs(180), model_params: HashMap::new(),
ml_algorithm: MLAlgorithm::EnsembleMethod,
multi_objective_weights: MultiObjectiveWeights::default(),
rl_params: RLParameters::default(),
ga_params: GAParameters::default(),
enable_prediction: true,
retrain_frequency: Duration::from_secs(3600), feature_params: FeatureParams::default(),
}
}
}
impl Default for SchedulingParams {
fn default() -> Self {
Self {
strategy: SchedulingStrategy::MLOptimized,
allocation_strategy: AllocationStrategy::SciRS2Optimized,
time_slice: Duration::from_secs(60),
max_jobs_per_user: Some(100),
fair_share_weights: HashMap::new(),
backfill_threshold: Duration::from_secs(300),
load_balance_factor: 0.8,
scirs2_params: SciRS2SchedulingParams::default(),
}
}
}
pub struct QuantumJobScheduler {
pub(super) params: Arc<RwLock<SchedulingParams>>,
pub(super) job_queues: Arc<Mutex<BTreeMap<JobPriority, VecDeque<JobId>>>>,
pub(super) jobs: Arc<RwLock<HashMap<JobId, Box<dyn std::any::Any + Send + Sync>>>>,
pub(super) backend_performance: Arc<RwLock<HashMap<HardwareBackend, BackendPerformance>>>,
pub(super) backends: Arc<RwLock<HashSet<HardwareBackend>>>,
pub(super) running_jobs: Arc<RwLock<HashMap<JobId, (HardwareBackend, SystemTime)>>>,
pub(super) execution_history: Arc<RwLock<Vec<JobExecution>>>,
pub(super) user_shares: Arc<RwLock<HashMap<String, UserShare>>>,
pub(super) scheduler_running: Arc<Mutex<bool>>,
pub(super) event_sender: mpsc::UnboundedSender<SchedulerEvent>,
pub(super) performance_predictor: Arc<Mutex<PerformancePredictor>>,
pub(super) resource_manager: Arc<Mutex<ResourceManager>>,
pub(super) job_status_map: Arc<RwLock<HashMap<JobId, JobStatus>>>,
pub(super) job_config_map: Arc<RwLock<HashMap<JobId, JobConfig>>>,
pub(super) job_metrics_map: Arc<RwLock<HashMap<JobId, ExecutionMetrics>>>,
}
#[derive(Debug, Clone)]
pub(super) struct UserShare {
pub(super) user_id: String,
pub(super) allocated_share: f64,
pub(super) used_share: f64,
pub(super) jobs_running: usize,
pub(super) jobs_queued: usize,
pub(super) last_updated: SystemTime,
}
#[derive(Debug, Clone)]
pub enum SchedulerEvent {
JobSubmitted(JobId),
JobScheduled(JobId, HardwareBackend),
JobStarted(JobId),
JobCompleted(JobId, CircuitResult),
JobFailed(JobId, String),
JobCancelled(JobId),
BackendStatusChanged(HardwareBackend, BackendStatus),
QueueAnalyticsUpdated(QueueAnalytics),
}
#[derive(Debug, Clone)]
pub enum BackendStatus {
Available,
Busy,
Maintenance,
Offline,
Error(String),
}
pub(super) struct PerformancePredictor {
pub(super) history: VecDeque<PredictionDataPoint>,
pub(super) model_params: HashMap<String, f64>,
pub(super) accuracy_metrics: HashMap<String, f64>,
}
#[derive(Debug, Clone)]
pub(super) struct PredictionDataPoint {
pub(super) timestamp: SystemTime,
pub(super) backend: HardwareBackend,
pub(super) queue_length: usize,
pub(super) job_complexity: f64,
pub(super) execution_time: Duration,
pub(super) success: bool,
}
pub(super) struct ResourceManager {
pub(super) available_resources: HashMap<HardwareBackend, ResourceCapacity>,
pub(super) reservations: HashMap<JobId, ResourceReservation>,
pub(super) utilization_history: VecDeque<ResourceSnapshot>,
}
#[derive(Debug, Clone)]
pub(super) struct ResourceCapacity {
pub(super) qubits: usize,
pub(super) max_circuit_depth: Option<usize>,
pub(super) memory_mb: u64,
pub(super) cpu_cores: u32,
pub(super) concurrent_jobs: usize,
pub(super) features: HashSet<String>,
}
#[derive(Debug, Clone)]
pub(super) struct ResourceReservation {
pub(super) job_id: JobId,
pub(super) backend: HardwareBackend,
pub(super) resources: ResourceRequirements,
pub(super) reserved_at: SystemTime,
pub(super) expires_at: SystemTime,
}
#[derive(Debug, Clone)]
pub(super) struct ResourceSnapshot {
pub(super) timestamp: SystemTime,
pub(super) backend: HardwareBackend,
pub(super) utilization: f64,
pub(super) active_jobs: usize,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum MLAlgorithm {
LinearRegression,
SVM,
RandomForest,
GradientBoosting,
NeuralNetwork,
EnsembleMethod,
DeepRL,
GraphNN,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MultiObjectiveWeights {
pub throughput: f64,
pub cost: f64,
pub energy: f64,
pub fairness: f64,
pub sla_compliance: f64,
pub qos: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RLParameters {
pub learning_rate: f64,
pub discount_factor: f64,
pub exploration_rate: f64,
pub episode_length: usize,
pub reward_weights: HashMap<String, f64>,
pub state_dimension: usize,
pub action_space_size: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GAParameters {
pub population_size: usize,
pub generations: usize,
pub crossover_prob: f64,
pub mutation_prob: f64,
pub selection_strategy: String,
pub elite_size: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FeatureParams {
pub enable_temporal_features: bool,
pub enable_complexity_features: bool,
pub enable_user_features: bool,
pub enable_platform_features: bool,
pub enable_historical_features: bool,
pub normalization_method: String,
pub selection_threshold: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SLAConfig {
pub max_queue_time: Duration,
pub max_execution_time: Duration,
pub min_availability: f64,
pub violation_penalty: f64,
pub tier: SLATier,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum SLATier {
Gold,
Silver,
Bronze,
Basic,
}
impl Default for MultiObjectiveWeights {
fn default() -> Self {
Self {
throughput: 0.3,
cost: 0.2,
energy: 0.15,
fairness: 0.15,
sla_compliance: 0.1,
qos: 0.1,
}
}
}
impl Default for RLParameters {
fn default() -> Self {
Self {
learning_rate: 0.001,
discount_factor: 0.95,
exploration_rate: 0.1,
episode_length: 1000,
reward_weights: [
("throughput".to_string(), 1.0),
("fairness".to_string(), 0.5),
("cost".to_string(), -0.3),
]
.into_iter()
.collect(),
state_dimension: 64,
action_space_size: 16,
}
}
}
impl Default for GAParameters {
fn default() -> Self {
Self {
population_size: 50,
generations: 100,
crossover_prob: 0.8,
mutation_prob: 0.1,
selection_strategy: "tournament".to_string(),
elite_size: 5,
}
}
}
impl Default for FeatureParams {
fn default() -> Self {
Self {
enable_temporal_features: true,
enable_complexity_features: true,
enable_user_features: true,
enable_platform_features: true,
enable_historical_features: true,
normalization_method: "z_score".to_string(),
selection_threshold: 0.1,
}
}
}