The Quantum Exact Simulation Toolkit v4.2.0
Loading...
Searching...
No Matches
test_gates.cpp
1/** @file
2 * Ported tests of the deprecated QuEST v3 interface,
3 * unit testing the "gates" module.
4 *
5 * This file should be excluded from doxygen parsing so
6 * as not to conflict with the doc of the v4 unit tests.
7 *
8 * @author Tyson Jones
9 * @author Oliver Thomson Brown (ported to Catch2 v3)
10 * @author Ali Rezaei (tested porting to QuEST v4)
11 */
12
13// must include catch.hpp first, because quest's
14// deprecation library will include a definition
15// of Vector{}
16#include <catch2/catch_test_macros.hpp>
17#include <catch2/catch_approx.hpp>
18#include <catch2/matchers/catch_matchers_string.hpp>
19#include <catch2/generators/catch_generators_range.hpp>
20
21#include "quest.h"
22#include "test_utilities.hpp"
23
24/* allows concise use of ContainsSubstring in catch's REQUIRE_THROWS_WITH */
25using Catch::Matchers::ContainsSubstring;
26using Catch::Approx;
27
28
29/** @sa collapseToOutcome
30 * @ingroup deprecatedtests
31 * @author Tyson Jones
32 */
33TEST_CASE( "collapseToOutcome", "[gates]" ) {
34
35 Qureg vec = createForcedQureg(NUM_QUBITS);
36 Qureg mat = createForcedDensityQureg(NUM_QUBITS);
37
38 SECTION( "correctness" ) {
39
40 int qubit = GENERATE( range(0,NUM_QUBITS) );
41 int outcome = GENERATE( 0, 1 );
42
43 // repeat these random tests 10 times on every qubit, and for both outcomes
44 GENERATE( range(0,10) );
45
46 SECTION( "state-vector" ) {
47
48 // use a random L2 state for every qubit & outcome
49 QVector vecRef = getRandomStateVector(NUM_QUBITS);
50 toQureg(vec, vecRef);
51
52 // calculate prob of outcome
53 qreal prob = 0;
54 for (size_t ind=0; ind<vecRef.size(); ind++) {
55 int bit = (ind >> qubit) & 1; // target-th bit
56 if (bit == outcome)
57 prob += pow(abs(vecRef[ind]), 2);
58 }
59
60 // renormalise by the outcome prob
61 for (size_t ind=0; ind<vecRef.size(); ind++) {
62 int bit = (ind >> qubit) & 1; // target-th bit
63 if (bit == outcome)
64 vecRef[ind] /= sqrt(prob);
65 else
66 vecRef[ind] = 0;
67 }
68
69 qreal res = collapseToOutcome(vec, qubit, outcome);
70 REQUIRE( res == Approx(prob) );
71 REQUIRE( areEqual(vec, vecRef) );
72 }
73 SECTION( "density-matrix" ) {
74
75 // use a random density matrix for every qubit & outcome
76 QMatrix matRef = getRandomDensityMatrix(NUM_QUBITS);
77 toQureg(mat, matRef);
78
79 // prob is sum of diagonal amps (should be real) where target bit is outcome
80 qcomp tr = 0;
81 for (size_t ind=0; ind<matRef.size(); ind++) {
82 int bit = (ind >> qubit) & 1; // qubit-th bit
83 if (bit == outcome)
84 tr += matRef[ind][ind];
85 }
86 REQUIRE( imag(tr) == Approx(0).margin(REAL_EPS) );
87 qreal prob = real(tr);
88
89 // renorm (/prob) every |*outcome*><*outcome*| state, zeroing all others
90 for (size_t r=0; r<matRef.size(); r++) {
91 for (size_t c=0; c<matRef.size(); c++) {
92 int ketBit = (c >> qubit) & 1;
93 int braBit = (r >> qubit) & 1;
94
95 if (ketBit == outcome && braBit == outcome)
96 matRef[r][c] /= prob;
97 else
98 matRef[r][c] = 0;
99 }
100 }
101
102 qreal res = collapseToOutcome(mat, qubit, outcome);
103 REQUIRE( res == Approx(prob) );
104 REQUIRE( areEqual(mat, matRef) );
105 }
106 }
107 SECTION( "input validation" ) {
108
109 SECTION( "qubit index" ) {
110
111 int qubit = GENERATE( -1, NUM_QUBITS );
112 int outcome = 0;
113 REQUIRE_THROWS_WITH( collapseToOutcome(mat, qubit, outcome), ContainsSubstring("Invalid target qubit") );
114 }
115 SECTION( "outcome value" ) {
116
117 int qubit = 0;
118 int outcome = GENERATE( -1, 2 );
119 REQUIRE_THROWS_WITH( collapseToOutcome(mat, qubit, outcome), ContainsSubstring("qubit measurement outcome") && ContainsSubstring("invalid") );
120 }
121 SECTION( "outcome probability" ) {
122
123 initZeroState(vec);
124 REQUIRE_THROWS_WITH( collapseToOutcome(vec, 0, 1), ContainsSubstring("impossibly unlikely") );
125 initClassicalState(vec, 1);
126 REQUIRE_THROWS_WITH( collapseToOutcome(vec, 0, 0), ContainsSubstring("impossibly unlikely") );
127 }
128 }
129 destroyQureg(vec);
130 destroyQureg(mat);
131}
132
133
134
135/** @sa measure
136 * @ingroup deprecatedtests
137 * @author Tyson Jones
138 */
139TEST_CASE( "measure", "[gates]" ) {
140
141 Qureg vec = createForcedQureg(NUM_QUBITS);
142 Qureg mat = createForcedDensityQureg(NUM_QUBITS);
143
144 SECTION( "correctness" ) {
145
146 int qubit = GENERATE( range(0,NUM_QUBITS) );
147
148 // repeat these random tests 10 times on every qubit
149 GENERATE( range(0,10) );
150
151 SECTION( "state-vector" ) {
152
153 QVector vecRef = getRandomStateVector(NUM_QUBITS);
154 toQureg(vec, vecRef);
155
156 int outcome = measure(vec, qubit);
157 REQUIRE( (outcome == 0 || outcome == 1) );
158
159 // calculate prob of this outcome
160 qreal prob = 0;
161 for (size_t ind=0; ind<vecRef.size(); ind++) {
162 int bit = (ind >> qubit) & 1; // target-th bit
163 if (bit == outcome)
164 prob += pow(abs(vecRef[ind]), 2);
165 }
166
167 REQUIRE( prob > REAL_EPS );
168
169 // renormalise by the outcome prob
170 for (size_t ind=0; ind<vecRef.size(); ind++) {
171 int bit = (ind >> qubit) & 1; // target-th bit
172 if (bit == outcome)
173 vecRef[ind] /= sqrt(prob);
174 else
175 vecRef[ind] = 0;
176 }
177 REQUIRE( areEqual(vec, vecRef) );
178 }
179 SECTION( "density-matrix" ) {
180
181 QMatrix matRef = getRandomDensityMatrix(NUM_QUBITS);
182 toQureg(mat, matRef);
183
184 int outcome = measure(mat, qubit);
185 REQUIRE( (outcome == 0 || outcome == 1) );
186
187 // compute prob of this outcome
188 qreal prob = 0;
189 for (size_t ind=0; ind<matRef.size(); ind++) {
190 int bit = (ind >> qubit) & 1; // qubit-th bit
191 if (bit == outcome)
192 prob += real(matRef[ind][ind]);
193 }
194
195 REQUIRE( prob > REAL_EPS );
196
197 // renorm (/prob) every |*outcome*><*outcome*| state, zeroing all others
198 for (size_t r=0; r<matRef.size(); r++) {
199 for (size_t c=0; c<matRef.size(); c++) {
200 int ketBit = (c >> qubit) & 1;
201 int braBit = (r >> qubit) & 1;
202
203 if (ketBit == outcome && braBit == outcome)
204 matRef[r][c] /= prob;
205 else
206 matRef[r][c] = 0;
207 }
208 }
209
210 REQUIRE( areEqual(mat, matRef) );
211 }
212 }
213 SECTION( "input validation" ) {
214
215 SECTION( "qubit index" ) {
216
217 int qubit = GENERATE( -1, NUM_QUBITS );
218 REQUIRE_THROWS_WITH( measure(vec, qubit), ContainsSubstring("Invalid target qubit") );
219 }
220 }
221 destroyQureg(vec);
222 destroyQureg(mat);
223}
224
225
226
227/** @sa measureWithStats
228 * @ingroup deprecatedtests
229 * @author Tyson Jones
230 */
231TEST_CASE( "measureWithStats", "[gates]" ) {
232
233 Qureg vec = createForcedQureg(NUM_QUBITS);
234 Qureg mat = createForcedDensityQureg(NUM_QUBITS);
235
236 SECTION( "correctness" ) {
237
238 int qubit = GENERATE( range(0,NUM_QUBITS) );
239
240 // repeat these random tests 10 times on every qubit
241 GENERATE( range(0,10) );
242
243 SECTION( "state-vector" ) {
244
245 QVector vecRef = getRandomStateVector(NUM_QUBITS);
246 toQureg(vec, vecRef);
247
248 qreal res;
249 int outcome = measureWithStats(vec, qubit, &res);
250 REQUIRE( (outcome == 0 || outcome == 1) );
251
252 // calculate prob of this outcome
253 qreal prob = 0;
254 for (size_t ind=0; ind<vecRef.size(); ind++) {
255 int bit = (ind >> qubit) & 1; // target-th bit
256 if (bit == outcome)
257 prob += pow(abs(vecRef[ind]), 2);
258 }
259
260 REQUIRE( prob == Approx(res) );
261
262 // renormalise by the outcome prob
263 for (size_t ind=0; ind<vecRef.size(); ind++) {
264 int bit = (ind >> qubit) & 1; // target-th bit
265 if (bit == outcome)
266 vecRef[ind] /= sqrt(prob);
267 else
268 vecRef[ind] = 0;
269 }
270 REQUIRE( areEqual(vec, vecRef) );
271 }
272 SECTION( "density-matrix" ) {
273
274 QMatrix matRef = getRandomDensityMatrix(NUM_QUBITS);
275 toQureg(mat, matRef);
276
277 qreal res;
278 int outcome = measureWithStats(mat, qubit, &res);
279 REQUIRE( (outcome == 0 || outcome == 1) );
280
281 // compute prob of this outcome
282 qreal prob = 0;
283 for (size_t ind=0; ind<matRef.size(); ind++) {
284 int bit = (ind >> qubit) & 1; // qubit-th bit
285 if (bit == outcome)
286 prob += real(matRef[ind][ind]);
287 }
288
289 REQUIRE( prob == Approx(res) );
290
291 // renorm (/prob) every |*outcome*><*outcome*| state, zeroing all others
292 for (size_t r=0; r<matRef.size(); r++) {
293 for (size_t c=0; c<matRef.size(); c++) {
294 int ketBit = (c >> qubit) & 1;
295 int braBit = (r >> qubit) & 1;
296
297 if (ketBit == outcome && braBit == outcome)
298 matRef[r][c] /= prob;
299 else
300 matRef[r][c] = 0;
301 }
302 }
303
304 REQUIRE( areEqual(mat, matRef) );
305 }
306 }
307 SECTION( "input validation" ) {
308
309 SECTION( "qubit index" ) {
310
311 int qubit = GENERATE( -1, NUM_QUBITS );
312 qreal res;
313 REQUIRE_THROWS_WITH( measureWithStats(vec, qubit, &res), ContainsSubstring("Invalid target qubit") );
314 }
315 }
316 destroyQureg(vec);
317 destroyQureg(mat);
318}
TEST_CASE("collapseToOutcome", "[gates]")
bool areEqual(QVector a, QVector b)
vector< vector< qcomp > > QMatrix
vector< qcomp > QVector
void toQureg(Qureg qureg, QVector vec)
void initZeroState(Qureg qureg)
void initClassicalState(Qureg qureg, qindex stateInd)
Qureg createForcedQureg(int numQubits)
Definition qureg.cpp:299
Qureg createForcedDensityQureg(int numQubits)
Definition qureg.cpp:309
void destroyQureg(Qureg qureg)
Definition qureg.cpp:334
qvector getRandomStateVector(int numQb)
Definition random.cpp:296
qmatrix getRandomDensityMatrix(int numQb)
Definition random.cpp:308
Definition qureg.h:49