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