Many problems in classical computer science can be reformulated
as searching a list for a unique element which matches some
predefined condition.
If no additional knowledge about the search-condition is
available, the best classical algorithm is a brute-force
search i.e. the elements are sequentially tested against
and as soon as an element matches the condition, the
algorithm terminates.
For a list of
elements, this requires an average of
comparisons.
By taking advantage of quantum parallelism and interference,
Grover found a quantum algorithm which can find the matching
element in only steps. [20]
The most straightforward way, albeit not the most convenient for
the algorithm, to implement the search condition is as a
quantum function
![]() |
(4.1) |
Grover's algorithm can then be used to solve the equation while
besides the fact that a solution exists and that it is unique,
no additional knowledge about
is required.
Usually, the implementation of
will be complicated
enough as not to allow an efficient algebraic solution, but
since the inner structure of
doesn't matter for the
algorithm, we can easily implement a test query with the
solution
as
qufunct query(qureg x,quvoid f,int n) { int i; for i=0 to #x-1 { // x -> NOT (x XOR n) if not bit(n,i) { Not(x[i]); } } CNot(f,x); // flip f if x=1111.. for i=0 to #x-1 { // x <- NOT (x XOR n) if not bit(n,i) { !Not(x[i]); } } } |
A more realistic application would be the search for an encryption
key in a known-plaintext attack.
With being the known plaintext to the ciphertext
, a
QCL implementation could look like this:
qufunct encrypt(int p,quconst key,quvoid c) { ... } qufunct query(int c,int p,quconst key,quvoid f) { int i; quscratch s[blocklength]; encrypt(p,key,s); for i=0 to #s-1 { // s -> NOT (s XOR p) if not bit(p,i) { Not(x[i]); } } CNot(f,x); // flip f if s=1111.. } |
The solution space of a bit query condition
is
.
On a quantum computer, this search space can be implemented as
a superposition of all eigenstates of an
qubit register, i.e.
![]() |
(4.2) |
![]() |
(4.3) |
The main loop of the algorithm consists of two steps
![]() |
(4.4) |
![]() |
(4.5) |
Since only one eigenvector
is supposed to match the search
condition
, the conditional phase shift will turn the
initial even superposition into
![]() |
(4.6) |
The effect of the diffusion operator on an arbitrary eigenvector
is
![]() |
(4.7) |
![]() |
(4.8) |
![]() |
(4.9) |
If the above loop operator is repeatedly applied to
the initial superposition
![]() |
(4.10) |
![]() |
![]() |
![]() |
(4.11) |
![]() |
![]() |
![]() |
(4.12) |
Using the substitution
the solution
of the above system can be written in closed form.
![]() |
![]() |
![]() |
(4.13) |
![]() |
![]() |
![]() |
(4.14) |
The probability to measure
is given as
and
has a maximum at
.
Since for large lists,
we can assume
that
and
and the number of iterations
for a maximum
is about
with
(due to rounding errors).
Alternatively, if we are content with
, then
iterations will do.
If we choose to formulate the query as quantum function with
a flag qubit to
allow for a strictly classical implementation, as
suggested in 4.1.1, then the operator
can
be constructed as
![]() |
(4.15) |
Using the Hadamard Transform (see 3.4.4.3) and a
conditional phase rotation
,
the diffusion operator
![]() |
(4.16) |
![]() |
(4.17) |
![]() |
(4.18) |
Using the operator from 3.4.7.4 and
a conditional phase gate
we can implement the
diffusion operator as
operator diffuse(qureg q) { Mix(q); // Hadamard Transform Not(q); // Invert q CPhase(pi,q); // Rotate if q=1111.. !Not(q); // undo inversion !Mix(q); // undo Hadamard Transform } |
In fact, the above operator implements , but since overall
phases make no physical difference, this doesn't matter.
By using the above, we can now give a QCL implementation of the complete algorithm:
procedure grover(int n) { int l=floor(log(n,2))+1; // no. of qubits int m=ceil(pi/8*sqrt(2^l)); // no. of iterations int x; int i; qureg q[l]; qureg f[1]; { reset; Mix(q); // prepare superposition for i= 1 to m { // main loop query(q,f,n); // calculate C(q) CPhase(pi,f); // negate |n> !query(q,f,n); // undo C(q) diffuse(q); // diffusion operator } measure q,x; // measurement print "measured",x; } until x==n; } |
qcl> grover(500); : 9 qubits, using 9 iterations : measured 500 qcl> grover(123); : 7 qubits, using 5 iterations : measured 74 : measured 123 qcl> grover(1234); : 11 qubits, using 18 iterations : measured 1234 |