Download as pdf or txt
Download as pdf or txt
You are on page 1of 4

7/27/23, 11:25 PM Grover’s Algorithm and Amplitude Amplification — Qiskit 0.43.

3 documentation

English

Table of Contents

• NOTE

This page was generated from tutorials/algorithms/06_grover.ipynb.

Grover ’s Algorithm and Amplitude Amplification ¶


Grover’s algorithm is one of the most famous quantum algorithms introduced by Lov Grover in 1996 [1]. It has initially been proposed for unstructured search problems,
i.e. for finding a marked element in a unstructured database. However, Grover’s algorithm is now a subroutine to several other algorithms, such as Grover Adaptive Search
[2]. For the details of Grover’s algorithm, please see Grover’s Algorithm in the Qiskit textbook.

Qiskit implements Grover’s algorithm in the Grover class. This class also includes the generalized version, Amplitude Amplification [3], and allows setting individual
iterations and other meta-settings to Grover’s algorithm.

References:

[1]: L. K. Grover, A fast quantum mechanical algorithm for database search. Proceedings 28th Annual Symposium on the Theory of Computing (STOC) 1996, pp. 212-219.
https://arxiv.org/abs/quant-ph/9605043

[2]: A. Gilliam, S. Woerner, C. Gonciulea, Grover Adaptive Search for Constrained Polynomial Binary Optimization. https://arxiv.org/abs/1912.04088

[3]: Brassard, G., Hoyer, P., Mosca, M., & Tapp, A. (2000). Quantum Amplitude Amplification and Estimation. http://arxiv.org/abs/quant-ph/0005055

Grover ’s algorithm ¶
Grover’s algorithm uses the Grover operator Q to amplify the amplitudes of the good states:


Q = AS0 A Sf

Here, * A is the initial search state for the algorithm, which is just Hadamards, H ⊗n for the textbook Grover search, but can be more elaborate for Amplitude Amplification
* S0 is the reflection about the all 0 state

