use crate::{CircuitExecutor, CircuitResult, DeviceError, DeviceResult, QuantumDevice};
use quantrs2_circuit::prelude::Circuit;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::time::Duration;
pub mod client;
pub mod config;
pub mod device;
pub mod gate_operations;
pub mod protocols;
pub mod rydberg;
pub mod tweezer_arrays;
pub use client::NeutralAtomClient;
pub use device::NeutralAtomDevice;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum NeutralAtomSystemType {
Rydberg,
OpticalTweezer,
MagneticTrap,
Hybrid,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum AtomStateEncoding {
GroundExcited,
Hyperfine,
Clock,
Zeeman,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NeutralAtomDeviceConfig {
pub system_type: NeutralAtomSystemType,
pub atom_count: usize,
pub atom_spacing: f64,
pub state_encoding: AtomStateEncoding,
pub blockade_radius: Option<f64>,
pub laser_wavelength: Option<f64>,
pub trap_depth: Option<f64>,
pub gate_fidelity: Option<f64>,
pub measurement_fidelity: Option<f64>,
pub loading_efficiency: Option<f64>,
pub max_execution_time: Option<Duration>,
pub hardware_acceleration: bool,
pub hardware_params: HashMap<String, String>,
}
impl Default for NeutralAtomDeviceConfig {
fn default() -> Self {
Self {
system_type: NeutralAtomSystemType::Rydberg,
atom_count: 100,
atom_spacing: 5.0,
state_encoding: AtomStateEncoding::GroundExcited,
blockade_radius: Some(8.0),
laser_wavelength: Some(480.0),
trap_depth: Some(1000.0),
gate_fidelity: Some(0.995),
measurement_fidelity: Some(0.99),
loading_efficiency: Some(0.95),
max_execution_time: Some(Duration::from_secs(60)),
hardware_acceleration: true,
hardware_params: HashMap::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NeutralAtomCircuitResult {
pub circuit_result: CircuitResult,
pub neutral_atom_data: NeutralAtomMeasurementData,
pub execution_metadata: NeutralAtomExecutionMetadata,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct NeutralAtomMeasurementData {
pub atom_positions: Vec<(f64, f64, f64)>,
pub atom_states: Vec<String>,
pub rydberg_patterns: Vec<Vec<bool>>,
pub correlations: HashMap<String, f64>,
pub fidelities: HashMap<String, f64>,
pub loading_success: Vec<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NeutralAtomExecutionMetadata {
pub system_type: NeutralAtomSystemType,
pub atoms_used: usize,
pub execution_time: Duration,
pub gate_sequence: Vec<String>,
pub optimizations_applied: Vec<String>,
pub temperature: Option<f64>,
pub laser_power: Option<f64>,
}
impl Default for NeutralAtomExecutionMetadata {
fn default() -> Self {
Self {
system_type: NeutralAtomSystemType::Rydberg,
atoms_used: 0,
execution_time: Duration::from_millis(0),
gate_sequence: Vec::new(),
optimizations_applied: Vec::new(),
temperature: None,
laser_power: None,
}
}
}
#[async_trait::async_trait]
pub trait NeutralAtomQuantumDevice: QuantumDevice + CircuitExecutor {
async fn system_type(&self) -> DeviceResult<NeutralAtomSystemType>;
async fn atom_count(&self) -> DeviceResult<usize>;
async fn atom_spacing(&self) -> DeviceResult<f64>;
async fn state_encoding(&self) -> DeviceResult<AtomStateEncoding>;
async fn blockade_radius(&self) -> DeviceResult<Option<f64>>;
async fn supports_rydberg_gates(&self) -> DeviceResult<bool>;
async fn supports_tweezer_manipulation(&self) -> DeviceResult<bool>;
async fn loading_efficiency(&self) -> DeviceResult<f64>;
async fn gate_fidelity(&self) -> DeviceResult<f64>;
async fn execute_neutral_atom_circuit<const N: usize>(
&self,
circuit: &Circuit<N>,
shots: usize,
config: Option<NeutralAtomDeviceConfig>,
) -> DeviceResult<NeutralAtomCircuitResult>;
async fn load_atoms(&self, positions: &[(f64, f64, f64)]) -> DeviceResult<Vec<bool>>;
async fn move_atoms(
&self,
atom_indices: &[usize],
new_positions: &[(f64, f64, f64)],
) -> DeviceResult<()>;
async fn rydberg_excitation(
&self,
atom_indices: &[usize],
excitation_time: Duration,
laser_power: f64,
) -> DeviceResult<Vec<bool>>;
async fn global_rydberg_operation(
&self,
operation: &str,
parameters: &HashMap<String, f64>,
) -> DeviceResult<()>;
async fn measure_atom_states(&self, atom_indices: &[usize]) -> DeviceResult<Vec<String>>;
async fn calculate_atom_correlations(
&self,
atom_pairs: &[(usize, usize)],
correlation_type: &str,
) -> DeviceResult<HashMap<String, f64>>;
async fn estimate_fidelity(
&self,
target_state: &str,
measurement_data: &NeutralAtomMeasurementData,
) -> DeviceResult<f64>;
}
pub const fn create_neutral_atom_device(
client: NeutralAtomClient,
device_id: String,
config: NeutralAtomDeviceConfig,
) -> DeviceResult<NeutralAtomDevice> {
Ok(NeutralAtomDevice::new(client, device_id, config))
}
pub fn validate_neutral_atom_config(config: &NeutralAtomDeviceConfig) -> DeviceResult<()> {
if config.atom_count == 0 {
return Err(DeviceError::InvalidInput(
"Atom count must be greater than 0".to_string(),
));
}
if config.atom_spacing <= 0.0 {
return Err(DeviceError::InvalidInput(
"Atom spacing must be positive".to_string(),
));
}
if let Some(blockade_radius) = config.blockade_radius {
if blockade_radius <= 0.0 {
return Err(DeviceError::InvalidInput(
"Blockade radius must be positive".to_string(),
));
}
}
if let Some(fidelity) = config.gate_fidelity {
if !(0.0..=1.0).contains(&fidelity) {
return Err(DeviceError::InvalidInput(
"Gate fidelity must be between 0 and 1".to_string(),
));
}
}
if let Some(efficiency) = config.loading_efficiency {
if !(0.0..=1.0).contains(&efficiency) {
return Err(DeviceError::InvalidInput(
"Loading efficiency must be between 0 and 1".to_string(),
));
}
}
Ok(())
}
pub mod gates {
use super::*;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RydbergExcitationGate {
pub atom_index: usize,
pub excitation_time: Duration,
pub laser_power: f64,
pub detuning: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RydbergBlockadeGate {
pub control_atom: usize,
pub target_atom: usize,
pub blockade_strength: f64,
pub interaction_time: Duration,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GlobalRydbergGate {
pub operation_type: String,
pub laser_power: f64,
pub pulse_duration: Duration,
pub phase: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TweezerMovementGate {
pub atom_index: usize,
pub start_position: (f64, f64, f64),
pub end_position: (f64, f64, f64),
pub movement_time: Duration,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HyperfineGate {
pub atom_index: usize,
pub target_state: String,
pub microwave_frequency: f64,
pub pulse_duration: Duration,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_neutral_atom_config_validation() {
let valid_config = NeutralAtomDeviceConfig::default();
assert!(validate_neutral_atom_config(&valid_config).is_ok());
let invalid_config = NeutralAtomDeviceConfig {
atom_count: 0,
..Default::default()
};
assert!(validate_neutral_atom_config(&invalid_config).is_err());
}
#[test]
fn test_neutral_atom_system_types() {
let rydberg_system = NeutralAtomSystemType::Rydberg;
assert_eq!(rydberg_system, NeutralAtomSystemType::Rydberg);
let tweezer_system = NeutralAtomSystemType::OpticalTweezer;
assert_eq!(tweezer_system, NeutralAtomSystemType::OpticalTweezer);
}
#[test]
fn test_atom_state_encoding() {
let ground_excited = AtomStateEncoding::GroundExcited;
assert_eq!(ground_excited, AtomStateEncoding::GroundExcited);
let hyperfine = AtomStateEncoding::Hyperfine;
assert_eq!(hyperfine, AtomStateEncoding::Hyperfine);
}
}