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) );
253 int startInd = GENERATE_COPY( range(0,numTotalAmps-numSetAmps) );
254 qvector amps = getRandomVector(numSetAmps);
256 auto testFunc = [&](
Qureg qureg) {
259 qvector refVec = getRandomVector(numTotalAmps);
260 setQuregToReference(qureg, refVec);
263 setSubVector(refVec, amps, startInd);
268 REQUIRE_AGREE( qureg, refVec );
271 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), testFunc); }
280 SECTION( LABEL_CORRECTNESS ) {
282 int numTotalRows = getPow2(getNumCachedQubits());
283 int numTotalAmps = numTotalRows * numTotalRows;
286 GENERATE( range(0,1000) );
288 int startInd =
getRandomInt(0, numTotalAmps - numSetAmps);
289 qvector amps = getRandomVector(numSetAmps);
291 auto testFunc = [&](
Qureg qureg) {
294 qmatrix refMat = getRandomMatrix(numTotalRows);
295 setQuregToReference(qureg, refMat);
298 refMat = getTranspose(refMat);
300 refMat = getTranspose(refMat);
306 REQUIRE_AGREE( qureg, refMat );
309 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), testFunc); }
318 SECTION( LABEL_CORRECTNESS ) {
320 int numTotalRowsCols = getPow2(getNumCachedQubits());
323 GENERATE( range(0,1000) );
326 int startRow =
getRandomInt(0, numTotalRowsCols - numSetRows);
327 int startCol =
getRandomInt(0, numTotalRowsCols - numSetCols);
330 qmatrix amps = getRandomNonSquareMatrix(numSetRows, numSetCols);
332 auto testFunc = [&](
Qureg qureg) {
335 qmatrix refMat = getRandomMatrix(numTotalRowsCols);
336 setQuregToReference(qureg, refMat);
339 std::vector<qcomp*> rowPtrs(numSetRows);
340 for (
size_t r=0; r<numSetRows; r++)
341 rowPtrs[r] = amps[r].data();
348 REQUIRE_AGREE( qureg, refMat );
351 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), testFunc); }
361 SECTION( LABEL_CORRECTNESS ) {
363 GENERATE( range(0,10) );
364 qindex dim = getPow2(getNumCachedQubits());
365 qvector refVec = getRandomVector(dim);
366 qmatrix refMat = getRandomMatrix(dim);
369 if (doScalarsAgree(getTrace(refMat), 0))
370 refMat[0][0] += 1/(qreal) dim;
377 refVec = getNormalised(refVec);
380 refMat /= getReferenceProbability(refMat);
382 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), funcVec, refVec); }
383 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), funcMat, refMat); }
392 SECTION( LABEL_CORRECTNESS ) {
394 GENERATE( range(0,10) );
395 int numQubits = getNumCachedQubits();
396 int numTerms = GENERATE_COPY( 1, numQubits, getPow2(2*numQubits) );
397 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
398 qmatrix refMat = getMatrix(sum, numQubits);
402 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFunc, refMat); }
409TEST_CASE(
"setQuregToWeightedSum", TEST_CATEGORY ) {
411 SECTION( LABEL_CORRECTNESS ) {
421 qindex quregDim = getPow2(getNumCachedQubits());
424 int numInQuregs = GENERATE( 1, 2, 3, 4, 5, 6, 20 );
425 CAPTURE( numInQuregs );
427 vector<qcomp> coeffs = getRandomVector(numInQuregs);
432 vector<Qureg> inQuregs(numInQuregs);
437 auto apiFuncGen = [&](
auto& inRefs) {
439 return [&](
Qureg outQureg) {
442 for (
int i=0; i<numInQuregs; i++) {
444 setQuregToReference(inQuregs[i], inRefs[i]);
451 for (
int i=0; i<numInQuregs; i++)
456 SECTION( LABEL_STATEVEC ) {
459 vector<qvector> inVecRefs(numInQuregs);
460 for (
int i=0; i<numInQuregs; i++)
461 inVecRefs[i] = getRandomVector(quregDim);
464 qvector outVecRef = getZeroVector(quregDim);
465 for (
int i=0; i<numInQuregs; i++)
466 outVecRef += coeffs[i] * inVecRefs[i];
468 TEST_ON_CACHED_QUREGS(getCachedStatevecs(), apiFuncGen(inVecRefs), outVecRef);
471 SECTION( LABEL_DENSMATR ) {
474 vector<qmatrix> inMatrRefs(numInQuregs);
475 for (
int i=0; i<numInQuregs; i++)
476 inMatrRefs[i] = getRandomMatrix(quregDim);
480 for (
int i=0; i<numInQuregs; i++)
481 outMatrRef += coeffs[i] * inMatrRefs[i];
483 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFuncGen(inMatrRefs), outMatrRef);
487 SECTION( LABEL_VALIDATION ) {
490 Qureg qureg = getCachedStatevecs().begin()->second;
492 SECTION(
"out qureg uninitialised" ) {
496 badQureg.numQubits = -123;
500 ContainsSubstring(
"invalid Qureg") );
503 SECTION(
"in qureg uninitialised" ) {
507 vector<Qureg> inQuregs(numIn, qureg);
511 badQureg.numQubits = -123;
512 int badInd = GENERATE_COPY( range(0,numIn) );
513 inQuregs[badInd] = badQureg;
517 ContainsSubstring(
"invalid Qureg") );
520 SECTION(
"invalid number of quregs" ) {
522 int numIn = GENERATE( -1, 0 );
526 ContainsSubstring(
"number of passed Quregs") && ContainsSubstring(
"is invalid") );
529 SECTION(
"inconsistent qureg types" ) {
537 vector<Qureg> inQuregs(numIn, sv);
540 int badInd = GENERATE_COPY( range(0,numIn) );
541 inQuregs[badInd] = dm;
545 ContainsSubstring(
"inconsistent attributes") );
551 SECTION(
"inconsistent qureg sizes" ) {
559 vector<Qureg> inQuregs(numIn, quregA);
562 int badInd = GENERATE_COPY( range(0,numIn) );
563 inQuregs[badInd] = quregB;
567 ContainsSubstring(
"inconsistent attributes") );
573 SECTION(
"inconsistent qureg deployments" ) {
578 for (
auto& [label, badQureg]: getCachedStatevecs()) {
580 if ((badQureg.isGpuAccelerated == qureg.isGpuAccelerated) &&
581 (badQureg.isDistributed == qureg.isDistributed))
586 vector<Qureg> inQuregs(numIn, qureg);
589 int badInd = GENERATE_COPY( range(0,numIn) );
590 inQuregs[badInd] = badQureg;
594 ContainsSubstring(
"inconsistent attributes") );
601 SECTION(
"different number of quregs and coeffs") {
609 ContainsSubstring(
"different number of coefficients") );
615TEST_CASE(
"setQuregToMixture", TEST_CATEGORY ) {
617 SECTION( LABEL_CORRECTNESS ) {
628 int numInQuregs = GENERATE( 1, 2, 3, 4, 5, 6, 20 );
629 CAPTURE( numInQuregs );
636 vector<Qureg> inQuregs(numInQuregs);
638 SECTION( LABEL_DENSMATR ) {
641 vector<qmatrix> inMatrRefs(numInQuregs);
642 for (
int i=0; i<numInQuregs; i++)
643 inMatrRefs[i] = getRandomMatrix(getPow2(getNumCachedQubits()));
646 qmatrix outMatrRef =
getZeroMatrix(getPow2(getNumCachedQubits()));
647 for (
int i=0; i<numInQuregs; i++)
648 outMatrRef += probs[i] * inMatrRefs[i];
650 auto apiFunc = [&](
Qureg outQureg) {
653 for (
int i=0; i<numInQuregs; i++) {
655 setQuregToReference(inQuregs[i], inMatrRefs[i]);
662 for (
int i=0; i<numInQuregs; i++)
666 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFunc, outMatrRef);
670 SECTION( LABEL_VALIDATION ) {
673 Qureg qureg = getCachedDensmatrs().begin()->second;
675 SECTION(
"out qureg uninitialised" ) {
679 badQureg.numQubits = -123;
683 ContainsSubstring(
"invalid Qureg") );
686 SECTION(
"in qureg uninitialised" ) {
690 vector<Qureg> inQuregs(numIn, qureg);
694 badQureg.numQubits = -123;
695 int badInd = GENERATE_COPY( range(0,numIn) );
696 inQuregs[badInd] = badQureg;
700 ContainsSubstring(
"invalid Qureg") );
703 SECTION(
"out qureg is statevector" ) {
705 Qureg badQureg = getCachedStatevecs().begin()->second;
709 ContainsSubstring(
"received a statevector") );
712 SECTION(
"in qureg is statevector" ) {
716 vector<Qureg> inQuregs(numIn, qureg);
719 int badInd = GENERATE_COPY( range(0,numIn) );
720 inQuregs[badInd] = getCachedStatevecs().begin()->second;;
724 ContainsSubstring(
"One or more Quregs were statevectors") );
727 SECTION(
"number of quregs" ) {
729 int numIn = GENERATE( -1, 0 );
733 ContainsSubstring(
"number of passed Quregs") && ContainsSubstring(
"is invalid") );
736 SECTION(
"inconsistent qureg sizes" ) {
744 vector<Qureg> inQuregs(numIn, quregA);
747 int badInd = GENERATE_COPY( range(0,numIn) );
748 inQuregs[badInd] = quregB;
752 ContainsSubstring(
"inconsistent attributes") );
758 SECTION(
"inconsistent qureg deployments" ) {
763 for (
auto& [label, badQureg]: getCachedDensmatrs()) {
765 if ((badQureg.isGpuAccelerated == qureg.isGpuAccelerated) &&
766 (badQureg.isDistributed == qureg.isDistributed))
771 vector<Qureg> inQuregs(numIn, qureg);
774 int badInd = GENERATE_COPY( range(0,numIn) );
775 inQuregs[badInd] = badQureg;
779 ContainsSubstring(
"inconsistent attributes") );
786 SECTION(
"invalid probs" ) {
790 vector<Qureg> inQuregs(numIn, qureg);
793 int badInd = GENERATE_COPY( range(0,numIn) );
795 probs[badInd] = GENERATE( -1., -0.1, 1.1, 2. );
799 ContainsSubstring(
"One or more given probabilities are invalid") );
802 SECTION(
"unnormalised probs" ) {
806 vector<Qureg> inQuregs(numIn, qureg);
809 qreal probSum = GENERATE( 0.9, 1.1 );
810 vector<qreal> probs(numIn, probSum / numIn);
814 ContainsSubstring(
"probabilities do not sum to") && ContainsSubstring(
"one") );
817 SECTION(
"different number of quregs and probs") {
825 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)