clawft_kernel/
quantum_backend.rs1use async_trait::async_trait;
14use serde::{Deserialize, Serialize};
15use std::time::Duration;
16
17use crate::quantum_state::QuantumCognitiveState;
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct JobHandle {
22 pub backend: &'static str,
23 pub job_id: String,
24 pub batch_id: Option<String>,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct QuantumResults {
30 pub bitstrings: Vec<Vec<u8>>,
32 pub rydberg_probs: Vec<f64>,
34 pub shots: u32,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
40pub enum JobStatus {
41 Pending,
42 Running,
43 Done,
44 Canceled,
45 Error,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct BackendStatus {
51 pub name: &'static str,
52 pub reachable: bool,
53 pub queue_depth: Option<u32>,
54 pub estimated_wait: Option<Duration>,
55 pub max_qubits: usize,
56}
57
58#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
61pub struct EvolutionParams {
62 pub duration_ns: u64,
63 pub omega_rad_per_us: f64,
64 pub detuning_rad_per_us: f64,
65 pub phase_rad: f64,
66 pub shots: u32,
67}
68
69impl Default for EvolutionParams {
70 fn default() -> Self {
71 Self {
72 duration_ns: 1000,
73 omega_rad_per_us: 1.0,
74 detuning_rad_per_us: 0.0,
75 phase_rad: 0.0,
76 shots: 100,
77 }
78 }
79}
80
81#[derive(Debug, thiserror::Error)]
83pub enum QuantumError {
84 #[error("backend not implemented (experimental 0.6.x interface)")]
85 NotImplemented,
86 #[error("authentication failed: {0}")]
87 Auth(String),
88 #[error("transport error: {0}")]
89 Transport(String),
90 #[error("backend rejected request: {0}")]
91 Rejected(String),
92 #[error("graph too large for backend: {nodes} > {max}")]
93 GraphTooLarge { nodes: usize, max: usize },
94 #[error("invalid register layout: {0}")]
95 InvalidRegister(String),
96 #[error("serialization: {0}")]
97 Serde(String),
98}
99
100#[async_trait]
105pub trait QuantumBackend: Send + Sync {
106 fn name(&self) -> &'static str;
107
108 fn max_qubits(&self) -> usize;
109
110 async fn health_check(&self) -> Result<BackendStatus, QuantumError>;
111
112 async fn submit_evolution(
115 &self,
116 register: &[(String, [f64; 2])],
117 state: &QuantumCognitiveState,
118 params: EvolutionParams,
119 ) -> Result<JobHandle, QuantumError>;
120
121 async fn poll(&self, handle: &JobHandle) -> Result<JobStatus, QuantumError>;
122
123 async fn get_results(&self, handle: &JobHandle)
124 -> Result<Option<QuantumResults>, QuantumError>;
125
126 async fn cancel(&self, handle: &JobHandle) -> Result<(), QuantumError>;
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 fn _assert_object_safe(_: &dyn QuantumBackend) {}
134
135 #[test]
136 fn evolution_params_default_sane() {
137 let p = EvolutionParams::default();
138 assert!(p.shots > 0);
139 assert!(p.duration_ns > 0);
140 }
141
142 #[test]
143 fn not_implemented_error_formats() {
144 let e = QuantumError::NotImplemented;
145 assert!(e.to_string().contains("not implemented"));
146 }
147
148 #[test]
149 fn graph_too_large_error_contains_counts() {
150 let e = QuantumError::GraphTooLarge {
151 nodes: 500,
152 max: 100,
153 };
154 let msg = e.to_string();
155 assert!(msg.contains("500"));
156 assert!(msg.contains("100"));
157 }
158}