I need your expert opinions/comments on this problem.
Suppose I have a database (say 16 entries), such that db[0] = 0.12, db[1] = 0.84, db[2] = 0.55, ..., db[15] = 0.91. I want the oracle to mark those indexes whose value is > 0.8 (for example). In this case the oracle should mark the index of 1 & 15 so that the Grover algo is able to pick out one of the desired index after a certain number of iterations. How should I go about doing this?
My solution (I use Q#):
- I create 4 quantum registers; targetReg, yReg, x1Reg, x2Reg.
- x1Reg has 4 qubits, representing the database indices and in uniform superposition.
- x2Reg has qubits enough to represent the real numbers associated with each index. In this case, 7 qubits is suffice (I can simply multiply the values by 100 so that they become integers).
- yReg has the same number of qubits as x2Reg and initialized to 0.8 (or 80 after multiplication).
- targetReg has a single qubit.
- Start iteration {
- within {Compare yReg and x2Reg and set yReg to |0> if x@Reg > yReg.}
- apply {ControlledOnInt(0, X)(yReg, targetReg)}.
- Then perform the reflection.
- } End iteration.
- Measure x1Reg.
Is this how it should be done? I have not actually tried it yet but I believe it should work although I have no clue how to implement Item 7 (the comparison). I was wondering if there are other alternate ways of doing it.
Edit: I have written a Q# program that finds and marked entries that are equal to the desired entry. It seems to be working fine although my apologies if my code looks amateurish since I only started to learn Q# a month ago. Now I need to find out how to find and marked entries that are greater than the desired entry.
operation GroverSearchIntDatabase() : Unit {
let indexRegLength = 4; // number of qubits to represent the database indices
let intRegLength = 7; // number of qubits to represent the integers
// Generate the database randomly
let databaseSize = 2 ^ indexRegLength;
mutable database = [0, size = databaseSize];
for idx in 0 .. databaseSize - 1 {
set database w/= idx <- DrawRandomInt(0, (2 ^ intRegLength) - 1);
}
// Randomly select an index pointing to the desired integer
let solutionIndex = DrawRandomInt(0, databaseSize - 1);
let solutionInt = database[solutionIndex];
Message($"The desired integer: {solutionInt}");
// Find out how many indices have the same desired integer
let predicate = EqualI(_, solutionInt);
let nSolutions = Count(predicate, database);
Message($"Number of indices with the same integer: {nSolutions}");
// Initiailize the quantum registers
use indexReg = Qubit[indexRegLength];
use intReg = Qubit[intRegLength];
use desiredIntReg = Qubit[intRegLength];
use targetReg = Qubit();
let nIterations = Floor(Sqrt(IntAsDouble(databaseSize) / IntAsDouble(nSolutions)) * PI() / 4.0);
mutable measuredIndex = 0;
// Theoretical success probability
let success_prob = Sin((2.0 * IntAsDouble(nIterations) + 1.0) * ArcSin(Sqrt(IntAsDouble(nSolutions)) / Sqrt(IntAsDouble(databaseSize)))) ^ 2.0;
Message($"Success probability: {success_prob}");
// Grover Search
ApplyToEach(H, indexReg);
for _ in 1..nIterations {
// This is the oracle
within {
X(targetReg);
H(targetReg);
// Associate the integers to the corresponding indices
for idx in 0 .. databaseSize - 1 {
ControlledOnInt(idx, ApplyXorInPlace)(indexReg, (database[idx], LittleEndian(intReg)));
}
// Set the desiredIntReg to |0> if it is equal to solutionInt
ApplyXorInPlace(solutionInt, LittleEndian(desiredIntReg));
for (q0, q1) in Zipped(intReg, desiredIntReg) {
CNOT(q0, q1);
}
} apply {
ControlledOnInt(0, X)(desiredIntReg, targetReg);
}
// This will be the reflect about uniform
within {
ApplyToEachA(H, indexReg);
ApplyToEachA(X, indexReg);
} apply {
Controlled Z(Most(indexReg), Tail(indexReg));
}
}
set measuredIndex = MeasureInteger(LittleEndian(indexReg));
Message($"Desired integer: {solutionInt}, Integer of measured index: {database[measuredIndex]}");
}