12#include <catch2/catch_test_macros.hpp>
13#include <catch2/matchers/catch_matchers_string.hpp>
14#include <catch2/generators/catch_generators_range.hpp>
16#include "tests/utils/qvector.hpp"
17#include "tests/utils/qmatrix.hpp"
18#include "tests/utils/cache.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/measure.hpp"
26#include "tests/utils/random.hpp"
28using Catch::Matchers::ContainsSubstring;
37#define TEST_CATEGORY \
38 LABEL_UNIT_TAG "[initialisations]"
41void TEST_ON_CACHED_QUREGS(quregCache quregs,
auto testFunc) {
43 for (
auto& [label, qureg]: quregs) {
45 DYNAMIC_SECTION( label ) {
53void TEST_ON_CACHED_QUREGS(quregCache quregs,
auto apiFunc,
auto refState) {
57 auto testFunc = [&](
Qureg qureg) {
59 REQUIRE_AGREE( qureg, refState );
62 TEST_ON_CACHED_QUREGS(quregs, testFunc);
77 SECTION( LABEL_CORRECTNESS ) {
79 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(),
initBlankState, getRefStatevec()); }
80 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(),
initBlankState, getRefDensmatr()); }
89 SECTION( LABEL_CORRECTNESS ) {
91 qvector refVec = getRefStatevec(); refVec[0] = 1;
92 qmatrix refMat = getRefDensmatr(); refMat[0][0] = 1;
94 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(),
initZeroState, refVec); }
95 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(),
initZeroState, refMat); }
104 SECTION( LABEL_CORRECTNESS ) {
106 int numQubits = getNumCachedQubits();
107 qreal vecElem = 1. / std::sqrt(getPow2(numQubits));
108 qreal matElem = 1. / getPow2(numQubits);
110 qvector refVec = getConstantVector(getPow2(numQubits), vecElem);
111 qmatrix refMat = getConstantMatrix(getPow2(numQubits), matElem);
113 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(),
initPlusState, refVec); }
114 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(),
initPlusState, refMat); }
123 SECTION( LABEL_CORRECTNESS ) {
125 int numQubits = getNumCachedQubits();
126 int numInds = (int) getPow2(numQubits);
127 int stateInd = GENERATE_COPY( range(0,numInds) );
129 qvector refVec = getRefStatevec(); refVec[stateInd] = 1;
130 qmatrix refMat = getRefDensmatr(); refMat[stateInd][stateInd] = 1;
134 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), apiFunc, refVec); }
135 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFunc, refMat); }
144 SECTION( LABEL_CORRECTNESS ) {
146 qvector refVec = getRefStatevec(); setToDebugState(refVec);
147 qmatrix refMat = getRefDensmatr(); setToDebugState(refMat);
149 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(),
initDebugState, refVec); }
150 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(),
initDebugState, refMat); }
159 SECTION( LABEL_CORRECTNESS ) {
162 GENERATE( range(0,10) );
164 auto testFunc = [&](
Qureg qureg) {
173 REQUIRE( qureg.cpuAmps[0] != qureg.cpuAmps[1] );
176 REQUIRE_AGREE( prob, 1 );
179 REQUIRE_AGREE( purity, 1 );
182 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), testFunc); }
183 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), testFunc); }
192 SECTION( LABEL_CORRECTNESS ) {
196 GENERATE( range(0,10) );
197 int numPureStates = GENERATE( 1, 2, 10 );
199 auto testFunc = [&](
Qureg qureg) {
208 REQUIRE( qureg.cpuAmps[0] != qureg.cpuAmps[1] );
211 REQUIRE_AGREE( prob, 1 );
214 if (numPureStates == 1)
215 REQUIRE_AGREE( purity, 1 );
217 REQUIRE( purity < 1 );
220 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), testFunc); }
229 SECTION( LABEL_CORRECTNESS ) {
232 qvector refVec = getRandomVector(getPow2(getNumCachedQubits()));
233 qmatrix refMat = getOuterProduct(refVec, refVec);
237 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), apiFunc, refVec); }
238 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFunc, refMat); }
249 SECTION( LABEL_CORRECTNESS ) {
251 int numTotalAmps = getPow2(getNumCachedQubits());
252 int numSetAmps = GENERATE_COPY( range(0,numTotalAmps+1) );
257 if (numTotalAmps - numSetAmps > 0) {
258 startInd = GENERATE_COPY( range(0,numTotalAmps-numSetAmps) );
261 qvector amps = getRandomVector(numSetAmps);
263 auto testFunc = [&](
Qureg qureg) {
266 qvector refVec = getRandomVector(numTotalAmps);
267 setQuregToReference(qureg, refVec);
270 setSubVector(refVec, amps, startInd);
275 REQUIRE_AGREE( qureg, refVec );
278 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), testFunc); }
287 SECTION( LABEL_CORRECTNESS ) {
289 int numTotalRows = getPow2(getNumCachedQubits());
290 int numTotalAmps = numTotalRows * numTotalRows;
293 GENERATE( range(0,1000) );
295 int startInd =
getRandomInt(0, numTotalAmps - numSetAmps);
296 qvector amps = getRandomVector(numSetAmps);
298 auto testFunc = [&](
Qureg qureg) {
301 qmatrix refMat = getRandomMatrix(numTotalRows);
302 setQuregToReference(qureg, refMat);
305 refMat = getTranspose(refMat);
307 refMat = getTranspose(refMat);
313 REQUIRE_AGREE( qureg, refMat );
316 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), testFunc); }
325 SECTION( LABEL_CORRECTNESS ) {
327 int numTotalRowsCols = getPow2(getNumCachedQubits());
330 GENERATE( range(0,1000) );
333 int startRow =
getRandomInt(0, numTotalRowsCols - numSetRows);
334 int startCol =
getRandomInt(0, numTotalRowsCols - numSetCols);
337 qmatrix amps = getRandomNonSquareMatrix(numSetRows, numSetCols);
339 auto testFunc = [&](
Qureg qureg) {
342 qmatrix refMat = getRandomMatrix(numTotalRowsCols);
343 setQuregToReference(qureg, refMat);
346 std::vector<qcomp*> rowPtrs(numSetRows);
347 for (
size_t r=0; r<numSetRows; r++)
348 rowPtrs[r] = amps[r].data();
355 REQUIRE_AGREE( qureg, refMat );
358 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), testFunc); }
368 SECTION( LABEL_CORRECTNESS ) {
370 GENERATE( range(0,10) );
371 qindex dim = getPow2(getNumCachedQubits());
372 qvector refVec = getRandomVector(dim);
373 qmatrix refMat = getRandomMatrix(dim);
376 if (doScalarsAgree(getTrace(refMat), 0))
377 refMat[0][0] += 1/(qreal) dim;
384 refVec = getNormalised(refVec);
387 refMat /= getReferenceProbability(refMat);
389 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), funcVec, refVec); }
390 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), funcMat, refMat); }
399 SECTION( LABEL_CORRECTNESS ) {
401 GENERATE( range(0,10) );
402 int numQubits = getNumCachedQubits();
403 int numTerms = GENERATE_COPY( 1, numQubits, getPow2(2*numQubits) );
404 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
405 qmatrix refMat = getMatrix(sum, numQubits);
409 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFunc, refMat); }
416TEST_CASE(
"setQuregToWeightedSum", TEST_CATEGORY ) {
418 SECTION( LABEL_CORRECTNESS ) {
428 qindex quregDim = getPow2(getNumCachedQubits());
431 int numInQuregs = GENERATE( 1, 2, 3, 4, 5, 6, 20 );
432 CAPTURE( numInQuregs );
434 vector<qcomp> coeffs = getRandomVector(numInQuregs);
439 vector<Qureg> inQuregs(numInQuregs);
444 auto apiFuncGen = [&](
auto& inRefs) {
446 return [&](
Qureg outQureg) {
449 for (
int i=0; i<numInQuregs; i++) {
451 setQuregToReference(inQuregs[i], inRefs[i]);
458 for (
int i=0; i<numInQuregs; i++)
463 SECTION( LABEL_STATEVEC ) {
466 vector<qvector> inVecRefs(numInQuregs);
467 for (
int i=0; i<numInQuregs; i++)
468 inVecRefs[i] = getRandomVector(quregDim);
471 qvector outVecRef = getZeroVector(quregDim);
472 for (
int i=0; i<numInQuregs; i++)
473 outVecRef += coeffs[i] * inVecRefs[i];
475 TEST_ON_CACHED_QUREGS(getCachedStatevecs(), apiFuncGen(inVecRefs), outVecRef);
478 SECTION( LABEL_DENSMATR ) {
481 vector<qmatrix> inMatrRefs(numInQuregs);
482 for (
int i=0; i<numInQuregs; i++)
483 inMatrRefs[i] = getRandomMatrix(quregDim);
487 for (
int i=0; i<numInQuregs; i++)
488 outMatrRef += coeffs[i] * inMatrRefs[i];
490 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFuncGen(inMatrRefs), outMatrRef);
494 SECTION( LABEL_VALIDATION ) {
496 Qureg qureg = getArbitraryCachedStatevec();
498 SECTION(
"out qureg uninitialised" ) {
502 badQureg.numQubits = -123;
506 ContainsSubstring(
"invalid Qureg") );
509 SECTION(
"in qureg uninitialised" ) {
513 vector<Qureg> inQuregs(numIn, qureg);
517 badQureg.numQubits = -123;
518 int badInd = GENERATE_COPY( range(0,numIn) );
519 inQuregs[badInd] = badQureg;
523 ContainsSubstring(
"invalid Qureg") );
526 SECTION(
"invalid number of quregs" ) {
528 int numIn = GENERATE( -1, 0 );
532 ContainsSubstring(
"number of passed Quregs") && ContainsSubstring(
"is invalid") );
535 SECTION(
"inconsistent qureg types" ) {
543 vector<Qureg> inQuregs(numIn, sv);
546 int badInd = GENERATE_COPY( range(0,numIn) );
547 inQuregs[badInd] = dm;
551 ContainsSubstring(
"inconsistent attributes") );
557 SECTION(
"inconsistent qureg sizes" ) {
565 vector<Qureg> inQuregs(numIn, quregA);
568 int badInd = GENERATE_COPY( range(0,numIn) );
569 inQuregs[badInd] = quregB;
573 ContainsSubstring(
"inconsistent attributes") );
579 SECTION(
"inconsistent qureg deployments" ) {
584 for (
auto& [label, badQureg]: getCachedStatevecs()) {
586 if ((badQureg.isGpuAccelerated == qureg.isGpuAccelerated) &&
587 (badQureg.isDistributed == qureg.isDistributed))
592 vector<Qureg> inQuregs(numIn, qureg);
595 int badInd = GENERATE_COPY( range(0,numIn) );
596 inQuregs[badInd] = badQureg;
600 ContainsSubstring(
"inconsistent attributes") );
607 SECTION(
"different number of quregs and coeffs") {
615 ContainsSubstring(
"different number of coefficients") );
621TEST_CASE(
"setQuregToMixture", TEST_CATEGORY ) {
623 SECTION( LABEL_CORRECTNESS ) {
634 int numInQuregs = GENERATE( 1, 2, 3, 4, 5, 6, 20 );
635 CAPTURE( numInQuregs );
642 vector<Qureg> inQuregs(numInQuregs);
644 SECTION( LABEL_DENSMATR ) {
647 vector<qmatrix> inMatrRefs(numInQuregs);
648 for (
int i=0; i<numInQuregs; i++)
649 inMatrRefs[i] = getRandomMatrix(getPow2(getNumCachedQubits()));
652 qmatrix outMatrRef =
getZeroMatrix(getPow2(getNumCachedQubits()));
653 for (
int i=0; i<numInQuregs; i++)
654 outMatrRef += probs[i] * inMatrRefs[i];
656 auto apiFunc = [&](
Qureg outQureg) {
659 for (
int i=0; i<numInQuregs; i++) {
661 setQuregToReference(inQuregs[i], inMatrRefs[i]);
668 for (
int i=0; i<numInQuregs; i++)
672 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFunc, outMatrRef);
676 SECTION( LABEL_VALIDATION ) {
679 Qureg qureg = getCachedDensmatrs().begin()->second;
681 SECTION(
"out qureg uninitialised" ) {
685 badQureg.numQubits = -123;
689 ContainsSubstring(
"invalid Qureg") );
692 SECTION(
"in qureg uninitialised" ) {
696 vector<Qureg> inQuregs(numIn, qureg);
700 badQureg.numQubits = -123;
701 int badInd = GENERATE_COPY( range(0,numIn) );
702 inQuregs[badInd] = badQureg;
706 ContainsSubstring(
"invalid Qureg") );
709 SECTION(
"out qureg is statevector" ) {
711 Qureg badQureg = getArbitraryCachedStatevec();
715 ContainsSubstring(
"received a statevector") );
718 SECTION(
"in qureg is statevector" ) {
722 vector<Qureg> inQuregs(numIn, qureg);
725 int badInd = GENERATE_COPY( range(0,numIn) );
726 inQuregs[badInd] = getArbitraryCachedStatevec();
730 ContainsSubstring(
"One or more Quregs were statevectors") );
733 SECTION(
"number of quregs" ) {
735 int numIn = GENERATE( -1, 0 );
739 ContainsSubstring(
"number of passed Quregs") && ContainsSubstring(
"is invalid") );
742 SECTION(
"inconsistent qureg sizes" ) {
750 vector<Qureg> inQuregs(numIn, quregA);
753 int badInd = GENERATE_COPY( range(0,numIn) );
754 inQuregs[badInd] = quregB;
758 ContainsSubstring(
"inconsistent attributes") );
764 SECTION(
"inconsistent qureg deployments" ) {
769 for (
auto& [label, badQureg]: getCachedDensmatrs()) {
771 if ((badQureg.isGpuAccelerated == qureg.isGpuAccelerated) &&
772 (badQureg.isDistributed == qureg.isDistributed))
777 vector<Qureg> inQuregs(numIn, qureg);
780 int badInd = GENERATE_COPY( range(0,numIn) );
781 inQuregs[badInd] = badQureg;
785 ContainsSubstring(
"inconsistent attributes") );
792 SECTION(
"invalid probs" ) {
796 vector<Qureg> inQuregs(numIn, qureg);
799 int badInd = GENERATE_COPY( range(0,numIn) );
801 probs[badInd] = GENERATE( -1., -0.1, 1.1, 2. );
805 ContainsSubstring(
"One or more given probabilities are invalid") );
808 SECTION(
"unnormalised probs" ) {
812 vector<Qureg> inQuregs(numIn, qureg);
815 qreal probSum = GENERATE( 0.9, 1.1 );
816 vector<qreal> probs(numIn, probSum / numIn);
820 ContainsSubstring(
"probabilities do not sum to") && ContainsSubstring(
"one") );
823 SECTION(
"different number of quregs and probs") {
831 ContainsSubstring(
"different number of probabilities") );
qreal calcPurity(Qureg qureg)
qreal calcTotalProb(Qureg qureg)
void setDensityQuregFlatAmps(Qureg qureg, qindex startInd, qcomp *amps, qindex numAmps)
void setQuregToReducedDensityMatrix(Qureg out, Qureg in, int *retainQubits, int numRetainQubits)
void setQuregToWeightedSum(Qureg out, qcomp *coeffs, Qureg *in, int numIn)
void setQuregToPauliStrSum(Qureg qureg, PauliStrSum sum)
void setQuregToClone(Qureg targetQureg, Qureg copyQureg)
void setQuregToMixture(Qureg out, qreal *probs, Qureg *in, int numIn)
void setQuregAmps(Qureg qureg, qindex startInd, qcomp *amps, qindex numAmps)
void setQuregToPartialTrace(Qureg out, Qureg in, int *traceOutQubits, int numTraceQubits)
qreal setQuregToRenormalized(Qureg qureg)
void setDensityQuregAmps(Qureg qureg, qindex startRow, qindex startCol, qcomp **amps, qindex numRows, qindex numCols)
void initArbitraryPureState(Qureg qureg, qcomp *amps)
void initRandomPureState(Qureg qureg)
void initPlusState(Qureg qureg)
void initZeroState(Qureg qureg)
void initPureState(Qureg qureg, Qureg pure)
void initDebugState(Qureg qureg)
void initRandomMixedState(Qureg qureg, qindex numPureStates)
void initClassicalState(Qureg qureg, qindex stateInd)
void initBlankState(Qureg qureg)
Qureg createCloneQureg(Qureg qureg)
Qureg createCustomQureg(int numQubits, int isDensMatr, int useDistrib, int useGpuAccel, int useMultithread)
void destroyQureg(Qureg qureg)
void syncQuregFromGpu(Qureg qureg)
void setSubMatrix(qmatrix &dest, qmatrix sub, size_t r, size_t c)
qmatrix getZeroMatrix(size_t dim)
vector< qreal > getRandomProbabilities(int numProbs)
int getRandomInt(int min, int maxExcl)
static qcomp getQcomp(qreal re, qreal im)
TEST_CASE("initBlankState", TEST_CATEGORY)