1use crate::{CircuitExecutor, CircuitResult, DeviceError, DeviceResult, QuantumDevice};
7use quantrs2_circuit::prelude::Circuit;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::time::Duration;
11
12pub mod client;
13pub mod config;
14pub mod device;
15pub mod gate_operations;
16pub mod protocols;
17pub mod rydberg;
18pub mod tweezer_arrays;
19
20pub use client::NeutralAtomClient;
21pub use device::NeutralAtomDevice;
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
25pub enum NeutralAtomSystemType {
26 Rydberg,
28 OpticalTweezer,
30 MagneticTrap,
32 Hybrid,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
38pub enum AtomStateEncoding {
39 GroundExcited,
41 Hyperfine,
43 Clock,
45 Zeeman,
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct NeutralAtomDeviceConfig {
52 pub system_type: NeutralAtomSystemType,
54 pub atom_count: usize,
56 pub atom_spacing: f64,
58 pub state_encoding: AtomStateEncoding,
60 pub blockade_radius: Option<f64>,
62 pub laser_wavelength: Option<f64>,
64 pub trap_depth: Option<f64>,
66 pub gate_fidelity: Option<f64>,
68 pub measurement_fidelity: Option<f64>,
70 pub loading_efficiency: Option<f64>,
72 pub max_execution_time: Option<Duration>,
74 pub hardware_acceleration: bool,
76 pub hardware_params: HashMap<String, String>,
78}
79
80impl Default for NeutralAtomDeviceConfig {
81 fn default() -> Self {
82 Self {
83 system_type: NeutralAtomSystemType::Rydberg,
84 atom_count: 100,
85 atom_spacing: 5.0,
86 state_encoding: AtomStateEncoding::GroundExcited,
87 blockade_radius: Some(8.0),
88 laser_wavelength: Some(480.0),
89 trap_depth: Some(1000.0),
90 gate_fidelity: Some(0.995),
91 measurement_fidelity: Some(0.99),
92 loading_efficiency: Some(0.95),
93 max_execution_time: Some(Duration::from_secs(60)),
94 hardware_acceleration: true,
95 hardware_params: HashMap::new(),
96 }
97 }
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct NeutralAtomCircuitResult {
103 pub circuit_result: CircuitResult,
105 pub neutral_atom_data: NeutralAtomMeasurementData,
107 pub execution_metadata: NeutralAtomExecutionMetadata,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct NeutralAtomMeasurementData {
114 pub atom_positions: Vec<(f64, f64, f64)>,
116 pub atom_states: Vec<String>,
118 pub rydberg_patterns: Vec<Vec<bool>>,
120 pub correlations: HashMap<String, f64>,
122 pub fidelities: HashMap<String, f64>,
124 pub loading_success: Vec<bool>,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
130pub struct NeutralAtomExecutionMetadata {
131 pub system_type: NeutralAtomSystemType,
133 pub atoms_used: usize,
135 pub execution_time: Duration,
137 pub gate_sequence: Vec<String>,
139 pub optimizations_applied: Vec<String>,
141 pub temperature: Option<f64>,
143 pub laser_power: Option<f64>,
145}
146
147impl Default for NeutralAtomMeasurementData {
148 fn default() -> Self {
149 Self {
150 atom_positions: Vec::new(),
151 atom_states: Vec::new(),
152 rydberg_patterns: Vec::new(),
153 correlations: HashMap::new(),
154 fidelities: HashMap::new(),
155 loading_success: Vec::new(),
156 }
157 }
158}
159
160impl Default for NeutralAtomExecutionMetadata {
161 fn default() -> Self {
162 Self {
163 system_type: NeutralAtomSystemType::Rydberg,
164 atoms_used: 0,
165 execution_time: Duration::from_millis(0),
166 gate_sequence: Vec::new(),
167 optimizations_applied: Vec::new(),
168 temperature: None,
169 laser_power: None,
170 }
171 }
172}
173
174#[async_trait::async_trait]
176pub trait NeutralAtomQuantumDevice: QuantumDevice + CircuitExecutor {
177 async fn system_type(&self) -> DeviceResult<NeutralAtomSystemType>;
179
180 async fn atom_count(&self) -> DeviceResult<usize>;
182
183 async fn atom_spacing(&self) -> DeviceResult<f64>;
185
186 async fn state_encoding(&self) -> DeviceResult<AtomStateEncoding>;
188
189 async fn blockade_radius(&self) -> DeviceResult<Option<f64>>;
191
192 async fn supports_rydberg_gates(&self) -> DeviceResult<bool>;
194
195 async fn supports_tweezer_manipulation(&self) -> DeviceResult<bool>;
197
198 async fn loading_efficiency(&self) -> DeviceResult<f64>;
200
201 async fn gate_fidelity(&self) -> DeviceResult<f64>;
203
204 async fn execute_neutral_atom_circuit<const N: usize>(
206 &self,
207 circuit: &Circuit<N>,
208 shots: usize,
209 config: Option<NeutralAtomDeviceConfig>,
210 ) -> DeviceResult<NeutralAtomCircuitResult>;
211
212 async fn load_atoms(&self, positions: &[(f64, f64, f64)]) -> DeviceResult<Vec<bool>>;
214
215 async fn move_atoms(
217 &self,
218 atom_indices: &[usize],
219 new_positions: &[(f64, f64, f64)],
220 ) -> DeviceResult<()>;
221
222 async fn rydberg_excitation(
224 &self,
225 atom_indices: &[usize],
226 excitation_time: Duration,
227 laser_power: f64,
228 ) -> DeviceResult<Vec<bool>>;
229
230 async fn global_rydberg_operation(
232 &self,
233 operation: &str,
234 parameters: &HashMap<String, f64>,
235 ) -> DeviceResult<()>;
236
237 async fn measure_atom_states(&self, atom_indices: &[usize]) -> DeviceResult<Vec<String>>;
239
240 async fn calculate_atom_correlations(
242 &self,
243 atom_pairs: &[(usize, usize)],
244 correlation_type: &str,
245 ) -> DeviceResult<HashMap<String, f64>>;
246
247 async fn estimate_fidelity(
249 &self,
250 target_state: &str,
251 measurement_data: &NeutralAtomMeasurementData,
252 ) -> DeviceResult<f64>;
253}
254
255pub fn create_neutral_atom_device(
257 client: NeutralAtomClient,
258 device_id: String,
259 config: NeutralAtomDeviceConfig,
260) -> DeviceResult<NeutralAtomDevice> {
261 Ok(NeutralAtomDevice::new(client, device_id, config))
262}
263
264pub fn validate_neutral_atom_config(config: &NeutralAtomDeviceConfig) -> DeviceResult<()> {
266 if config.atom_count == 0 {
267 return Err(DeviceError::InvalidInput(
268 "Atom count must be greater than 0".to_string(),
269 ));
270 }
271
272 if config.atom_spacing <= 0.0 {
273 return Err(DeviceError::InvalidInput(
274 "Atom spacing must be positive".to_string(),
275 ));
276 }
277
278 if let Some(blockade_radius) = config.blockade_radius {
279 if blockade_radius <= 0.0 {
280 return Err(DeviceError::InvalidInput(
281 "Blockade radius must be positive".to_string(),
282 ));
283 }
284 }
285
286 if let Some(fidelity) = config.gate_fidelity {
287 if fidelity < 0.0 || fidelity > 1.0 {
288 return Err(DeviceError::InvalidInput(
289 "Gate fidelity must be between 0 and 1".to_string(),
290 ));
291 }
292 }
293
294 if let Some(efficiency) = config.loading_efficiency {
295 if efficiency < 0.0 || efficiency > 1.0 {
296 return Err(DeviceError::InvalidInput(
297 "Loading efficiency must be between 0 and 1".to_string(),
298 ));
299 }
300 }
301
302 Ok(())
303}
304
305pub mod gates {
307 use super::*;
308
309 #[derive(Debug, Clone, Serialize, Deserialize)]
311 pub struct RydbergExcitationGate {
312 pub atom_index: usize,
313 pub excitation_time: Duration,
314 pub laser_power: f64,
315 pub detuning: f64,
316 }
317
318 #[derive(Debug, Clone, Serialize, Deserialize)]
320 pub struct RydbergBlockadeGate {
321 pub control_atom: usize,
322 pub target_atom: usize,
323 pub blockade_strength: f64,
324 pub interaction_time: Duration,
325 }
326
327 #[derive(Debug, Clone, Serialize, Deserialize)]
329 pub struct GlobalRydbergGate {
330 pub operation_type: String,
331 pub laser_power: f64,
332 pub pulse_duration: Duration,
333 pub phase: f64,
334 }
335
336 #[derive(Debug, Clone, Serialize, Deserialize)]
338 pub struct TweezerMovementGate {
339 pub atom_index: usize,
340 pub start_position: (f64, f64, f64),
341 pub end_position: (f64, f64, f64),
342 pub movement_time: Duration,
343 }
344
345 #[derive(Debug, Clone, Serialize, Deserialize)]
347 pub struct HyperfineGate {
348 pub atom_index: usize,
349 pub target_state: String,
350 pub microwave_frequency: f64,
351 pub pulse_duration: Duration,
352 }
353}
354
355#[cfg(test)]
356mod tests {
357 use super::*;
358
359 #[test]
360 fn test_neutral_atom_config_validation() {
361 let valid_config = NeutralAtomDeviceConfig::default();
362 assert!(validate_neutral_atom_config(&valid_config).is_ok());
363
364 let invalid_config = NeutralAtomDeviceConfig {
365 atom_count: 0,
366 ..Default::default()
367 };
368 assert!(validate_neutral_atom_config(&invalid_config).is_err());
369 }
370
371 #[test]
372 fn test_neutral_atom_system_types() {
373 let rydberg_system = NeutralAtomSystemType::Rydberg;
374 assert_eq!(rydberg_system, NeutralAtomSystemType::Rydberg);
375
376 let tweezer_system = NeutralAtomSystemType::OpticalTweezer;
377 assert_eq!(tweezer_system, NeutralAtomSystemType::OpticalTweezer);
378 }
379
380 #[test]
381 fn test_atom_state_encoding() {
382 let ground_excited = AtomStateEncoding::GroundExcited;
383 assert_eq!(ground_excited, AtomStateEncoding::GroundExcited);
384
385 let hyperfine = AtomStateEncoding::Hyperfine;
386 assert_eq!(hyperfine, AtomStateEncoding::Hyperfine);
387 }
388}