使用平台为Jupyter Notebook,Python版本3.6,QISKit版本0.6.0。本文的github链接为: https://github.com/yangjy0826/IBM-QISKit/blob/master/qiskit_QFT.ipynb。
Quantum Fourier Transform
This is a tutorial for quantum Fourier transform (QFT), realized by the IBM package – QISKit (version 0.6.0).
For more materials on QFT, you can check:
- Michael Nielsen and Isaac Chuang (2000). Quantum Computation and Quantum Information. Cambridge: Cambridge University Press. from P217
- Quantum Machine Learning for Data Scientists, from P27
- Wikipedia page for Quantum Fourier Transform
- Quantum Fourier Transform realized by QISKit
- Quantum Fourier Transform realzied by PyQuil
Import all the pakages that may need and load token, please always run these before any other part of the code:
import math
# importing Qiskit
from qiskit import Aer, IBMQ
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute
from qiskit.backends.ibmq import least_busy
# useful additional packages
from qiskit.wrapper.jupyter import *
from qiskit.tools.visualization import plot_histogram
# Load IBM token
IBMQ.load_accounts()
import warnings # Ignore the warning message
warnings.filterwarnings('ignore')
1. Implement the QFT (Quantum Fourier Transform)
1.1 QFT quantum circuit and its measurement
The code in this part is the modified version of QISKit Github.
'''
def input_state(circ, q, n):
"""n-qubit input state for QFT that produces output 1."""
for j in range(n):
circ.h(q[j])
circ.u1(math.pi/float(2**(j)), q[j]).inverse()
'''
def qft(circ, q, n):
"""n-qubit QFT on q in circ."""
for j in range(n):
for k in range(j):
circ.cu1(math.pi/float(2**(j-k)), q[j], q[k])
circ.h(q[j])
n = 3 # No. of qubits
q = QuantumRegister(n)
c = ClassicalRegister(n)
qft_n = QuantumCircuit(q, c)
#input_state(qft_n, q, n)
qft(qft_n, q, n)
for i in range(n):
qft_n.measure(q[i], c[i])
print(qft_n.qasm())
OPENQASM 2.0;
include "qelib1.inc";
qreg q0[3];
creg c0[3];
h q0[0];
cu1(1.57079632679490) q0[1],q0[0];
h q0[1];
cu1(0.785398163397448) q0[2],q0[0];
cu1(1.57079632679490) q0[2],q0[1];
h q0[2];
measure q0[0] -> c0[0];
measure q0[1] -> c0[1];
measure q0[2] -> c0[2];
Draw the quantum circuit:
# Visualizing quantum circuit
from qiskit.tools.visualization import circuit_drawer
circuit_drawer(qft_n)
WARNING: Unable to compile latex. Is `pdflatex` installed? Skipping latex circuit drawing...
1.2 Run QFT on a local simulator
This is the ideal result of running a QFT algorithm.
backend = Aer.get_backend("qasm_simulator")
#config = {'data': ['saved_quantum_state',
# 'saved_density',
# 'saved_quantum_state_ket',
# 'saved_probabilities']}
simulate = execute(qft_n, backend=backend, shots=1024).result() # To execute a circuit for many shots and obtain a histogram of all measurement result
# shots=1024, in total we tried 1024 times
simulate.get_counts()
{'000': 117,
'001': 143,
'010': 123,
'011': 118,
'100': 133,
'101': 127,
'110': 128,
'111': 135}
1.3 Run QFT on a remote quantum chip
# %%qiskit_job_status
# # Use the IBM Quantum Experience
# backend = least_busy(IBMQ.backends(simulator=False))
# job_exp = execute(qft3, backend=backend, shots=shots)
# see a list of available remote backends
ibmq_backends = IBMQ.backends()
print("Remote backends: ", ibmq_backends)
# Compile and run the Quantum Program on a real device backend
least_busy_device = least_busy(IBMQ.backends(simulator=False))
print("Running on current least busy device: ", least_busy_device)
# runing the job
job_exp = execute(qft_n, backend=least_busy_device, shots=1024)
Remote backends: [<IBMQBackend('ibmqx4') from IBMQ()>, <IBMQBackend('ibmq_16_melbourne') from IBMQ()>, <IBMQBackend('ibmq_qasm_simulator') from IBMQ()>]
Running on current least busy device: ibmqx4
In most cases, the remote devices we are able to use are:
-
ibmqx4: a 5-qubit backend
-
ibmq_16_melbourne: a 16-qubit backend
results = job_exp.result()
plot_histogram(results.get_counts(qft_n))
2 Verify the correctness of QFT algorithm
2.1 Important information before coding
QFT = iFFT
Applying QFT to a vector corresponds to applying inverse FFT to it.
The relationship between input bits (FFT) and input qubits (QFT)
e.g. We wish to compute the fast fourier transform of bit string 01000000
. The length of its input is N=2^3=8, then the number of input qubits for the equal QFT system is n=3. Because 01000000
has 1
in the 1st bit, its related quantum state is |001>. This is very similar to the one-hot coding in Machine Learning. If we wish to apply QFT to an arbitrary vector, then we need to use superposition state coding.
2.2 Result using QFT and iFFT
Wavefunction is an object that stores a quantum state as a list of amplitudes. In this part we will check wether the wavefunction of QFT is the same to that of the iFFT. The method of obtaining wavefunction in QISKit can be found in this link.
For more information about wavefunction, please check the wikipedia webpage for wavefunction.
# QFT
def qft(circ, q, n):
"""n-qubit QFT on q in circ."""
for j in range(n):
for k in range(j):
circ.cu1(math.pi/float(2**(j-k)), q[j], q[k]) # cu1 is the controlled phase gate Rm
circ.h(q[j])
n = 3 # No. of qubits
q = QuantumRegister(n)
c = ClassicalRegister(n)
qft_n = QuantumCircuit(q, c)
qft_n.x(q[2]) # Add X gate to the 2nd qubit, to make it from 0 to 1. Now the input quantum state is |001>
qft(qft_n, q, n)
backend = Aer.get_backend('statevector_simulator')
result = execute(qft_n, backend=backend).result()
result.get_data(qft_n)
{'counts': {'000': 1},
'statevector': array([ 3.53553391e-01-4.32978028e-17j, 2.50000000e-01+2.50000000e-01j,
8.32667268e-17+3.53553391e-01j, -2.50000000e-01+2.50000000e-01j,
-3.53553391e-01+4.32978028e-17j, -2.50000000e-01-2.50000000e-01j,
-8.32667268e-17-3.53553391e-01j, 2.50000000e-01-2.50000000e-01j])}
# iFFT
from numpy.fft import ifft
ifft([0,1,0,0,0,0,0,0], norm="ortho")
array([ 0.35355339+0.j , 0.25 +0.25j ,
0. +0.35355339j, -0.25 +0.25j ,
-0.35355339+0.j , -0.25 -0.25j ,
0. -0.35355339j, 0.25 -0.25j ])
We can find out that the above two have the same result. Thus we can verify the correctness og QFT algorithm.