forked from microsoft/Quantum
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Program.qs
177 lines (148 loc) · 7.33 KB
/
Program.qs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
namespace Microsoft.Quantum.Samples.DatabaseSearch {
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Convert;
@EntryPoint()
operation RunRandomSearch() : Unit {
// Let us investigate the success probability of classical random search. This corresponds
// to the case where we only prepare the start state, and do not perform any Grover iterations
// to amplify the marked subspace.
let nIterations = 0;
// We now define the size `N` = 2^n of the database to searched in terms of number of qubits
// `n`.
let nDatabaseQubits = 3;
let databaseSize = 2 ^ nDatabaseQubits;
// We now execute the classical random search and verify that the success probability
// matches the classical result of 1/N. Let us repeat 100 times to collect enough
// statistics.
let classicalSuccessProbability = 1.0 / IntAsDouble(databaseSize);
let repeats = 1000;
mutable successCount = 0;
Message(
"Classical random search for marked element in database.\n" +
$" Database size: {databaseSize}.\n" +
$" Success probability: {classicalSuccessProbability}\n"
);
for attempt in 1 .. repeats {
// Extract the marked qubit state.
let (markedQubit, databaseRegister) = ApplyQuantumSearch(nIterations, nDatabaseQubits);
set successCount += markedQubit == One ? 1 | 0;
// Print the results of the search every 100 attempts.
if attempt % 100 == 0 {
Message(
$"Attempt {attempt}. " +
$"Success: {markedQubit}, " +
$"Probability: {RoundDigits(IntAsDouble(successCount) / IntAsDouble(attempt), 3)} " +
$"Found database index {databaseRegister}"
);
}
}
}
@EntryPoint()
operation RunQuantumSearch() : Unit {
// Let us investigate the success probability of the quantum search.
// We define the size `N` = 2^n of the database to searched in terms of number of qubits
// `n`.
let nDatabaseQubits = 6;
let databaseSize = 2 ^ nDatabaseQubits;
// We now perform Grover iterations to amplify the marked subspace.
let nIterations = 3;
// Number of queries to database oracle.
let queries = nIterations * 2 + 1;
// We now execute the quantum search and verify that the success probability matches the
// theoretical prediction.
let classicalSuccessProbability = 1.0 / IntAsDouble(databaseSize);
let quantumSuccessProbability = Sin((2.0 * IntAsDouble(nIterations) + 1.0) * ArcSin(1.0 / Sqrt(IntAsDouble(databaseSize)))) ^ 2.0;
let repeats = 100;
mutable successCount = 0;
Message(
"\n\nQuantum search for marked element in database.\n" +
$" Database size: {databaseSize}.\n" +
$" Classical success probability: {classicalSuccessProbability}\n" +
$" Queries per search: {queries} \n" +
$" Quantum success probability: {quantumSuccessProbability}\n"
);
for attempt in 1 .. repeats {
// Extract the marked qubit state.
let (markedQubit, databaseRegister) = ApplyQuantumSearch(nIterations, nDatabaseQubits);
set successCount += markedQubit == One ? 1 | 0;
// Print the results of the search every 10 attempts.
if attempt % 10 == 0 {
let empiricalSuccessProbability = RoundDigits(IntAsDouble(successCount) / IntAsDouble(attempt), 3);
// This is how much faster the quantum algorithm performs on average over the
// classical search.
let speedupFactor = RoundDigits(empiricalSuccessProbability / classicalSuccessProbability / IntAsDouble(queries), 3);
Message(
$"Attempt {attempt}. " +
$"Success: {markedQubit}, " +
$"Probability: {empiricalSuccessProbability} " +
$"Speedup: {speedupFactor} " +
$"Found database index {databaseRegister}"
);
}
}
}
@EntryPoint()
operation RunMultipleQuantumSearch() : Unit {
// Let us investigate the success probability of the quantum search with multiple
// marked elements.
// We define the size `N` = 2^n of the database to searched in terms of
// number of qubits `n`.
let nDatabaseQubits = 8;
let databaseSize = 2 ^ nDatabaseQubits;
// We define the marked elements. These must be smaller than `databaseSize`.
let markedElements = [0, 39, 101, 234];
let nMarkedElements = Length(markedElements);
// We now perform Grover iterations to amplify the marked subspace.
let nIterations = 3;
// Number of queries to database oracle.
let queries = nIterations * 2 + 1;
// We now execute the quantum search and verify that the success
// probability matches the theoretical prediction.
let classicalSuccessProbability = IntAsDouble(nMarkedElements) / IntAsDouble(databaseSize);
let quantumSuccessProbability = Sin((2.0 * IntAsDouble(nIterations) + 1.0) * ArcSin(Sqrt(IntAsDouble(nMarkedElements)) / Sqrt(IntAsDouble(databaseSize)))) ^ 2.0;
let repeats = 10;
mutable successCount = 0;
Message(
"\n\nQuantum search for marked element in database.\n" +
$" Database size: {databaseSize}.\n" +
$" Marked elements: {markedElements}" +
$" Classical success probability: {classicalSuccessProbability}\n" +
$" Queries per search: {queries} \n" +
$" Quantum success probability: {quantumSuccessProbability}\n"
);
for attempt in 1 .. repeats {
// Extract the marked qubit state.
let (markedQubit, databaseRegister) = ApplyGroverSearch(markedElements, nIterations, nDatabaseQubits);
set successCount += markedQubit == One ? 1 | 0;
// Print the results of the search every attempt.
let empiricalSuccessProbability = RoundDigits(IntAsDouble(successCount) / IntAsDouble(attempt), 3);
// This is how much faster the quantum algorithm performs on average
// over the classical search.
let speedupFactor = RoundDigits(empiricalSuccessProbability / classicalSuccessProbability / IntAsDouble(queries), 3);
Message(
$"Attempt {attempt}. " +
$"Success: {markedQubit}, " +
$"Probability: {empiricalSuccessProbability} " +
$"Speedup: {speedupFactor} " +
$"Found database index {databaseRegister}"
);
}
}
/// # Summary
/// Rounds a number to a specific number of digits.
///
/// # Input
/// ## value
/// The number to round.
/// ## digits
/// The number of digits to round to.
///
/// # Output
/// The rounded number.
internal function RoundDigits(value : Double, digits : Int) : Double {
return IntAsDouble(Round(value * 10.0 ^ IntAsDouble(digits))) / 10.0 ^ IntAsDouble(digits);
}
}