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/config.hpp"
27#include "tests/utils/cache.hpp"
28#include "tests/utils/measure.hpp"
34using Catch::Matchers::ContainsSubstring;
44#define TEST_CATEGORY \
45 LABEL_UNIT_TAG "[calculations]"
48void TEST_ON_CACHED_QUREGS(quregCache cache,
auto refState,
auto apiFunc,
auto refFunc) {
50 for (
auto& [label, qureg]: cache) {
52 DYNAMIC_SECTION( label ) {
57 setToRandomState(refState);
58 setQuregToReference(qureg, refState);
65 auto apiResult = apiFunc(qureg);
66 auto refResult = refFunc(refState);
67 REQUIRE_AGREE( apiResult, refResult );
70 if constexpr (std::is_same_v<
decltype(apiResult),
Qureg>)
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); }
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; } ) \
87void TEST_ON_MIXED_CACHED_QUREGS(quregCache cacheA, quregCache cacheB,
auto refA,
auto refB,
auto apiFunc,
auto refFunc) {
91 for (
auto& [labelA, quregA]: cacheA) {
92 for (
auto& [labelB, quregB]: cacheB) {
95 if (quregA.isDensityMatrix != quregB.isDensityMatrix &&
96 quregA.isDistributed != quregB.isDistributed &&
97 quregA.isDistributed == quregB.isDensityMatrix)
101 if (quregA.isDensityMatrix == quregB.isDensityMatrix &&
102 quregA.isGpuAccelerated != quregB.isGpuAccelerated)
105 DYNAMIC_SECTION( labelA + LABEL_DELIMITER + labelB ) {
109 setToRandomState(refA); setQuregToReference(quregA, refA);
110 setToRandomState(refB); setQuregToReference(quregB, refB);
113 auto apiResult = apiFunc(quregA, quregB);
114 auto refResult = refFunc(refA, refB);
115 REQUIRE_AGREE( apiResult, refResult );
122void TEST_ON_CACHED_QUREG_AND_MATRIX(quregCache quregs, matrixCache matrices,
auto apiFunc,
auto refState,
auto refMatr,
auto refFunc) {
126 for (
auto& [labelA, qureg]: quregs) {
127 for (
auto& [labelB, matrix]: matrices) {
131 DYNAMIC_SECTION( labelA + LABEL_DELIMITER + labelB ) {
138 setToRandomState(refState);
139 setQuregToReference(qureg, refState);
142 auto apiResult = apiFunc(qureg, matrix);
143 auto refResult = refFunc(refState, refMatr);
144 REQUIRE_AGREE( apiResult, refResult );
163 SECTION( LABEL_CORRECTNESS ) {
165 int numQubits = getNumCachedQubits();
166 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
167 auto targets = GENERATE_TARGS(numQubits, numTargs);
169 PauliStr str = getRandomPauliStr(targets);
173 state, std::real(getReferenceExpectationValue(state, str))
184 SECTION( LABEL_CORRECTNESS ) {
186 int numQubits = getNumCachedQubits();
187 int numTerms = GENERATE_COPY( 1, numQubits, getPow2(2*numQubits) );
189 GENERATE( range(0,10) );
190 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
194 state, std::real(getReferenceExpectationValue(state, sum))
205TEST_CASE(
"calcExpecNonHermitianPauliStrSum", TEST_CATEGORY ) {
207 SECTION( LABEL_CORRECTNESS ) {
209 GENERATE( range(0,10) );
210 int numQubits = getNumCachedQubits();
211 int numTerms = GENERATE_COPY( 1, numQubits, getPow2(2*numQubits) );
213 PauliStrSum sum = createRandomNonHermitianPauliStrSum(numQubits, numTerms);
217 state, getReferenceExpectationValue(state, sum)
230 SECTION( LABEL_CORRECTNESS ) {
232 qindex index = GENERATE( range(0, 1 << getNumCachedQubits()) );
236 state, getReferenceProbability(state, index)
247 SECTION( LABEL_CORRECTNESS ) {
249 int target = GENERATE( range(0, getNumCachedQubits()) );
250 int outcome = GENERATE( 0, 1 );
254 state, getReferenceProbability(state, {target}, {outcome})
263TEST_CASE(
"calcProbOfMultiQubitOutcome", TEST_CATEGORY ) {
265 SECTION( LABEL_CORRECTNESS ) {
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);
274 state, getReferenceProbability(state, targets, outcomes)
283TEST_CASE(
"calcProbsOfAllMultiQubitOutcomes", TEST_CATEGORY ) {
285 SECTION( LABEL_CORRECTNESS ) {
287 int numQubits = getNumCachedQubits();
288 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
289 auto targets = GENERATE_TARGS(numQubits, numTargs);
291 auto apiFunc = [&](
Qureg qureg) {
292 vector<qreal> out(getPow2(numTargs));
296 auto refFunc = [&](
auto& state) {
297 return getAllReferenceProbabilities(state, targets);
300 TEST_ON_CACHED_STATEVECS_AND_DENSMATRS( apiFunc, refFunc );
310 SECTION( LABEL_CORRECTNESS ) {
312 GENERATE( range(0,100) );
316 state, getReferenceProbability(state)
327 SECTION( LABEL_CORRECTNESS ) {
329 GENERATE( range(0,100) );
333 state, getReferencePurity(state)
343int getMaxNumTracedQubits(
int numQubits) {
359 SECTION( LABEL_CORRECTNESS ) {
361 SECTION( LABEL_DENSMATR ) {
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);
369 auto refFunc = [&](qmatrix ref) {
return getPartialTrace(ref, targets); };
371 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), getRefDensmatr(), apiFunc, refFunc);
384 SECTION( LABEL_CORRECTNESS ) {
386 SECTION( LABEL_DENSMATR ) {
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);
397 auto refFunc = [&](qmatrix ref) {
return getPartialTrace(ref, targets); };
399 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), getRefDensmatr(), apiFunc, refFunc);
408TEST_CASE(
"calcInnerProduct", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
410 SECTION( LABEL_CORRECTNESS ) {
412 qvector refSV = getRefStatevec();
413 qmatrix refDM = getRefDensmatr();
416 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
418 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
421 auto refFunc = [&](qvector a, qvector b) {
return getInnerProduct (a,b); };
423 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc );
426 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
429 auto refFunc = [&](qvector a, qmatrix b) {
return getInnerProduct(a, b * a); };
431 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
434 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
438 auto refFunc = [&](qmatrix a, qvector b) {
return getInnerProduct(b,
getConjugateTranspose(a) * b); };
440 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
443 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_DENSMATR ) {
448 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedDensmatrs(), refDM, refDM, apiFunc, refFunc );
457TEST_CASE(
"calcFidelity", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
459 SECTION( LABEL_CORRECTNESS ) {
461 qvector refSV = getRefStatevec();
462 qmatrix refDM = getRefDensmatr();
465 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
467 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
470 auto refFunc = [&](qvector a, qvector b) {
return std::norm(getInnerProduct(a,b)); };
472 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc );
475 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
478 auto refFunc = [&](qvector a, qmatrix b) {
return std::real(getInnerProduct(a, b * a)); };
480 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
483 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
486 auto refFunc = [&](qmatrix a, qvector b) {
return std::real(getInnerProduct(b, a * b)); };
488 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
499TEST_CASE(
"calcDistance", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
501 SECTION( LABEL_CORRECTNESS ) {
503 qvector refSV = getRefStatevec();
504 qmatrix refDM = getRefDensmatr();
507 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
509 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
512 auto refFunc = [&](qvector a, qvector b) {
return std::sqrt(2 - 2 * std::abs(getInnerProduct(a,b))); };
514 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc);
517 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
520 auto refFunc = [&](qvector a, qmatrix b) {
return std::sqrt(1 - std::real(getInnerProduct(a, b * a))); };
522 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
525 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
528 auto refFunc = [&](qmatrix a, qvector b) {
return std::sqrt(1 - std::real(getInnerProduct(b, a * b))); };
530 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
533 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_DENSMATR ) {
536 auto refFunc = [&](qmatrix a, qmatrix b) {
return std::sqrt(std::real(getTrace((a-b)*
getConjugateTranspose(a-b)))); };
538 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedDensmatrs(), refDM, refDM, apiFunc, refFunc );
547TEST_CASE(
"calcExpecFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
549 SECTION( LABEL_CORRECTNESS ) {
551 qmatrix refMatr = getRandomDiagonalHermitian(getNumCachedQubits());
554 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
556 SECTION( LABEL_STATEVEC ) {
558 auto refFunc = [&] (qvector state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
560 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
563 SECTION( LABEL_DENSMATR ) {
565 auto refFunc = [&] (qmatrix state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
567 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
576TEST_CASE(
"calcExpecNonHermitianFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
578 SECTION( LABEL_CORRECTNESS ) {
580 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(getNumCachedQubits()));
583 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
585 SECTION( LABEL_STATEVEC ) {
587 auto refFunc = [&] (qvector state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
589 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
592 SECTION( LABEL_DENSMATR ) {
594 auto refFunc = [&] (qmatrix state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
596 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
605TEST_CASE(
"calcExpecFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
607 SECTION( LABEL_CORRECTNESS ) {
609 qmatrix refMatr = getRandomDiagonalHermitian(getNumCachedQubits());
612 bool isIntegerExp = GENERATE(
true,
false );
613 qreal exponent = (isIntegerExp)?
621 for (
size_t i=0; i<refMatr.size(); i++)
622 refMatr[i][i] = std::abs(std::real(refMatr[i][i]));
630 for (
size_t i=0; i<refMatr.size(); i++)
631 refMatr[i][i] *= 100;
639 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
641 SECTION( LABEL_STATEVEC ) {
643 auto refFunc = [&] (qvector state, qmatrix matr) {
644 matr = getPowerOfDiagonalMatrix(matr, qcomp(exponent,0));
645 return getReferenceExpectationValue(state, matr);
648 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
651 SECTION( LABEL_DENSMATR ) {
653 auto refFunc = [&] (qmatrix state, qmatrix matr) {
654 matr = getPowerOfDiagonalMatrix(matr, qcomp(exponent,0));
655 return getReferenceExpectationValue(state, matr);
658 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
667TEST_CASE(
"calcExpecNonHermitianFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
669 SECTION( LABEL_CORRECTNESS ) {
671 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(getNumCachedQubits()));
680 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
682 SECTION( LABEL_STATEVEC ) {
684 auto refFunc = [&] (qvector state, qmatrix matr) {
685 matr = getPowerOfDiagonalMatrix(matr, exponent);
686 return getReferenceExpectationValue(state, matr);
689 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
692 SECTION( LABEL_DENSMATR ) {
694 auto refFunc = [&] (qmatrix state, qmatrix matr) {
695 matr = getPowerOfDiagonalMatrix(matr, exponent);
696 return getReferenceExpectationValue(state, matr);
699 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
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)
void setFullStateDiagMatr(FullStateDiagMatr out, qindex startInd, qcomp *in, qindex numElems)
void destroyPauliStrSum(PauliStrSum sum)
void destroyQureg(Qureg qureg)
qmatrix getConjugateTranspose(qmatrix m)
qreal getRandomReal(qreal min, qreal maxExcl)
int getRandomInt(int min, int maxExcl)
TEST_CASE("calcExpecPauliStr", TEST_CATEGORY)