qml.QFT

QFT = <Subroutine: QFT>[source]

QFT(wires) Apply a quantum Fourier transform (QFT).

For the \(N\)-qubit computational basis state \(|m\rangle\), the QFT performs the transformation

\[|m\rangle \rightarrow \frac{1}{\sqrt{2^{N}}}\sum_{n=0}^{2^{N} - 1}\omega_{N}^{mn} |n\rangle,\]

where \(\omega_{N} = e^{\frac{2 \pi i}{2^{N}}}\) is the \(2^{N}\)-th root of unity.

Details:

  • Number of wires: Any (the operation can act on any number of wires)

  • Number of parameters: 0

  • Gradient recipe: None

Parameters:

wires (int or Iterable[Number, str]]) – the wire(s) the operation acts on

Example

The quantum Fourier transform is applied by specifying the corresponding wires:

wires = 3

dev = qml.device('default.qubit',wires=wires)

@qml.qnode(dev)
def circuit_qft(basis_state):
    qml.BasisState(basis_state, wires=range(wires))
    qml.QFT(wires=range(wires))
    return qml.state()
>>> circuit_qft(np.array([1.0, 0.0, 0.0])) 
array([ 0.3536+0.j, -0.3536+0.j,  0.3536+0.j, -0.3536+0.j,  0.3536+0.j,
       -0.3536+0.j,  0.3536+0.j, -0.3536+0.j])

If the QFT is the last subroutine applied within a circuit, it can be replaced by a semiclassical Fourier transform. It makes use of mid-circuit measurements and dynamic circuit control based on the measurement values, allowing to reduce the number of two-qubit gates.

As an example, consider the following circuit implementing addition between two numbers with n_wires bits (modulo 2**n_wires):

dev = qml.device("default.qubit")

@qml.qnode(dev, shots=1)
def qft_add(m, k, n_wires):
    qml.BasisEmbedding(m, wires=range(n_wires))
    qml.adjoint(qml.QFT)(wires=range(n_wires))
    for j in range(n_wires):
        qml.RZ(-k * np.pi / (2**j), wires=j)
    qml.QFT(wires=range(n_wires))
    return qml.sample()
>>> qft_add(7, 3, n_wires=4)
array([[1, 0, 1, 0]])

The last building block of this circuit is a QFT, so we may replace it by its semiclassical counterpart:

def scFT(n_wires):
    '''semiclassical Fourier transform'''
    for w in range(n_wires-1):
        qml.Hadamard(w)
        mcm = qml.measure(w)
        for m in range(w + 1, n_wires):
            qml.cond(mcm, qml.PhaseShift)(np.pi / 2 ** (m + 1), wires=m)
    qml.Hadamard(n_wires-1)

@qml.qnode(dev)
def scFT_add(m, k, n_wires):
    qml.BasisEmbedding(m, wires=range(n_wires))
    qml.adjoint(qml.QFT)(wires=range(n_wires))
    for j in range(n_wires):
        qml.RZ(-k * np.pi / (2**j), wires=j)
    scFT(n_wires)
    # Revert wire order because of PL's QFT convention
    return qml.sample(wires=list(range(n_wires-1, -1, -1)))
>>> qml.set_shots(scFT_add, 1)(7, 3, n_wires=4) 
array([[1, 1, 1, 0]])