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