The Quantum Exact Simulation Toolkit v4.2.0
Loading...
Searching...
No Matches
calculations.cpp
1/** @file
2 * Unit tests of the calculations module.
3 *
4 * @author Tyson Jones
5 *
6 * @defgroup unitcalcs Calculations
7 * @ingroup unittests
8 */
9
10#include "quest.h"
11
12#include <catch2/catch_test_macros.hpp>
13#include <catch2/generators/catch_generators_range.hpp>
14#include <catch2/matchers/catch_matchers_string.hpp>
15#include <catch2/matchers/catch_matchers_floating_point.hpp>
16
17#include "tests/utils/qvector.hpp"
18#include "tests/utils/qmatrix.hpp"
19#include "tests/utils/compare.hpp"
20#include "tests/utils/convert.hpp"
21#include "tests/utils/evolve.hpp"
22#include "tests/utils/linalg.hpp"
23#include "tests/utils/lists.hpp"
24#include "tests/utils/macros.hpp"
25#include "tests/utils/random.hpp"
26#include "tests/utils/config.hpp"
27#include "tests/utils/cache.hpp"
28#include "tests/utils/measure.hpp"
29
30#include <vector>
31#include <algorithm>
32#include <type_traits>
33
34using Catch::Matchers::ContainsSubstring;
35using std::vector;
36
37
38
39/*
40 * UTILITIES
41 */
42
43
44#define TEST_CATEGORY \
45 LABEL_UNIT_TAG "[calculations]"
46
47
48void TEST_ON_CACHED_QUREGS(quregCache cache, auto refState, auto apiFunc, auto refFunc) {
49
50 for (auto& [label, qureg]: cache) {
51
52 DYNAMIC_SECTION( label ) {
53
54 // we initialise to a valid pure or mixed state, rather than the
55 // debug state, since many API functions validate the output domain
56 // which is often invalid for unnormalised states
57 setToRandomState(refState);
58 setQuregToReference(qureg, refState);
59
60 /// @todo
61 /// validate that above is correct, i.e. not the all-zero
62 /// state, which would permit flawed tests to succeed
63
64 // results can be a scalar, a vector, or even a Qureg & qmatrix/qvector
65 auto apiResult = apiFunc(qureg);
66 auto refResult = refFunc(refState);
67 REQUIRE_AGREE( apiResult, refResult );
68
69 // free API result if it is a newly created Qureg
70 if constexpr (std::is_same_v<decltype(apiResult),Qureg>)
71 destroyQureg(apiResult);
72 }
73 }
74}
75
76void TEST_ON_CACHED_STATEVECS_AND_DENSMATRS(auto apiFunc, auto refFunc) {
77 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), getRefStatevec(), apiFunc, refFunc); }
78 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), getRefDensmatr(), apiFunc, refFunc); }
79}
80
81#define TEST_ALL_QUREGS( quregVar, apiExpr, stateVar, refExpr ) \
82 TEST_ON_CACHED_STATEVECS_AND_DENSMATRS( \
83 [&](Qureg quregVar) { return apiExpr; }, \
84 [&](auto& stateVar) { return refExpr; } ) \
85
86
87void TEST_ON_MIXED_CACHED_QUREGS(quregCache cacheA, quregCache cacheB, auto refA, auto refB, auto apiFunc, auto refFunc) {
88
89 // test all combinations of deployments (where cacheA != cacheB)
90
91 for (auto& [labelA, quregA]: cacheA) {
92 for (auto& [labelB, quregB]: cacheB) {
93
94 // skip illegal (local densitymatrix, distributed statevector) combo
95 if (quregA.isDensityMatrix != quregB.isDensityMatrix && // (sv,dm) or (dm,sv)
96 quregA.isDistributed != quregB.isDistributed && // differing distributions
97 quregA.isDistributed == quregB.isDensityMatrix) // dm.dist=0
98 continue;
99
100 // skip illegal same-size different-GPU-accel combo
101 if (quregA.isDensityMatrix == quregB.isDensityMatrix && // (sv,sv) or (dm,dm)
102 quregA.isGpuAccelerated != quregB.isGpuAccelerated) // differing GPU-accel
103 continue;
104
105 DYNAMIC_SECTION( labelA + LABEL_DELIMITER + labelB ) {
106
107 // initialise to random states (rather than debug) since
108 // tested function will likely validate output domain
109 setToRandomState(refA); setQuregToReference(quregA, refA);
110 setToRandomState(refB); setQuregToReference(quregB, refB);
111
112 // results will always be a scalar
113 auto apiResult = apiFunc(quregA, quregB);
114 auto refResult = refFunc(refA, refB);
115 REQUIRE_AGREE( apiResult, refResult );
116 }
117 }
118 }
119}
120
121
122void TEST_ON_CACHED_QUREG_AND_MATRIX(quregCache quregs, matrixCache matrices, auto apiFunc, auto refState, auto refMatr, auto refFunc) {
123
124 // test all combinations of deployments (where cacheA != cacheB)
125
126 for (auto& [labelA, qureg]: quregs) {
127 for (auto& [labelB, matrix]: matrices) {
128
129 // all combinations are legal; none are skipped!
130
131 DYNAMIC_SECTION( labelA + LABEL_DELIMITER + labelB ) {
132
133 // set API matrix to pre-initialised reference matrix
134 setFullStateDiagMatr(matrix, 0, getDiagonals(refMatr));
135
136 // initialise to random states (rather than debug) since
137 // tested function will likely validate output domain
138 setToRandomState(refState);
139 setQuregToReference(qureg, refState);
140
141 // results will always be a scalar
142 auto apiResult = apiFunc(qureg, matrix);
143 auto refResult = refFunc(refState, refMatr);
144 REQUIRE_AGREE( apiResult, refResult );
145 }
146 }
147 }
148}
149
150
151
152/**
153 * TESTS
154 *
155 * @ingroup unitcalcs
156 * @{
157 */
158
159
160
161TEST_CASE( "calcExpecPauliStr", TEST_CATEGORY ) {
162
163 SECTION( LABEL_CORRECTNESS ) {
164
165 int numQubits = getNumCachedQubits();
166 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
167 auto targets = GENERATE_TARGS(numQubits, numTargs);
168
169 PauliStr str = getRandomPauliStr(targets);
170
171 TEST_ALL_QUREGS(
172 qureg, calcExpecPauliStr(qureg, str),
173 state, std::real(getReferenceExpectationValue(state, str))
174 );
175 }
176
177 /// @todo input validation
178}
179
180
181
182TEST_CASE( "calcExpecPauliStrSum", TEST_CATEGORY ) {
183
184 SECTION( LABEL_CORRECTNESS ) {
185
186 int numQubits = getNumCachedQubits();
187 int numTerms = GENERATE_COPY( 1, numQubits, getPow2(2*numQubits) );
188
189 GENERATE( range(0,10) );
190 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
191
192 TEST_ALL_QUREGS(
193 qureg, calcExpecPauliStrSum(qureg, sum),
194 state, std::real(getReferenceExpectationValue(state, sum))
195 );
196
198 }
199
200 /// @todo input validation
201}
202
203
204
205TEST_CASE( "calcExpecNonHermitianPauliStrSum", TEST_CATEGORY ) {
206
207 SECTION( LABEL_CORRECTNESS ) {
208
209 GENERATE( range(0,10) );
210 int numQubits = getNumCachedQubits();
211 int numTerms = GENERATE_COPY( 1, numQubits, getPow2(2*numQubits) );
212
213 PauliStrSum sum = createRandomNonHermitianPauliStrSum(numQubits, numTerms);
214
215 TEST_ALL_QUREGS(
216 qureg, calcExpecNonHermitianPauliStrSum(qureg, sum),
217 state, getReferenceExpectationValue(state, sum)
218 );
219
221 }
222
223 /// @todo input validation
224}
225
226
227
228TEST_CASE( "calcProbOfBasisState", TEST_CATEGORY ) {
229
230 SECTION( LABEL_CORRECTNESS ) {
231
232 qindex index = GENERATE( range(0, 1 << getNumCachedQubits()) );
233
234 TEST_ALL_QUREGS(
235 qureg, calcProbOfBasisState(qureg, index),
236 state, getReferenceProbability(state, index)
237 );
238 }
239
240 /// @todo input validation
241}
242
243
244
245TEST_CASE( "calcProbOfQubitOutcome", TEST_CATEGORY ) {
246
247 SECTION( LABEL_CORRECTNESS ) {
248
249 int target = GENERATE( range(0, getNumCachedQubits()) );
250 int outcome = GENERATE( 0, 1 );
251
252 TEST_ALL_QUREGS(
253 qureg, calcProbOfQubitOutcome(qureg, target, outcome),
254 state, getReferenceProbability(state, {target}, {outcome})
255 );
256 }
257
258 /// @todo input validation
259}
260
261
262
263TEST_CASE( "calcProbOfMultiQubitOutcome", TEST_CATEGORY ) {
264
265 SECTION( LABEL_CORRECTNESS ) {
266
267 int numQubits = getNumCachedQubits();
268 int numTargs = GENERATE_COPY( range(1, numQubits+1) );
269 auto targets = GENERATE_TARGS(numQubits, numTargs);
270 auto outcomes = getRandomOutcomes(numTargs);
271
272 TEST_ALL_QUREGS(
273 qureg, calcProbOfMultiQubitOutcome(qureg, targets.data(), outcomes.data(), numTargs),
274 state, getReferenceProbability(state, targets, outcomes)
275 );
276 }
277
278 /// @todo input validation
279}
280
281
282
283TEST_CASE( "calcProbsOfAllMultiQubitOutcomes", TEST_CATEGORY ) {
284
285 SECTION( LABEL_CORRECTNESS ) {
286
287 int numQubits = getNumCachedQubits();
288 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
289 auto targets = GENERATE_TARGS(numQubits, numTargs);
290
291 auto apiFunc = [&](Qureg qureg) {
292 vector<qreal> out(getPow2(numTargs));
293 calcProbsOfAllMultiQubitOutcomes(out.data(), qureg, targets.data(), numTargs);
294 return out;
295 };
296 auto refFunc = [&](auto& state) {
297 return getAllReferenceProbabilities(state, targets);
298 };
299
300 TEST_ON_CACHED_STATEVECS_AND_DENSMATRS( apiFunc, refFunc );
301 }
302
303 /// @todo input validation
304}
305
306
307
308TEST_CASE( "calcTotalProb", TEST_CATEGORY ) {
309
310 SECTION( LABEL_CORRECTNESS ) {
311
312 GENERATE( range(0,100) );
313
314 TEST_ALL_QUREGS(
315 qureg, calcTotalProb(qureg),
316 state, getReferenceProbability(state)
317 );
318 }
319
320 /// @todo input validation
321}
322
323
324
325TEST_CASE( "calcPurity", TEST_CATEGORY ) {
326
327 SECTION( LABEL_CORRECTNESS ) {
328
329 GENERATE( range(0,100) );
330
331 TEST_ALL_QUREGS(
332 qureg, calcPurity(qureg),
333 state, getReferencePurity(state)
334 );
335 }
336
337 /// @todo input validation
338}
339
340
341
342/// @private
343int getMaxNumTracedQubits(int numQubits) {
344
345 // cannot reduce all qubits, nor so many that the final qureg is
346 // illegally distributed (which we enforce even upon the testsed
347 // non-distributed Quregs for simplicity)
348
349 return std::min(
350 numQubits - 1,
351 numQubits - getLog2(getQuESTEnv().numNodes));
352}
353
354
355TEST_CASE( "calcPartialTrace", TEST_CATEGORY ) {
356
357 // no statevector equivalent
358
359 SECTION( LABEL_CORRECTNESS ) {
360
361 SECTION( LABEL_DENSMATR ) {
362
363 int numQubits = getNumCachedQubits();
364 int maxNumTargs = getMaxNumTracedQubits(numQubits);
365 int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
366 auto targets = GENERATE_TARGS(numQubits, numTargs);
367
368 auto apiFunc = [&](Qureg qureg) { return calcPartialTrace(qureg, targets.data(), numTargs); };
369 auto refFunc = [&](qmatrix ref) { return getPartialTrace(ref, targets); };
370
371 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), getRefDensmatr(), apiFunc, refFunc);
372 }
373 }
374
375 /// @todo input validation
376}
377
378
379
380TEST_CASE( "calcReducedDensityMatrix", TEST_CATEGORY ) {
381
382 // no statevector equivalent
383
384 SECTION( LABEL_CORRECTNESS ) {
385
386 SECTION( LABEL_DENSMATR ) {
387
388 int numQubits = getNumCachedQubits();
389 int maxNumTraced = getMaxNumTracedQubits(numQubits);
390 int minNumRetained = numQubits - maxNumTraced;
391 int maxNumRetained = numQubits - 1;
392 int numRetained = GENERATE_COPY( range(minNumRetained, maxNumRetained+1) );
393 auto retains = GENERATE_TARGS(numQubits, numRetained);
394 auto targets = getComplement(getRange(numQubits), retains);
395
396 auto apiFunc = [&](Qureg qureg) { return calcReducedDensityMatrix(qureg, retains.data(), numRetained); };
397 auto refFunc = [&](qmatrix ref) { return getPartialTrace(ref, targets); };
398
399 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), getRefDensmatr(), apiFunc, refFunc);
400 }
401 }
402
403 /// @todo input validation
404}
405
406
407
408TEST_CASE( "calcInnerProduct", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
409
410 SECTION( LABEL_CORRECTNESS ) {
411
412 qvector refSV = getRefStatevec();
413 qmatrix refDM = getRefDensmatr();
414 auto apiFunc = calcInnerProduct;
415
416 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
417
418 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
419
420 // <a|b>
421 auto refFunc = [&](qvector a, qvector b) { return getInnerProduct (a,b); };
422
423 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc );
424 }
425
426 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
427
428 // <A|B|A>
429 auto refFunc = [&](qvector a, qmatrix b) { return getInnerProduct(a, b * a); };
430
431 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
432 }
433
434 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
435
436 // <B|A^dagger|B>
437
438 auto refFunc = [&](qmatrix a, qvector b) { return getInnerProduct(b, getConjugateTranspose(a) * b); };
439
440 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
441 }
442
443 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_DENSMATR ) {
444
445 // Tr(a^dagger b)
446 auto refFunc = [&](qmatrix a, qmatrix b) { return getTrace(getConjugateTranspose(a) * b); };
447
448 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedDensmatrs(), refDM, refDM, apiFunc, refFunc );
449 }
450 }
451
452 /// @todo input validation
453}
454
455
456
457TEST_CASE( "calcFidelity", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
458
459 SECTION( LABEL_CORRECTNESS ) {
460
461 qvector refSV = getRefStatevec();
462 qmatrix refDM = getRefDensmatr();
463 auto apiFunc = calcFidelity;
464
465 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
466
467 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
468
469 // |<a|b>|^2
470 auto refFunc = [&](qvector a, qvector b) { return std::norm(getInnerProduct(a,b)); };
471
472 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc );
473 }
474
475 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
476
477 // Re[<A|B|A>]
478 auto refFunc = [&](qvector a, qmatrix b) { return std::real(getInnerProduct(a, b * a)); };
479
480 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
481 }
482
483 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
484
485 // Re[<B|A|B>]
486 auto refFunc = [&](qmatrix a, qvector b) { return std::real(getInnerProduct(b, a * b)); };
487
488 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
489 }
490
491 // (densitymatrix, densitymatrix) not supported
492 }
493
494 /// @todo input validation
495}
496
497
498
499TEST_CASE( "calcDistance", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
500
501 SECTION( LABEL_CORRECTNESS ) {
502
503 qvector refSV = getRefStatevec();
504 qmatrix refDM = getRefDensmatr();
505 auto apiFunc = calcDistance;
506
507 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
508
509 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
510
511 // sqrt(2 - 2 |<A|B>|)
512 auto refFunc = [&](qvector a, qvector b) { return std::sqrt(2 - 2 * std::abs(getInnerProduct(a,b))); };
513
514 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc);
515 }
516
517 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
518
519 // sqrt(1 - <psi|rho|psi>)
520 auto refFunc = [&](qvector a, qmatrix b) { return std::sqrt(1 - std::real(getInnerProduct(a, b * a))); };
521
522 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
523 }
524
525 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
526
527 // sqrt(1 - <psi|rho|psi>)
528 auto refFunc = [&](qmatrix a, qvector b) { return std::sqrt(1 - std::real(getInnerProduct(b, a * b))); };
529
530 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
531 }
532
533 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_DENSMATR ) {
534
535 // sqrt(Tr((A-B)(A-B)^dagger)
536 auto refFunc = [&](qmatrix a, qmatrix b) { return std::sqrt(std::real(getTrace((a-b)*getConjugateTranspose(a-b)))); };
537
538 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedDensmatrs(), refDM, refDM, apiFunc, refFunc );
539 }
540 }
541
542 /// @todo input validation
543}
544
545
546
547TEST_CASE( "calcExpecFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
548
549 SECTION( LABEL_CORRECTNESS ) {
550
551 qmatrix refMatr = getRandomDiagonalHermitian(getNumCachedQubits());
552 auto apiFunc = calcExpecFullStateDiagMatr;
553
554 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
555
556 SECTION( LABEL_STATEVEC ) {
557
558 auto refFunc = [&] (qvector state, qmatrix matr) { return getReferenceExpectationValue(state, matr); };
559
560 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
561 }
562
563 SECTION( LABEL_DENSMATR ) {
564
565 auto refFunc = [&] (qmatrix state, qmatrix matr) { return getReferenceExpectationValue(state, matr); };
566
567 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
568 }
569 }
570
571 /// @todo input validation
572}
573
574
575
576TEST_CASE( "calcExpecNonHermitianFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
577
578 SECTION( LABEL_CORRECTNESS ) {
579
580 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(getNumCachedQubits()));
582
583 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
584
585 SECTION( LABEL_STATEVEC ) {
586
587 auto refFunc = [&] (qvector state, qmatrix matr) { return getReferenceExpectationValue(state, matr); };
588
589 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
590 }
591
592 SECTION( LABEL_DENSMATR ) {
593
594 auto refFunc = [&] (qmatrix state, qmatrix matr) { return getReferenceExpectationValue(state, matr); };
595
596 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
597 }
598 }
599
600 /// @todo input validation
601}
602
603
604
605TEST_CASE( "calcExpecFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
606
607 SECTION( LABEL_CORRECTNESS ) {
608
609 qmatrix refMatr = getRandomDiagonalHermitian(getNumCachedQubits());
610
611 // integer and non-integer exponents have different requirements
612 bool isIntegerExp = GENERATE( true, false );
613 qreal exponent = (isIntegerExp)?
614 getRandomInt(-3, 3):
615 getRandomReal(-3, 3);
616
617 // when exponent is non-integer, the matrix cannot contain negative
618 // numbers which otherwise become complex, making the matrix non-
619 // Hermitian and triggering validation
620 if (!isIntegerExp)
621 for (size_t i=0; i<refMatr.size(); i++)
622 refMatr[i][i] = std::abs(std::real(refMatr[i][i]));
623
624 // when exponent is negative, the matrix cannot contain near-zero
625 // magnitude numbers which create divergences and trigger validation.
626 // Negative exponents are particularly unstable (they can produce
627 // very large matrix elements which ergo have less post-decimal
628 // precision and sum catastrophically), so we scale up matrix.
629 if (exponent < 0)
630 for (size_t i=0; i<refMatr.size(); i++)
631 refMatr[i][i] *= 100;
632
633 auto apiFunc = [&](Qureg qureg, FullStateDiagMatr matr) {
634 return calcExpecFullStateDiagMatrPower(qureg, matr, exponent);
635 };
636
637 CAPTURE( exponent );
638
639 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
640
641 SECTION( LABEL_STATEVEC ) {
642
643 auto refFunc = [&] (qvector state, qmatrix matr) {
644 matr = getPowerOfDiagonalMatrix(matr, qcomp(exponent,0));
645 return getReferenceExpectationValue(state, matr);
646 };
647
648 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
649 }
650
651 SECTION( LABEL_DENSMATR ) {
652
653 auto refFunc = [&] (qmatrix state, qmatrix matr) {
654 matr = getPowerOfDiagonalMatrix(matr, qcomp(exponent,0));
655 return getReferenceExpectationValue(state, matr);
656 };
657
658 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
659 }
660 }
661
662 /// @todo input validation
663}
664
665
666
667TEST_CASE( "calcExpecNonHermitianFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
668
669 SECTION( LABEL_CORRECTNESS ) {
670
671 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(getNumCachedQubits()));
672 qcomp exponent = getRandomComplex();
673
674 auto apiFunc = [&](Qureg qureg, FullStateDiagMatr matr) {
675 return calcExpecNonHermitianFullStateDiagMatrPower(qureg, matr, exponent);
676 };
677
678 CAPTURE( exponent );
679
680 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
681
682 SECTION( LABEL_STATEVEC ) {
683
684 auto refFunc = [&] (qvector state, qmatrix matr) {
685 matr = getPowerOfDiagonalMatrix(matr, exponent);
686 return getReferenceExpectationValue(state, matr);
687 };
688
689 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
690 }
691
692 SECTION( LABEL_DENSMATR ) {
693
694 auto refFunc = [&] (qmatrix state, qmatrix matr) {
695 matr = getPowerOfDiagonalMatrix(matr, exponent);
696 return getReferenceExpectationValue(state, matr);
697 };
698
699 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
700 }
701 }
702
703 /// @todo input validation
704}
705
706
707
708/** @} (end defgroup) */
qreal calcFidelity(Qureg qureg, Qureg other)
qreal calcDistance(Qureg qureg, Qureg other)
qcomp calcInnerProduct(Qureg qureg, Qureg other)
qreal calcExpecFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matr)
qcomp calcExpecNonHermitianFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matr)
qreal calcExpecPauliStrSum(Qureg qureg, PauliStrSum sum)
qcomp calcExpecNonHermitianPauliStrSum(Qureg qureg, PauliStrSum sum)
qreal calcExpecFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qreal exponent)
qcomp calcExpecNonHermitianFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent)
qreal calcExpecPauliStr(Qureg qureg, PauliStr str)
Qureg calcReducedDensityMatrix(Qureg qureg, int *retainQubits, int numRetainQubits)
Qureg calcPartialTrace(Qureg qureg, int *traceOutQubits, int numTraceQubits)
qreal calcProbOfQubitOutcome(Qureg qureg, int qubit, int outcome)
void calcProbsOfAllMultiQubitOutcomes(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
qreal calcProbOfBasisState(Qureg qureg, qindex index)
qreal calcProbOfMultiQubitOutcome(Qureg qureg, int *qubits, int *outcomes, int numQubits)
qreal calcPurity(Qureg qureg)
qreal calcTotalProb(Qureg qureg)
QuESTEnv getQuESTEnv()
void setFullStateDiagMatr(FullStateDiagMatr out, qindex startInd, qcomp *in, qindex numElems)
Definition matrices.cpp:443
void destroyPauliStrSum(PauliStrSum sum)
Definition paulis.cpp:251
void destroyQureg(Qureg qureg)
Definition qureg.cpp:334
qmatrix getConjugateTranspose(qmatrix m)
Definition linalg.cpp:291
qcomp getRandomComplex()
Definition random.cpp:107
qreal getRandomReal(qreal min, qreal maxExcl)
Definition random.cpp:63
int getRandomInt(int min, int maxExcl)
Definition random.cpp:90
TEST_CASE("calcExpecPauliStr", TEST_CATEGORY)
Definition qureg.h:49