Grover's Algorithm: Difference between revisions

From wikiluntti
 
(One intermediate revision by the same user not shown)
Line 16: Line 16:


== Application: Lights Out ==
== Application: Lights Out ==
[[File:LightsOut.png|thumb]]


We solve the <math>3\times3</math> tiling game using superposition (instead of Gaussian elimination). The algorithm finds the N-qubit for which the initial state becomes zero.
We solve the <math>3\times3</math> tiling game using superposition (instead of Gaussian elimination). The algorithm finds the N-qubit for which the initial state becomes zero.
Line 176: Line 178:
print( final_score )
print( final_score )
</syntaxhighlight>
</syntaxhighlight>
The example above is very low and inefficient. It can be sped up.


=== References ===
=== References ===

Latest revision as of 11:55, 29 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 {0, 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 .

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 output 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 )

The example above is very low and inefficient. It can be sped up.

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

https://github.com/qiskit-community/IBMQuantumChallenge2020/blob/main/hints/hint_2a_nb/hint_2a_ex.ipynb

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/