A General Grover Model#
Code at: https://github.com/qiboteam/qibo/tree/master/examples/grover.
The examples presented here provide information to run a general Grover model accessible as
from qibo.models import Grover
. This model allows to construct a general
circuit to make use of generalized Grover models to search for states on an
unstructured database. References can be checked at
For Grover’s original search algorithm: arXiv:quant-ph/9605043
For the iterative version with unknown solutions:arXiv:quant-ph/9605034
For the Grover algorithm with any superposition:arXiv:quant-ph/9712011
The arguments of the model are
oracle (
qibo.core.circuit.Circuit
): quantum circuit that flips the sign using a Grover ancilla initialized with -X-H-. Grover ancilla expected to be the last qubit of oracle circuit.superposition_circuit (
qibo.core.circuit.Circuit
): quantum circuit that takes an initial state to a superposition. Expected to use the first set of qubits to store the relevant superposition.initial_state_circuit (
qibo.core.circuit.Circuit
): quantum circuit that initializes the state. If empty defaults to |000..00>superposition_qubits (int): number of qubits that store the relevant superposition. Leave empty if superposition does not use ancillas.
superposition_size (int): how many states are in a superposition. Leave empty if its an equal superposition of quantum states.
number_solutions (int): number of expected solutions. Needed for normal Grover. Leave empty for iterative version.
target_amplitude (float): absolute value of the amplitude of the target state. Only for advanced use and known systems.
check (function): function that returns True if the solution has been found. Required of iterative approach. First argument should be the bitstring to check.
check_args (tuple): arguments needed for the check function. The found bitstring not included.
iterative (bool): force the use of the iterative Grover
We provide three different examples to run Grover with:
Example 1: standard Hadamard superposition and simple oracle.#
In this first example we show how to use a standard Grover search where the search space is an equally weighted superposition of quantum states and the oracle is simply defined through a layer of Hadamard gates. This example makes no use of ancilla qubits, so the command lines simplify greatly.
First we create a superposition circuit. It is done by just initializing a 5-qubit circuit, and adding Hadamard gates
superposition = Circuit(5)
superposition.add([gates.H(i) for i in range(5)])
The next step is creating the oracle. In this case, we look for the states where all the qubits are in the
1
state
oracle = Circuit(5 + 1)
oracle.add(gates.X(5).controlled_by(*range(5)))
Now we create the Grover model.
grover = Grover(oracle, superposition_circuit=superposition, number_solutions=1)
solution, iterations = grover()
In this case there are no ancilla qubits, and it is straightforward to see that there is only one possible solution, so we do not have to use any further information as the input for the circuit.
Example 2: standard Hadamard superposition and oracle with ancillas#
This second example is more complicated since we create an oracle function that makes use of ancilla qubits.
We want to create a Grover model such that it searches all the basis states with num_1
qubits in the
1
state. The search space is all the possibilities with qubits
qubits. Those parameters
are to be defined in the script. Functions one_sum, sum_circuit, oracle
create the corresponding circuits for the oracle.
The superposition circuit is the standard Hadamard one and is therefore not specified. However, note that since
there are ancilla qubits in the oracle, we need to give the information of the size of the search space through the
argument superposition_qubits
. We also provide a check
function counting the number of 1
in a bit string to be used
in the iterative approach.
In the non-iterative standard case we must write
grover = Grover(oracle, superposition_qubits=qubits, number_solutions=int(binom(qubits, num_1)))
solution, iterations = grover()
For the iterative case, the corresponding code is
grover = Grover(oracle, superposition_qubits=qubits, check=check, check_args=(num_1,))
solution, iterations = grover()
Example 3: Ancillas for superposition and oracle, setting size of search space#
In this third example we create a Grover model with two components:
A superposition circuit creating all the elements in the computational basis with
num_1
qubits in the1
state.An oracle checking that the first
num_1
qubits are in the1
state and does not care about any other qubit. This oracle is written in such a way that it needs ancilla qubits. This is not necessary in Qibo, it is done in this way for illustrating the model.
The joint action of both elements looks for the |1…10…0> element. The size of the search space is not 2^n in this case, but smaller.
First, the superposition circuit is created
superposition = superposition_circuit(qubits, num_1)
This circuit has qubits
superposition qubits and some ancillas.
Then the oracle is created
oracle = oracle(qubits, num_1)
or_circuit = Circuit(oracle.nqubits)
or_circuit.add(oracle.on_qubits(*(list(range(qubits)) + [oracle.nqubits - 1] + list(range(qubits, oracle.nqubits - 1)))))
The oracle
object has qubits
qubits for the superposition, an ancilla qubit detecting whether the conditions are
fulfilled or not, and some other auxiliary ancillas. In order to relabel the qubits so that the important ancilla is
at the bottom of the circuit, we must add two more lines and use a feature provided by Qibo.
Again, calling the Grover model is enough to execute the circuit. The binomial function allows to obtain the exact size of the search space.
grover = Grover(or_circuit, superposition_circuit=superposition, superposition_qubits=qubits, number_solutions=1,
superposition_size=int(binomial(qubits, num_1)))