Grover Search and Long Algorithms Based on MindSpore Quantum
Translators: unseenme and Waikikilick
Overview
If you have heard of quantum computing, you must have heard of the Grover search algorithm. In 1996, Lov Grover [1] proposed the Grover search algorithm, which is an algorithm that uses the superposition of quantum states to perform parallel computing and achieve acceleration. The Grover search algorithm is recognized as the second great quantum algorithm after Shor algorithm, and it is also the first quantum algorithm to be fully experimentally implemented, which solves the problem of unordered
database search. In 1997, Bennett [2] et al. proved that for the unstructured quantum search problem, at least
The Unordered Database Search problem is to find some elements that meet the requirements from an unordered database with a large number of elements. Since the number of elements in the database is huge and the elements are unordered, it is easy to verify that a given element satisfies the requirements, but conversely, it is not easy to find these elements.
To solve the unordered database search problem (it may be assumed that there is only one target search data), the time complexity required by the classical algorithm is
This document will introduce the basic principles of Grover search algorithm, and show how to use MindSpore Quantum to implement the algorithm by two specific simple examples.
Problem Description
We need to search in an unordered set of
Without loss of generality, assuming
At the same time, it is assumed that the search problem has only one target state
Fundamentals of Grover Search Algorithm
The basic principle of Grover search algorithm: First, a uniform superposition state is generated by the Hadamard gate, and then the Grover iteration (or
The Grover search algorithm mainly includes the following steps:
Step 1: Database Initialization
Perform the
Step 2: Grover Iteration
Grover iteration can be further decomposed into four steps:
SubStep One
Execute the Oracle Operator
In order to distinguish the data to be found from other data, the easiest way is to flip the phase of the target state (add a negative sign). At this time, we need to construct an Oracle operator
Since when
Its matrix expression is
SubStep Two
Perform
Perform
SubStep Three
Execute conditional phase shift operator
The conditional phase shift operator
Its matrix expression is
SubStep Four
Perform
So far, the complete
Note: The number of iterations required for the
where,
Step 3: Measurement
By performing
The complete quantum circuit model of Grover search algorithm is shown below:
Constructing a Unitary Operator that Flips the Phase of a Qubit
By the above introduction, we found that the most critical part of the Grover search algorithm is that there is a unitary operator that can flip the phase of the qubit, the Oracle operator
Next, we will construct a unitary operator that can flip the phase of a qubit, defined as follows:
[1]:
from mindquantum.core.circuit import Circuit
from mindquantum.core.gates import Z
def bitphaseflip_operator(phase_inversion_qubit, n_qubits): # Define a function that flips the phase of a qubit
s = [1 for i in range(1 << n_qubits)]
for i in phase_inversion_qubit:
s[i] = -1
if s[0] == -1:
for i in range(len(s)):
s[i] = -1 * s[i]
circuit = Circuit()
length = len(s)
cz = []
for i in range(length):
if s[i] == -1:
cz.append([])
current = i
t = 0
while current != 0:
if (current & 1) == 1:
cz[-1].append(t)
t += 1
current = current >> 1
for j in range(i + 1, length):
if i & j == i:
s[j] = -1 * s[j]
for i in cz:
if i:
if len(i) > 1:
circuit += Z.on(i[-1], i[:-1])
else:
circuit += Z.on(i[0])
return circuit
Now, the bitphaseflip_operator()
function can flip the phase of a qubit, and users only need to input the target quantum state and the total number of qubits that need to flip the phase.
As an example, we now generate a uniform superposition of 3 qubits by running the following code:
[2]:
# pylint: disable=W0104
from mindquantum.core.circuit import UN
from mindquantum.core.gates import H
from mindquantum.simulator import Simulator
n_qubits = 3 # Set the number of qubits to 3
sim = Simulator('mqvector', n_qubits) # Use the mqvector simulator, named sim
circuit = Circuit() # Initialize the quantum circuit, named circuit
circuit += UN(H, n_qubits) # H-gate operations are performed on each qubit
sim.apply_circuit(circuit) # Run the built quantum circuit circuit by the simulator sim
circuit.svg() # Print the quantum circuit circuit at this time # Print the quantum line circuit at this point
[2]:
[3]:
print(sim.get_qs(True)) # Print the final state after running the quantum circuit circuit in the simulator sim
√2/4¦000⟩
√2/4¦001⟩
√2/4¦010⟩
√2/4¦011⟩
√2/4¦100⟩
√2/4¦101⟩
√2/4¦110⟩
√2/4¦111⟩
From the running results, we can see the quantum circuit at this time, and a uniform superposition state of 3 qubits has been generated successfully.
Suppose we need to flip the phase of the bitphaseflip_operator()
function we defined and run the following code:
[4]:
# pylint: disable=W0104
sim.reset() # Reset the quantum state maintained by the simulator sim so that the initialized quantum state is |000>
phase_inversion_qubit = [4] # Invert the phase of the |4> state
operator = bitphaseflip_operator(phase_inversion_qubit, n_qubits)# Call our defined bitphaseflip_operator() function
circuit += operator # Add the quantum gate required to flip the phase of the |4> state in the quantum circuit circuit
sim.apply_circuit(circuit) # Run the built quantum circuit circuit again by the simulator sim
circuit.svg() # Print the quantum circuit circuit at this time
[4]:
[5]:
print(sim.get_qs(True)) # Print the final state after running the quantum circuit in the simulator sim
√2/4¦000⟩
√2/4¦001⟩
√2/4¦010⟩
√2/4¦011⟩
-√2/4¦100⟩
√2/4¦101⟩
√2/4¦110⟩
√2/4¦111⟩
From the running results, we can see that the quantum circuit at this time, and the phase of
[6]:
print(int('100', 2))
4
It can be seen from the running results that the
Assuming we need to flip the phase of every state except the
[7]:
# pylint: disable=W0104
n_qubits = 3 # Set the number of qubits to 3
sim1 = Simulator('mqvector', n_qubits) # Use the mqvector simulator, named sim1
operator1 = bitphaseflip_operator([i for i in range(1, pow(2, n_qubits))], n_qubits) # Call our defined bitphaseflip_operator() function to flip the phase of each state except |0> state, named operator1
circuit1 = Circuit() # Initialize the quantum circuit, named circuit1
circuit1 += UN(H, n_qubits) # H-gate operations are performed on each qubit
circuit1 += operator1 # Add the quantum gates required to flip the phase of each state except the |0> state in the quantum circuit circuit1
sim1.apply_circuit(circuit1) # Run the built quantum circuit circuit1 by the simulator sim1
circuit1.svg() # Print the quantum circuit circuit1 at this time # Print the quantum line circuit at this point
[7]:
[8]:
print(sim1.get_qs(True)) # Print the final state after running the quantum circuit circuit1 in the simulator sim1
√2/4¦000⟩
-√2/4¦001⟩
-√2/4¦010⟩
-√2/4¦011⟩
-√2/4¦100⟩
-√2/4¦101⟩
-√2/4¦110⟩
-√2/4¦111⟩
From the running results, we can see the quantum circuit at this time, and we successfully flip the phase of every state except the
That is to say, the function bitphaseflip_operator()
we define can implement the Oracle operator
Examples of Grover Search Algorithm Using MindSpore Quantum
Example 1: , (single target)
First, we need to define the
[9]:
def G(phase_inversion_qubit, n_qubits): # Define the G operator in Grover search algorithm
operator = bitphaseflip_operator(phase_inversion_qubit, n_qubits)
operator += UN(H, n_qubits)
operator += bitphaseflip_operator([i for i in range(1, pow(2, n_qubits))], n_qubits)
operator += UN(H, n_qubits)
return operator
Then, we build the corresponding quantum circuit in MindSpore Quantum according to the quantum circuit model of Grover search algorithm:
[10]:
# pylint: disable=W0104
from numpy import pi, sqrt
n_qubits = 3 # Set the number of qubits to 3
phase_inversion_qubit = [2] # Set the target state that needs to flip the phase, and flip the phase of the |2> state here
N = 2 ** (n_qubits) # Calculate the total number of elements in the database
M = len(phase_inversion_qubit) # Calculate the total number of target states
r = int(pi / 4 * sqrt(N / M)) # Set the number of iterations of the G operator to r
sim2 = Simulator('mqvector', n_qubits) # Use the mqvector simulator, named sim2
circuit2 = Circuit() # Initialize the quantum circuit, named circuit2
circuit2 += UN(H, n_qubits) # H-gate operations are performed on each qubit
for i in range(r): # Execute the G operator r times in a loop
circuit2 += G(phase_inversion_qubit, n_qubits)
sim2.apply_circuit(circuit2) # Run the built quantum circuit circuit2 by the simulator sim2
circuit2.svg() # Print the quantum circuit circuit2 at this time
[10]:
[11]:
print(sim2.get_qs(True)) # Print the final state after running the quantum circuit circuit2 in the simulator sim2
-√2/16¦000⟩
-√2/16¦001⟩
0.9722718241315036¦010⟩
-√2/16¦011⟩
-√2/16¦100⟩
-√2/16¦101⟩
-√2/16¦110⟩
-√2/16¦111⟩
From the results of the operation, we can see that the amplitude of the
[12]:
# pylint: disable=W0104
from mindquantum.core.gates import Measure
sim2.reset() # Reset the quantum state maintained by the simulator sim2, so that the initialized quantum state is |000>
circuit2 += UN(Measure(), circuit2.n_qubits) # Add a measurement gate to each qubit in the quantum circuit circuit2
result = sim2.sampling(circuit2, shots=1000) # Sampling the quantum circuit circuit2 1000 times by the simulator sim2
result.svg() # print sampling results
[12]:
It can be seen from the running results that 934 of the 1000 samples have the sampling result of 010 (the sampling result may fluctuate randomly). Convert it to a decimal number and run the following code:
[13]:
print(int('010', 2))
2
It can be seen from the running results that we successfully search for the
Example 2: , and (multi-target)
In Example 1, single-target search is implemented, and now we try to achieve multi-target search. First, the
[14]:
# pylint: disable=W0104
n_qubits = 5 # Set the number of qubits to 5
phase_inversion_qubit = [5, 11] # Set the target state to be phase-flipped, and flip the phases of the |5> state and |11> state here
N = 2 ** (n_qubits) # Calculate the total number of elements in the database
M = len(phase_inversion_qubit) # Calculate the total number of target states
r = int(pi / 4 * sqrt(N / M)) # Set the number of iterations of the G operator to r
sim3 = Simulator('mqvector', n_qubits) # Use the mqvector simulator, named sim3
circuit3 = Circuit() # Initialize the quantum circuit, named circuit3
circuit3 += UN(H, n_qubits) # H-gate operations are performed on each qubit
for i in range(r): # Execute the G operator r times in a loop
circuit3 += G(phase_inversion_qubit, n_qubits)
sim3.apply_circuit(circuit3) # Run the built quantum circuit circuit3 by the simulator sim3
circuit3.svg() # Print the quantum circuit circuit3 at this time
[14]:
[15]:
print(sim3.get_qs(True)) # Print the final state after running the quantum circuit circuit3 in the simulator sim3
-0.035907766232129455¦00000⟩
-0.035907766232129365¦00001⟩
-0.03590776623212947¦00010⟩
-0.035907766232129254¦00011⟩
-0.03590776623212947¦00100⟩
0.6932961018664989¦00101⟩
-0.035907766232129455¦00110⟩
-0.035907766232129365¦00111⟩
-0.035907766232129455¦01000⟩
-0.035907766232129365¦01001⟩
-0.03590776623212947¦01010⟩
0.6932961018664989¦01011⟩
-0.03590776623212947¦01100⟩
-0.035907766232129254¦01101⟩
-0.035907766232129455¦01110⟩
-0.035907766232129365¦01111⟩
-0.0359077662321294¦10000⟩
-0.03590776623212939¦10001⟩
-0.03590776623212936¦10010⟩
-0.03590776623212949¦10011⟩
-0.03590776623212936¦10100⟩
-0.03590776623212949¦10101⟩
-0.0359077662321294¦10110⟩
-0.03590776623212939¦10111⟩
-0.0359077662321294¦11000⟩
-0.03590776623212939¦11001⟩
-0.03590776623212936¦11010⟩
-0.03590776623212949¦11011⟩
-0.03590776623212936¦11100⟩
-0.03590776623212949¦11101⟩
-0.0359077662321294¦11110⟩
-0.03590776623212939¦11111⟩
It can be seen from the running results that the amplitudes of the
[16]:
# pylint: disable=W0104
sim3.reset() # Reset the quantum state maintained by the simulator sim3 so that the initialized quantum state is |00000>
circuit3 += UN(Measure(), circuit3.n_qubits) # Add a measurement gate to each qubit in the quantum circuit circuit3
result1 = sim3.sampling(circuit3, shots=1000) # The quantum circuit circuit3 is sampled 1000 times by the simulator sim3
result1.svg() # print sampling results
[16]:
It can be seen from the running results that 478 of the 1000 samplings have the sampling result of 00101 and 476 samplings have the result of 01011. Convert it to a decimal number and run the following code (The sampling results may fluctuate randomly):
[17]:
print(int('00101', 2))
print(int('01011', 2))
5
11
It can be seen from the running results that we successfully search for the
So far, we have introduced the basic principles of Grover search algorithm, and shown how to use MindSpore Quantum to implement the algorithm by two specific small examples! Hurry up and experience the fun of quantum programming!
Long Algorithm
Except for the scenario of finding one data in a database of size 4, the Grover algorithm is not able to search the marked state precisely. Professor Guilu Long of Tsinghua University proposed the quantum exact search algorithm - Long algorithm [3] on the base of Grover’s algorithm, which is able to search the target state in all scenarios with the accuracy of 1. The main idea is to rewrite the Grover operator as the follows,
where
To find the target state with probability 1, we only need to perform the Long operator
Quntum Circuit for General Angle Phase Rotation
With the aid of auxiliary bits, we build a quantum circuit for general angle phase rotation on a certain basis vector.
[18]:
from mindquantum.core.gates import X, PhaseShift
from mindquantum.core.circuit import Circuit
def change_phase_with_anclia(which, n_qubits, phase):
c = Circuit()
which_bit = bin(which)[2:].zfill(n_qubits)[::-1]
polarity_circ = Circuit()
for idx, bit in enumerate(which_bit):
if bit == "0":
polarity_circ += X.on(idx)
c += polarity_circ
c += PhaseShift(phase).on(n_qubits, list(range(n_qubits)))
c += polarity_circ
return c
Constructing the Long Operator
[19]:
from mindquantum.core.gates import BARRIER, Z
def L(which, n_qubits, theta, phi):
U = UN(H, n_qubits)
R0 = change_phase_with_anclia(0, n_qubits, theta)
R_t = change_phase_with_anclia(which, n_qubits, phi)
g_ops = R_t + BARRIER + U + BARRIER + R0 + BARRIER + U + BARRIER
g_ops += Z.on(n_qubits)
return g_ops
Performing the Quantum Exact Search Algorithm: Long Algorithm
Here we take the example of searching
[20]:
import numpy as np
from mindquantum.core.gates import H
from mindquantum.core.circuit import UN
n_qubits = 3
will_find = 2
beta = np.arcsin(np.sqrt(1 / 2**n_qubits))
Js = int((np.pi / 2 - beta) / 2 / beta)
theta = 2 * np.arcsin(np.sin(np.pi / (4 * Js + 6)) / np.sin(beta))
phi = theta
g = L(will_find, n_qubits, theta, phi) # Constructing the Long operator for exact search
circ = UN(H, n_qubits) + X.on(n_qubits)
for i in range(Js + 1):
circ += g
circ.svg()
[20]:
Next, we calculate the quantum state of the circuit.
[21]:
print(circ.get_qs(ket=True))
(0.048708136684586345-0.9988130542902997j)¦1010⟩
It is found that by removing the phase, we can get the target state exactly. By sampling, we can also obtain similar results as follows.
[22]:
from mindquantum.simulator import Simulator
from mindquantum.core.gates import Measure
sim = Simulator('mqvector', circ.n_qubits)
res = sim.sampling(circ + UN(Measure(), circ.n_qubits), shots=100)
res.svg()
[22]:
[23]:
from mindquantum.utils.show_info import InfoTable
InfoTable('mindquantum', 'scipy', 'numpy')
[23]:
Software | Version |
---|---|
mindquantum | 0.9.11 |
scipy | 1.10.1 |
numpy | 1.23.5 |
System | Info |
Python | 3.9.16 |
OS | Linux x86_64 |
Memory | 8.3 GB |
CPU Max Thread | 8 |
Date | Sat Dec 30 22:57:12 2023 |
References:
[1] L. K. Grover, A fast quantum mechanical algorithm for database search[C]// Proceedings of the twenty-eighth annual ACM symposium on Theory of computing. ACM, 1996: 212-219.
[2] G. Brassard, P. Hoyer, M. Mosca, et al. Quantum amplitude amplification and estimation[J]. Contemporary Mathematics, 2002, 305: 53-74.
[3] Long G L. Grover algorithm with zero theoretical failure rate. Physical Rev A, 2001, 64: 022307.