1use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
9use std::sync::{Arc, Mutex, RwLock};
10use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
11
12use quantrs2_circuit::prelude::*;
13use quantrs2_core::{
14 error::{QuantRS2Error, QuantRS2Result},
15 gate::GateOp,
16 qubit::QubitId,
17};
18
19#[cfg(feature = "scirs2")]
21use scirs2_linalg::{det, eig, inv, matrix_norm, prelude::*, svd, LinalgError, LinalgResult};
22#[cfg(feature = "scirs2")]
23use scirs2_optimize::{minimize, OptimizeResult};
24use scirs2_stats::ttest::Alternative;
25#[cfg(feature = "scirs2")]
26use scirs2_stats::{corrcoef, distributions, mean, pearsonr, spearmanr, std, var};
27
28#[cfg(not(feature = "scirs2"))]
30mod fallback_scirs2 {
31 use scirs2_core::ndarray::{Array1, Array2, ArrayView1, ArrayView2};
32
33 pub fn mean(_data: &ArrayView1<f64>) -> Result<f64, String> {
34 Ok(0.0)
35 }
36 pub fn std(_data: &ArrayView1<f64>, _ddof: i32) -> Result<f64, String> {
37 Ok(1.0)
38 }
39 pub fn pearsonr(
40 _x: &ArrayView1<f64>,
41 _y: &ArrayView1<f64>,
42 _alt: &str,
43 ) -> Result<(f64, f64), String> {
44 Ok((0.0, 0.5))
45 }
46
47 pub struct OptimizeResult {
48 pub x: Array1<f64>,
49 pub fun: f64,
50 pub success: bool,
51 pub nit: usize,
52 pub nfev: usize,
53 pub message: String,
54 }
55
56 pub fn minimize(
57 _func: fn(&Array1<f64>) -> f64,
58 _x0: &Array1<f64>,
59 _method: &str,
60 ) -> Result<OptimizeResult, String> {
61 Ok(OptimizeResult {
62 x: Array1::zeros(2),
63 fun: 0.0,
64 success: true,
65 nit: 0,
66 nfev: 0,
67 message: "Fallback optimization".to_string(),
68 })
69 }
70
71 pub fn genetic_algorithm(
72 _func: fn(&Array1<f64>) -> f64,
73 _bounds: &[(f64, f64)],
74 ) -> Result<OptimizeResult, String> {
75 Ok(OptimizeResult {
76 x: Array1::zeros(2),
77 fun: 0.0,
78 success: true,
79 nit: 0,
80 nfev: 0,
81 message: "Fallback genetic algorithm".to_string(),
82 })
83 }
84
85 pub fn random_forest(_x: &Array2<f64>, _y: &Array1<f64>) -> Result<String, String> {
86 Ok("fallback_model".to_string())
87 }
88}
89
90#[cfg(not(feature = "scirs2"))]
91use fallback_scirs2::*;
92
93#[cfg(feature = "security")]
94use chrono::{DateTime, Duration as ChronoDuration, Utc};
95use scirs2_core::ndarray::{s, Array1, Array2, Array3, Array4, ArrayView1, ArrayView2, Axis};
96use scirs2_core::random::prelude::*;
97use scirs2_core::Complex64;
98use serde::{Deserialize, Serialize};
99use tokio::sync::{broadcast, mpsc, RwLock as TokioRwLock, Semaphore};
100use uuid::Uuid;
101
102use crate::{
103 backend_traits::{query_backend_capabilities, BackendCapabilities},
104 calibration::{CalibrationManager, DeviceCalibration},
105 integrated_device_manager::{
106 DeviceInfo, IntegratedExecutionResult, IntegratedQuantumDeviceManager,
107 },
108 job_scheduling::{JobConfig, JobPriority, JobStatus, QuantumJob, QuantumJobScheduler},
109 noise_model::CalibrationNoiseModel,
110 topology::HardwareTopology,
111 CircuitExecutor, CircuitResult, DeviceError, DeviceResult, QuantumDevice,
112};
113
114pub mod allocation;
116pub mod cost_estimation;
117pub mod cost_management;
118pub mod monitoring;
119pub mod orchestration;
120pub mod provider_migration;
121pub mod provider_optimizations;
122pub mod providers;
123
124pub use allocation::*;
126pub use cost_estimation::*;
127pub use cost_management::*;
128pub use monitoring::*;
129pub use orchestration::*;
130pub use provider_migration::*;
131pub use provider_optimizations::*;
132pub use providers::*;
133
134pub use orchestration::load_balancing::CloudLoadBalancingConfig;
136pub use orchestration::performance::AutoScalingConfig;
137pub use orchestration::performance::CloudPerformanceConfig;
138pub use orchestration::CloudSecurityConfig;
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct QuantumCloudConfig {
143 pub provider_config: MultiProviderConfig,
145 pub allocation_config: ResourceAllocationConfig,
147 pub cost_config: CostManagementConfig,
149 pub performance_config: CloudPerformanceConfig,
151 pub load_balancing_config: CloudLoadBalancingConfig,
153 pub security_config: CloudSecurityConfig,
155 pub monitoring_config: CloudMonitoringConfig,
157 pub ml_config: CloudMLConfig,
159 pub scaling_config: AutoScalingConfig,
161 pub budget_config: BudgetConfig,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct CloudMLConfig {
168 pub enable_ml_optimization: bool,
170 pub optimization_models: Vec<String>,
172 pub predictive_analytics: bool,
174 pub automated_decision_threshold: f64,
176 pub model_training_enabled: bool,
178 pub feature_engineering_enabled: bool,
180}
181
182impl Default for CloudMLConfig {
183 fn default() -> Self {
184 Self {
185 enable_ml_optimization: false,
186 optimization_models: vec![],
187 predictive_analytics: false,
188 automated_decision_threshold: 0.8,
189 model_training_enabled: false,
190 feature_engineering_enabled: false,
191 }
192 }
193}
194
195#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
197pub struct CloudJobId(pub String);
198
199impl std::fmt::Display for CloudJobId {
200 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
201 write!(f, "{}", self.0)
202 }
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct CloudJob {
212 pub name: String,
214 pub qasm_source: String,
216 pub preferred_provider: Option<CloudProvider>,
218 pub shots: usize,
220 pub timeout: std::time::Duration,
222 pub metadata: std::collections::HashMap<String, String>,
224}
225
226#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
228pub enum CloudJobStatus {
229 Queued,
231 Submitted { provider: CloudProvider },
233 Running { provider: CloudProvider },
235 Completed { provider: CloudProvider },
237 Failed { reason: String },
239 Cancelled,
241}
242
243#[derive(Debug, Clone)]
245pub struct CloudCostEstimate {
246 pub recommended_provider: CloudProvider,
248 pub estimated_usd: f64,
250 pub provider_breakdown: std::collections::HashMap<CloudProvider, f64>,
252 pub confidence: f64,
254}
255
256#[derive(Debug, Clone)]
258struct JobRecord {
259 job: CloudJob,
260 status: CloudJobStatus,
261 submitted_at: std::time::SystemTime,
262 completed_at: Option<std::time::SystemTime>,
263}
264
265pub struct QuantumCloudManager {
275 config: QuantumCloudConfig,
276 jobs: std::sync::RwLock<std::collections::HashMap<CloudJobId, JobRecord>>,
278}
279
280impl QuantumCloudManager {
281 pub fn new(config: QuantumCloudConfig) -> DeviceResult<Self> {
283 Ok(Self {
284 config,
285 jobs: std::sync::RwLock::new(std::collections::HashMap::new()),
286 })
287 }
288
289 pub fn submit_job(&self, job: CloudJob) -> DeviceResult<CloudJobId> {
294 if job.qasm_source.trim().is_empty() {
295 return Err(DeviceError::InvalidInput(
296 "CloudJob.qasm_source must not be empty".to_string(),
297 ));
298 }
299 let provider = self.select_provider(&job)?;
300 let id = CloudJobId(Uuid::new_v4().to_string());
301 let record = JobRecord {
302 status: CloudJobStatus::Submitted {
303 provider: provider.clone(),
304 },
305 job,
306 submitted_at: std::time::SystemTime::now(),
307 completed_at: None,
308 };
309 self.jobs
310 .write()
311 .map_err(|e| DeviceError::LockError(format!("jobs write lock: {e}")))?
312 .insert(id.clone(), record);
313 Ok(id)
314 }
315
316 pub fn get_job_status(&self, id: &CloudJobId) -> DeviceResult<CloudJobStatus> {
318 let jobs = self
319 .jobs
320 .read()
321 .map_err(|e| DeviceError::LockError(format!("jobs read lock: {e}")))?;
322 jobs.get(id)
323 .map(|r| r.status.clone())
324 .ok_or_else(|| DeviceError::DeviceNotFound(format!("job '{}' not found", id)))
325 }
326
327 pub fn cancel_job(&self, id: &CloudJobId) -> DeviceResult<()> {
329 let mut jobs = self
330 .jobs
331 .write()
332 .map_err(|e| DeviceError::LockError(format!("jobs write lock: {e}")))?;
333 let record = jobs
334 .get_mut(id)
335 .ok_or_else(|| DeviceError::DeviceNotFound(format!("job '{}' not found", id)))?;
336 match &record.status {
337 CloudJobStatus::Queued | CloudJobStatus::Submitted { .. } => {
338 record.status = CloudJobStatus::Cancelled;
339 record.completed_at = Some(std::time::SystemTime::now());
340 Ok(())
341 }
342 other => Err(DeviceError::InvalidInput(format!(
343 "cannot cancel job '{}' in state {:?}",
344 id, other
345 ))),
346 }
347 }
348
349 pub fn list_providers(&self) -> Vec<CloudProvider> {
351 self.config.provider_config.enabled_providers.clone()
352 }
353
354 pub fn estimate_cost(&self, job: &CloudJob) -> DeviceResult<CloudCostEstimate> {
360 let providers = self.list_providers();
361 if providers.is_empty() {
362 return Err(DeviceError::UnsupportedOperation(
363 "no cloud providers configured".to_string(),
364 ));
365 }
366
367 let cost_per_shot = |p: &CloudProvider| -> f64 {
371 match p {
372 CloudProvider::IBM => 0.000_05,
373 CloudProvider::AWS => 0.000_075,
374 CloudProvider::Azure => 0.000_065,
375 CloudProvider::Google => 0.000_08,
376 CloudProvider::IonQ => 0.000_01,
377 CloudProvider::Rigetti => 0.000_04,
378 CloudProvider::Xanadu => 0.000_03,
379 CloudProvider::DWave => 0.000_02,
380 CloudProvider::Custom(_) => 0.000_05,
381 }
382 };
383
384 let shots = job.shots.max(1) as f64;
385 let mut breakdown = std::collections::HashMap::new();
386 let mut cheapest_provider = providers[0].clone();
387 let mut cheapest_cost = f64::MAX;
388
389 for provider in &providers {
390 let cost = cost_per_shot(provider) * shots;
391 if cost < cheapest_cost {
392 cheapest_cost = cost;
393 cheapest_provider = provider.clone();
394 }
395 breakdown.insert(provider.clone(), cost);
396 }
397
398 Ok(CloudCostEstimate {
399 recommended_provider: cheapest_provider,
400 estimated_usd: cheapest_cost,
401 provider_breakdown: breakdown,
402 confidence: 0.8,
403 })
404 }
405
406 fn select_provider(&self, job: &CloudJob) -> DeviceResult<CloudProvider> {
411 if let Some(preferred) = &job.preferred_provider {
413 if self
414 .config
415 .provider_config
416 .enabled_providers
417 .contains(preferred)
418 {
419 return Ok(preferred.clone());
420 }
421 }
422 let estimate = self.estimate_cost(job)?;
424 Ok(estimate.recommended_provider)
425 }
426}