Grover's Algorithm: Difference between revisions
Line 74: | Line 74: | ||
qc.h(flip[:]) | qc.h(flip[:]) | ||
qc.x(oracle[0]) | qc.x(oracle[0]) | ||
qc.h(oracle[0]) | qc.h(oracle[0]) #Hadamard superposition | ||
# Subroutine for oracle | # Subroutine for oracle | ||
def flip_tile(qc,flip,tile): | def flip_tile(qc,flip,tile): | ||
qc.cx(flip[0], tile[0]) | qc.cx(flip[0], tile[0]) | ||
Line 135: | Line 132: | ||
qc.barrier() | qc.barrier() | ||
for i in range(17): | for i in range(17): | ||
# oracle | # oracle | ||
flip_tile(qc,flip,tile) | flip_tile(qc,flip,tile) | ||
qc.barrier() | qc.barrier() | ||
all_zero(qc, tile) | all_zero(qc, tile) | ||
qc.barrier() | qc.barrier() | ||
# U^dagger of flip_tile | # U^dagger of flip_tile. | ||
flip_tile(qc,flip,tile) | flip_tile(qc,flip,tile) | ||
qc.barrier() | qc.barrier() | ||
Line 162: | Line 153: | ||
qc.h(flip) | qc.h(flip) | ||
qc.barrier() | qc.barrier() | ||
# Uncompute | # Uncompute | ||
Line 180: | Line 169: | ||
backend = Aer.get_backend('statevector_simulator') | backend = Aer.get_backend('statevector_simulator') | ||
job = execute(qc,backend) | job = execute(qc,backend) | ||
result = job.result() | result = job.result() | ||
count = result.get_counts() | count = result.get_counts() | ||
score_sorted = sorted(count.items(), key=lambda x:x[1], reverse=True) | score_sorted = sorted(count.items(), key=lambda x:x[1], reverse=True) |
Revision as of 14:45, 27 November 2020
Introduction
Theory
Oracle Function
Amplitude Amplification
The uniform superposition: , where is the Hadamard gate.
Apply the oracle reflection .
Apply an other reflection about the state , also . Thus we are at state . This amplifies by two the amplitude of state .
Repeat times, where .
Application: Lights Out
We solve the tiling game using superposition (instead of Gaussian elimination). The algorithm finds the N-qubit for which the initial state becomes zero.
First, the numbering system is shown below:
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
Second, we need a function that flips the lights: By pressing 0 the light in cells {1,3} will toggle. Thus the toggle mapping is:
- 0 -> {0, 1, 3}
- 1 -> {0, 1, 2, 4}
- 2 -> {1, 2, 5}
- 3 -> {0, 3, 4, 6}
- 4 -> {1, 3, 4, 5, 7}
- 5 -> {2, 4, 5, 8}
- 6 -> {3, 6, 7}
- 7 -> {4, 6, 7, 8}
- 8 -> {5, 7, 8}
The diffusion (Amplification) part is the most difficult.
Solution space is , the optimal number of iteration is about <math>\frac{\pi}{4} \sqrt{2^9} - \frac{1}{2} \approx 17.3 \approx 17<math>.
lights = [0, 0, 0,
0, 1, 1,
0, 1, 0]
def map_board(lights, qc, qr):
j = 0
for i in lights:
if i==1:
qc.x(qr[j])
j+=1
else:
j+=1
from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister
tile = QuantumRegister(9)
flip = QuantumRegister(9)
oracle = QuantumRegister(1)
result = ClassicalRegister(9)
#19=9+9+1 qubit + 4bit
qc = QuantumCircuit(oracle, tile, flip, result)
def initialize():
map_board(lights, qc, tile)
qc.h(flip[:])
qc.x(oracle[0])
qc.h(oracle[0]) #Hadamard superposition
# Subroutine for oracle
def flip_tile(qc,flip,tile):
qc.cx(flip[0], tile[0])
qc.cx(flip[0], tile[1])
qc.cx(flip[0], tile[3])
qc.cx(flip[1], tile[0])
qc.cx(flip[1], tile[1])
qc.cx(flip[1], tile[2])
qc.cx(flip[1], tile[4])
qc.cx(flip[2], tile[1])
qc.cx(flip[2], tile[2])
qc.cx(flip[2], tile[5])
qc.cx(flip[3], tile[0])
qc.cx(flip[3], tile[3])
qc.cx(flip[3], tile[4])
qc.cx(flip[3], tile[6])
qc.cx(flip[4], tile[1])
qc.cx(flip[4], tile[3])
qc.cx(flip[4], tile[4])
qc.cx(flip[4], tile[5])
qc.cx(flip[4], tile[7])
qc.cx(flip[5], tile[2])
qc.cx(flip[5], tile[4])
qc.cx(flip[5], tile[5])
qc.cx(flip[5], tile[8])
qc.cx(flip[6], tile[3])
qc.cx(flip[6], tile[6])
qc.cx(flip[6], tile[7])
qc.cx(flip[7], tile[4])
qc.cx(flip[7], tile[6])
qc.cx(flip[7], tile[7])
qc.cx(flip[7], tile[8])
qc.cx(flip[8], tile[5])
qc.cx(flip[8], tile[7])
qc.cx(flip[8], tile[8])
def all_zero(qc, tile):
qc.x(tile[0:9])
qc.mct(tile[0:9], oracle[0])
qc.x(tile[0:9])
# create the circuit
initialize()
qc.barrier()
for i in range(17):
# oracle
flip_tile(qc,flip,tile)
qc.barrier()
all_zero(qc, tile)
qc.barrier()
# U^dagger of flip_tile.
flip_tile(qc,flip,tile)
qc.barrier()
# diffusion
qc.h(flip)
qc.x(flip)
qc.h(flip[8])
qc.mct(flip[0:8], flip[8])
qc.h(flip[8])
qc.x(flip)
qc.h(flip)
qc.barrier()
# Uncompute
qc.h(oracle[0])
qc.x(oracle[0])
qc.barrier()
# Measurement
qc.measure(flip,result)
qc.barrier()
# Make the Out put order the same as the input.
qc = qc.reverse_bits()
from qiskit import execute, Aer
backend = Aer.get_backend('statevector_simulator')
job = execute(qc,backend)
result = job.result()
count = result.get_counts()
score_sorted = sorted(count.items(), key=lambda x:x[1], reverse=True)
final_score = score_sorted[0:20]
print( final_score )
References
https://mathworld.wolfram.com/LightsOutPuzzle.html
http://perfectweb.org/ddo/solver/vale_puzzle.html
https://gaming.stackexchange.com/questions/11123/strategy-for-solving-lights-out-puzzle
References
https://medium.om/swlh/grovers-algorithm-quantum-computing-1171e826bcfb
https://quantumcomputinguk.org/tutorials/grovers-algorithm-with-code
https://jonathan-hui.medium.com/qc-grovers-algorithm-cd81e61cf248
https://arxiv.org/pdf/1804.03719.pdf
https://www.quantum-inspire.com/kbase/grover-algorithm/
http://davidbkemp.github.io/animated-qubits/grover.html
https://quantum-computing.ibm.com/docs/iqx/guide/grovers-algorithm
https://qudev.phys.ethz.ch/static/content/courses/QSIT12/presentations/Grover_superconducting.pdf
https://quantumcomputing.stackexchange.com/questions/2110/grovers-algorithm-where-is-the-list
https://qudev.phys.ethz.ch/static/content/QSIT16/talks/Grover_QSIT.pdf
https://grove-docs.readthedocs.io/en/latest/grover.html
https://thequantumdaily.com/2019/11/13/quantum-programming-101-grovers-algorithm/