use std::time::{Duration, SystemTime};
use crate::job_scheduling::{JobPriority, ResourceRequirements};
const RUNTIME_EPSILON_SECS: f64 = 1.0e-3;
pub fn wsjf_priority(weight: f64, estimated_runtime: Duration) -> f64 {
let runtime_secs = estimated_runtime.as_secs_f64().max(RUNTIME_EPSILON_SECS);
weight / runtime_secs
}
pub fn time_to_deadline(deadline: SystemTime, now: SystemTime) -> Option<Duration> {
deadline.duration_since(now).ok()
}
pub fn is_overdue(deadline: SystemTime, now: SystemTime) -> bool {
now > deadline
}
pub fn slack_seconds(deadline: SystemTime, now: SystemTime, estimated_runtime: Duration) -> i64 {
let to_deadline_secs: i64 = match deadline.duration_since(now) {
Ok(d) => i64::try_from(d.as_secs()).unwrap_or(i64::MAX),
Err(e) => -i64::try_from(e.duration().as_secs()).unwrap_or(i64::MAX),
};
let runtime_secs = i64::try_from(estimated_runtime.as_secs()).unwrap_or(i64::MAX);
to_deadline_secs.saturating_sub(runtime_secs)
}
pub fn throughput(completed_jobs: usize, window: Duration) -> f64 {
let secs = window.as_secs_f64();
if secs <= 0.0 {
0.0
} else {
completed_jobs as f64 / secs
}
}
pub fn edf_sort_key(deadline: Option<SystemTime>, now: SystemTime) -> Duration {
match deadline {
Some(d) => d.duration_since(now).unwrap_or(Duration::ZERO),
None => Duration::MAX,
}
}
pub fn available_qubits(capacity_qubits: usize, used_qubits: usize) -> usize {
capacity_qubits.saturating_sub(used_qubits)
}
pub fn device_compatible(
req: &ResourceRequirements,
capacity_qubits: usize,
capacity_max_depth: Option<usize>,
capacity_memory_mb: Option<u64>,
capacity_cpu_cores: Option<u32>,
capacity_features: &std::collections::HashSet<String>,
) -> bool {
if capacity_qubits < req.min_qubits {
return false;
}
if let Some(req_depth) = req.max_depth {
if let Some(cap_depth) = capacity_max_depth {
if req_depth > cap_depth {
return false;
}
}
}
if let Some(req_mem) = req.memory_mb {
if let Some(cap_mem) = capacity_memory_mb {
if req_mem > cap_mem {
return false;
}
}
}
if let Some(req_cpu) = req.cpu_cores {
if let Some(cap_cpu) = capacity_cpu_cores {
if req_cpu > cap_cpu {
return false;
}
}
}
for feature in &req.required_features {
if !capacity_features.contains(feature) {
return false;
}
}
true
}
pub fn sort_by_edf<T, F>(items: &mut [T], now: SystemTime, deadline_of: F)
where
F: Fn(&T) -> Option<SystemTime>,
{
items.sort_by_key(|item| edf_sort_key(deadline_of(item), now));
}
pub fn sort_by_wsjf<T, FW, FR>(items: &mut [T], weight_of: FW, runtime_of: FR)
where
FW: Fn(&T) -> f64,
FR: Fn(&T) -> Duration,
{
items.sort_by(|a, b| {
let pa = wsjf_priority(weight_of(a), runtime_of(a));
let pb = wsjf_priority(weight_of(b), runtime_of(b));
pb.partial_cmp(&pa).unwrap_or(std::cmp::Ordering::Equal)
});
}
pub fn priority_weight(p: JobPriority) -> f64 {
match p {
JobPriority::Critical => 16.0,
JobPriority::High => 8.0,
JobPriority::Normal => 4.0,
JobPriority::Low => 2.0,
JobPriority::BestEffort => 1.0,
}
}