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, Default)]
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 NeutralAtomExecutionMetadata {
148 fn default() -> Self {
149 Self {
150 system_type: NeutralAtomSystemType::Rydberg,
151 atoms_used: 0,
152 execution_time: Duration::from_millis(0),
153 gate_sequence: Vec::new(),
154 optimizations_applied: Vec::new(),
155 temperature: None,
156 laser_power: None,
157 }
158 }
159}
160
161#[async_trait::async_trait]
163pub trait NeutralAtomQuantumDevice: QuantumDevice + CircuitExecutor {
164 async fn system_type(&self) -> DeviceResult<NeutralAtomSystemType>;
166
167 async fn atom_count(&self) -> DeviceResult<usize>;
169
170 async fn atom_spacing(&self) -> DeviceResult<f64>;
172
173 async fn state_encoding(&self) -> DeviceResult<AtomStateEncoding>;
175
176 async fn blockade_radius(&self) -> DeviceResult<Option<f64>>;
178
179 async fn supports_rydberg_gates(&self) -> DeviceResult<bool>;
181
182 async fn supports_tweezer_manipulation(&self) -> DeviceResult<bool>;
184
185 async fn loading_efficiency(&self) -> DeviceResult<f64>;
187
188 async fn gate_fidelity(&self) -> DeviceResult<f64>;
190
191 async fn execute_neutral_atom_circuit<const N: usize>(
193 &self,
194 circuit: &Circuit<N>,
195 shots: usize,
196 config: Option<NeutralAtomDeviceConfig>,
197 ) -> DeviceResult<NeutralAtomCircuitResult>;
198
199 async fn load_atoms(&self, positions: &[(f64, f64, f64)]) -> DeviceResult<Vec<bool>>;
201
202 async fn move_atoms(
204 &self,
205 atom_indices: &[usize],
206 new_positions: &[(f64, f64, f64)],
207 ) -> DeviceResult<()>;
208
209 async fn rydberg_excitation(
211 &self,
212 atom_indices: &[usize],
213 excitation_time: Duration,
214 laser_power: f64,
215 ) -> DeviceResult<Vec<bool>>;
216
217 async fn global_rydberg_operation(
219 &self,
220 operation: &str,
221 parameters: &HashMap<String, f64>,
222 ) -> DeviceResult<()>;
223
224 async fn measure_atom_states(&self, atom_indices: &[usize]) -> DeviceResult<Vec<String>>;
226
227 async fn calculate_atom_correlations(
229 &self,
230 atom_pairs: &[(usize, usize)],
231 correlation_type: &str,
232 ) -> DeviceResult<HashMap<String, f64>>;
233
234 async fn estimate_fidelity(
236 &self,
237 target_state: &str,
238 measurement_data: &NeutralAtomMeasurementData,
239 ) -> DeviceResult<f64>;
240}
241
242pub const fn create_neutral_atom_device(
244 client: NeutralAtomClient,
245 device_id: String,
246 config: NeutralAtomDeviceConfig,
247) -> DeviceResult<NeutralAtomDevice> {
248 Ok(NeutralAtomDevice::new(client, device_id, config))
249}
250
251pub fn validate_neutral_atom_config(config: &NeutralAtomDeviceConfig) -> DeviceResult<()> {
253 if config.atom_count == 0 {
254 return Err(DeviceError::InvalidInput(
255 "Atom count must be greater than 0".to_string(),
256 ));
257 }
258
259 if config.atom_spacing <= 0.0 {
260 return Err(DeviceError::InvalidInput(
261 "Atom spacing must be positive".to_string(),
262 ));
263 }
264
265 if let Some(blockade_radius) = config.blockade_radius {
266 if blockade_radius <= 0.0 {
267 return Err(DeviceError::InvalidInput(
268 "Blockade radius must be positive".to_string(),
269 ));
270 }
271 }
272
273 if let Some(fidelity) = config.gate_fidelity {
274 if !(0.0..=1.0).contains(&fidelity) {
275 return Err(DeviceError::InvalidInput(
276 "Gate fidelity must be between 0 and 1".to_string(),
277 ));
278 }
279 }
280
281 if let Some(efficiency) = config.loading_efficiency {
282 if !(0.0..=1.0).contains(&efficiency) {
283 return Err(DeviceError::InvalidInput(
284 "Loading efficiency must be between 0 and 1".to_string(),
285 ));
286 }
287 }
288
289 Ok(())
290}
291
292pub mod gates {
294 use super::*;
295
296 #[derive(Debug, Clone, Serialize, Deserialize)]
298 pub struct RydbergExcitationGate {
299 pub atom_index: usize,
300 pub excitation_time: Duration,
301 pub laser_power: f64,
302 pub detuning: f64,
303 }
304
305 #[derive(Debug, Clone, Serialize, Deserialize)]
307 pub struct RydbergBlockadeGate {
308 pub control_atom: usize,
309 pub target_atom: usize,
310 pub blockade_strength: f64,
311 pub interaction_time: Duration,
312 }
313
314 #[derive(Debug, Clone, Serialize, Deserialize)]
316 pub struct GlobalRydbergGate {
317 pub operation_type: String,
318 pub laser_power: f64,
319 pub pulse_duration: Duration,
320 pub phase: f64,
321 }
322
323 #[derive(Debug, Clone, Serialize, Deserialize)]
325 pub struct TweezerMovementGate {
326 pub atom_index: usize,
327 pub start_position: (f64, f64, f64),
328 pub end_position: (f64, f64, f64),
329 pub movement_time: Duration,
330 }
331
332 #[derive(Debug, Clone, Serialize, Deserialize)]
334 pub struct HyperfineGate {
335 pub atom_index: usize,
336 pub target_state: String,
337 pub microwave_frequency: f64,
338 pub pulse_duration: Duration,
339 }
340}
341
342#[cfg(test)]
343mod tests {
344 use super::*;
345
346 #[test]
347 fn test_neutral_atom_config_validation() {
348 let valid_config = NeutralAtomDeviceConfig::default();
349 assert!(validate_neutral_atom_config(&valid_config).is_ok());
350
351 let invalid_config = NeutralAtomDeviceConfig {
352 atom_count: 0,
353 ..Default::default()
354 };
355 assert!(validate_neutral_atom_config(&invalid_config).is_err());
356 }
357
358 #[test]
359 fn test_neutral_atom_system_types() {
360 let rydberg_system = NeutralAtomSystemType::Rydberg;
361 assert_eq!(rydberg_system, NeutralAtomSystemType::Rydberg);
362
363 let tweezer_system = NeutralAtomSystemType::OpticalTweezer;
364 assert_eq!(tweezer_system, NeutralAtomSystemType::OpticalTweezer);
365 }
366
367 #[test]
368 fn test_atom_state_encoding() {
369 let ground_excited = AtomStateEncoding::GroundExcited;
370 assert_eq!(ground_excited, AtomStateEncoding::GroundExcited);
371
372 let hyperfine = AtomStateEncoding::Hyperfine;
373 assert_eq!(hyperfine, AtomStateEncoding::Hyperfine);
374 }
375}