Shor’s Algorithm#
In the realm of quantum computing, where classical limitations are challenged and new horizons are explored, Shor’s Algorithm stands as a testament to the transformative potential of quantum mechanics in the field of cryptography. Developed by mathematician Peter Shor in 1994, this groundbreaking algorithm has the power to revolutionize the world of cryptography by efficiently factoring large numbers—once considered an insurmountable task for classical computers.
Qrisp provides a dead simple interface to integer factorization using your own backend. For details how this algorithm is implemented, please check the Shor’s algorithm tutorial.
- shors_alg(N: int, inpl_adder: Callable | None = None, mes_kwargs: dict | None = None) int[source]#
Performs Shor’s factorization algorithm on a given integer N.
The adder used for factorization can be customized. To learn more about this feature, please read QuantumModulus
- Parameters:
- Ninteger
The integer to be factored.
- inpl_addercallable, optional
A function that performs in-place addition. The default is None.
- mes_kwargsdict, optional
A dictionary of keyword arguments for
get_measurement. This especially allows you to specify an execution backend. The default is {}.
- Returns:
- resinteger
A factor of N.
Examples
We factor 65:
>>> from qrisp.shor import shors_alg >>> shors_alg(65) 5
For resource estimation and for programs in Jasp mode, the quantum part of order finding is also available with a semiclassical phase estimation, which needs a single control qubit instead of a phase register.
- semiclassical_order_finding(a: int, N: int, precision: int | None = None, inpl_adder: Callable | None = None) BigInteger[source]#
Run the quantum part of order finding with a semiclassical phase estimation, and return its outcome.
This is the quantum subroutine of Shor’s algorithm: the phase estimation of the multiplication by \(a\) modulo \(N\) on a QuantumModulus initialized to 1. Its outcome \(y\) is close to \(s \cdot 2^t / r\) for a random \(s\), where \(r\) is the order of \(a\) modulo \(N\) and \(t\) is the precision, so that \(r\) can be recovered classically, for example with continued fractions.
Instead of a \(t\)-qubit phase register followed by the inverse quantum Fourier transform, the phase estimation uses the semiclassical Fourier transform of Griffiths and Niu (1996), with one control qubit at a time following Mosca and Ekert (1999). Step \(j\) applies the multiplication by \(a^{2^{t-1-j}} \bmod N\) controlled on a fresh qubit, rotates the qubit by the phase of the bits measured before, measures bit \(j\) of \(y\), and resets the qubit before releasing it. The outcome has the same distribution as with the full phase register. The circuit needs \(t - 1\) fewer qubits, and \(t\) single-qubit rotations replace the \(t (t - 1) / 2\) controlled phase gates and \(\lfloor t / 2 \rfloor\) swaps of the inverse quantum Fourier transform. It requires mid-circuit measurements and rotations that depend on their outcomes.
The classical multipliers \(a^{2^k} \bmod N\) and their inverses modulo \(N\), which the in-place multiplications need, are computed exactly with Python integers when the function is called, so
aandNmust be integers and cannot be traced.Note
This function can only be called in Jasp mode, for example within jaspify, or in the resource estimators count_ops and num_qubits.
- Parameters:
- aint
The number whose order is found, coprime to
N.- Nint
The modulus, an odd integer larger than 2.
- precisionint, optional
The number \(t\) of bits of the outcome. The default is \(2n\), where \(n = \lceil \log_2 N \rceil\) is the number of bits of \(N\).
- inpl_adderCallable, optional
The in-place adder of the modular multiplication, see QuantumModulus. The default is the
gidney_adder.
- Returns:
- BigInteger
The outcome \(y\), with \(\lceil t / 32 \rceil\) limbs. All qubits are reset and released before returning, so that repeated calls do not keep them allocated and later allocations can reuse them.
- Raises:
- TypeError
If
a,Norprecisionis not an integer.- ValueError
If
Nis even or smaller than 3, ifais not coprime toN, or ifprecisionis smaller than 1.- RuntimeError
If the function is called outside of Jasp mode.
Examples
The order of 7 modulo 15 is \(r = 4\), and \(2^t\) with the default precision \(t = 8\) is a multiple of \(r\). The outcome is therefore one of the multiples \(s \cdot 2^8 / 4 = 64 s\), each with probability \(1/4\). Calling the returned BigInteger gives its value:
>>> from qrisp.algorithms.shor import semiclassical_order_finding >>> from qrisp.jasp import jaspify >>> def order_finding(): ... return semiclassical_order_finding(7, 15) >>> outcome = jaspify(order_finding)() >>> print(outcome() % 64) 0
The resource estimators count the same circuit without simulating it. With the default adder, the circuit needs \(3n + 2 \lceil \log_2 n \rceil + 2\) qubits, 18 for \(n = 4\). It applies one rotation per bit of the outcome, 8 for \(t = 8\):
>>> from qrisp.jasp import count_ops, num_qubits >>> print(num_qubits(meas_behavior="1")(order_finding)()["peak_allocations"]) 18 >>> print(count_ops(meas_behavior="1")(order_finding)()["rz"]) 8
Cryptography tools#
These tools can be utilized to spy on your enemies.
|
Encrypts an integer using a public key pair \((e,N)\). |
|
Decrypts an integer using factorization powered by Shor's algorithm. |
|
Encrypts an arbitrary Python string using RSA. |
|
Decrypts a bitstring into a human readable string. |