use std::f64::consts::PI;
const ATTENUATION_LENGTH_KM: f64 = 22.0;
#[derive(Debug, Clone)]
pub struct DlczNode {
pub write_efficiency: f64,
pub read_efficiency: f64,
pub coupling_to_fiber: f64,
pub detector_efficiency: f64,
pub memory_time_s: f64,
pub mode_number: usize,
}
impl DlczNode {
pub fn entanglement_probability(&self, excitation_prob: f64) -> f64 {
let p_exc = excitation_prob.clamp(0.0, 1.0);
self.write_efficiency.clamp(0.0, 1.0)
* self.coupling_to_fiber.clamp(0.0, 1.0)
* self.detector_efficiency.clamp(0.0, 1.0)
* p_exc
}
pub fn time_to_entangle_s(
&self,
repetition_rate_hz: f64,
segment_loss: f64,
) -> f64 {
let eta_link = 10.0_f64.powf(-segment_loss / 10.0);
let p_success =
self.write_efficiency * self.coupling_to_fiber * self.detector_efficiency * eta_link;
let t_rep = 1.0 / repetition_rate_hz.max(f64::MIN_POSITIVE);
t_rep / p_success.max(f64::MIN_POSITIVE)
}
pub fn distribution_rate_hz(
&self,
n_segments: usize,
repetition_rate_hz: f64,
segment_loss_db: f64,
) -> f64 {
let n = n_segments.max(1) as f64;
let t_1seg = self.time_to_entangle_s(repetition_rate_hz, segment_loss_db);
let eta_link = 10.0_f64.powf(-segment_loss_db / 10.0);
let p_1seg = self.write_efficiency
* self.coupling_to_fiber
* self.detector_efficiency
* eta_link;
let p_chain = p_1seg.powf(n);
let rate = p_chain / (2.0_f64.powf(n) * t_1seg.max(f64::MIN_POSITIVE));
rate * self.mode_number as f64
}
pub fn fidelity_at_time(&self, time_s: f64, initial_fidelity: f64) -> f64 {
let f0 = initial_fidelity.clamp(0.0, 1.0);
let t = time_s.max(0.0);
f0 * (-t / self.memory_time_s.max(f64::MIN_POSITIVE)).exp()
}
}
#[derive(Debug, Clone)]
pub struct QuantumRepeaterChain {
pub total_distance_km: f64,
pub n_segments: usize,
pub fiber_loss_db_km: f64,
pub node: DlczNode,
}
impl QuantumRepeaterChain {
#[inline]
pub fn segment_length_km(&self) -> f64 {
self.total_distance_km / self.n_segments.max(1) as f64
}
pub fn segment_transmission(&self) -> f64 {
let l_seg = self.segment_length_km();
let loss_db = self.fiber_loss_db_km * l_seg;
10.0_f64.powf(-loss_db / 10.0)
}
pub fn entanglement_rate_hz(&self, rep_rate_hz: f64) -> f64 {
let segment_loss_db = self.fiber_loss_db_km * self.segment_length_km();
self.node
.distribution_rate_hz(self.n_segments, rep_rate_hz, segment_loss_db)
}
pub fn secret_key_rate_bps(&self, rep_rate_hz: f64) -> f64 {
let r_ent = self.entanglement_rate_hz(rep_rate_hz);
let secure_fraction = 1.0 - 2.0 * 0.2864;
r_ent * secure_fraction.max(0.0)
}
pub fn break_even_distance_km(&self) -> f64 {
let l_att = ATTENUATION_LENGTH_KM;
let n = self.n_segments as f64;
l_att * n.max(1.0).ln()
}
pub fn direct_link_rate_hz(&self, rep_rate_hz: f64) -> f64 {
let total_loss_db = self.fiber_loss_db_km * self.total_distance_km;
let eta_fiber = 10.0_f64.powf(-total_loss_db / 10.0);
let eta_total = self.node.write_efficiency
* self.node.coupling_to_fiber
* self.node.detector_efficiency
* eta_fiber;
rep_rate_hz * eta_total
}
}
#[cfg(test)]
mod tests {
use super::*;
fn test_node() -> DlczNode {
DlczNode {
write_efficiency: 0.8,
read_efficiency: 0.9,
coupling_to_fiber: 0.7,
detector_efficiency: 0.85,
memory_time_s: 1e-3,
mode_number: 100,
}
}
fn test_chain() -> QuantumRepeaterChain {
QuantumRepeaterChain {
total_distance_km: 1000.0,
n_segments: 10,
fiber_loss_db_km: 0.2,
node: test_node(),
}
}
#[test]
fn dlcz_entanglement_probability() {
let node = test_node();
let p = node.entanglement_probability(0.01);
assert!(p > 0.0 && p < 0.01, "p={}", p);
}
#[test]
fn dlcz_time_to_entangle_positive() {
let node = test_node();
let t = node.time_to_entangle_s(1e8, 10.0);
assert!(t > 0.0, "t_entangle={}", t);
}
#[test]
fn dlcz_distribution_rate_less_than_direct() {
let node = test_node();
let r1 = node.distribution_rate_hz(1, 1e8, 3.0);
let r5 = node.distribution_rate_hz(5, 1e8, 3.0);
assert!(r1 > r5, "r1={} r5={}", r1, r5);
}
#[test]
fn dlcz_fidelity_decay() {
let node = test_node();
let f0 = 0.99;
let f_half = node.fidelity_at_time(node.memory_time_s, f0);
assert!(
(f_half - f0 / std::f64::consts::E).abs() < 1e-6,
"fidelity decay mismatch: {}",
f_half
);
}
#[test]
fn repeater_segment_length_correct() {
let chain = test_chain();
let l_seg = chain.segment_length_km();
assert!(
(l_seg - 100.0).abs() < 1e-10,
"l_seg={} km",
l_seg
);
}
#[test]
fn repeater_segment_transmission_range() {
let chain = test_chain();
let eta = chain.segment_transmission();
assert!(eta > 0.0 && eta < 1.0, "η_seg={}", eta);
}
#[test]
fn repeater_outperforms_direct_at_long_distance() {
let chain = test_chain();
let r_rep = chain.entanglement_rate_hz(1e8);
let r_dir = chain.direct_link_rate_hz(1e8);
assert!(r_rep > r_dir, "repeater r={} direct r={}", r_rep, r_dir);
}
#[test]
fn secret_key_rate_positive() {
let chain = test_chain();
let skr = chain.secret_key_rate_bps(1e8);
assert!(skr > 0.0, "SKR={}", skr);
}
}