1use crate::{DeviceError, DeviceResult};
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10use std::time::Duration;
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub enum NeutralAtomGateType {
15 SingleQubitRotation,
17 RydbergExcitation,
19 RydbergBlockade,
21 GlobalRydberg,
23 TweezerMovement,
25 HyperfineManipulation,
27 Measurement,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct NeutralAtomGateParams {
34 pub gate_type: NeutralAtomGateType,
36 pub target_atoms: Vec<usize>,
38 pub duration: Duration,
40 pub parameters: HashMap<String, f64>,
42 pub metadata: HashMap<String, String>,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct SingleQubitRotationParams {
49 pub angle: f64,
51 pub axis: RotationAxis,
53 pub laser_power: f64,
55 pub pulse_duration: Duration,
57}
58
59#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
61pub enum RotationAxis {
62 X,
64 Y,
66 Z,
68 Arbitrary { x: f64, y: f64, z: f64 },
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
74pub struct RydbergExcitationParams {
75 pub atom_index: usize,
77 pub excitation_time: Duration,
79 pub laser_power: f64,
81 pub detuning: f64,
83 pub rabi_frequency: f64,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct RydbergBlockadeParams {
90 pub control_atom: usize,
92 pub target_atom: usize,
94 pub blockade_strength: f64,
96 pub interaction_time: Duration,
98 pub phase: f64,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct GlobalRydbergParams {
105 pub operation_type: String,
107 pub laser_power: f64,
109 pub pulse_duration: Duration,
111 pub phase: f64,
113 pub frequency_sweep: Option<FrequencySweepParams>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct FrequencySweepParams {
120 pub start_frequency: f64,
122 pub end_frequency: f64,
124 pub sweep_rate: f64,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
130pub struct TweezerMovementParams {
131 pub atom_index: usize,
133 pub start_position: (f64, f64, f64),
135 pub end_position: (f64, f64, f64),
137 pub movement_time: Duration,
139 pub trajectory: MovementTrajectory,
141}
142
143#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
145pub enum MovementTrajectory {
146 Linear,
148 Smooth,
150 Custom(Vec<(f64, f64, f64)>),
152}
153
154#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct HyperfineManipulationParams {
157 pub atom_index: usize,
159 pub initial_state: String,
161 pub target_state: String,
163 pub microwave_frequency: f64,
165 pub pulse_duration: Duration,
167 pub pulse_power: f64,
169}
170
171#[derive(Debug, Clone, Serialize, Deserialize)]
173pub struct MeasurementParams {
174 pub target_atoms: Vec<usize>,
176 pub measurement_type: MeasurementType,
178 pub integration_time: Duration,
180 pub basis: MeasurementBasis,
182}
183
184#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
186pub enum MeasurementType {
187 StateDetection,
189 Fluorescence,
191 Ionization,
193 Correlation,
195}
196
197#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
199pub enum MeasurementBasis {
200 Computational,
202 X,
204 Y,
206 Custom(String),
208}
209
210pub struct NeutralAtomGateBuilder {
212 gate_type: Option<NeutralAtomGateType>,
213 target_atoms: Vec<usize>,
214 duration: Option<Duration>,
215 parameters: HashMap<String, f64>,
216 metadata: HashMap<String, String>,
217}
218
219impl NeutralAtomGateBuilder {
220 pub fn new() -> Self {
222 Self {
223 gate_type: None,
224 target_atoms: Vec::new(),
225 duration: None,
226 parameters: HashMap::new(),
227 metadata: HashMap::new(),
228 }
229 }
230
231 #[must_use]
233 pub const fn gate_type(mut self, gate_type: NeutralAtomGateType) -> Self {
234 self.gate_type = Some(gate_type);
235 self
236 }
237
238 #[must_use]
240 pub fn target_atoms(mut self, atoms: &[usize]) -> Self {
241 self.target_atoms.extend_from_slice(atoms);
242 self
243 }
244
245 #[must_use]
247 pub const fn duration(mut self, duration: Duration) -> Self {
248 self.duration = Some(duration);
249 self
250 }
251
252 #[must_use]
254 pub fn parameter(mut self, key: &str, value: f64) -> Self {
255 self.parameters.insert(key.to_string(), value);
256 self
257 }
258
259 #[must_use]
261 pub fn metadata(mut self, key: &str, value: &str) -> Self {
262 self.metadata.insert(key.to_string(), value.to_string());
263 self
264 }
265
266 pub fn build(self) -> DeviceResult<NeutralAtomGateParams> {
268 let gate_type = self
269 .gate_type
270 .ok_or_else(|| DeviceError::InvalidInput("Gate type must be specified".to_string()))?;
271
272 let duration = self.duration.ok_or_else(|| {
273 DeviceError::InvalidInput("Gate duration must be specified".to_string())
274 })?;
275
276 if self.target_atoms.is_empty() {
277 return Err(DeviceError::InvalidInput(
278 "At least one target atom must be specified".to_string(),
279 ));
280 }
281
282 Ok(NeutralAtomGateParams {
283 gate_type,
284 target_atoms: self.target_atoms,
285 duration,
286 parameters: self.parameters,
287 metadata: self.metadata,
288 })
289 }
290}
291
292impl Default for NeutralAtomGateBuilder {
293 fn default() -> Self {
294 Self::new()
295 }
296}
297
298pub fn validate_gate_params(params: &NeutralAtomGateParams) -> DeviceResult<()> {
300 if params.target_atoms.is_empty() {
302 return Err(DeviceError::InvalidInput(
303 "Gate operation must have at least one target atom".to_string(),
304 ));
305 }
306
307 if params.duration.is_zero() {
309 return Err(DeviceError::InvalidInput(
310 "Gate duration must be positive".to_string(),
311 ));
312 }
313
314 match params.gate_type {
316 NeutralAtomGateType::SingleQubitRotation => {
317 validate_single_qubit_rotation_params(params)?;
318 }
319 NeutralAtomGateType::RydbergExcitation => {
320 validate_rydberg_excitation_params(params)?;
321 }
322 NeutralAtomGateType::RydbergBlockade => {
323 validate_rydberg_blockade_params(params)?;
324 }
325 NeutralAtomGateType::TweezerMovement => {
326 validate_tweezer_movement_params(params)?;
327 }
328 _ => {} }
330
331 Ok(())
332}
333
334fn validate_single_qubit_rotation_params(params: &NeutralAtomGateParams) -> DeviceResult<()> {
335 if params.target_atoms.len() != 1 {
336 return Err(DeviceError::InvalidInput(
337 "Single-qubit rotation must target exactly one atom".to_string(),
338 ));
339 }
340
341 if !params.parameters.contains_key("angle") {
342 return Err(DeviceError::InvalidInput(
343 "Single-qubit rotation must specify rotation angle".to_string(),
344 ));
345 }
346
347 Ok(())
348}
349
350fn validate_rydberg_excitation_params(params: &NeutralAtomGateParams) -> DeviceResult<()> {
351 if params.target_atoms.len() != 1 {
352 return Err(DeviceError::InvalidInput(
353 "Rydberg excitation must target exactly one atom".to_string(),
354 ));
355 }
356
357 if !params.parameters.contains_key("laser_power") {
358 return Err(DeviceError::InvalidInput(
359 "Rydberg excitation must specify laser power".to_string(),
360 ));
361 }
362
363 Ok(())
364}
365
366fn validate_rydberg_blockade_params(params: &NeutralAtomGateParams) -> DeviceResult<()> {
367 if params.target_atoms.len() != 2 {
368 return Err(DeviceError::InvalidInput(
369 "Rydberg blockade must target exactly two atoms".to_string(),
370 ));
371 }
372
373 if !params.parameters.contains_key("blockade_strength") {
374 return Err(DeviceError::InvalidInput(
375 "Rydberg blockade must specify blockade strength".to_string(),
376 ));
377 }
378
379 Ok(())
380}
381
382fn validate_tweezer_movement_params(params: &NeutralAtomGateParams) -> DeviceResult<()> {
383 if params.target_atoms.len() != 1 {
384 return Err(DeviceError::InvalidInput(
385 "Tweezer movement must target exactly one atom".to_string(),
386 ));
387 }
388
389 let required_params = ["start_x", "start_y", "start_z", "end_x", "end_y", "end_z"];
390 for param in &required_params {
391 if !params.parameters.contains_key(*param) {
392 return Err(DeviceError::InvalidInput(format!(
393 "Tweezer movement must specify {param}"
394 )));
395 }
396 }
397
398 Ok(())
399}
400
401pub fn create_single_qubit_rotation(
403 atom_index: usize,
404 angle: f64,
405 axis: RotationAxis,
406 duration: Duration,
407) -> DeviceResult<NeutralAtomGateParams> {
408 let axis_str = match axis {
409 RotationAxis::X => "x".to_string(),
410 RotationAxis::Y => "y".to_string(),
411 RotationAxis::Z => "z".to_string(),
412 RotationAxis::Arbitrary { x, y, z } => format!("arbitrary_{x}_{y}_{z}"),
413 };
414
415 NeutralAtomGateBuilder::new()
416 .gate_type(NeutralAtomGateType::SingleQubitRotation)
417 .target_atoms(&[atom_index])
418 .duration(duration)
419 .parameter("angle", angle)
420 .metadata("axis", &axis_str)
421 .build()
422}
423
424pub fn create_rydberg_excitation(
426 atom_index: usize,
427 laser_power: f64,
428 excitation_time: Duration,
429 detuning: f64,
430) -> DeviceResult<NeutralAtomGateParams> {
431 NeutralAtomGateBuilder::new()
432 .gate_type(NeutralAtomGateType::RydbergExcitation)
433 .target_atoms(&[atom_index])
434 .duration(excitation_time)
435 .parameter("laser_power", laser_power)
436 .parameter("detuning", detuning)
437 .build()
438}
439
440pub fn create_rydberg_blockade(
442 control_atom: usize,
443 target_atom: usize,
444 blockade_strength: f64,
445 interaction_time: Duration,
446) -> DeviceResult<NeutralAtomGateParams> {
447 NeutralAtomGateBuilder::new()
448 .gate_type(NeutralAtomGateType::RydbergBlockade)
449 .target_atoms(&[control_atom, target_atom])
450 .duration(interaction_time)
451 .parameter("blockade_strength", blockade_strength)
452 .parameter("control_atom", control_atom as f64)
453 .parameter("target_atom", target_atom as f64)
454 .build()
455}
456
457#[cfg(test)]
458mod tests {
459 use super::*;
460
461 #[test]
462 fn test_gate_builder() {
463 let gate = NeutralAtomGateBuilder::new()
464 .gate_type(NeutralAtomGateType::SingleQubitRotation)
465 .target_atoms(&[0])
466 .duration(Duration::from_micros(100))
467 .parameter("angle", std::f64::consts::PI)
468 .build()
469 .expect("Failed to build single-qubit rotation gate");
470
471 assert_eq!(gate.gate_type, NeutralAtomGateType::SingleQubitRotation);
472 assert_eq!(gate.target_atoms, vec![0]);
473 assert_eq!(gate.duration, Duration::from_micros(100));
474 assert_eq!(gate.parameters.get("angle"), Some(&std::f64::consts::PI));
475 }
476
477 #[test]
478 fn test_gate_validation() {
479 let gate = NeutralAtomGateParams {
480 gate_type: NeutralAtomGateType::SingleQubitRotation,
481 target_atoms: vec![0],
482 duration: Duration::from_micros(100),
483 parameters: [("angle".to_string(), std::f64::consts::PI)].into(),
484 metadata: HashMap::new(),
485 };
486
487 assert!(validate_gate_params(&gate).is_ok());
488 }
489
490 #[test]
491 fn test_create_single_qubit_rotation() {
492 let gate = create_single_qubit_rotation(
493 0,
494 std::f64::consts::PI,
495 RotationAxis::X,
496 Duration::from_micros(100),
497 )
498 .expect("Failed to create single-qubit rotation gate");
499
500 assert_eq!(gate.gate_type, NeutralAtomGateType::SingleQubitRotation);
501 assert_eq!(gate.target_atoms, vec![0]);
502 assert_eq!(gate.parameters.get("angle"), Some(&std::f64::consts::PI));
503 }
504}