1use crate::{DeviceError, DeviceResult};
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use std::time::Duration;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct RydbergConfig {
14 pub principal_quantum_number: u32,
16 pub excitation_wavelength: f64,
18 pub blockade_radius: f64,
20 pub max_rabi_frequency: f64,
22 pub laser_linewidth: f64,
24 pub atom_spacing: f64,
26 pub temperature: f64,
28}
29
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
32pub enum RydbergState {
33 Ground,
35 Rydberg,
37 Superposition {
39 amplitude_ground: f64,
40 amplitude_rydberg: f64,
41 },
42}
43
44#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
46pub enum RydbergGateType {
47 SingleExcitation,
49 ControlledZ,
51 ControlledPhase,
53 MultiExcitation,
55 GlobalRotation,
57 AdiabaticPassage,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct RydbergGateParams {
64 pub gate_type: RydbergGateType,
66 pub target_atoms: Vec<usize>,
68 pub laser_params: RydbergLaserParams,
70 pub timing: RydbergTimingParams,
72 pub additional_params: HashMap<String, f64>,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct RydbergLaserParams {
79 pub rabi_frequency: f64,
81 pub detuning: f64,
83 pub power: f64,
85 pub beam_waist: f64,
87 pub polarization: LaserPolarization,
89 pub phase: f64,
91}
92
93#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
95pub enum LaserPolarization {
96 Linear,
98 CircularLeft,
100 CircularRight,
102 Elliptical { ratio: f64, angle: f64 },
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct RydbergTimingParams {
109 pub pulse_duration: Duration,
111 pub rise_time: Duration,
113 pub fall_time: Duration,
115 pub wait_time: Duration,
117}
118
119#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
121pub enum RydbergInteractionType {
122 VanDerWaals,
124 DipoleDipole,
126 Forster,
128 LongRange,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct RydbergInteraction {
135 pub interaction_type: RydbergInteractionType,
137 pub strength: f64,
139 pub range: f64,
141 pub atom_pairs: Vec<(usize, usize)>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct RydbergPulseSequence {
148 pub name: String,
150 pub pulses: Vec<RydbergPulse>,
152 pub total_duration: Duration,
154 pub repetitions: usize,
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct RydbergPulse {
161 pub pulse_id: String,
163 pub start_time: Duration,
165 pub parameters: RydbergGateParams,
167 pub pulse_shape: PulseShape,
169}
170
171#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
173pub enum PulseShape {
174 Rectangular,
176 Gaussian,
178 Blackman,
180 Hanning,
182 Custom(String),
184}
185
186pub struct RydbergSimulator {
188 config: RydbergConfig,
189 atom_states: Vec<RydbergState>,
190 interactions: Vec<RydbergInteraction>,
191}
192
193impl RydbergSimulator {
194 pub fn new(config: RydbergConfig, num_atoms: usize) -> Self {
196 let atom_states = vec![RydbergState::Ground; num_atoms];
197
198 Self {
199 config,
200 atom_states,
201 interactions: Vec::new(),
202 }
203 }
204
205 pub fn add_interaction(&mut self, interaction: RydbergInteraction) {
207 self.interactions.push(interaction);
208 }
209
210 pub fn apply_gate(&mut self, gate_params: &RydbergGateParams) -> DeviceResult<()> {
212 match gate_params.gate_type {
213 RydbergGateType::SingleExcitation => {
214 self.apply_single_excitation(gate_params)?;
215 }
216 RydbergGateType::ControlledZ => {
217 self.apply_controlled_z(gate_params)?;
218 }
219 RydbergGateType::GlobalRotation => {
220 self.apply_global_rotation(gate_params)?;
221 }
222 _ => {
223 return Err(DeviceError::UnsupportedOperation(format!(
224 "Gate type {:?} not yet implemented",
225 gate_params.gate_type
226 )));
227 }
228 }
229
230 Ok(())
231 }
232
233 fn apply_single_excitation(&mut self, gate_params: &RydbergGateParams) -> DeviceResult<()> {
235 if gate_params.target_atoms.len() != 1 {
236 return Err(DeviceError::InvalidInput(
237 "Single excitation requires exactly one target atom".to_string(),
238 ));
239 }
240
241 let atom_index = gate_params.target_atoms[0];
242 if atom_index >= self.atom_states.len() {
243 return Err(DeviceError::InvalidInput(format!(
244 "Atom index {atom_index} out of bounds"
245 )));
246 }
247
248 let rabi_freq = gate_params.laser_params.rabi_frequency;
250 let duration = gate_params.timing.pulse_duration.as_secs_f64() * 1e6; let excitation_prob = (rabi_freq * duration * std::f64::consts::PI / 2.0)
252 .sin()
253 .powi(2);
254
255 if excitation_prob > 0.5 {
257 self.atom_states[atom_index] = RydbergState::Rydberg;
258 } else {
259 self.atom_states[atom_index] = RydbergState::Superposition {
260 amplitude_ground: (1.0 - excitation_prob).sqrt(),
261 amplitude_rydberg: excitation_prob.sqrt(),
262 };
263 }
264
265 Ok(())
266 }
267
268 fn apply_controlled_z(&mut self, gate_params: &RydbergGateParams) -> DeviceResult<()> {
270 if gate_params.target_atoms.len() != 2 {
271 return Err(DeviceError::InvalidInput(
272 "Controlled-Z gate requires exactly two target atoms".to_string(),
273 ));
274 }
275
276 let control_atom = gate_params.target_atoms[0];
277 let target_atom = gate_params.target_atoms[1];
278
279 let distance = self.calculate_atom_distance(control_atom, target_atom)?;
281 if distance > self.config.blockade_radius {
282 return Err(DeviceError::InvalidInput(
283 "Atoms are too far apart for blockade interaction".to_string(),
284 ));
285 }
286
287 match (
289 &self.atom_states[control_atom],
290 &self.atom_states[target_atom],
291 ) {
292 (RydbergState::Rydberg, RydbergState::Ground) => {
293 }
295 (RydbergState::Ground, RydbergState::Rydberg) => {
296 }
298 (RydbergState::Rydberg, RydbergState::Rydberg) => {
299 }
303 _ => {
304 }
306 }
307
308 Ok(())
309 }
310
311 fn apply_global_rotation(&mut self, gate_params: &RydbergGateParams) -> DeviceResult<()> {
313 let rotation_angle = gate_params
314 .additional_params
315 .get("rotation_angle")
316 .copied()
317 .unwrap_or(std::f64::consts::PI / 2.0);
318
319 for i in 0..self.atom_states.len() {
320 match &self.atom_states[i] {
321 RydbergState::Ground => {
322 let excitation_prob = (rotation_angle / 2.0).sin().powi(2);
323 self.atom_states[i] = RydbergState::Superposition {
324 amplitude_ground: (1.0 - excitation_prob).sqrt(),
325 amplitude_rydberg: excitation_prob.sqrt(),
326 };
327 }
328 RydbergState::Rydberg => {
329 let ground_prob = (rotation_angle / 2.0).sin().powi(2);
330 self.atom_states[i] = RydbergState::Superposition {
331 amplitude_ground: ground_prob.sqrt(),
332 amplitude_rydberg: (1.0 - ground_prob).sqrt(),
333 };
334 }
335 RydbergState::Superposition { .. } => {
336 }
339 }
340 }
341
342 Ok(())
343 }
344
345 fn calculate_atom_distance(&self, atom1: usize, atom2: usize) -> DeviceResult<f64> {
347 if atom1 >= self.atom_states.len() || atom2 >= self.atom_states.len() {
348 return Err(DeviceError::InvalidInput(
349 "Atom index out of bounds".to_string(),
350 ));
351 }
352
353 let distance = (atom1 as f64 - atom2 as f64).abs() * self.config.atom_spacing;
355 Ok(distance)
356 }
357
358 pub fn get_atom_states(&self) -> &[RydbergState] {
360 &self.atom_states
361 }
362
363 pub fn measure_atoms(&mut self, atom_indices: &[usize]) -> DeviceResult<Vec<bool>> {
365 let mut results = Vec::new();
366
367 for &atom_index in atom_indices {
368 if atom_index >= self.atom_states.len() {
369 return Err(DeviceError::InvalidInput(format!(
370 "Atom index {atom_index} out of bounds"
371 )));
372 }
373
374 let measurement_result = match &self.atom_states[atom_index] {
375 RydbergState::Ground => false,
376 RydbergState::Rydberg => true,
377 RydbergState::Superposition {
378 amplitude_rydberg, ..
379 } => {
380 use std::collections::hash_map::DefaultHasher;
382 use std::hash::{Hash, Hasher};
383
384 let mut hasher = DefaultHasher::new();
385 atom_index.hash(&mut hasher);
386 let hash = hasher.finish();
387 let random_value = (hash % 1000) as f64 / 1000.0;
388
389 random_value < amplitude_rydberg.powi(2)
390 }
391 };
392
393 self.atom_states[atom_index] = if measurement_result {
395 RydbergState::Rydberg
396 } else {
397 RydbergState::Ground
398 };
399
400 results.push(measurement_result);
401 }
402
403 Ok(results)
404 }
405
406 pub fn reset(&mut self) {
408 for state in &mut self.atom_states {
409 *state = RydbergState::Ground;
410 }
411 }
412
413 pub fn calculate_energy(&self) -> f64 {
415 let mut energy = 0.0;
416
417 for state in &self.atom_states {
419 match state {
420 RydbergState::Rydberg => {
421 energy += 1.0; }
423 RydbergState::Superposition {
424 amplitude_rydberg, ..
425 } => {
426 energy += amplitude_rydberg.powi(2);
427 }
428 RydbergState::Ground => {} }
430 }
431
432 for interaction in &self.interactions {
434 for &(atom1, atom2) in &interaction.atom_pairs {
435 let interaction_energy = match (&self.atom_states[atom1], &self.atom_states[atom2])
436 {
437 (RydbergState::Rydberg, RydbergState::Rydberg) => interaction.strength,
438 _ => 0.0,
439 };
440 energy += interaction_energy;
441 }
442 }
443
444 energy
445 }
446}
447
448impl Default for RydbergConfig {
449 fn default() -> Self {
450 Self {
451 principal_quantum_number: 70,
452 excitation_wavelength: 480.0,
453 blockade_radius: 8.0,
454 max_rabi_frequency: 10.0,
455 laser_linewidth: 1.0,
456 atom_spacing: 5.0,
457 temperature: 1.0,
458 }
459 }
460}
461
462impl Default for RydbergLaserParams {
463 fn default() -> Self {
464 Self {
465 rabi_frequency: 1.0,
466 detuning: 0.0,
467 power: 1.0,
468 beam_waist: 1.0,
469 polarization: LaserPolarization::Linear,
470 phase: 0.0,
471 }
472 }
473}
474
475impl Default for RydbergTimingParams {
476 fn default() -> Self {
477 Self {
478 pulse_duration: Duration::from_micros(1),
479 rise_time: Duration::from_nanos(100),
480 fall_time: Duration::from_nanos(100),
481 wait_time: Duration::from_micros(1),
482 }
483 }
484}
485
486pub fn create_single_excitation_gate(
488 atom_index: usize,
489 rabi_frequency: f64,
490 duration: Duration,
491) -> RydbergGateParams {
492 RydbergGateParams {
493 gate_type: RydbergGateType::SingleExcitation,
494 target_atoms: vec![atom_index],
495 laser_params: RydbergLaserParams {
496 rabi_frequency,
497 ..Default::default()
498 },
499 timing: RydbergTimingParams {
500 pulse_duration: duration,
501 ..Default::default()
502 },
503 additional_params: HashMap::new(),
504 }
505}
506
507pub fn create_controlled_z_gate(
509 control_atom: usize,
510 target_atom: usize,
511 interaction_strength: f64,
512 duration: Duration,
513) -> RydbergGateParams {
514 let mut additional_params = HashMap::new();
515 additional_params.insert("interaction_strength".to_string(), interaction_strength);
516
517 RydbergGateParams {
518 gate_type: RydbergGateType::ControlledZ,
519 target_atoms: vec![control_atom, target_atom],
520 laser_params: RydbergLaserParams::default(),
521 timing: RydbergTimingParams {
522 pulse_duration: duration,
523 ..Default::default()
524 },
525 additional_params,
526 }
527}
528
529pub fn create_global_rotation_gate(
531 num_atoms: usize,
532 rotation_angle: f64,
533 duration: Duration,
534) -> RydbergGateParams {
535 let target_atoms: Vec<usize> = (0..num_atoms).collect();
536 let mut additional_params = HashMap::new();
537 additional_params.insert("rotation_angle".to_string(), rotation_angle);
538
539 RydbergGateParams {
540 gate_type: RydbergGateType::GlobalRotation,
541 target_atoms,
542 laser_params: RydbergLaserParams::default(),
543 timing: RydbergTimingParams {
544 pulse_duration: duration,
545 ..Default::default()
546 },
547 additional_params,
548 }
549}
550
551#[cfg(test)]
552mod tests {
553 use super::*;
554
555 #[test]
556 fn test_rydberg_simulator_creation() {
557 let config = RydbergConfig::default();
558 let simulator = RydbergSimulator::new(config, 5);
559
560 assert_eq!(simulator.get_atom_states().len(), 5);
561 assert!(simulator
562 .get_atom_states()
563 .iter()
564 .all(|s| *s == RydbergState::Ground));
565 }
566
567 #[test]
568 fn test_single_excitation_gate() {
569 let config = RydbergConfig::default();
570 let mut simulator = RydbergSimulator::new(config, 3);
571
572 let gate = create_single_excitation_gate(0, 1.0, Duration::from_micros(1));
573 assert!(simulator.apply_gate(&gate).is_ok());
574 }
575
576 #[test]
577 fn test_measurement() {
578 let config = RydbergConfig::default();
579 let mut simulator = RydbergSimulator::new(config, 2);
580
581 let results = simulator
582 .measure_atoms(&[0, 1])
583 .expect("measurement should succeed");
584 assert_eq!(results.len(), 2);
585 assert!(results.iter().all(|&r| !r)); }
587
588 #[test]
589 fn test_energy_calculation() {
590 let config = RydbergConfig::default();
591 let simulator = RydbergSimulator::new(config, 2);
592
593 let energy = simulator.calculate_energy();
594 assert_eq!(energy, 0.0); }
596}