10#include "quest/include/quest.h"
12#include <catch2/catch_test_macros.hpp>
13#include <catch2/generators/catch_generators_range.hpp>
14#include <catch2/matchers/catch_matchers_floating_point.hpp>
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"
33using namespace Catch::Matchers;
42#define TEST_CATEGORY \
43 LABEL_UNIT_TAG "[calculations]"
46void TEST_ON_CACHED_QUREGS(quregCache cache,
auto refState,
auto apiFunc,
auto refFunc) {
48 for (
auto& [label, qureg]: cache) {
50 DYNAMIC_SECTION( label ) {
55 setToRandomState(refState);
56 setQuregToReference(qureg, refState);
63 auto apiResult = apiFunc(qureg);
64 auto refResult = refFunc(refState);
65 REQUIRE_AGREE( apiResult, refResult );
68 if constexpr (std::is_same_v<
decltype(apiResult),
Qureg>)
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); }
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; } ) \
85void TEST_ON_MIXED_CACHED_QUREGS(quregCache cacheA, quregCache cacheB,
auto refA,
auto refB,
auto apiFunc,
auto refFunc) {
89 for (
auto& [labelA, quregA]: cacheA) {
90 for (
auto& [labelB, quregB]: cacheB) {
93 if (quregA.isDensityMatrix != quregB.isDensityMatrix &&
94 quregA.isDistributed != quregB.isDistributed &&
95 quregA.isDistributed == quregB.isDensityMatrix)
99 if (quregA.isDensityMatrix == quregB.isDensityMatrix &&
100 quregA.isGpuAccelerated != quregB.isGpuAccelerated)
103 DYNAMIC_SECTION( labelA + LABEL_DELIMITER + labelB ) {
107 setToRandomState(refA); setQuregToReference(quregA, refA);
108 setToRandomState(refB); setQuregToReference(quregB, refB);
111 auto apiResult = apiFunc(quregA, quregB);
112 auto refResult = refFunc(refA, refB);
113 REQUIRE_AGREE( apiResult, refResult );
120void TEST_ON_CACHED_QUREG_AND_MATRIX(quregCache quregs, matrixCache matrices,
auto apiFunc,
auto refState,
auto refMatr,
auto refFunc) {
124 for (
auto& [labelA, qureg]: quregs) {
125 for (
auto& [labelB, matrix]: matrices) {
129 DYNAMIC_SECTION( labelA + LABEL_DELIMITER + labelB ) {
136 setToRandomState(refState);
137 setQuregToReference(qureg, refState);
140 auto apiResult = apiFunc(qureg, matrix);
141 auto refResult = refFunc(refState, refMatr);
142 REQUIRE_AGREE( apiResult, refResult );
161 SECTION( LABEL_CORRECTNESS ) {
163 int numQubits = getNumCachedQubits();
164 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
165 auto targets = GENERATE_TARGS(numQubits, numTargs);
167 PauliStr str = getRandomPauliStr(targets);
171 state, std::real(getReferenceExpectationValue(state, str))
182 SECTION( LABEL_CORRECTNESS ) {
184 int numQubits = getNumCachedQubits();
185 int numTerms = GENERATE_COPY( 1, numQubits, getPow2(2*numQubits) );
187 GENERATE( range(0,10) );
188 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
192 state, std::real(getReferenceExpectationValue(state, sum))
203TEST_CASE(
"calcExpecNonHermitianPauliStrSum", TEST_CATEGORY ) {
205 SECTION( LABEL_CORRECTNESS ) {
207 GENERATE( range(0,10) );
208 int numQubits = getNumCachedQubits();
209 int numTerms = GENERATE_COPY( 1, numQubits, getPow2(2*numQubits) );
211 PauliStrSum sum = createRandomNonHermitianPauliStrSum(numQubits, numTerms);
215 state, getReferenceExpectationValue(state, sum)
228 SECTION( LABEL_CORRECTNESS ) {
230 qindex index = GENERATE( range(0, 1 << getNumCachedQubits()) );
234 state, getReferenceProbability(state, index)
245 SECTION( LABEL_CORRECTNESS ) {
247 int target = GENERATE( range(0, getNumCachedQubits()) );
248 int outcome = GENERATE( 0, 1 );
252 state, getReferenceProbability(state, {target}, {outcome})
261TEST_CASE(
"calcProbOfMultiQubitOutcome", TEST_CATEGORY ) {
263 SECTION( LABEL_CORRECTNESS ) {
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);
272 state, getReferenceProbability(state, targets, outcomes)
281TEST_CASE(
"calcProbsOfAllMultiQubitOutcomes", TEST_CATEGORY ) {
283 SECTION( LABEL_CORRECTNESS ) {
285 int numQubits = getNumCachedQubits();
286 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
287 auto targets = GENERATE_TARGS(numQubits, numTargs);
289 auto apiFunc = [&](
Qureg qureg) {
290 vector<qreal> out(getPow2(numTargs));
294 auto refFunc = [&](
auto& state) {
295 return getAllReferenceProbabilities(state, targets);
298 TEST_ON_CACHED_STATEVECS_AND_DENSMATRS( apiFunc, refFunc );
308 SECTION( LABEL_CORRECTNESS ) {
310 GENERATE( range(0,100) );
314 state, getReferenceProbability(state)
325 SECTION( LABEL_CORRECTNESS ) {
327 GENERATE( range(0,100) );
331 state, getReferencePurity(state)
341int getMaxNumTracedQubits(
int numQubits) {
357 SECTION( LABEL_CORRECTNESS ) {
359 SECTION( LABEL_DENSMATR ) {
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);
367 auto refFunc = [&](qmatrix ref) {
return getPartialTrace(ref, targets); };
369 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), getRefDensmatr(), apiFunc, refFunc);
382 SECTION( LABEL_CORRECTNESS ) {
384 SECTION( LABEL_DENSMATR ) {
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);
395 auto refFunc = [&](qmatrix ref) {
return getPartialTrace(ref, targets); };
397 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), getRefDensmatr(), apiFunc, refFunc);
406TEST_CASE(
"calcInnerProduct", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
408 SECTION( LABEL_CORRECTNESS ) {
410 qvector refSV = getRefStatevec();
411 qmatrix refDM = getRefDensmatr();
416 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
419 auto refFunc = [&](qvector a, qvector b) {
return getInnerProduct (a,b); };
421 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc );
424 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
427 auto refFunc = [&](qvector a, qmatrix b) {
return getInnerProduct(a, b * a); };
429 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
432 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
436 auto refFunc = [&](qmatrix a, qvector b) {
return getInnerProduct(b,
getConjugateTranspose(a) * b); };
438 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
441 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_DENSMATR ) {
446 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedDensmatrs(), refDM, refDM, apiFunc, refFunc );
455TEST_CASE(
"calcFidelity", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
457 SECTION( LABEL_CORRECTNESS ) {
459 qvector refSV = getRefStatevec();
460 qmatrix refDM = getRefDensmatr();
465 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
468 auto refFunc = [&](qvector a, qvector b) {
return std::norm(getInnerProduct(a,b)); };
470 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc );
473 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
476 auto refFunc = [&](qvector a, qmatrix b) {
return std::real(getInnerProduct(a, b * a)); };
478 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
481 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
484 auto refFunc = [&](qmatrix a, qvector b) {
return std::real(getInnerProduct(b, a * b)); };
486 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
497TEST_CASE(
"calcDistance", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
499 SECTION( LABEL_CORRECTNESS ) {
501 qvector refSV = getRefStatevec();
502 qmatrix refDM = getRefDensmatr();
507 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_STATEVEC ) {
510 auto refFunc = [&](qvector a, qvector b) {
return std::sqrt(2 - 2 * std::abs(getInnerProduct(a,b))); };
512 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedStatevecs(), refSV, refSV, apiFunc, refFunc);
515 SECTION( LABEL_STATEVEC LABEL_DELIMITER LABEL_DENSMATR ) {
518 auto refFunc = [&](qvector a, qmatrix b) {
return std::sqrt(1 - std::real(getInnerProduct(a, b * a))); };
520 TEST_ON_MIXED_CACHED_QUREGS( getCachedStatevecs(), getAltCachedDensmatrs(), refSV, refDM, apiFunc, refFunc );
523 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_STATEVEC ) {
526 auto refFunc = [&](qmatrix a, qvector b) {
return std::sqrt(1 - std::real(getInnerProduct(b, a * b))); };
528 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedStatevecs(), refDM, refSV, apiFunc, refFunc );
531 SECTION( LABEL_DENSMATR LABEL_DELIMITER LABEL_DENSMATR ) {
534 auto refFunc = [&](qmatrix a, qmatrix b) {
return std::sqrt(std::real(getTrace((a-b)*
getConjugateTranspose(a-b)))); };
536 TEST_ON_MIXED_CACHED_QUREGS( getCachedDensmatrs(), getAltCachedDensmatrs(), refDM, refDM, apiFunc, refFunc );
545TEST_CASE(
"calcExpecFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
547 SECTION( LABEL_CORRECTNESS ) {
549 qmatrix refMatr = getRandomDiagonalHermitian(getNumCachedQubits());
554 SECTION( LABEL_STATEVEC ) {
556 auto refFunc = [&] (qvector state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
558 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
561 SECTION( LABEL_DENSMATR ) {
563 auto refFunc = [&] (qmatrix state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
565 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
574TEST_CASE(
"calcExpecNonHermitianFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
576 SECTION( LABEL_CORRECTNESS ) {
578 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(getNumCachedQubits()));
583 SECTION( LABEL_STATEVEC ) {
585 auto refFunc = [&] (qvector state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
587 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
590 SECTION( LABEL_DENSMATR ) {
592 auto refFunc = [&] (qmatrix state, qmatrix matr) {
return getReferenceExpectationValue(state, matr); };
594 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
603TEST_CASE(
"calcExpecFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
605 SECTION( LABEL_CORRECTNESS ) {
607 qmatrix refMatr = getRandomDiagonalHermitian(getNumCachedQubits());
610 bool isIntegerExp = GENERATE(
true,
false );
611 qreal exponent = (isIntegerExp)?
619 for (
size_t i=0; i<refMatr.size(); i++)
620 refMatr[i][i] = std::abs(std::real(refMatr[i][i]));
628 for (
size_t i=0; i<refMatr.size(); i++)
629 refMatr[i][i] *= 100;
639 SECTION( LABEL_STATEVEC ) {
641 auto refFunc = [&] (qvector state, qmatrix matr) {
642 matr = getPowerOfDiagonalMatrix(matr, qcomp(exponent,0));
643 return getReferenceExpectationValue(state, matr);
646 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
649 SECTION( LABEL_DENSMATR ) {
651 auto refFunc = [&] (qmatrix state, qmatrix matr) {
652 matr = getPowerOfDiagonalMatrix(matr, qcomp(exponent,0));
653 return getReferenceExpectationValue(state, matr);
656 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedDensmatrs(), getCachedFullStateDiagMatrs(), apiFunc, getRefDensmatr(), refMatr, refFunc);
665TEST_CASE(
"calcExpecNonHermitianFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
667 SECTION( LABEL_CORRECTNESS ) {
669 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(getNumCachedQubits()));
680 SECTION( LABEL_STATEVEC ) {
682 auto refFunc = [&] (qvector state, qmatrix matr) {
683 matr = getPowerOfDiagonalMatrix(matr, exponent);
684 return getReferenceExpectationValue(state, matr);
687 TEST_ON_CACHED_QUREG_AND_MATRIX( getCachedStatevecs(), getCachedFullStateDiagMatrs(), apiFunc, getRefStatevec(), refMatr, refFunc);
690 SECTION( LABEL_DENSMATR ) {
692 auto refFunc = [&] (qmatrix state, qmatrix matr) {
693 matr = getPowerOfDiagonalMatrix(matr, exponent);
694 return getReferenceExpectationValue(state, matr);
697 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)