use crate::network::network::QuantumNetwork;
use crate::physics::NoiseModel;
use crate::physics::QuantumChannel;
#[derive(Debug)]
pub struct QuantumRepeaterNode {
pub node_id: String,
pub location: (f64, f64), pub memory_slots: Vec<MemorySlot>,
pub swap_success_rate: f64,
pub noise_model: NoiseModel,
}
#[derive(Debug)]
pub struct MemorySlot {
pub slot_id: usize,
pub qubit: Option<usize>,
pub entangled_with: Option<(String, usize)>, pub fidelity: f64,
pub created_at: Instant,
}
impl QuantumRepeaterNode {
pub fn new(node_id: String, location: (f64, f64), memory_slots: usize) -> Self {
let slots = (0..memory_slots)
.map(|i| MemorySlot {
slot_id: i,
qubit: None,
entangled_with: None,
fidelity: 0.0,
created_at: Instant::now(),
})
.collect();
QuantumRepeaterNode {
node_id,
location,
memory_slots: slots,
swap_success_rate: 0.85, noise_model: NoiseModel::realistic_nv_center(),
}
}
pub fn store_entanglement(
&mut self,
qubit: usize,
partner_node: String,
partner_qubit: usize,
fidelity: f64,
) -> Result<usize, Box<dyn Error>> {
let slot = self
.memory_slots
.iter_mut()
.find(|s| s.qubit.is_none())
.ok_or("No free memory slots")?;
slot.qubit = Some(qubit);
slot.entangled_with = Some((partner_node, partner_qubit));
slot.fidelity = fidelity;
slot.created_at = Instant::now();
Ok(slot.slot_id)
}
pub fn can_swap(&self) -> bool {
let occupied_slots = self
.memory_slots
.iter()
.filter(|s| s.qubit.is_some())
.count();
occupied_slots >= 2
}
pub fn memory_utilization(&self) -> f64 {
let occupied = self
.memory_slots
.iter()
.filter(|s| s.qubit.is_some())
.count();
occupied as f64 / self.memory_slots.len() as f64
}
}
#[derive(Debug, Clone)]
pub struct QuantumPath {
pub nodes: Vec<String>,
pub total_distance: f64,
pub expected_fidelity: f64,
pub expected_generation_time: Duration,
}
pub struct EntanglementSwapper {
network: Arc<Mutex<QuantumNetwork>>,
pub repeaters: HashMap<String, QuantumRepeaterNode>,
}
impl EntanglementSwapper {
pub fn new(network: Arc<Mutex<QuantumNetwork>>) -> Self {
EntanglementSwapper {
network,
repeaters: HashMap::new(),
}
}
pub fn add_repeater(&mut self, repeater: QuantumRepeaterNode) {
self.repeaters.insert(repeater.node_id.clone(), repeater);
}
pub async fn perform_swap(
&mut self,
repeater_id: &str,
left_slot: usize,
right_slot: usize,
) -> Result<SwapResult, Box<dyn Error>> {
let repeater = self
.repeaters
.get_mut(repeater_id)
.ok_or("Repeater not found")?;
let (left_qubit, left_partner, left_fidelity, left_created) = {
let left = &repeater.memory_slots[left_slot];
let qubit = left.qubit.ok_or("Left slot empty")?;
let partner = left
.entangled_with
.as_ref()
.ok_or("Left qubit not entangled")?
.clone();
(qubit, partner, left.fidelity, left.created_at)
};
let (right_qubit, right_partner, right_fidelity, right_created) = {
let right = &repeater.memory_slots[right_slot];
let qubit = right.qubit.ok_or("Right slot empty")?;
let partner = right
.entangled_with
.as_ref()
.ok_or("Right qubit not entangled")?
.clone();
(qubit, partner, right.fidelity, right.created_at)
};
let combined_fidelity = left_fidelity * right_fidelity * repeater.swap_success_rate;
let left_decoherence = calculate_decoherence(&repeater.noise_model, left_created.elapsed());
let right_decoherence =
calculate_decoherence(&repeater.noise_model, right_created.elapsed());
let final_fidelity = combined_fidelity * left_decoherence * right_decoherence;
if final_fidelity < 0.5 {
return Err("Fidelity too low for swapping".into());
}
let mut network = self.network.lock().await;
if let Some(node) = network.nodes.get_mut(repeater_id) {
if let Some(system) = &mut node.local_system {
system.cnot(left_qubit, right_qubit).await?;
system.h(left_qubit).await?;
}
}
let m1 = network.measure(repeater_id, left_qubit)?;
let m2 = network.measure(repeater_id, right_qubit)?;
drop(network);
let repeater = self.repeaters.get_mut(repeater_id).unwrap();
repeater.memory_slots[left_slot].qubit = None;
repeater.memory_slots[left_slot].entangled_with = None;
repeater.memory_slots[right_slot].qubit = None;
repeater.memory_slots[right_slot].entangled_with = None;
Ok(SwapResult {
left_partner,
right_partner,
measurement: (m1, m2),
final_fidelity,
})
}
pub async fn establish_multihop_entanglement(
&mut self,
path: &QuantumPath,
) -> Result<MultihopResult, Box<dyn Error>> {
log::debug!(
"\n🔗 Establishing {}-hop entanglement",
path.nodes.len() - 1
);
log::debug!(" Path: {}", path.nodes.join(" → "));
let mut segment_results = Vec::new();
let start_time = Instant::now();
for i in 0..path.nodes.len() - 1 {
let node1 = &path.nodes[i];
let node2 = &path.nodes[i + 1];
log::debug!(" Segment {}: {} ↔ {}", i + 1, node1, node2);
let mut network = self.network.lock().await;
let (q1, q2) = network.create_epr_pair(node1, node2)?;
let distance = self.calculate_distance(node1, node2);
let channel = QuantumChannel::realistic_fiber(distance);
let segment_fidelity = channel.output_fidelity(0.98);
log::debug!(
" Distance: {:.1} km, Fidelity: {:.3}",
distance,
segment_fidelity
);
if i > 0 && node1 != &path.nodes[0] {
if let Some(repeater) = self.repeaters.get_mut(node1) {
repeater.store_entanglement(q1, node2.clone(), q2, segment_fidelity)?;
}
}
if i < path.nodes.len() - 2 && node2 != path.nodes.last().unwrap() {
if let Some(repeater) = self.repeaters.get_mut(node2) {
repeater.store_entanglement(q2, node1.clone(), q1, segment_fidelity)?;
}
}
segment_results.push(SegmentResult {
node1: node1.clone(),
node2: node2.clone(),
qubit1: q1,
qubit2: q2,
fidelity: segment_fidelity,
});
tokio::time::sleep(Duration::from_millis(10)).await;
}
log::debug!(" Performing entanglement swapping...");
let mut final_fidelity = 1.0;
let mut corrections = Vec::new();
for i in 1..path.nodes.len() - 1 {
let repeater_id = &path.nodes[i];
log::debug!(" Swapping at {}", repeater_id);
let repeater = self
.repeaters
.get(repeater_id)
.ok_or("Repeater not found")?;
let slots: Vec<_> = repeater
.memory_slots
.iter()
.enumerate()
.filter(|(_, s)| s.qubit.is_some())
.map(|(idx, _)| idx)
.collect();
if slots.len() >= 2 {
let swap_result = self.perform_swap(repeater_id, slots[0], slots[1]).await?;
final_fidelity *= swap_result.final_fidelity;
corrections.push(swap_result.measurement);
log::debug!(
" ✓ Swap successful, F={:.3}",
swap_result.final_fidelity
);
}
}
let total_time = start_time.elapsed();
Ok(MultihopResult {
source: path.nodes[0].clone(),
target: path.nodes.last().unwrap().clone(),
hops: path.nodes.len() - 1,
final_fidelity,
generation_time: total_time,
corrections,
memory_usage: self.get_memory_stats(),
})
}
fn calculate_distance(&self, node1: &str, node2: &str) -> f64 {
match (node1, node2) {
("Singapore", "Mumbai") => 3900.0,
("Mumbai", "Amsterdam") => 7000.0,
("Amsterdam", "NewYork") => 5900.0,
_ => 1000.0, }
}
fn get_memory_stats(&self) -> HashMap<String, f64> {
self.repeaters
.iter()
.map(|(id, r)| (id.clone(), r.memory_utilization()))
.collect()
}
}
#[derive(Debug)]
pub struct SwapResult {
pub left_partner: (String, usize),
pub right_partner: (String, usize),
pub measurement: (u8, u8),
pub final_fidelity: f64,
}
#[derive(Debug)]
pub struct SegmentResult {
pub node1: String,
pub node2: String,
pub qubit1: usize,
pub qubit2: usize,
pub fidelity: f64,
}
#[derive(Debug)]
pub struct MultihopResult {
pub source: String,
pub target: String,
pub hops: usize,
pub final_fidelity: f64,
pub generation_time: Duration,
pub corrections: Vec<(u8, u8)>,
pub memory_usage: HashMap<String, f64>,
}
fn calculate_decoherence(noise: &NoiseModel, elapsed: Duration) -> f64 {
let t = elapsed.as_secs_f64();
(-t * noise.dephasing_rate).exp()
}
use std::collections::HashMap;
use std::error::Error;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::sync::Mutex;