The Quantum Exact Simulation Toolkit v4.0.0
Loading...
Searching...
No Matches
test_state_initialisations.cpp
1/** @file
2 * Ported tests of the deprecated QuEST v3 interface,
3 * unit testing the "state initialisation" 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#include <catch2/catch_test_macros.hpp>
14#include <catch2/generators/catch_generators_range.hpp>
15#include <catch2/matchers/catch_matchers_string.hpp>
16
17#define INCLUDE_DEPRECATED_FUNCTIONS 1
18#define DISABLE_DEPRECATION_WARNINGS 1
19#include "quest/include/quest.h"
20
21#include "test_utilities.hpp"
22
23/* allows concise use of ContainsSubstring in catch's REQUIRE_THROWS_WITH */
24using Catch::Matchers::ContainsSubstring;
25
26
27
28/** @sa cloneQureg
29 * @ingroup deprecatedtests
30 * @author Tyson Jones
31 */
32TEST_CASE( "cloneQureg", "[state_initialisations]" ) {
33
34 Qureg vec1 = createForcedQureg(NUM_QUBITS);
35 Qureg mat1 = createForcedDensityQureg(NUM_QUBITS);
36
37 SECTION( "correctness" ) {
38
39 SECTION( "state-vector" ) {
40
41 Qureg vec2 = createForcedQureg(NUM_QUBITS);
42
43 // make sure states start differently
44 initDebugState(vec1);
45 initBlankState(vec2);
46 REQUIRE( !areEqual(vec1, vec2) );
47
48 // make sure vec2 is changed
49 QVector copy1 = toQVector(vec1);
50 cloneQureg(vec2, vec1);
51 REQUIRE( areEqual(vec1, vec2) );
52
53 // make sure vec1 unaffected
54 REQUIRE( areEqual(vec1, copy1) );
55
56 destroyQureg(vec2);
57 }
58 SECTION( "density-matrix" ) {
59
60 Qureg mat2 = createForcedDensityQureg(NUM_QUBITS);
61
62 // make sure states start differently
63 initDebugState(mat1);
64 initBlankState(mat2);
65 REQUIRE( !areEqual(mat1, mat2) );
66
67 // make sure vec2 is changed
68 QMatrix copy1 = toQMatrix(mat1);
69 cloneQureg(mat2, mat1);
70 REQUIRE( areEqual(mat1, mat2) );
71
72 // make sure vec1 unaffected
73 REQUIRE( areEqual(mat1, copy1) );
74
75 destroyQureg(mat2);
76 }
77 }
78 SECTION( "input validation" ) {
79
80 SECTION( "qureg type" ) {
81
82 REQUIRE_THROWS_WITH( cloneQureg(mat1, vec1), ContainsSubstring("must both be statevectors, or both be density matrices") );
83 REQUIRE_THROWS_WITH( cloneQureg(vec1, mat1), ContainsSubstring("must both be statevectors, or both be density matrices") );
84 }
85 SECTION( "qureg dimensions" ) {
86
87 Qureg vec3 = createForcedQureg(vec1.numQubits + 1);
88 Qureg mat3 = createForcedDensityQureg(mat1.numQubits + 1);
89
90 REQUIRE_THROWS_WITH( cloneQureg(vec1, vec3), ContainsSubstring("different number of qubits") );
91 REQUIRE_THROWS_WITH( cloneQureg(mat1, mat3), ContainsSubstring("different number of qubits") );
92
93 destroyQureg(vec3);
94 destroyQureg(mat3);
95 }
96 }
97 destroyQureg(vec1);
98 destroyQureg(mat1);
99}
100
101
102
103/** @sa initBlankState
104 * @ingroup deprecatedtests
105 * @author Tyson Jones
106 */
107TEST_CASE( "initBlankState", "[state_initialisations]" ) {
108
109 Qureg vec = createForcedQureg(NUM_QUBITS);
110 Qureg mat = createForcedDensityQureg(NUM_QUBITS);
111
112 SECTION( "correctness" ) {
113
114 SECTION( "state-vector" ) {
115
116 initBlankState(vec);
117 REQUIRE( areEqual(vec, QVector(1<<NUM_QUBITS)) );
118 }
119 SECTION( "density-matrix" ) {
120
121 initBlankState(mat);
122 REQUIRE( areEqual(mat, getZeroMatrix(1<<NUM_QUBITS)) );
123 }
124 }
125 SECTION( "input validation" ) {
126
127 // no user validation
128 SUCCEED( );
129 }
130 destroyQureg(vec);
131 destroyQureg(mat);
132}
133
134
135
136/** @sa initClassicalState
137 * @ingroup deprecatedtests
138 * @author Tyson Jones
139 */
140TEST_CASE( "initClassicalState", "[state_initialisations]" ) {
141
142 Qureg vec = createForcedQureg(NUM_QUBITS);
143 Qureg mat = createForcedDensityQureg(NUM_QUBITS);
144
145 SECTION( "correctness" ) {
146
147 int numInds = (1<<NUM_QUBITS);
148 int ind = GENERATE_COPY( range(0,numInds) );
149
150 SECTION( "state-vector" ) {
151
152 initClassicalState(vec, ind);
153 QVector vecRef = QVector(1<<NUM_QUBITS);
154 vecRef[ind] = 1;
155 REQUIRE( areEqual(vec, vecRef) );
156 }
157 SECTION( "density-matrix" ) {
158
159 initClassicalState(mat, ind);
160 QMatrix matRef = getZeroMatrix(1<<NUM_QUBITS);
161 matRef[ind][ind] = 1;
162 REQUIRE( areEqual(mat, matRef) );
163 }
164 }
165 SECTION( "input validation" ) {
166
167 SECTION( "state index" ) {
168
169 int ind = GENERATE( -1, (1<<NUM_QUBITS) );
170 REQUIRE_THROWS_WITH( initClassicalState(vec, ind), ContainsSubstring("Basis state index") );
171 }
172 }
173 destroyQureg(vec);
174 destroyQureg(mat);
175}
176
177
178
179/** @sa initPlusState
180 * @ingroup deprecatedtests
181 * @author Tyson Jones
182 */
183TEST_CASE( "initPlusState", "[state_initialisations]" ) {
184
185 Qureg vec = createForcedQureg(NUM_QUBITS);
186 Qureg mat = createForcedDensityQureg(NUM_QUBITS);
187
188 SECTION( "correctness" ) {
189
190 SECTION( "state-vector" ) {
191
192 // |+> = 1/sqrt(N^2) sum_i |i>
193 // = 1/sqrt(N^2) {1, ..., 1}
194 initPlusState(vec);
195 QVector vecRef = QVector(1<<NUM_QUBITS);
196 for (size_t i=0; i<vecRef.size(); i++)
197 vecRef[i] = 1./sqrt(pow(2,NUM_QUBITS));
198 REQUIRE( areEqual(vec, vecRef) );
199 }
200 SECTION( "density-matrix" ) {
201
202 // |+><+| = 1/sqrt(N^2) sum_i |i> 1/sqrt(N^2) sum_j <j|
203 // = 1/(N^2) sum_{ij} |i><j|
204 // = 1/(N^2) {{1, ..., 1}, ...}
205 initPlusState(mat);
206 QMatrix matRef = getZeroMatrix(1<<NUM_QUBITS);
207 for (size_t i=0; i<matRef.size(); i++)
208 for (size_t j=0; j<matRef.size(); j++)
209 matRef[i][j] = 1./pow(2, NUM_QUBITS);
210 REQUIRE( areEqual(mat, matRef) );
211 }
212 }
213 SECTION( "input validation" ) {
214
215 // no user validation
216 SUCCEED( );
217 }
218 destroyQureg(vec);
219 destroyQureg(mat);
220}
221
222
223
224/** @sa initPureState
225 * @ingroup deprecatedtests
226 * @author Tyson Jones
227 */
228TEST_CASE( "initPureState", "[state_initialisations]" ) {
229
230 Qureg vec1 = createForcedQureg(NUM_QUBITS);
231 Qureg mat1 = createForcedDensityQureg(NUM_QUBITS);
232
233 SECTION( "correctness" ) {
234
235 SECTION( "state-vector" ) {
236
237 /* state-vector version just performs cloneQureg */
238
239 Qureg vec2 = createForcedQureg(NUM_QUBITS);
240
241 // make sure states start differently
242 initDebugState(vec1);
243 initBlankState(vec2);
244 REQUIRE( !areEqual(vec1, vec2) );
245
246 // make sure vec2 is overwritten with vec1
247 QVector copy1 = toQVector(vec1);
248 initPureState(vec2, vec1);
249 REQUIRE( areEqual(vec1, vec2) );
250
251 // make sure vec1 was not modified
252 REQUIRE( areEqual(vec1, copy1) );
253
254 destroyQureg(vec2);
255 }
256 SECTION( "density-matrix" ) {
257
258 /* density matrix version initialises matrix in |pure><pure| */
259
260 initDebugState(vec1); // |vec1> = sum_i a_i |i>
261 QVector copy1 = toQVector(vec1);
262
263 // make sure mat1 is modified correctly
264 initBlankState(mat1);
265 initPureState(mat1, vec1); // mat1 = |vec1><vec1| = sum_{ij} a_i a_j* |i><j|
266
267 QMatrix matRef = getZeroMatrix(1<<NUM_QUBITS);
268 for (size_t i=0; i<matRef.size(); i++)
269 for (size_t j=0; j<matRef.size(); j++)
270 matRef[i][j] = copy1[i] * conj(copy1[j]);
271 REQUIRE( areEqual(mat1, matRef) );
272
273 // make sure vec1 was not modified
274 REQUIRE( areEqual(vec1, copy1) );
275 }
276 }
277 SECTION( "input validation" ) {
278
279 SECTION( "qureg types" ) {
280
281 // density matrix as second arg is illegal (regardless of first arg)
282 REQUIRE_THROWS_WITH( initPureState(vec1, mat1), ContainsSubstring("(the second argument) must be a statevector") );
283 REQUIRE_THROWS_WITH( initPureState(mat1, mat1), ContainsSubstring("(the second argument) must be a statevector") );
284 }
285 SECTION( "qureg dimensions" ) {
286
287 Qureg vec2 = createForcedQureg(NUM_QUBITS + 1);
288 REQUIRE_THROWS_WITH( initPureState(vec1, vec2), ContainsSubstring("differing number of qubits") );
289 REQUIRE_THROWS_WITH( initPureState(mat1, vec2), ContainsSubstring("differing number of qubits") );
290 destroyQureg(vec2);
291 }
292 }
293 destroyQureg(vec1);
294 destroyQureg(mat1);
295}
296
297
298
299/** @sa initArbitraryPureState
300 * @ingroup deprecatedtests
301 * @author Tyson Jones
302 */
303TEST_CASE( "initArbitraryPureState", "[state_initialisations]" ) {
304
305 Qureg vec = createForcedQureg(NUM_QUBITS);
306 Qureg mat = createForcedDensityQureg(NUM_QUBITS);
307
308 // create random (unnormalised) vector
309 QVector vecRef = getRandomQVector(1<<NUM_QUBITS);
310
311 SECTION( "correctness" ) {
312
313 SECTION( "state-vector" ) {
314
315 initArbitraryPureState(vec, vecRef.data());
316
317 REQUIRE( areEqual(vec, vecRef) );
318 }
319 SECTION( "density-matrix" ) {
320
321 initArbitraryPureState(mat, vecRef.data());
322
323 // matRef = |vecRef><vecRef|
324 QMatrix matRef = getZeroMatrix(vecRef.size());
325 for (size_t r=0; r<vecRef.size(); r++)
326 for (size_t c=0; c<vecRef.size(); c++)
327 matRef[r][c] = vecRef[r] * conj(vecRef[c]);
328
329 REQUIRE( areEqual(mat, matRef) );
330 }
331 }
332 destroyQureg(vec);
333 destroyQureg(mat);
334}
335
336
337
338/** @sa initZeroState
339 * @ingroup deprecatedtests
340 * @author Tyson Jones
341 */
342TEST_CASE( "initZeroState", "[state_initialisations]" ) {
343
344 Qureg vec = createForcedQureg(NUM_QUBITS);
345 Qureg mat = createForcedDensityQureg(NUM_QUBITS);
346
347 SECTION( "correctness" ) {
348
349 SECTION( "state-vector" ) {
350
351 initBlankState(vec);
352 initZeroState(vec);
353
354 QVector refVec = QVector(vec.numAmps);
355 refVec[0] = 1;
356 REQUIRE( areEqual(vec, refVec) );
357 }
358 SECTION( "density-matrix" ) {
359
360 initBlankState(mat);
361 initZeroState(mat);
362
363 QMatrix refMat = getZeroMatrix(1<<mat.numQubits);
364 refMat[0][0] = 1;
365 REQUIRE( areEqual(mat, refMat) );
366 }
367 }
368 SECTION( "input validation" ) {
369
370 // no input validation
371 SUCCEED( );
372 }
373 destroyQureg(vec);
374 destroyQureg(mat);
375}
376
377
378
379/** @sa setAmps
380 * @ingroup deprecatedtests
381 * @author Tyson Jones
382 */
383TEST_CASE( "setQuregAmps", "[state_initialisations]" ) {
384
385 Qureg vec = createForcedQureg(NUM_QUBITS);
386
387 int maxInd = vec.numAmps;
388 QVector amps = getRandomQVector(maxInd);
389
390 SECTION( "correctness" ) {
391
392 SECTION( "state-vector" ) {
393
394 // all valid number of amplitudes and offsets
395 int startInd = GENERATE_COPY( range(0,maxInd) );
396 int numAmps = GENERATE_COPY( range(0,1+maxInd-startInd) ); // upper-bound allows all amps specified
397
398 // check both specified and un-specified amplitudes are correctly handled
399 initDebugState(vec);
400 QVector vecRef = toQVector(vec);
401
402 setQuregAmps(vec, startInd, amps.data(), numAmps);
403 for (int i=0; i<numAmps; i++)
404 vecRef[startInd+i] = amps[i];
405
406 REQUIRE( areEqual(vec, vecRef) );
407 }
408 }
409 SECTION( "input validation" ) {
410
411 SECTION( "start index" ) {
412
413 int startInd = GENERATE_COPY( -1, maxInd );
414 int numAmps = 0;
415 REQUIRE_THROWS_WITH( setQuregAmps(vec, startInd, amps.data(), numAmps), ContainsSubstring("starting basis state index") );
416 }
417
418 SECTION( "number of amplitudes" ) {
419
420 // independent
421 int startInd = 0;
422 int numAmps = GENERATE_COPY( -1, maxInd+1 );
423 REQUIRE_THROWS_WITH( setQuregAmps(vec, startInd, amps.data(), numAmps), ContainsSubstring("number of amplitudes") );
424
425 // invalid considering start-index
426 startInd = maxInd - 1;
427 numAmps = 2;
428 REQUIRE_THROWS_WITH( setQuregAmps(vec, startInd, amps.data(), numAmps), ContainsSubstring("implies an end index") );
429 }
430 SECTION( "density-matrix" ) {
431
432 Qureg mat = createForcedDensityQureg(NUM_QUBITS);
433 REQUIRE_THROWS_WITH( setQuregAmps(mat, 0, amps.data(), 0), ContainsSubstring("Expected a statevector Qureg but received a density matrix") );
434 destroyQureg(mat);
435 }
436 }
437 destroyQureg(vec);
438}
439
440
441
442// setDensityAmps removed because replacement setDensityQuregAmps
443// has an incompatible signature (accepting qcomps directly). Note
444// I do not know why we updated setQuregAmps above to the v4 API :)
445
446 // /** @sa setDensityAmps
447 // * @ingroup deprecatedtests
448 // * @author Tyson Jones
449 // */
450 // TEST_CASE( "setDensityAmps", "[state_initialisations]" ) {
451
452 // Qureg matr = createForcedDensityQureg(NUM_QUBITS);
453 // QVector amps = getRandomQVector(matr.numAmps);
454 // int maxInd = (1 << NUM_QUBITS);
455
456 // SECTION( "correctness" ) {
457
458 // SECTION( "density-matrix" ) {
459
460 // // try all valid number of amplitudes and offsets
461 // int startRow = GENERATE_COPY( range(0,maxInd) );
462 // int startCol = GENERATE_COPY( range(0,maxInd) );
463
464 // // determine the max number of amps that can be passed from the given start indices
465 // int numPriorAmps = startRow + startCol*(1 << matr.numQubits);
466 // int maxNumAmps = matr.numAmps - numPriorAmps;
467
468 // // previously, we tried all possible number of amps, like so:
469 // // int numAmps = GENERATE_COPY( range(0,maxNumAmps) ); // upper-bound allows all amps specified
470 // // but this is too many and causes a timeout on Ubuntu.
471 // // So we instead randomly choose the number of amps, and repeat 10 times.
472 // int numAmps = getRandomInt(0, maxNumAmps);
473 // GENERATE_COPY( range(0,10) );
474
475 // // check both specified and un-specified amplitudes are correctly handled
476 // initDebugState(matr);
477 // QMatrix matrRef = toQMatrix(matr);
478
479 // setDensityQuregAmps(matr, startRow, startCol, reals, imags, numAmps);
480
481 // int r=startRow;
482 // int c=startCol;
483 // for (int i=0; i<numAmps; i++) {
484 // qcomp amp = reals[i] + imags[i] * (qcomp) 1i;
485 // matrRef[r][c] = amp;
486
487 // r++;
488 // if (r >= maxInd ) {
489 // r=0;
490 // c++;
491 // }
492 // }
493
494 // REQUIRE( areEqual(matr, matrRef) );
495 // }
496 // }
497 // SECTION( "input validation" ) {
498
499 // SECTION( "start index" ) {
500
501 // int badInd = GENERATE_COPY( -1, maxInd );
502 // int numAmps = 0;
503 // REQUIRE_THROWS_WITH( setDensityAmps(matr, badInd, 0, reals, imags, numAmps), ContainsSubstring("Invalid amplitude index") );
504 // REQUIRE_THROWS_WITH( setDensityAmps(matr, 0, badInd, reals, imags, numAmps), ContainsSubstring("Invalid amplitude index") );
505 // }
506 // SECTION( "number of amplitudes" ) {
507
508 // // independent
509 // int numAmps = GENERATE_COPY( -1, matr.numAmps+1 );
510 // REQUIRE_THROWS_WITH( setDensityAmps(matr, 0, 0, reals, imags, numAmps), ContainsSubstring("Invalid number of amplitudes") );
511
512 // // invalid considering start-index
513 // REQUIRE_THROWS_WITH( setDensityAmps(matr, maxInd-1, maxInd-1, reals, imags, 2), ContainsSubstring("More amplitudes given than exist") );
514 // REQUIRE_THROWS_WITH( setDensityAmps(matr, maxInd-1, maxInd-2, reals, imags, maxInd+2), ContainsSubstring("More amplitudes given than exist") );
515 // }
516 // SECTION( "state-vector" ) {
517
518 // Qureg vec = createForcedQureg(NUM_QUBITS);
519 // REQUIRE_THROWS_WITH( setDensityAmps(vec, 0, 0, reals, imags, 0), ContainsSubstring("valid only for density matrices") );
520 // destroyQureg(vec);
521 // }
522 // }
523 // destroyQureg(matr);
524 // }
525
526
527
528// setQuregToPauliHamil removed because replacement setQuregToPauliStrSum
529// accepts new type PauliStrSum which has an initialiser incompatible
530// with the deprecated PauliHamil type
531
532 // /** @sa setQuregToPauliHamil
533 // * @ingroup deprecatedtests
534 // * @author Tyson Jones
535 // */
536 // TEST_CASE( "setQuregToPauliHamil", "[state_initialisations]" ) {
537
538 // Qureg rho = createForcedDensityQureg(NUM_QUBITS);
539
540 // SECTION( "correctness" ) {
541
542 // // too expensive to enumerate all paulis, so try 10x with random ones
543 // GENERATE( range(0,10) );
544
545 // int numTerms = GENERATE( 1, 2, 10, 15, 100, 1000 );
546 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
547 // setRandomPauliSum(hamil);
548
549 // setQuregToPauliHamil(rho, hamil);
550 // REQUIRE( areEqual(rho, toQMatrix(hamil)) );
551
552 // destroyPauliHamil(hamil);
553 // }
554 // SECTION( "input validation" ) {
555
556 // SECTION( "density-matrix" ) {
557
558 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, 5);
559 // Qureg vec = createForcedQureg(NUM_QUBITS);
560
561 // REQUIRE_THROWS_WITH( setQuregToPauliHamil(vec, hamil), ContainsSubstring("density matrices") );
562
563 // destroyQureg(vec);
564 // destroyPauliHamil(hamil);
565 // }
566 // SECTION( "pauli codes" ) {
567
568 // int numTerms = 3;
569 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
570
571 // // make one pauli code wrong
572 // hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
573 // REQUIRE_THROWS_WITH( setQuregToPauliHamil(rho, hamil), ContainsSubstring("Invalid Pauli code") );
574
575 // destroyPauliHamil(hamil);
576 // }
577 // SECTION( "matching hamiltonian qubits" ) {
578
579 // int numTerms = 1;
580 // PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, numTerms);
581
582 // REQUIRE_THROWS_WITH( setQuregToPauliHamil(rho, hamil), ContainsSubstring("same number of qubits") );
583
584 // destroyPauliHamil(hamil);
585 // }
586 // }
587 // destroyQureg(rho);
588 // }
589
590
591
592/** @sa setWeightedQureg
593 * @ingroup deprecatedtests
594 * @author Tyson Jones
595 */
596TEST_CASE( "setWeightedQureg", "[state_initialisations]" ) {
597
598 SECTION( "correctness" ) {
599
600 // repeat each test below 10 times
601 GENERATE( range(0,10) );
602
603 /* note tolerance in areEqual increases with tests, since
604 * small differences propogate in vecC which is not re-initialised
605 */
606
607 SECTION( "state-vector" ) {
608
609 // make three random vectors
610 Qureg vecA = createForcedQureg(NUM_QUBITS);
611 Qureg vecB = createForcedQureg(NUM_QUBITS);
612 Qureg vecC = createForcedQureg(NUM_QUBITS);
613 for (int j=0; j<vecA.numAmpsPerNode; j++) {
614 vecA.cpuAmps[j] = getRandomComplex();
615 vecB.cpuAmps[j] = getRandomComplex();
616 vecC.cpuAmps[j] = getRandomComplex();
617 }
618 copyStateToGPU(vecA); copyStateToGPU(vecB); copyStateToGPU(vecC);
619 QVector refA = toQVector(vecA);
620 QVector refB = toQVector(vecB);
621 QVector refC = toQVector(vecC);
622 QVector refOut;
623
624 // get three random factors
625 qcomp numA = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
626 qcomp numB = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
627 qcomp numC = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
628 Complex facA; facA.real = real(numA); facA.imag = imag(numA);
629 Complex facB; facB.real = real(numB); facB.imag = imag(numB);
630 Complex facC; facC.real = real(numC); facC.imag = imag(numC);
631
632 // check out-qureg is correct, when all quregs are unique...
633 setWeightedQureg(facA, vecA, facB, vecB, facC, vecC);
634 refOut = numA*refA + numB*refB + numC*refC;
635 REQUIRE( areEqual(vecC, refOut) );
636
637 // ... and that other qureg's aren't modified
638 REQUIRE( areEqual(vecA, refA) );
639 REQUIRE( areEqual(vecB, refB) );
640
641 // check quregOut correct, when it's also qureg2
642 refC = toQVector(vecC);
643 setWeightedQureg(facB, vecB, facC, vecC, facA, vecC);
644 refOut = numB*refB + numC*refC + numA*refC;
645 REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
646
647 // ... and that the remaining qureg is not modified
648 REQUIRE( areEqual(vecB, refB) );
649
650 // check quregOut correct, when it's also qureg1
651 refC = toQVector(vecC);
652 setWeightedQureg(facC, vecC, facB, vecB, facA, vecC);
653 refOut = numC*refC + numB*refB + numA*refC;
654 REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
655
656 // ... and that the remaining qureg is not modified
657 REQUIRE( areEqual(vecB, refB) );
658
659 // check quregOut is correct when it's both input quregs
660 refC = toQVector(vecC);
661 setWeightedQureg(facA, vecC, facB, vecC, facC, vecC);
662 refOut = numA*refC + numB*refC + numC*refC;
663 REQUIRE( areEqual(vecC, refOut, 1E3*REAL_EPS) );
664
665 // cleanup
666 destroyQureg(vecA);
667 destroyQureg(vecB);
668 destroyQureg(vecC);
669 }
670
671 // v4 does not permit superposing of density matrices
672
673 // SECTION( "density-matrix" ) {
674
675 // // make three random matrices
676 // Qureg matA = createForcedDensityQureg(NUM_QUBITS);
677 // Qureg matB = createForcedDensityQureg(NUM_QUBITS);
678 // Qureg matC = createForcedDensityQureg(NUM_QUBITS);
679 // for (int j=0; j<matA.numAmpsPerNode; j++) {
680 // matA.cpuAmps[j] = getRandomComplex();
681 // matB.cpuAmps[j] = getRandomComplex();
682 // matC.cpuAmps[j] = getRandomComplex();
683 // }
684 // copyStateToGPU(matA); copyStateToGPU(matB); copyStateToGPU(matC);
685 // QMatrix refA = toQMatrix(matA);
686 // QMatrix refB = toQMatrix(matB);
687 // QMatrix refC = toQMatrix(matC);
688 // QMatrix refOut;
689
690 // // get three random factors
691 // qcomp numA = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
692 // qcomp numB = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
693 // qcomp numC = getRandomReal(-5,5) + getRandomReal(-5,5) * (qcomp) 1i;
694 // Complex facA; facA.real = real(numA); facA.imag = imag(numA);
695 // Complex facB; facB.real = real(numB); facB.imag = imag(numB);
696 // Complex facC; facC.real = real(numC); facC.imag = imag(numC);
697
698 // // check out-qureg is correct, when all quregs are unique...
699 // setWeightedQureg(facA, matA, facB, matB, facC, matC);
700 // refOut = numA*refA + numB*refB + numC*refC;
701 // REQUIRE( areEqual(matC, refOut) );
702
703 // // ... and that other qureg's aren't modified
704 // REQUIRE( areEqual(matA, refA) );
705 // REQUIRE( areEqual(matB, refB) );
706
707 // // check quregOut correct, when it's also qureg2
708 // refC = toQMatrix(matC);
709 // setWeightedQureg(facB, matB, facC, matC, facA, matC);
710 // refOut = numB*refB + numC*refC + numA*refC;
711 // REQUIRE( areEqual(matC, refOut, 10*REAL_EPS) );
712
713 // // ... and that the remaining qureg is not modified
714 // REQUIRE( areEqual(matB, refB) );
715
716 // // check quregOut correct, when it's also qureg1
717 // refC = toQMatrix(matC);
718 // setWeightedQureg(facC, matC, facB, matB, facA, matC);
719 // refOut = numC*refC + numB*refB + numA*refC;
720 // REQUIRE( areEqual(matC, refOut, 1E2*REAL_EPS) );
721
722 // // ... and that the remaining qureg is not modified
723 // REQUIRE( areEqual(matB, refB) );
724
725 // // check quregOut is correct when it's both input quregs
726 // refC = toQMatrix(matC);
727 // setWeightedQureg(facA, matC, facB, matC, facC, matC);
728 // refOut = numA*refC + numB*refC + numC*refC;
729 // REQUIRE( areEqual(matC, refOut, 1E3*REAL_EPS) );
730
731 // // cleanup
732 // destroyQureg(matA);
733 // destroyQureg(matB);
734 // destroyQureg(matC);
735 // }
736 }
737 SECTION( "input validation" ) {
738
739 SECTION( "qureg types" ) {
740
741 Qureg vec = createForcedQureg(NUM_QUBITS);
742 Qureg mat = createForcedDensityQureg(NUM_QUBITS);
743 Complex f; f.real = 0; f.imag = 0;
744
745 // two state-vecs, one density-matrix
746 REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, vec), ContainsSubstring("Cannot superpose a density matrix. All quregs must be statevectors") );
747 REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, vec), ContainsSubstring("Cannot superpose a density matrix. All quregs must be statevectors") );
748 REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, vec, f, mat), ContainsSubstring("Cannot superpose a density matrix. All quregs must be statevectors") );
749
750 // one state-vec, two density-matrices
751 REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, mat), ContainsSubstring("Cannot superpose a density matrix. All quregs must be statevectors") );
752 REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, mat), ContainsSubstring("Cannot superpose a density matrix. All quregs must be statevectors") );
753 REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, mat, f, vec), ContainsSubstring("Cannot superpose a density matrix. All quregs must be statevectors") );
754
755 destroyQureg(vec);
756 destroyQureg(mat);
757 }
758 SECTION( "qureg dimensions" ) {
759
760 Qureg vecA = createForcedQureg(NUM_QUBITS);
761 Qureg vecB = createForcedQureg(NUM_QUBITS + 1);
762 Qureg matA = createForcedDensityQureg(NUM_QUBITS);
763 Qureg matB = createForcedDensityQureg(NUM_QUBITS + 1);
764 Complex f; f.real = 0; f.imag = 0;
765
766 // state-vecs
767 REQUIRE_THROWS_WITH( setWeightedQureg(f, vecA, f, vecB, f, vecB), ContainsSubstring("differing numbers of qubits") );
768 REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecA, f, vecB), ContainsSubstring("differing numbers of qubits") );
769 REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecB, f, vecA), ContainsSubstring("differing numbers of qubits") );
770
771 // v4 does not permit superposing density matrices
772
773 // // density-matrices
774 // REQUIRE_THROWS_WITH( setWeightedQureg(f, matA, f, matB, f, matB), ContainsSubstring("differing numbers of qubits") );
775 // REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matA, f, matB), ContainsSubstring("differing numbers of qubits") );
776 // REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matB, f, matA), ContainsSubstring("differing numbers of qubits") );
777
778 destroyQureg(vecA);
779 destroyQureg(vecB);
780 destroyQureg(matA);
781 destroyQureg(matB);
782 }
783 }
784}
TEST_CASE("cloneQureg", "[state_initialisations]")
QVector getRandomQVector(int dim)
bool areEqual(QVector a, QVector b)
vector< vector< qcomp > > QMatrix
QMatrix toQMatrix(CompMatr1 src)
vector< qcomp > QVector
QVector toQVector(Qureg qureg)
void setQuregAmps(Qureg qureg, qindex startInd, qcomp *amps, qindex numAmps)
void initArbitraryPureState(Qureg qureg, qcomp *amps)
void initPlusState(Qureg qureg)
void initZeroState(Qureg qureg)
void initPureState(Qureg qureg, Qureg pure)
void initDebugState(Qureg qureg)
void initClassicalState(Qureg qureg, qindex stateInd)
void initBlankState(Qureg qureg)
Qureg createForcedQureg(int numQubits)
Definition qureg.cpp:293
Qureg createForcedDensityQureg(int numQubits)
Definition qureg.cpp:303
void destroyQureg(Qureg qureg)
Definition qureg.cpp:328
qmatrix getZeroMatrix(size_t dim)
Definition qmatrix.cpp:18
qcomp getRandomComplex()
Definition random.cpp:85
qreal getRandomReal(qreal min, qreal maxIncl)
Definition random.cpp:60
Definition qureg.h:42