Classical part (The order finding problem)
The classical part of Shor's algorithm involves finding the order r of a modulo N. The order finding problem can be shown below:
Given integers a and N, find the smallest positive integer r such that a^r ≡ 1 (mod N).
In classical computing, solving the order finding problem is believed to be computationally difficult for large values of N. However, Shor's algorithm uses a quantum computer to solve this problem efficiently.
The classical part of the algorithm also includes the computation of the greatest common divisors (GCDs) in step 4, which is done using the Euclidean algorithm. This step is performed on a classical computer once the order r has been found using the quantum computer.
Quantum part
The quantum part of Shor's algorithm is responsible for finding the order r efficiently. This is achieved through below mentioned steps:
1. Initialize a quantum register with two sets of qubits: one set representing the number a and the other representing the exponent x.
2. Apply a quantum Fourier transform (QFT) to the exponent qubits, creating a superposition of all possible exponent values.
3. Perform a modular exponentiation operation using the number qubits and the exponent qubits, which computes a^x (mod N) for all possible values of x simultaneously.
4. Apply an inverse quantum Fourier transform (IQFT) to the exponent qubits.
5. Measure the exponent qubits, which will yield an approximation of the order r with high probability.
The quantum part of the algorithm uses the properties of quantum superposition and entanglement to perform the computation efficiently, which is helpful for a significant speedup compared to classical algorithms.
Now, let’s see the code implementation of Shor’s algorithm:
Python
from qiskit import QuantumCircuit, Aer, execute
from qiskit.visualization import plot_histogram
from math import gcd
import numpy as np
def qft_dagger(qc, n):
"""Apply the inverse QFT to the first n qubits in the circuit."""
for qubit in range(n//2):
qc.swap(qubit, n-qubit-1)
for j in range(n):
for m in range(j):
qc.cp(-np.pi/float(2**(j-m)), m, j)
qc.h(j)
def qpe_amod15(a):
"""Quantum Phase Estimation for finding the order of a modulo 15."""
n_count = 4
qc = QuantumCircuit(n_count + 4, n_count)
# Initialize counting qubits in state |+>
for q in range(n_count):
qc.h(q)
# Initialize auxiliary register in state |1>
qc.x(3+n_count)
# Apply the controlled-U operations
for q in range(n_count):
qc.append(c_amod15(a, 2**q),
[q] + [i+n_count for i in range(4)])
# Apply inverse QFT
qft_dagger(qc, n_count)
# Measure
qc.measure(range(n_count), range(n_count))
# Simulate the circuit
backend = Aer.get_backend('qasm_simulator')
counts = execute(qc, backend, shots=1024).result().get_counts()
return counts
def c_amod15(a, power):
"""Controlled multiplication by a modulo 15."""
U = QuantumCircuit(4)
for iteration in range(power):
if a in [2, 13]:
U.swap(0, 1)
U.swap(1, 2)
U.swap(2, 3)
if a in [4, 11]:
U.swap(0, 2)
U.swap(1, 3)
if a in [7, 8]:
U.swap(0, 3)
U.swap(1, 2)
U.swap(2, 3)
if a in [13, 11, 8]:
U.x(range(4))
U = U.to_gate()
U.name = f"{a}^{power} mod 15"
c_U = U.control()
return c_U
def shor(N):
# Choose a random integer a such that 1 < a < N and gcd(a, N) = 1
a = np.random.randint(2, N)
while gcd(a, N) != 1:
a = np.random.randint(2, N)
# Perform Quantum Phase Estimation
counts = qpe_amod15(a)
# Analyze the results
measurement = max(counts, key=counts.get)
phase = int(measurement, 2) / (2**len(measurement))
# Find r
r = 1 / phase
r = round(r)
# Check if r is odd or if a^(r/2) ≡ -1 (mod N)
if r % 2 == 1 or pow(a, r // 2, N) == N - 1:
return None
# Compute the factors using the Euclidean algorithm
factor1 = gcd(pow(a, r // 2) + 1, N)
factor2 = gcd(pow(a, r // 2) - 1, N)
return factor1, factor2
# Test the Shor's algorithm
N = 15
factors = shor(N)
if factors is not None:
print(f"The factors of {N} are {factors[0]} and {factors[1]}")
else:
print("Failed to find the factors")

You can also try this code with Online Python Compiler
Run Code
C++
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
int power(int a, int b, int mod) {
int result = 1;
while (b > 0) {
if (b & 1)
result = (result * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return result;
}
int findOrder(int a, int N) {
int r = 1;
int powerMod = power(a, r, N);
while (powerMod != 1 && r < N) {
r++;
powerMod = power(a, r, N);
}
return (powerMod == 1) ? r : -1;
}
int shor(int N) {
srand(time(NULL));
// Choose a random integer a such that 1 < a < N and gcd(a, N) = 1
int a = rand() % (N - 2) + 2;
while (gcd(a, N) != 1)
a = rand() % (N - 2) + 2;
// Find the order r of a modulo N
int r = findOrder(a, N);
// Check if we failed to find a useful r
if (r == -1 || r % 2 == 1 || power(a, r / 2, N) == N - 1)
return -1;
// Compute the factors using the Euclidean algorithm
int factor1 = gcd(power(a, r / 2, N) + 1, N);
int factor2 = gcd(power(a, r / 2, N) - 1, N);
return (factor1 == 1 || factor2 == 1) ? -1 : factor1;
}
int main() {
int N = 15;
int factor = shor(N);
if (factor == -1)
cout << "Failed to find the factors" << endl;
else
cout << "The factors of " << N << " are " << factor << " and " << N / factor << endl;
return 0;
}

You can also try this code with Online C++ Compiler
Run Code
Java
import java.util.Random;
public class Shor {
public static int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
public static int power(int a, int b, int mod) {
int result = 1;
while (b > 0) {
if ((b & 1) != 0)
result = (result * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return result;
}
public static int shor(int N) {
Random rand = new Random();
// Choose a random integer a such that 1 < a < N and gcd(a, N) = 1
int a = rand.nextInt(N - 2) + 2;
while (gcd(a, N) != 1)
a = rand.nextInt(N - 2) + 2;
// Find the order r of a modulo N
int r = 1;
while (power(a, r, N) != 1 && r < N) {
r++;
}
// Check if we failed to find a useful r
if (r == N || r % 2 == 1 || power(a, r / 2, N) == N - 1)
return -1;
// Compute the factors using the Euclidean algorithm
int factor1 = gcd(power(a, r / 2, N) + 1, N);
int factor2 = gcd(power(a, r / 2, N) - 1, N);
return (factor1 == 1 || factor2 == 1) ? -1 : factor1;
}
public static void main(String[] args) {
int N = 15;
int factor = shor(N);
if (factor == -1)
System.out.println("Failed to find the factors");
else
System.out.println("The factors of " + N + " are " + factor + " and " + (N / factor));
}
}

You can also try this code with Online Java Compiler
Run Code
Output
The factors of 15 are 5 and 3
Time & Space complexity
Shor's algorithm achieves a significant speedup over classical factorization algorithms. The time complexity of Shor's algorithm is O((log N)^3), where N is the integer to be factored. This is an exponential improvement compared to the best-known classical algorithm, the general number field filters, which has a time complexity of O(exp((log N)^(1/3) (log log N)^(2/3))).
The space complexity of Shor's algorithm is O((log N)^2), which is also more efficient than classical algorithms. This is because quantum computers can store and process information using qubits, which can exist in superposition and entanglement states, allowing for more efficient use of memory compared to classical bits.
It's important to note that these complexities refer to the asymptotic behavior of the algorithm and assume the availability of a large-scale, error-corrected quantum computer. In practice, the actual performance of Shor's algorithm may vary depending on the specific implementation and the limitations of current quantum hardware.
Frequently Asked Questions
What is the impact of Shor's algorithm on cryptography?
Shor's algorithm poses a threat to widely used public-key cryptographic systems, such as RSA, which rely on the difficulty of factoring large numbers. If a large-scale quantum computer is built, it could break these cryptographic systems, compromising the security of digital communications and transactions.
Can Shor's algorithm be used to factor any number?
In theory, Shor's algorithm can factor any composite number. However, the practicality of using Shor's algorithm depends on the size of the number and the capabilities of the quantum computer. Current quantum computers are not yet advanced enough to factor large numbers used in real-world cryptographic systems.
Are there any quantum-resistant cryptographic algorithms?
Yes, there are several quantum-resistant cryptographic algorithms, such as lattice-based cryptography, code-based cryptography, and multivariate cryptography. These algorithms are designed to be secure against attacks by both classical and quantum computers. Research in post-quantum cryptography aims to develop and standardize these algorithms for future use.
Conclusion
In this article, we discussed the Shor's algorithm, a quantum algorithm for integer factorization. We learned about its dependence on quantum superposition and entanglement, and how it efficiently solves the order finding problem, which is the key to its speedup over classical algorithms. We also explained the classical and quantum parts of the algorithm, along with its time and space complexity.
You can also check out our other blogs on Code360.