−|x⟩, x ≠ 0
|x⟩ ↦ {
|x⟩, x = 0

* Sf is the oracle that applies

f (x)
|x⟩ ↦ (−1) |x⟩

where f (x) is 1 if x is a good state and otherwise 0.

In a nutshell, Grover’s algorithm applies different powers of Q and after each execution checks whether a good solution has been found.

Running Grover’s algorithm ¶


To run Grover’s algorithm with the Grover class, firstly, we need to specify an oracle for the circuit of Grover’s algorithm. In the following example, we use QuantumCircuit
as the oracle of Grover’s algorithm. However, there are several other class that we can use as the oracle of Grover’s algorithm. We talk about them later in this tutorial.

Note that the oracle for Grover must be a phase-flip oracle. That is, it multiplies the amplitudes of the of “good states” by a factor of −1. We explain later how to convert a
bit-flip oracle to a phase-flip oracle.

[1]: from qiskit import QuantumCircuit


from qiskit.algorithms import AmplificationProblem

# the state we desire to find is '11'


good_state = ['11']

# specify the oracle that marks the state '11' as a good solution
oracle = QuantumCircuit(2)
oracle.cz(0, 1)

# define Grover's algorithm


problem = AmplificationProblem(oracle, is_good_state=good_state)

# now we can have a look at the Grover operator that is used in running the algorithm
# (Algorithm circuits are wrapped in a gate to appear in composition as a block
# so we have to decompose() the op to see it expanded into its component gates.)
problem.grover_operator.decompose().draw(output='mpl')

[1]:

Then, we specify a backend and call the run method of Grover with a backend to execute the circuits. The returned result type is a GroverResult .

If the search was successful, the oracle_evaluation attribute of the result will be True . In this case, the most sampled measurement, top_measurement , is one of the “good
states”. Otherwise, oracle_evaluation will be False.

[2]: from qiskit.algorithms import Grover


from qiskit.primitives import Sampler

grover = Grover(sampler=Sampler())
result = grover.amplify(problem)
print('Result type:', type(result))
print()
print('Success!' if result.oracle_evaluation else 'Failure!')
print('Top measurement:', result.top_measurement)

Result type: <class 'qiskit.algorithms.a

Success!
Top measurement: 11

In the example, the result of top_measurement is 11 which is one of “good state”. Thus, we succeeded to find the answer by using Grover .

Using the different types of classes as the oracle of Grover ¶


In the above example, we used QuantumCircuit as the oracle of Grover . However, we can also use qiskit.quantum_info.Statevector as oracle. All the following examples are
when |11⟩ is “good state”

[3]: from qiskit.quantum_info import Statevector


oracle = Statevector.from_label('11')
problem = AmplificationProblem(oracle, is_good_state=['11'])

grover = Grover(sampler=Sampler())
result = grover.amplify(problem)
print('Result type:', type(result))
print()
print('Success!' if result.oracle_evaluation else 'Failure!')
print('Top measurement:', result.top_measurement)

Result type: <class 'qiskit.algorithms.a

Success!
Top measurement: 11

Internally, the statevector is mapped to a quantum circuit:

[4]: problem.grover_operator.oracle.decompose().draw(output='mpl')

https://qiskit.org/documentation/tutorials/algorithms/06_grover.html#Amplitude-amplification 1/4
7/27/23, 11:25 PM Grover’s Algorithm and Amplitude Amplification — Qiskit 0.43.3 documentation
[4]:

Qiskit allows for an easy construction of more complex oracles: * PhaseOracle : for parsing logical expressions such as '~a | b' . This is especially useful for solving 3-SAT
problems and is shown in the accompanying Grover Examples tutorial.

Here we’ll use the PhaseOracle for the simple example of finding the state |11⟩, which corresponds to 'a & b' .

[5]: from qiskit.circuit.library.phase_oracle import PhaseOracle


from qiskit.exceptions import MissingOptionalLibraryError

# `Oracle` (`PhaseOracle`) as the `oracle` argument


expression = '(a & b)'
try:
oracle = PhaseOracle(expression)
problem = AmplificationProblem(oracle)
display(problem.grover_operator.oracle.decompose().draw(output='mpl'))
except MissingOptionalLibraryError as ex:
print(ex)

Which we observe that this oracle implements a phase flip when the state is |11⟩

As mentioned above, Grover’s algorithm requires a phase-flip oracle. A bit-flip oracle flips the state of an auxiliary qubit if the other qubits satisfy the condition. To use
these types of oracles with Grover’s we need to convert the bit-flip oracle to a phase-flip oracle by sandwiching the auxiliary qubit of the bit-flip oracle by X and H gates.

Note: This transformation from a bit-flip to a phase-flip oracle holds generally and you can use this to convert your oracle to the right representation.

Amplitude amplification ¶
Grover’s algorithm uses Hadamard gates to create the uniform superposition of all the states at the beginning of the Grover operator Q. If some information on the good
states is available, it might be useful to not start in a uniform superposition but only initialize specific states. This, generalized, version of Grover’s algorithm is referred to
Amplitude Amplification.

In Qiskit, the initial superposition state can easily be adjusted by setting the state_preparation argument.

State preparation ¶
A state_preparation argument is used to specify a quantum circuit that prepares a quantum state for the start point of the amplitude amplification. By default, a circuit with
H
⊗n
is used to prepare uniform superposition (so it will be Grover’s search). The diffusion circuit of the amplitude amplification reflects state_preparation automatically.

[6]: import numpy as np

# Specifying `state_preparation`
# to prepare a superposition of |01>, |10>, and |11>
oracle = QuantumCircuit(3)
oracle.ccz(0, 1, 2)

theta = 2 * np.arccos(1 / np.sqrt(3))


state_preparation = QuantumCircuit(3)
state_preparation.ry(theta, 0)
state_preparation.ch(0,1)
state_preparation.x(1)
state_preparation.h(2)

# we only care about the first two bits being in state 1, thus add both possibilities for the last qubit
problem = AmplificationProblem(oracle, state_preparation=state_preparation, is_good_state=['110', '111'])

# state_preparation
print('state preparation circuit:')
problem.grover_operator.state_preparation.draw(output='mpl')

state preparation circuit:

[6]:

[7]: grover = Grover(sampler=Sampler())


result = grover.amplify(problem)
print('Success!' if result.oracle_evaluation else 'Failure!')
print('Top measurement:', result.top_measurement)

Success!
Top measurement: 111

Full flexibility ¶
For more advanced use, it is also possible to specify the entire Grover operator by setting the grover_operator argument. This might be useful if you know more efficient
implementation for Q than the default construction via zero reflection, oracle and state preparation.

The qiskit.circuit.library.GroverOperator can be a good starting point and offers more options for an automated construction of the Grover operator. You can for instance
* set the mcx_mode * ignore qubits in the zero reflection by setting reflection_qubits * explicitly exchange the Sf , S0 and A operations using the oracle , zero_reflection
and state_preparation arguments

For instance, imagine the good state is a three qubit state |111⟩ but we used 2 additional qubits as auxiliary qubits.

[8]: oracle = QuantumCircuit(5)


oracle.ccz(0, 1, 2)
oracle.draw(output='mpl')

https://qiskit.org/documentation/tutorials/algorithms/06_grover.html#Amplitude-amplification 2/4
7/27/23, 11:25 PM Grover’s Algorithm and Amplitude Amplification — Qiskit 0.43.3 documentation
[8]:

Then, per default, the Grover operator implements the zero reflection on all five qubits.

[9]: from qiskit.circuit.library import GroverOperator


grover_op = GroverOperator(oracle, insert_barriers=True)
grover_op.decompose().draw(output='mpl')

[9]:

But we know that we only need to consider the first three:

[10]: grover_op = GroverOperator(oracle, reflection_qubits=[0, 1, 2], insert_barriers=True)


grover_op.decompose().draw(output='mpl')

[10]:

Dive into other arguments of Grover ¶

Grover has arguments other than oracle and state_preparation . We will explain them in this section.

Specifying good_state ¶
good_state is used to check whether the measurement result is correct or not internally. It can be a list of binary strings, a list of integer, Statevector , and Callable. If the
input is a list of bitstrings, each bitstrings in the list represents a good state. If the input is a list of integer, each integer represent the index of the good state to be |1⟩. If it
is a Statevector , it represents a superposition of all good states.

[11]: # a list of binary strings good state


oracle = QuantumCircuit(2)
oracle.cz(0, 1)
good_state = ['11', '00']
problem = AmplificationProblem(oracle, is_good_state=good_state)
print(problem.is_good_state('11'))

True

[12]: # a list of integer good state


oracle = QuantumCircuit(2)
oracle.cz(0, 1)
good_state = [0, 1]
problem = AmplificationProblem(oracle, is_good_state=good_state)
print(problem.is_good_state('11'))

True

[13]: from qiskit.quantum_info import Statevector

# `Statevector` good state


oracle = QuantumCircuit(2)
oracle.cz(0, 1)
good_state = Statevector.from_label('11')
problem = AmplificationProblem(oracle, is_good_state=good_state)
print(problem.is_good_state('11'))

True

[14]: # Callable good state


def callable_good_state(bitstr):
if bitstr == "11":
return True
return False

oracle = QuantumCircuit(2)
oracle.cz(0, 1)
problem = AmplificationProblem(oracle, is_good_state=good_state)
print(problem.is_good_state('11'))

True

The number of iterations ¶


The number of repetition of applying the Grover operator is important to obtain the correct result with Grover’s algorithm. The number of iteration can be set by the
iteration argument of Grover . The following inputs are supported: * an integer to specify a single power of the Grover operator that’s applied * or a list of integers, in which
all these different powers of the Grover operator are run consecutively and after each time we check if a correct solution has been found

Additionally there is the sample_from_iterations argument. When it is True , instead of the specific power in iterations , a random integer between 0 and the value in
iteration is used as the power Grover’s operator. This approach is useful when we don’t even know the number of solution.

https://qiskit.org/documentation/tutorials/algorithms/06_grover.html#Amplitude-amplification 3/4
7/27/23, 11:25 PM Grover’s Algorithm and Amplitude Amplification — Qiskit 0.43.3 documentation
For more details of the algorithm using sample_from_iterations , see [4].

References:

[4]: Boyer et al., Tight bounds on quantum searching arxiv:quant-ph/9605034

[15]: # integer iteration


oracle = QuantumCircuit(2)
oracle.cz(0, 1)
problem = AmplificationProblem(oracle, is_good_state=['11'])
grover = Grover(iterations=1)

[16]: # list iteration


oracle = QuantumCircuit(2)
oracle.cz(0, 1)
problem = AmplificationProblem(oracle, is_good_state=['11'])
grover = Grover(iterations=[1, 2, 3])

[17]: # using sample_from_iterations


oracle = QuantumCircuit(2)
oracle.cz(0, 1)
problem = AmplificationProblem(oracle, is_good_state=['11'])
grover = Grover(iterations=[1, 2, 3], sample_from_iterations=True)

When the number of solutions is known, we can also use a static method optimal_num_iterations to find the optimal number of iterations. Note that the output iterations is
an approximate value. When the number of qubits is small, the output iterations may not be optimal. In addition, the calculation of this value assumes the standard
uniform superposition state preparation and may not be accurate for other state preparations.

[18]: iterations = Grover.optimal_num_iterations(num_solutions=1, num_qubits=8)


iterations

[18]: 12

Applying post_processing ¶
We can apply an optional post processing to the top measurement for ease of readability. It can be used e.g. to convert from the bit-representation of the measurement
[1, 0, 1] to a DIMACS CNF format [1, -2, 3] .

[19]: def to_DIAMACS_CNF_format(bit_rep):


return [index+1 if val==1 else -1 * (index + 1) for index, val in enumerate(bit_rep)]

oracle = QuantumCircuit(2)
oracle.cz(0, 1)
problem = AmplificationProblem(oracle, is_good_state=['11'], post_processing=to_DIAMACS_CNF_format)
problem.post_processing([1, 0, 1])

[19]: [1, -2, 3]

[20]: import qiskit.tools.jupyter


%qiskit_version_table
%qiskit_copyright

Version Information

This code is a part of Qiskit


© Copyright IBM 2017, 2023.

This code is licensed under the Apache Licen


obtain a copy of this license in the LICENSE.t
of this source tree or at http://www.apache.o

Any modifications or derivative works of this


copyright notice, and modified files need to c
that they have been altered from the original

Was this page helpful? Yes No

Previous Next

© Copyright 2017-2023, Qiskit Development Team. Last updated on 2023/07/25.


Built with Sphinx using Qiskit Sphinx Theme (based on PyTorch Sphinx Theme).

https://qiskit.org/documentation/tutorials/algorithms/06_grover.html#Amplitude-amplification 4/4

You might also like