Download simulator/algorithms/src/shor.rs from Snapkitty/sov-kernel-monster: direct link, hf CLI and curl.
- Browser
- Download file 10.6 kB
-
https://huggingface.co/Snapkitty/sov-kernel-monster/resolve/main/simulator/algorithms/src/shor.rs
- Command line
-
hf download hf://Snapkitty/sov-kernel-monster/simulator/algorithms/src/shor.rs
-
curl -L -o shor.rs https://huggingface.co/Snapkitty/sov-kernel-monster/resolve/main/simulator/algorithms/src/shor.rs
10.6 kB
| //! Shor's Algorithm - Modular Arithmetic & Factoring | |
| //! | |
| //! Factorizes N via order-finding: find r where a^r ≡ 1 (mod N) | |
| //! Then compute gcd(a^(r/2) ± 1, N) to factor. | |
| //! | |
| //! Pipeline: | |
| //! 1. ModularExponentiation: quantum circuit for a^x mod N | |
| //! 2. PeriodFinding: use phase estimation to find r | |
| //! 3. ContinuedFractions: extract r from measured phase | |
| //! 4. Factor via gcd | |
| use crate::{AlgorithmError, AlgorithmResult}; | |
| use std::f64::consts::PI; | |
| /// Modular exponentiation: compute a^x mod N | |
| pub struct ModularExponentiation { | |
| /// Base a | |
| pub a: u64, | |
| /// Modulus N | |
| pub n: u64, | |
| /// Exponent x | |
| pub x: u64, | |
| } | |
| impl ModularExponentiation { | |
| /// Create new modular exponentiation | |
| pub fn new(a: u64, n: u64) -> AlgorithmResult<Self> { | |
| if n == 0 { | |
| return Err(AlgorithmError::InvalidParameters("N must be nonzero".to_string())); | |
| } | |
| if a >= n { | |
| return Err(AlgorithmError::InvalidParameters( | |
| "Base must be less than N".to_string(), | |
| )); | |
| } | |
| Ok(ModularExponentiation { a, n, x: 0 }) | |
| } | |
| /// Compute a^x mod n (classical) | |
| pub fn compute(&self, x: u64) -> u64 { | |
| modpow(self.a, x, self.n) | |
| } | |
| /// Get circuit depth for quantum implementation | |
| pub fn circuit_depth(&self) -> usize { | |
| // Rough estimate: 3L² for L = bit length of N | |
| let bits = (self.n as f64).log2().ceil() as usize; | |
| 3 * bits * bits | |
| } | |
| } | |
| /// Classical modular exponentiation a^b mod m | |
| fn modpow(mut a: u64, mut b: u64, m: u64) -> u64 { | |
| let mut result = 1u64; | |
| a %= m; | |
| while b > 0 { | |
| if b & 1 == 1 { | |
| result = ((result as u128 * a as u128) % m as u128) as u64; | |
| } | |
| b >>= 1; | |
| a = ((a as u128 * a as u128) % m as u128) as u64; | |
| } | |
| result | |
| } | |
| /// Greatest common divisor | |
| fn gcd(mut a: u64, mut b: u64) -> u64 { | |
| while b != 0 { | |
| let temp = b; | |
| b = a % b; | |
| a = temp; | |
| } | |
| a | |
| } | |
| /// Period finding: find r where a^r ≡ 1 (mod N) | |
| pub struct PeriodFinding { | |
| /// Base a | |
| pub a: u64, | |
| /// Modulus N | |
| pub n: u64, | |
| /// Found period r (if any) | |
| pub period: Option<u64>, | |
| } | |
| impl PeriodFinding { | |
| /// Create period finder | |
| pub fn new(a: u64, n: u64) -> AlgorithmResult<Self> { | |
| if gcd(a, n) != 1 { | |
| return Err(AlgorithmError::InvalidParameters( | |
| "a and N must be coprime".to_string(), | |
| )); | |
| } | |
| Ok(PeriodFinding { | |
| a, | |
| n, | |
| period: None, | |
| }) | |
| } | |
| /// Find period by brute force (classical, for small N) | |
| pub fn find_period_classical(&mut self) -> AlgorithmResult<u64> { | |
| for r in 1..=self.n { | |
| if modpow(self.a, r, self.n) == 1 { | |
| self.period = Some(r); | |
| return Ok(r); | |
| } | |
| } | |
| Err(AlgorithmError::MathematicalError( | |
| "No period found (a and N may not be coprime)".to_string(), | |
| )) | |
| } | |
| /// Estimated period (Carmichael lambda function) | |
| pub fn estimated_period(&self) -> u64 { | |
| // Rough bound: r ≤ N | |
| self.n | |
| } | |
| } | |
| /// Continued fractions for phase estimation → order extraction | |
| pub struct ContinuedFractions { | |
| /// Numerator | |
| pub numerator: u64, | |
| /// Denominator (estimated order) | |
| pub denominator: u64, | |
| } | |
| impl ContinuedFractions { | |
| /// Extract order from measured phase | |
| /// Phase φ = 2π * (k/r) where r is the order | |
| pub fn from_phase(phase: f64, max_denominator: u64) -> AlgorithmResult<Self> { | |
| // Simplified: assume phase = 2π * k/r | |
| // We want to find r (denominator) | |
| let fraction = phase / (2.0 * PI); | |
| // Simple rational approximation | |
| let (num, den) = approximate_fraction(fraction, max_denominator); | |
| Ok(ContinuedFractions { | |
| numerator: num, | |
| denominator: den, | |
| }) | |
| } | |
| /// Get estimated order | |
| pub fn order(&self) -> u64 { | |
| self.denominator | |
| } | |
| } | |
| /// Rational approximation via continued fractions | |
| fn approximate_fraction(x: f64, max_denom: u64) -> (u64, u64) { | |
| let mut num = 0i64; | |
| let mut den = 1i64; | |
| let mut prev_num = 1i64; | |
| let mut prev_den = 0i64; | |
| let mut remaining = x; | |
| for _ in 0..20 { | |
| let a = remaining.floor() as i64; | |
| let temp_num = a * num + prev_num; | |
| let temp_den = a * den + prev_den; | |
| if temp_den.abs() as u64 > max_denom { | |
| break; | |
| } | |
| prev_num = num; | |
| prev_den = den; | |
| num = temp_num; | |
| den = temp_den; | |
| remaining -= a as f64; | |
| if remaining.abs() < 1e-10 { | |
| break; | |
| } | |
| remaining = 1.0 / remaining; | |
| } | |
| (num.abs() as u64, den.abs() as u64) | |
| } | |
| /// Shor's factoring algorithm | |
| pub struct ShorFactoring { | |
| /// Number to factor | |
| pub n: u64, | |
| /// Found factors | |
| pub factors: Vec<u64>, | |
| } | |
| impl ShorFactoring { | |
| /// Create factoring instance | |
| pub fn new(n: u64) -> AlgorithmResult<Self> { | |
| if n < 2 { | |
| return Err(AlgorithmError::InvalidParameters("N must be >= 2".to_string())); | |
| } | |
| Ok(ShorFactoring { | |
| n, | |
| factors: Vec::new(), | |
| }) | |
| } | |
| /// Check if N is even | |
| pub fn check_even(&mut self) -> Option<u64> { | |
| if self.n % 2 == 0 { | |
| self.factors.push(2); | |
| return Some(self.n / 2); | |
| } | |
| None | |
| } | |
| /// Check if N is a perfect power | |
| pub fn check_perfect_power(&self) -> Option<u64> { | |
| for k in 2..64 { | |
| let root = (self.n as f64).powf(1.0 / k as f64) as u64; | |
| for candidate in root.saturating_sub(2)..=root + 2 { | |
| if candidate > 1 { | |
| if let Some(power) = candidate.checked_pow(k as u32) { | |
| if power == self.n { | |
| return Some(candidate); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| None | |
| } | |
| /// Shor's algorithm (quantum-classical hybrid, simplified) | |
| pub fn factor(&mut self) -> AlgorithmResult<Vec<u64>> { | |
| // Check easy cases | |
| if let Some(factor) = self.check_even() { | |
| if factor > 1 { | |
| self.factors.push(factor); | |
| return Ok(self.factors.clone()); | |
| } | |
| } | |
| if let Some(base) = self.check_perfect_power() { | |
| self.factors.push(base); | |
| return Ok(self.factors.clone()); | |
| } | |
| // Pick random a < N | |
| let a = 2; // Simplified: use 2 | |
| // Find period r | |
| let mut pf = PeriodFinding::new(a, self.n)?; | |
| let r = pf.find_period_classical()?; | |
| // r must be even | |
| if r % 2 != 0 { | |
| return Err(AlgorithmError::MathematicalError( | |
| "Period r is odd".to_string(), | |
| )); | |
| } | |
| // Compute x = a^(r/2) mod N | |
| let x = modpow(a, r / 2, self.n); | |
| if x == 0 || x == self.n - 1 { | |
| return Err(AlgorithmError::MathematicalError( | |
| "Shor's algorithm failed".to_string(), | |
| )); | |
| } | |
| // Factors: gcd(x-1, N) and gcd(x+1, N) | |
| // Use wrapping arithmetic to avoid panics | |
| let f1 = gcd(x.wrapping_sub(1), self.n); | |
| let f2 = gcd(x.wrapping_add(1), self.n); | |
| if f1 > 1 && f1 < self.n { | |
| self.factors.push(f1); | |
| } | |
| if f2 > 1 && f2 < self.n { | |
| self.factors.push(f2); | |
| } | |
| if self.factors.is_empty() { | |
| return Err(AlgorithmError::MathematicalError( | |
| "No non-trivial factors found".to_string(), | |
| )); | |
| } | |
| Ok(self.factors.clone()) | |
| } | |
| /// Get circuit size estimate | |
| pub fn circuit_size_estimate(&self) -> usize { | |
| let bits = (self.n as f64).log2().ceil() as usize; | |
| // Rough: 6L² for L = bit length | |
| 6 * bits * bits | |
| } | |
| /// Success probability (at least 4/π²) | |
| pub fn success_probability() -> f64 { | |
| 4.0 / (std::f64::consts::PI * std::f64::consts::PI) | |
| } | |
| } | |
| mod tests { | |
| use super::*; | |
| fn test_modpow() { | |
| assert_eq!(modpow(2, 4, 15), 1); // 2^4 mod 15 = 16 mod 15 = 1 | |
| assert_eq!(modpow(7, 4, 15), 1); // 7^4 mod 15 = 2401 mod 15 = 1 | |
| assert_eq!(modpow(2, 10, 1000), 24); // 2^10 mod 1000 = 1024 mod 1000 = 24 | |
| } | |
| fn test_gcd() { | |
| assert_eq!(gcd(12, 8), 4); | |
| assert_eq!(gcd(15, 10), 5); | |
| assert_eq!(gcd(13, 7), 1); | |
| } | |
| fn test_modular_exponentiation() { | |
| let exp = ModularExponentiation::new(2, 15).unwrap(); | |
| assert_eq!(exp.compute(4), 1); | |
| } | |
| fn test_period_finding() { | |
| let mut pf = PeriodFinding::new(2, 15).unwrap(); | |
| let period = pf.find_period_classical().unwrap(); | |
| assert_eq!(period, 4); // 2^4 ≡ 1 (mod 15) | |
| } | |
| fn test_period_finding_7_mod_15() { | |
| let mut pf = PeriodFinding::new(7, 15).unwrap(); | |
| let period = pf.find_period_classical().unwrap(); | |
| assert_eq!(period, 4); // 7^4 ≡ 1 (mod 15) | |
| } | |
| fn test_continued_fractions() { | |
| let cf = ContinuedFractions::from_phase(PI / 2.0, 100).unwrap(); | |
| assert!(cf.denominator > 0); | |
| } | |
| fn test_shor_factoring_15() { | |
| let mut shor = ShorFactoring::new(15).unwrap(); | |
| // Just test that the algorithm structure works | |
| // Result may vary depending on random a selection | |
| match shor.factor() { | |
| Ok(factors) => { | |
| // If we get factors, they should be valid | |
| for factor in &factors { | |
| assert!(15 % factor == 0, "Factor {} doesn't divide 15", factor); | |
| } | |
| } | |
| Err(_) => { | |
| // Algorithm may fail to factor if a=2 doesn't work | |
| // That's OK for this test | |
| } | |
| } | |
| } | |
| fn test_shor_check_even() { | |
| let mut shor = ShorFactoring::new(6).unwrap(); | |
| assert_eq!(shor.check_even(), Some(3)); | |
| } | |
| fn test_shor_success_probability() { | |
| let prob = ShorFactoring::success_probability(); | |
| assert!(prob > 0.4 && prob < 0.5); // 4/π² ≈ 0.405 | |
| } | |
| fn test_circuit_size_estimate() { | |
| let shor = ShorFactoring::new(15).unwrap(); | |
| let size = shor.circuit_size_estimate(); | |
| assert!(size > 0); | |
| } | |
| } | |
| // Made with Bob | |