shor_s_algorithm.sf 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #!/usr/bin/ruby
  2. # Simple implementation of Shor's algorithm for integer factorization.
  3. # See also:
  4. # https://en.wikipedia.org/wiki/Shor%27s_algorithm
  5. func find_period(a, n) {
  6. # Find the smallest integer r such that a^(x+r) == a^x (mod n).
  7. # TODO: implement this function on a quantum computer.
  8. return znorder(a, n) # shortcut
  9. func f(x) {
  10. powmod(a, x, n)
  11. }
  12. var t = f(n)
  13. for r in (2 .. Inf) {
  14. if (t == f(n+r)) {
  15. return r
  16. }
  17. }
  18. }
  19. func shor_algorithm(n) {
  20. return n if n.is_prime # n must not be prime
  21. return n if n.is_power # n must not be a prime power
  22. var a = irand(2, n-1) # pick a random number 2 <= a < n
  23. var g = gcd(a, n) # compute gcd(a, n)
  24. return g if (g != 1) # make sure gcd(a, n) = 1
  25. var r = find_period(a, n) # find the multiplication order of `a` in group (Z_n)^x
  26. if (r.is_odd) { # if `r` is odd, try again
  27. return shor_algorithm(n)
  28. }
  29. var t = powmod(a, r/2, n) # a^(r/2) (mod n)
  30. if (t == n-1) { # if a^(r/2) == -1 (mod n), try again
  31. return shor_algorithm(n)
  32. }
  33. # `gcd(a^(r/2) - 1, n)` and `gcd(a^(r/2) + 1, n)` are non-trivial factors of n
  34. [gcd(t-1, n), gcd(t+1, n)].grep { .is_between(2, n-1) }.sort
  35. }
  36. say shor_algorithm(43*97) #=> [43, 97]
  37. say shor_algorithm(2**64 + 1) #=> [274177, 67280421310721]
  38. say shor_algorithm(2**128 + 1) #=> [59649589127497217, 5704689200685129054721]