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>
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/cache.hpp"
27#include "tests/utils/measure.hpp"
33using Catch::Matchers::ContainsSubstring;
43#define TEST_CATEGORY \
44 LABEL_UNIT_TAG "[calculations]"
47void TEST_ON_CACHED_QUREGS(quregCache cache,
auto refState,
auto apiFunc,
auto refFunc) {
49 for (
auto& [label, qureg]: cache) {
51 DYNAMIC_SECTION( label ) {
56 setToRandomState(refState);
57 setQuregToReference(qureg, refState);
64 auto apiResult = apiFunc(qureg);
65 auto refResult = refFunc(refState);
66 REQUIRE_AGREE( apiResult, refResult );
69 if constexpr (std::is_same_v<
decltype(apiResult),
Qureg>)
75void TEST_ON_CACHED_STATEVECS_AND_DENSMATRS(
auto apiFunc,
auto refFunc) {
76 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), getRefStatevec(), apiFunc, refFunc); }
77 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), getRefDensmatr(), apiFunc, refFunc); }
80#define TEST_ALL_QUREGS( quregVar, apiExpr, stateVar, refExpr ) \
81 TEST_ON_CACHED_STATEVECS_AND_DENSMATRS( \
82 [&](Qureg quregVar) { return apiExpr; }, \
83 [&](auto& stateVar) { return refExpr; } ) \
86void TEST_ON_MIXED_CACHED_QUREGS(quregCache cacheA, quregCache cacheB,
auto refA,
auto refB,
auto apiFunc,
auto refFunc) {
90 for (
auto& [labelA, quregA]: cacheA) {
91 for (
auto& [labelB, quregB]: cacheB) {
94 if (quregA.isDensityMatrix != quregB.isDensityMatrix &&
95 quregA.isDistributed != quregB.isDistributed &&
96 quregA.isDistributed == quregB.isDensityMatrix)
100 if (quregA.isDensityMatrix == quregB.isDensityMatrix &&
101 quregA.isGpuAccelerated != quregB.isGpuAccelerated)
104 DYNAMIC_SECTION( labelA + LABEL_DELIMITER + labelB ) {
108 setToRandomState(refA); setQuregToReference(quregA, refA);
109 setToRandomState(refB); setQuregToReference(quregB, refB);
112 auto apiResult = apiFunc(quregA, quregB);
113 auto refResult = refFunc(refA, refB);
114 REQUIRE_AGREE( apiResult, refResult );
121void TEST_ON_CACHED_QUREG_AND_MATRIX(quregCache quregs, matrixCache matrices,
auto apiFunc,
auto refState,
auto refMatr,
auto refFunc) {
125 for (
auto& [labelA, qureg]: quregs) {
126 for (
auto& [labelB, matrix]: matrices) {
130 DYNAMIC_SECTION( labelA + LABEL_DELIMITER + labelB ) {
137 setToRandomState(refState);
138 setQuregToReference(qureg, refState);
141 auto apiResult = apiFunc(qureg, matrix);
142 auto refResult = refFunc(refState, refMatr);
143 REQUIRE_AGREE( apiResult, refResult );
162 SECTION( LABEL_CORRECTNESS ) {
164 int numQubits = getNumCachedQubits();
165 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
166 auto targets = GENERATE_TARGS(numQubits, numTargs);
168 PauliStr str = getRandomPauliStr(targets);
172 state, std::real(getReferenceExpectationValue(state, str))
183 SECTION( LABEL_CORRECTNESS ) {
185 int numQubits = getNumCachedQubits();
186 int numTerms = GENERATE_COPY( 1, numQubits, getPow2(2*numQubits) );
188 GENERATE( range(0,10) );
189 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
193 state, std::real(getReferenceExpectationValue(state, sum))
204TEST_CASE(
"calcExpecNonHermitianPauliStrSum", TEST_CATEGORY ) {
206 SECTION( LABEL_CORRECTNESS ) {
208 GENERATE( range(0,10) );
209 int numQubits = getNumCachedQubits();
210 int numTerms = GENERATE_COPY( 1, numQubits, getPow2(2*numQubits) );
212 PauliStrSum sum = createRandomNonHermitianPauliStrSum(numQubits, numTerms);
216 state, getReferenceExpectationValue(state, sum)
229 SECTION( LABEL_CORRECTNESS ) {
231 qindex index = GENERATE( range(0, 1 << getNumCachedQubits()) );
235 state, getReferenceProbability(state, index)
246 SECTION( LABEL_CORRECTNESS ) {
248 int target = GENERATE( range(0, getNumCachedQubits()) );
249 int outcome = GENERATE( 0, 1 );
253 state, getReferenceProbability(state, {target}, {outcome})
262TEST_CASE(
"calcProbOfMultiQubitOutcome", TEST_CATEGORY ) {
264 SECTION( LABEL_CORRECTNESS ) {
266 int numQubits = getNumCachedQubits();
267 int numTargs = GENERATE_COPY( range(1, numQubits+1) );
268 auto targets = GENERATE_TARGS(numQubits, numTargs);
269 auto outcomes = getRandomOutcomes(numTargs);
273 state, getReferenceProbability(state, targets, outcomes)
282TEST_CASE(
"calcProbsOfAllMultiQubitOutcomes", TEST_CATEGORY ) {
284 SECTION( LABEL_CORRECTNESS ) {
286 int numQubits = getNumCachedQubits();
287 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
288 auto targets = GENERATE_TARGS(numQubits, numTargs);
290 auto apiFunc = [&](
Qureg qureg) {
291 vector<qreal> out(getPow2(numTargs));
295 auto refFunc = [&](
auto& state) {
296 return getAllReferenceProbabilities(state, targets);
299 TEST_ON_CACHED_STATEVECS_AND_DENSMATRS( apiFunc, refFunc );
309 SECTION( LABEL_CORRECTNESS ) {
311 GENERATE( range(0,100) );
315 state, getReferenceProbability(state)
326 SECTION( LABEL_CORRECTNESS ) {
328 GENERATE( range(0,100) );
332 state, getReferencePurity(state)
342int getMaxNumTracedQubits(
int numQubits) {
358 SECTION( LABEL_CORRECTNESS ) {
360 SECTION( LABEL_DENSMATR ) {
362 int numQubits = getNumCachedQubits();
363 int maxNumTargs = getMaxNumTracedQubits(numQubits);
364 int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
365 auto targets = GENERATE_TARGS(numQubits, numTargs);
368 auto refFunc = [&](qmatrix ref) {
return getPartialTrace(ref, targets); };
370 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), getRefDensmatr(), apiFunc, refFunc);
383 SECTION( LABEL_CORRECTNESS ) {
385 SECTION( LABEL_DENSMATR ) {
387 int numQubits = getNumCachedQubits();
388 int maxNumTraced = getMaxNumTracedQubits(numQubits);
389 int minNumRetained = numQubits - maxNumTraced;
390 int maxNumRetained = numQubits - 1;
391 int numRetained = GENERATE_COPY( range(minNumRetained, maxNumRetained+1) );
392 auto retains = GENERATE_TARGS(numQubits, numRetained);
393 auto targets = getComplement(getRange(numQubits), retains);
396 auto refFunc = [&](qmatrix ref) {
return getPartialTrace(ref, targets); };
398 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), getRefDensmatr(), apiFunc, refFunc);
407TEST_CASE(
"calcInnerProduct", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
409 SECTION( LABEL_CORRECTNESS ) {
411 qvector refSV = getRefStatevec();
412 qmatrix refDM = getRefDensmatr();
417 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
420 auto refFunc = [&](qvector a, qvector b) {
return getInnerProduct (a,b); };
422 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc );
425 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
428 auto refFunc = [&](qvector a, qmatrix b) {
return getInnerProduct(a, b * a); };
430 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
433 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
437 auto refFunc = [&](qmatrix a, qvector b) {
return getInnerProduct(b,
getConjugateTranspose(a) * b); };
439 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
442 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_DENSMATR ) {
447 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedDensmatrs(), refDM, refDM, apiFunc, refFunc );
456TEST_CASE(
"calcFidelity", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
458 SECTION( LABEL_CORRECTNESS ) {
460 qvector refSV = getRefStatevec();
461 qmatrix refDM = getRefDensmatr();
466 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
469 auto refFunc = [&](qvector a, qvector b) {
return std::norm(getInnerProduct(a,b)); };
471 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc );
474 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
477 auto refFunc = [&](qvector a, qmatrix b) {
return std::real(getInnerProduct(a, b * a)); };
479 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
482 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
485 auto refFunc = [&](qmatrix a, qvector b) {
return std::real(getInnerProduct(b, a * b)); };
487 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
498TEST_CASE(
"calcDistance", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
500 SECTION( LABEL_CORRECTNESS ) {
502 qvector refSV = getRefStatevec();
503 qmatrix refDM = getRefDensmatr();
508 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
511 auto refFunc = [&](qvector a, qvector b) {
return std::sqrt(2 - 2 * std::abs(getInnerProduct(a,b))); };
513 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc);
516 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
519 auto refFunc = [&](qvector a, qmatrix b) {
return std::sqrt(1 - std::real(getInnerProduct(a, b * a))); };
521 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
524 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
527 auto refFunc = [&](qmatrix a, qvector b) {
return std::sqrt(1 - std::real(getInnerProduct(b, a * b))); };
529 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
532 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_DENSMATR ) {
535 auto refFunc = [&](qmatrix a, qmatrix b) {
return std::sqrt(std::real(getTrace((a-b)*
getConjugateTranspose(a-b)))); };
537 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedDensmatrs(), refDM, refDM, apiFunc, refFunc );
546TEST_CASE(
"calcExpecFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
548 SECTION( LABEL_CORRECTNESS ) {
550 qmatrix refMatr = getRandomDiagonalHermitian(getNumCachedQubits());
555 SECTION( LABEL_STATEVEC ) {
557 auto refFunc = [&] (qvector state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
559 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
562 SECTION( LABEL_DENSMATR ) {
564 auto refFunc = [&] (qmatrix state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
566 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
575TEST_CASE(
"calcExpecNonHermitianFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
577 SECTION( LABEL_CORRECTNESS ) {
579 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(getNumCachedQubits()));
584 SECTION( LABEL_STATEVEC ) {
586 auto refFunc = [&] (qvector state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
588 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
591 SECTION( LABEL_DENSMATR ) {
593 auto refFunc = [&] (qmatrix state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
595 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
604TEST_CASE(
"calcExpecFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
606 SECTION( LABEL_CORRECTNESS ) {
608 qmatrix refMatr = getRandomDiagonalHermitian(getNumCachedQubits());
611 bool isIntegerExp = GENERATE(
true,
false );
612 qreal exponent = (isIntegerExp)?
620 for (
size_t i=0; i<refMatr.size(); i++)
621 refMatr[i][i] = std::abs(std::real(refMatr[i][i]));
629 for (
size_t i=0; i<refMatr.size(); i++)
630 refMatr[i][i] *= 100;
640 SECTION( LABEL_STATEVEC ) {
642 auto refFunc = [&] (qvector state, qmatrix matr) {
643 matr = getPowerOfDiagonalMatrix(matr, qcomp(exponent,0));
644 return getReferenceExpectationValue(state, matr);
647 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
650 SECTION( LABEL_DENSMATR ) {
652 auto refFunc = [&] (qmatrix state, qmatrix matr) {
653 matr = getPowerOfDiagonalMatrix(matr, qcomp(exponent,0));
654 return getReferenceExpectationValue(state, matr);
657 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
666TEST_CASE(
"calcExpecNonHermitianFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
668 SECTION( LABEL_CORRECTNESS ) {
670 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(getNumCachedQubits()));
681 SECTION( LABEL_STATEVEC ) {
683 auto refFunc = [&] (qvector state, qmatrix matr) {
684 matr = getPowerOfDiagonalMatrix(matr, exponent);
685 return getReferenceExpectationValue(state, matr);
688 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
691 SECTION( LABEL_DENSMATR ) {
693 auto refFunc = [&] (qmatrix state, qmatrix matr) {
694 matr = getPowerOfDiagonalMatrix(matr, exponent);
695 return getReferenceExpectationValue(state, matr);
698 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
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)
void setFullStateDiagMatr(FullStateDiagMatr out, qindex startInd, qcomp *in, qindex numElems)
void destroyPauliStrSum(PauliStrSum sum)
void destroyQureg(Qureg qureg)
qmatrix getConjugateTranspose(qmatrix m)
const int TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS
qreal getRandomReal(qreal min, qreal maxExcl)
int getRandomInt(int min, int maxExcl)
TEST_CASE("calcExpecPauliStr", TEST_CATEGORY)