24#include <catch2/catch_test_macros.hpp>
25#include <catch2/catch_template_test_macros.hpp>
26#include <catch2/matchers/catch_matchers_string.hpp>
27#include <catch2/matchers/catch_matchers_floating_point.hpp>
28#include <catch2/generators/catch_generators_range.hpp>
30#include "tests/utils/config.hpp"
31#include "tests/utils/cache.hpp"
32#include "tests/utils/qvector.hpp"
33#include "tests/utils/qmatrix.hpp"
34#include "tests/utils/compare.hpp"
35#include "tests/utils/convert.hpp"
36#include "tests/utils/evolve.hpp"
37#include "tests/utils/linalg.hpp"
38#include "tests/utils/lists.hpp"
39#include "tests/utils/measure.hpp"
40#include "tests/utils/macros.hpp"
41#include "tests/utils/random.hpp"
46using Catch::Matchers::ContainsSubstring;
53extern int paulis_getPauliAt(
PauliStr str,
int ind);
60#define TEST_CATEGORY_OPS \
61 LABEL_UNIT_TAG "[operations]"
63#define TEST_CATEGORY_MULT \
64 LABEL_UNIT_TAG "[multiplication]"
71namespace FixedMatrices {
74 {1/std::sqrt(2), 1/std::sqrt(2)},
75 {1/std::sqrt(2), -1/std::sqrt(2)}};
77 qmatrix X = getPauliMatrix(1);
78 qmatrix Y = getPauliMatrix(2);
79 qmatrix Z = getPauliMatrix(3);
81 qreal PI = 3.14159265358979323846;
84 {0, std::exp(1_i * PI/4)}};
98 {0, (1+1_i)/2, (1-1_i)/2, 0},
99 {0, (1-1_i)/2, (1+1_i)/2, 0},
103namespace ParameterisedMatrices {
105 auto Rx = [](qreal p) {
return getExponentialOfPauliMatrix(p, FixedMatrices::X); };
106 auto Ry = [](qreal p) {
return getExponentialOfPauliMatrix(p, FixedMatrices::Y); };
107 auto Rz = [](qreal p) {
return getExponentialOfPauliMatrix(p, FixedMatrices::Z); };
109 auto PS = [](qreal p) {
return qmatrix{{1, 0}, {0, std::exp(p*1_i)}}; };
110 auto PS2 = [](qreal p) {
return getControlledMatrix(PS(p), 1); };
113namespace VariableSizeMatrices {
116 auto PF = [](
int n) {
return getControlledMatrix(FixedMatrices::Z, n - 1); };
119namespace VariableSizeParameterisedMatrices {
121 auto Z = [](qreal p,
int n) {
123 return getExponentialOfPauliMatrix(p, m);
126 auto PS = [](qreal p,
int n) {
127 qmatrix m = ParameterisedMatrices::PS(p);
128 return getControlledMatrix(m, n - 1);
143void TEST_ON_CACHED_QUREGS(quregCache quregs,
auto& reference,
auto& function) {
145 for (
auto& [label, qureg]: quregs) {
147 DYNAMIC_SECTION( label ) {
153 setToDebugState(reference);
155 function(qureg, reference);
156 REQUIRE_AGREE( qureg, reference );
161void TEST_ON_CACHED_QUREG_AND_MATRIX(quregCache quregs, matrixCache matrices,
auto apiFunc,
auto refState,
auto refMatr,
auto refFunc) {
163 for (
auto& [labelA, qureg]: quregs) {
164 for (
auto& [labelB, matrix]: matrices) {
167 if (matrix.isDistributed && ! qureg.isDistributed)
170 DYNAMIC_SECTION( labelA + LABEL_DELIMITER + labelB ) {
174 setToDebugState(refState);
180 apiFunc(qureg, matrix);
181 refFunc(refState, refMatr);
182 REQUIRE_AGREE( qureg, refState );
193#define PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef ) \
194 int numQubits = getNumCachedQubits(); \
195 auto statevecQuregs = getCachedStatevecs(); \
196 auto densmatrQuregs = getCachedDensmatrs(); \
197 qvector statevecRef = getZeroVector(getPow2(numQubits)); \
198 qmatrix densmatrRef = getZeroMatrix(getPow2(numQubits));
221enum ArgsFlag { none, scalar, axisrots, diagmatr, diagpower, compmatr, paulistr, pauligad };
238enum NumQubitsFlag { zero, one, two, any, anystates };
240void assertNumQubitsFlagsAreValid(NumQubitsFlag ctrlsFlag, NumQubitsFlag targsFlag) {
246 ctrlsFlag == anystates );
255void assertNumQubitsFlagsValid(
256 NumQubitsFlag ctrlsFlag, NumQubitsFlag targsFlag,
257 vector<int> ctrls, vector<int> states, vector<int> targs
259 assertNumQubitsFlagsAreValid(ctrlsFlag, targsFlag);
266 if (targsFlag == one)
267 DEMAND( targs.size() == 1 );
269 if (targsFlag == two)
270 DEMAND( targs.size() == 2 );
272 if (ctrlsFlag == zero)
273 DEMAND( ctrls.size() == 0 );
275 if (ctrlsFlag == one)
276 DEMAND( ctrls.size() == 1 );
278 if (ctrlsFlag == anystates)
279 DEMAND( states.size() == ctrls.size() );
281 DEMAND( states.size() == 0 );
294template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
295int GENERATE_NUM_TARGS(
int numQuregQubits) {
297 assertNumQubitsFlagsAreValid(zero, Targs);
298 DEMAND( Targs != one || numQuregQubits >= 1 );
299 DEMAND( Targs != two || numQuregQubits >= 2 );
300 DEMAND( numQuregQubits > 0 );
303 if constexpr (Targs == one)
305 if constexpr (Targs == two)
308 if constexpr (Targs == any) {
311 int maxNumTargs = numQuregQubits;
317 if (Args == compmatr)
318 maxNumTargs = numQuregQubits - getLog2(
getQuESTEnv().numNodes);
321 if (Ctrls == one && maxNumTargs == numQuregQubits)
324 return GENERATE_COPY( range(1, maxNumTargs+1) );
328template <NumQubitsFlag Ctrls>
329int GENERATE_NUM_CTRLS(
int numFreeQubits) {
331 assertNumQubitsFlagsAreValid(Ctrls, one);
332 DEMAND( Ctrls != one || numFreeQubits >= 1 );
333 DEMAND( numFreeQubits >= 0 );
335 if constexpr (Ctrls == zero)
338 if constexpr (Ctrls == one)
341 if constexpr (Ctrls == any || Ctrls == anystates)
342 return GENERATE_COPY( range(0, numFreeQubits+1) );
363template <NumQubitsFlag Ctrls, NumQubitsFlag Targs>
364void invokeApiOperation(
365 auto operation,
Qureg qureg,
366 vector<int> ctrls, vector<int> states,
int numCtrls,
367 vector<int> targs,
int numTargs,
370 assertNumQubitsFlagsValid(Ctrls, Targs, ctrls, states, targs);
372 if constexpr (Ctrls == zero) {
373 if constexpr (Targs == zero) operation(qureg, args...);
374 if constexpr (Targs == one) operation(qureg, targs[0], args...);
375 if constexpr (Targs == two) operation(qureg, targs[0], targs[1], args...);
376 if constexpr (Targs == any) operation(qureg, targs.data(), numTargs, args...);
378 if constexpr (Ctrls == one) {
379 if constexpr (Targs == zero) operation(qureg, ctrls[0], args...);
380 if constexpr (Targs == one) operation(qureg, ctrls[0], targs[0], args...);
381 if constexpr (Targs == two) operation(qureg, ctrls[0], targs[0], targs[1], args...);
382 if constexpr (Targs == any) operation(qureg, ctrls[0], targs.data(), numTargs, args...);
384 if constexpr (Ctrls == any) {
385 if constexpr (Targs == zero) operation(qureg, ctrls.data(), numCtrls, args...);
386 if constexpr (Targs == one) operation(qureg, ctrls.data(), numCtrls, targs[0], args...);
387 if constexpr (Targs == two) operation(qureg, ctrls.data(), numCtrls, targs[0], targs[1], args...);
388 if constexpr (Targs == any) operation(qureg, ctrls.data(), numCtrls, targs.data(), numTargs, args...);
390 if constexpr (Ctrls == anystates) {
391 if constexpr (Targs == zero) operation(qureg, ctrls.data(), states.data(), numCtrls, args...);
392 if constexpr (Targs == one) operation(qureg, ctrls.data(), states.data(), numCtrls, targs[0], args...);
393 if constexpr (Targs == two) operation(qureg, ctrls.data(), states.data(), numCtrls, targs[0], targs[1], args...);
394 if constexpr (Targs == any) operation(qureg, ctrls.data(), states.data(), numCtrls, targs.data(), numTargs, args...);
400template <NumQubitsFlag Ctrls, NumQubitsFlag Targs>
401void invokeApiOperation(
auto operation,
Qureg qureg, vector<int> ctrls, vector<int> states, vector<int> targs,
auto&... args) {
402 invokeApiOperation<Ctrls,Targs>(operation, qureg, ctrls, states, ctrls.size(), targs, targs.size(), args...);
415template <NumQubitsFlag Targs, ArgsFlag Args>
416auto getRandomOrIdentityApiMatrix(
int numTargs,
int elemsFlag) {
433 qm = (Args == compmatr)?
435 getRandomDiagonalUnitary(numTargs);
437 if constexpr (Args == compmatr && Targs == one)
440 if constexpr (Args == compmatr && Targs == two)
443 if constexpr (Args == compmatr && Targs == any) {
449 qvector dv = getDiagonals(qm);
450 constexpr bool diag = (Args == diagmatr || Args == diagpower);
452 if constexpr (diag && Targs == one)
455 if constexpr (diag && Targs == two)
458 if constexpr (diag && Targs == any) {
465template <NumQubitsFlag Targs, ArgsFlag Args>
auto getZeroApiMatrix (
int numTargs) {
return getRandomOrIdentityApiMatrix<Targs,Args>(numTargs, 0); }
466template <NumQubitsFlag Targs, ArgsFlag Args>
auto getIdentityApiMatrix(
int numTargs) {
return getRandomOrIdentityApiMatrix<Targs,Args>(numTargs, 1); }
467template <NumQubitsFlag Targs, ArgsFlag Args>
auto getRandomApiMatrix (
int numTargs) {
return getRandomOrIdentityApiMatrix<Targs,Args>(numTargs, 2); }
480template <NumQubitsFlag Targs, ArgsFlag Args>
481auto getRandomRemainingArgs(vector<int> targs) {
483 if constexpr (Args == none)
486 if constexpr (Args == scalar) {
487 qreal angle = getRandomPhase();
488 return tuple{ angle };
491 if constexpr (Args == axisrots) {
492 qreal angle = getRandomPhase();
496 return tuple{ angle, x, y, z };
499 if constexpr (Args == compmatr || Args == diagmatr) {
500 auto matrix = getRandomApiMatrix<Targs,Args>(targs.size());
501 return tuple{ matrix };
504 if constexpr (Args == diagpower) {
505 DiagMatr matrix = getRandomApiMatrix<Targs,Args>(targs.size());
507 return tuple{ matrix, exponent };
510 if constexpr (Args == paulistr) {
511 PauliStr str = getRandomPauliStr(targs);
515 if constexpr (Args == pauligad) {
516 PauliStr str = getRandomPauliStr(targs);
517 qreal angle = getRandomPhase();
518 return tuple{ str, angle };
523template <NumQubitsFlag Targs, ArgsFlag Args>
524void freeRemainingArgs(
auto args) {
526 if constexpr (Targs == any && Args == compmatr)
529 if constexpr (Targs == any && Args == diagmatr)
532 if constexpr (Targs == any && Args == diagpower)
545template <NumQubitsFlag Targs, ArgsFlag Args>
546qmatrix getReferenceMatrix(
auto matrixRefGen, vector<int> targs,
auto additionalArgs) {
548 if constexpr (Args == none && Targs != any)
551 if constexpr (Args == none && Targs == any)
552 return matrixRefGen(targs.size());
554 if constexpr (Args == scalar && Targs != any) {
555 qreal angle = std::get<0>(additionalArgs);
556 return matrixRefGen(angle);
559 if constexpr (Args == scalar && Targs == any) {
560 qreal angle = std::get<0>(additionalArgs);
561 return matrixRefGen(angle, targs.size());
564 if constexpr (Args == axisrots) {
565 qreal angle = std::get<0>(additionalArgs);
566 qreal x = std::get<1>(additionalArgs);
567 qreal y = std::get<2>(additionalArgs);
568 qreal z = std::get<3>(additionalArgs);
569 return getExponentialOfNormalisedPauliVector(angle, x, y, z);
572 if constexpr (Args == compmatr || Args == diagmatr) {
573 auto apiMatrix = std::get<0>(additionalArgs);
574 return getMatrix(apiMatrix);
577 if constexpr (Args == diagpower) {
578 auto apiMatrix = std::get<0>(additionalArgs);
579 qmatrix diag = getMatrix(apiMatrix);
580 qcomp power = std::get<1>(additionalArgs);
581 return getPowerOfDiagonalMatrix(diag, power);
584 if constexpr (Args == paulistr) {
585 PauliStr str = std::get<0>(additionalArgs);
586 return getMatrix(str, targs);
589 if constexpr (Args == pauligad) {
590 PauliStr str = std::get<0>(additionalArgs);
591 qreal angle = std::get<1>(additionalArgs);
592 qmatrix matr = getMatrix(str, targs);
593 return getExponentialOfPauliMatrix(angle, matr);
614enum ApplyFlag { apply, leftapply, rightapply };
630std::string toString(vector<int> list) {
632 std::string out =
"{ ";
634 out += std::to_string(e) +
" ";
639std::string toString(
PauliStr str, vector<int> targs) {
641 std::string labels =
"IXYZ";
644 std::string out =
"";
645 for (
int i=targs.size()-1; i>=0; i--)
646 out += labels[paulis_getPauliAt(str, targs[i])];
651template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
652void CAPTURE_RELEVANT( vector<int> ctrls, vector<int> states, vector<int> targs,
auto& args ) {
656 UNSCOPED_INFO(
"control := " << ctrls[0] );
657 if (Ctrls == any || Ctrls == anystates )
658 UNSCOPED_INFO(
"controls := " << toString(ctrls) );
661 if (Ctrls == anystates)
662 UNSCOPED_INFO(
"states := " << toString(states) );
666 UNSCOPED_INFO(
"target := " << targs[0] );
669 UNSCOPED_INFO(
"target A := " << targs[0] );
670 UNSCOPED_INFO(
"target B := " << targs[1] );
673 UNSCOPED_INFO(
"targets := " << toString(targs) );
676 if constexpr (Args == scalar)
677 UNSCOPED_INFO(
"angle := " << std::get<0>(args) );
680 if constexpr (Args == axisrots) {
681 UNSCOPED_INFO(
"angle := " << std::get<0>(args) );
682 UNSCOPED_INFO(
"x := " << std::get<1>(args) );
683 UNSCOPED_INFO(
"y := " << std::get<2>(args) );
684 UNSCOPED_INFO(
"z := " << std::get<3>(args) );
688 if constexpr (Args == compmatr || Args == diagmatr || Args == diagpower)
689 UNSCOPED_INFO(
"matrix := (omitted)" );
692 if constexpr (Args == diagpower) {
693 qcomp p = std::get<1>(args);
694 UNSCOPED_INFO(
"exponent := " << std::real(p) <<
" + (" << std::imag(p) <<
")i" );
698 if constexpr (Args == paulistr || Args == pauligad)
699 UNSCOPED_INFO(
"paulis := " << toString(std::get<0>(args), targs) );
702 if constexpr (Args == pauligad)
703 UNSCOPED_INFO(
"angle := " << std::get<1>(args) );
715template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args, ApplyFlag Apply>
716void testOperationCorrectness(
auto operation,
auto matrixRefGen) {
718 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
721 int numTargs = GENERATE_NUM_TARGS<Ctrls,Targs,Args>(numQubits);
722 int numCtrls = GENERATE_NUM_CTRLS<Ctrls>(numQubits - numTargs);
725 auto ctrlsAndTargs = GENERATE_CTRLS_AND_TARGS( numQubits, numCtrls, numTargs );
726 vector<int> ctrls = std::get<0>(ctrlsAndTargs);
727 vector<int> targs = std::get<1>(ctrlsAndTargs);
730 vector<int> states = getRandomOutcomes(numCtrls * (Ctrls == anystates));
733 auto primaryArgs = tuple{ ctrls, states, targs };
734 auto furtherArgs = getRandomRemainingArgs<Targs,Args>(targs);
737 qmatrix matrixRef = getReferenceMatrix<Targs,Args>(matrixRefGen, targs, furtherArgs);
740 constexpr NumQubitsFlag RevTargs = (Args==paulistr||Args==pauligad)? zero : Targs;
751 auto testFunc = [&](
Qureg qureg,
auto& stateRef) ->
void {
754 auto apiFunc = [](
auto&&... args) {
return invokeApiOperation<Ctrls,RevTargs>(args...); };
755 auto allArgs = std::tuple_cat(tuple{operation, qureg}, primaryArgs, furtherArgs);
756 std::apply(apiFunc, allArgs);
759 if constexpr (Apply == apply) applyReferenceOperator( stateRef, ctrls, states, targs, matrixRef);
760 if constexpr (Apply == leftapply) leftapplyReferenceOperator( stateRef, ctrls, states, targs, matrixRef);
761 if constexpr (Apply == rightapply) rightapplyReferenceOperator(stateRef, ctrls, states, targs, matrixRef);
765 CAPTURE_RELEVANT<Ctrls,Targs,Args>( ctrls, states, targs, furtherArgs );
769 if constexpr (Apply != rightapply) {
770 SECTION( LABEL_STATEVEC ) {
771 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc);
774 SECTION( LABEL_DENSMATR ) {
775 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc);
779 freeRemainingArgs<Targs,Args>(furtherArgs);
790template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
791auto getFixedCtrlsStatesTargs(
int numQubits) {
794 vector<int> targs, ctrls, states;
797 if constexpr (Targs == one) targs = {0};
798 if constexpr (Targs == two) targs = {0,1};
799 if constexpr (Targs == any) targs = {0,1,2};
800 if constexpr (Ctrls == one) ctrls = {3};
801 if constexpr (Ctrls == any) ctrls = {3,4};
802 if constexpr (Ctrls == anystates) ctrls = {3,4};
803 if constexpr (Ctrls == anystates) states = {0,0};
805 DEMAND( numQubits >= targs.size() + ctrls.size() );
807 return tuple{ ctrls, states, targs };
810template <NumQubitsFlag Targs, ArgsFlag Args>
811auto getFixedRemainingArgs(vector<int> targs) {
814 if constexpr (Args == paulistr || Args == pauligad)
815 DEMAND( targs.size() == 3 );
817 if constexpr (Args == none)
return tuple{ };
818 if constexpr (Args == scalar)
return tuple{ 0 };
819 if constexpr (Args == axisrots)
return tuple{ 0, 1,1,1 };
820 if constexpr (Args == compmatr)
return tuple{ getIdentityApiMatrix<Targs,Args>(targs.size()) };
821 if constexpr (Args == diagmatr)
return tuple{ getIdentityApiMatrix<Targs,Args>(targs.size()) };
822 if constexpr (Args == diagpower)
return tuple{ getIdentityApiMatrix<Targs,Args>(targs.size()), qcomp(1,0) };
823 if constexpr (Args == paulistr)
return tuple{
getPauliStr(
"XXX", targs) };
824 if constexpr (Args == pauligad)
return tuple{
getPauliStr(
"XXX", targs), 0 };
827template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args, ApplyFlag Apply>
828void testOperationValidation(
auto operation) {
831 Qureg qureg = getCachedDensmatrs().begin()->second;
835 auto [ctrls,states,targs] = getFixedCtrlsStatesTargs<Ctrls,Targs,Args>(qureg.numQubits);
836 auto furtherArgs = getFixedRemainingArgs<Targs,Args>(targs);
839 auto apiFunc = [&]() {
840 constexpr NumQubitsFlag RevTargs = (Args==paulistr||Args==pauligad)? zero : Targs;
841 auto func = [](
auto&&... allArgs) {
return invokeApiOperation<Ctrls,RevTargs>(allArgs...); };
842 std::apply(func, std::tuple_cat(tuple{operation, qureg, ctrls, states, targs}, furtherArgs));
846 int numQubits = qureg.numQubits;
847 int numTargs = (int) targs.size();
848 int numCtrls = (int) ctrls.size();
856 SECTION(
"qureg uninitialised" ) {
859 qureg.numQubits = -123;
860 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"invalid Qureg") );
863 SECTION(
"invalid target" ) {
866 if (Args == paulistr || Args == pauligad)
870 int ind = GENERATE_COPY( range(0,numTargs) );
871 int val = GENERATE_COPY( -1, numQubits );
874 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Invalid target qubit") );
877 SECTION(
"invalid non-Identity Pauli index" ) {
879 if (Args != paulistr && Args != pauligad)
883 if constexpr (Args == paulistr) furtherArgs = tuple{ badStr };
884 if constexpr (Args == pauligad) furtherArgs = tuple{ badStr, 1 };
886 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"highest-index non-identity Pauli operator") && ContainsSubstring(
"exceeds the maximum target") );
889 SECTION(
"invalid control" ) {
895 int ind = GENERATE_COPY( range(0,numCtrls) );
896 int val = GENERATE_COPY( -1, numQubits );
899 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Invalid control qubit") );
902 SECTION(
"control and target collision" ) {
908 int targInd = GENERATE_COPY( range(0,numTargs) );
909 int ctrlInd = GENERATE_COPY( range(0,numCtrls) );
910 ctrls[ctrlInd] = targs[targInd];
912 if (Args==paulistr||Args==pauligad)
913 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"control qubit overlaps a non-identity Pauli operator") );
915 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"qubit appeared among both the control and target qubits") );
918 SECTION(
"control states" ) {
923 int ind = GENERATE_COPY( range(0,numCtrls) );
924 int val = GENERATE( -1, 2 );
927 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"invalid control-state") );
930 SECTION(
"repetition in controls" ) {
935 int ind = GENERATE_COPY( range(1,numCtrls) );
936 ctrls[ind] = ctrls[0];
938 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"control qubits contained duplicates") );
941 SECTION(
"repetition in targets" ) {
944 if (Args==paulistr||Args==pauligad)
950 int ind = GENERATE_COPY( range(1,numTargs) );
951 targs[ind] = targs[0];
953 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"target qubits contained duplicates") );
956 SECTION(
"number of targets" ) {
960 if (Args == paulistr || Args == pauligad)
968 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Must specify one or more targets") );
971 targs = getRange(qureg.numQubits+1);
972 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"number of target qubits") && ContainsSubstring(
"exceeds the number of qubits in the Qureg") );
978 SECTION(
"mismatching matrix size" ) {
983 if (!(Args == compmatr || Args == diagmatr || Args == diagpower))
986 DEMAND( numTargs > 1 );
987 DEMAND( numCtrls + numTargs < numQubits );
989 targs.push_back(numQubits - 1);
990 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"matrix has an inconsistent size") );
994 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"matrix has an inconsistent size") );
997 SECTION(
"matrix unitarity" ) {
1000 if (Args != compmatr && Args != diagmatr && Args != diagpower)
1007 if constexpr (Args == compmatr || Args == diagmatr)
1008 furtherArgs = tuple{ getZeroApiMatrix<Targs,Args>(targs.size()) };
1009 if constexpr (Args == diagpower)
1010 furtherArgs = tuple{ getZeroApiMatrix<Targs,Args>(targs.size()), 1 };
1012 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"unitary") );
1015 SECTION(
"matrix uninitialised" ) {
1018 if constexpr (Args == compmatr || Args == diagmatr || Args == diagpower)
1019 std::get<0>(furtherArgs).numQubits = -1;
1023 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Invalid") );
1026 if constexpr (Args == compmatr || Args == diagmatr || Args == diagpower)
1027 std::get<0>(furtherArgs).numQubits = numTargs;
1030 SECTION(
"matrix unsynced" ) {
1036 if constexpr (Targs == any && (Args == compmatr || Args == diagmatr || Args == diagpower))
1037 *(std::get<0>(furtherArgs).wasGpuSynced) = 0;
1041 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"sync") );
1044 SECTION(
"targeted amps fit in node" ) {
1049 qureg = (Apply == rightapply)?
1050 getArbitraryCachedDensmatr():
1051 getArbitraryCachedStatevec();
1055 if (qureg.numNodes < 2)
1060 int minNumCtrls = (Ctrls == one)? 1 : 0;
1061 int numVecQubits = (qureg.isDensityMatrix)? 2*numQubits : numQubits;
1062 int minNumTargs = numVecQubits - qureg.logNumNodes + 1;
1063 int maxNumTargs = numQubits - minNumCtrls;
1064 if (minNumTargs > maxNumTargs)
1070 if constexpr (Args == compmatr && Targs == any) {
1076 int numNewTargs = GENERATE_COPY( range(minNumTargs, maxNumTargs+1) );
1077 targs = getRange(numNewTargs);
1081 ctrls = vector<int>(minNumCtrls, numQubits - 1);
1085 CompMatr matr = getIdentityApiMatrix<Targs,Args>(numNewTargs);
1086 furtherArgs = tuple{ matr };
1088 CAPTURE( minNumCtrls, numNewTargs, numQubits - minNumCtrls, ctrls, targs );
1089 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"cannot simultaneously store") && ContainsSubstring(
"remote amplitudes") );
1096 SECTION(
"non-unitary exponent" ) {
1102 if constexpr (Args == diagpower)
1103 furtherArgs = tuple{ std::get<0>(furtherArgs), qcomp(1,1) };
1107 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"exponent was not approximately real") );
1110 SECTION(
"diverging exponent" ) {
1117 if constexpr (Args == diagpower)
1118 furtherArgs = tuple{ getZeroApiMatrix<Targs,Args>(numTargs), qcomp(-1,0) };
1122 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"divergences") );
1125 SECTION(
"zero axis rotation" ) {
1127 if constexpr (Args == axisrots) {
1128 furtherArgs = tuple{ 0, 0, 0, 0 };
1132 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"zero vector") );
1135 SECTION(
"qureg type" ) {
1138 if (Apply != rightapply)
1142 qureg = getArbitraryCachedStatevec();
1143 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Expected a density matrix") );
1146 freeRemainingArgs<Targs,Args>(furtherArgs);
1155template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args, ApplyFlag Apply>
1156void testOperation(
auto operation,
auto matrixRefGen) {
1158 assertNumQubitsFlagsAreValid(Ctrls, Targs);
1160 SECTION( LABEL_CORRECTNESS ) {
1161 testOperationCorrectness<Ctrls,Targs,Args,Apply>(operation, matrixRefGen);
1164 SECTION( LABEL_VALIDATION ) {
1165 testOperationValidation<Ctrls,Targs,Args,Apply>(operation);
1205#define GET_FUNC_CTRL_SUB_SIG( numctrls ) GET_FUNC_CTRL_SUB_SIG_##numctrls
1206#define GET_FUNC_CTRL_SUB_SIG_zero
1207#define GET_FUNC_CTRL_SUB_SIG_one int,
1208#define GET_FUNC_CTRL_SUB_SIG_any int*,int,
1209#define GET_FUNC_CTRL_SUB_SIG_anystates int*,int*,int,
1215#define GET_FUNC_TARG_SUB_SIG( numtargs, argtype ) GET_FUNC_TARG_SUB_SIG_##argtype( numtargs )
1216#define GET_FUNC_TARG_SUB_SIG_none( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs
1217#define GET_FUNC_TARG_SUB_SIG_scalar( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1218#define GET_FUNC_TARG_SUB_SIG_axisrots( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1219#define GET_FUNC_TARG_SUB_SIG_compmatr( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1220#define GET_FUNC_TARG_SUB_SIG_diagmatr( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1221#define GET_FUNC_TARG_SUB_SIG_diagpower( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1222#define GET_FUNC_TARG_SUB_SIG_paulistr( numtargs )
1223#define GET_FUNC_TARG_SUB_SIG_pauligad( numtargs )
1224#define GET_FUNC_TARG_SUB_SIG_one int
1225#define GET_FUNC_TARG_SUB_SIG_two int,int
1226#define GET_FUNC_TARG_SUB_SIG_any int*,int
1229#define GET_FUNC_ARGS_SUB_SIG( numtargs, argtype ) GET_FUNC_ARGS_SUB_SIG_##numtargs##_##argtype
1230#define GET_FUNC_ARGS_SUB_SIG_one_none
1231#define GET_FUNC_ARGS_SUB_SIG_two_none
1232#define GET_FUNC_ARGS_SUB_SIG_any_none
1233#define GET_FUNC_ARGS_SUB_SIG_one_scalar qreal
1234#define GET_FUNC_ARGS_SUB_SIG_two_scalar qreal
1235#define GET_FUNC_ARGS_SUB_SIG_any_scalar qreal
1236#define GET_FUNC_ARGS_SUB_SIG_one_compmatr CompMatr1
1237#define GET_FUNC_ARGS_SUB_SIG_two_compmatr CompMatr2
1238#define GET_FUNC_ARGS_SUB_SIG_any_compmatr CompMatr
1239#define GET_FUNC_ARGS_SUB_SIG_one_diagmatr DiagMatr1
1240#define GET_FUNC_ARGS_SUB_SIG_two_diagmatr DiagMatr2
1241#define GET_FUNC_ARGS_SUB_SIG_any_diagmatr DiagMatr
1242#define GET_FUNC_ARGS_SUB_SIG_one_diagpower DiagMatr1,qcomp
1243#define GET_FUNC_ARGS_SUB_SIG_two_diagpower DiagMatr2,qcomp
1244#define GET_FUNC_ARGS_SUB_SIG_any_diagpower DiagMatr, qcomp
1245#define GET_FUNC_ARGS_SUB_SIG_one_axisrots qreal,qreal,qreal,qreal
1246#define GET_FUNC_ARGS_SUB_SIG_any_paulistr PauliStr
1247#define GET_FUNC_ARGS_SUB_SIG_any_pauligad PauliStr,qreal
1250#define GET_FUNC_NAME_PREFIX( numctrls ) GET_FUNC_NAME_PREFIX_##numctrls
1251#define GET_FUNC_NAME_PREFIX_zero apply
1252#define GET_FUNC_NAME_PREFIX_one applyControlled
1253#define GET_FUNC_NAME_PREFIX_any applyMultiControlled
1254#define GET_FUNC_NAME_PREFIX_anystates applyMultiStateControlled
1257#define GET_FUNC_NAME(numctrls, suffix) GET_FUNC_NAME_INNER(GET_FUNC_NAME_PREFIX(numctrls), suffix)
1258#define GET_FUNC_NAME_INNER(A, B) GET_FUNC_NAME_INNER_INNER(A, B)
1259#define GET_FUNC_NAME_INNER_INNER(A, B) A##B
1262#define GET_FUNC_NAME_STR(numctrls, suffix) GET_FUNC_NAME_STR_INNER( GET_FUNC_NAME(numctrls,suffix) )
1263#define GET_FUNC_NAME_STR_INNER(expr) GET_FUNC_NAME_STR_INNER_INNER(expr)
1264#define GET_FUNC_NAME_STR_INNER_INNER(symbol) #symbol
1270#define GET_FUNC_SIG( numctrls, numtargs, argtype ) \
1273 GET_FUNC_CTRL_SUB_SIG( numctrls ) \
1274 GET_FUNC_TARG_SUB_SIG( numtargs, argtype ) \
1275 GET_FUNC_ARGS_SUB_SIG( numtargs, argtype ) \
1280#define GET_CASTED_FUNC( namesuffix, numctrls, numtargs, argtype ) \
1281 static_cast< GET_FUNC_SIG(numctrls, numtargs, argtype) > ( \
1282 GET_FUNC_NAME(numctrls, namesuffix) )
1285#define TEST_CASE_OPERATION( namesuffix, numctrls, numtargs, argtype, matrixgen ) \
1286 TEST_CASE( GET_FUNC_NAME_STR(numctrls, namesuffix), TEST_CATEGORY_OPS ) { \
1287 testOperation<numctrls, numtargs, argtype, apply>( \
1288 GET_CASTED_FUNC(namesuffix, numctrls, numtargs, argtype), \
1293#define TEST_ALL_CTRL_OPERATIONS( namesuffix, numtargs, argtype, matrixgen ) \
1294 TEST_CASE_OPERATION( namesuffix, zero, numtargs, argtype, matrixgen ) \
1295 TEST_CASE_OPERATION( namesuffix, one, numtargs, argtype, matrixgen ) \
1296 TEST_CASE_OPERATION( namesuffix, any, numtargs, argtype, matrixgen ) \
1297 TEST_CASE_OPERATION( namesuffix, anystates, numtargs, argtype, matrixgen )
1342TEST_CASE(
"applyPhaseFlip", TEST_CATEGORY_OPS ) { testOperation<zero,one,none,apply> (
applyPhaseFlip, VariableSizeMatrices::PF(1)); }
1344TEST_CASE(
"applyPhaseShift", TEST_CATEGORY_OPS ) { testOperation<zero,one,scalar,apply>(
applyPhaseShift, ParameterisedMatrices::PS ); }
1355TEST_CASE(
"applyMultiQubitPhaseFlip", TEST_CATEGORY_OPS ) {
1357 testOperation<zero,any,none,apply>(func, VariableSizeMatrices::PF);
1360TEST_CASE(
"applyMultiQubitPhaseShift", TEST_CATEGORY_OPS ) {
1362 testOperation<zero,any,scalar,apply>(func, VariableSizeParameterisedMatrices::PS);
1370TEST_CASE(
"applyQuantumFourierTransform", TEST_CATEGORY_OPS ) {
1372 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1374 SECTION( LABEL_CORRECTNESS ) {
1376 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1377 auto targs = GENERATE_TARGS( numQubits, numTargs );
1378 bool inverse = GENERATE(
false,
true);
1382 SECTION( LABEL_STATEVEC ) {
1384 auto testFunc = [&](
Qureg qureg, qvector& ref) {
1386 ref = getDiscreteFourierTransform(ref, targs, inverse);
1390 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc);
1393 SECTION( LABEL_DENSMATR ) {
1396 auto states = getRandomOrthonormalStateVectors(numQubits,
getRandomInt(1,10));
1399 auto testFunc = [&](
Qureg qureg, qmatrix& ref) {
1402 setQuregToReference(qureg, getMixture(states, probs));
1406 for (
size_t i=0; i<states.size(); i++) {
1407 qvector vec = getDiscreteFourierTransform(states[i], targs, inverse);
1408 ref += probs[i] * getOuterProduct(vec, vec);
1413 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc);
1417 SECTION( LABEL_VALIDATION ) {
1419 Qureg qureg = getArbitraryCachedStatevec();
1420 int targs[] = {0, 1, 2};
1422 bool inverse =
false;
1424 SECTION(
"qureg uninitialised" ) {
1426 Qureg badQureg = qureg;
1427 badQureg.numQubits = -1;
1428 REQUIRE_THROWS_WITH(
1430 ContainsSubstring(
"invalid Qureg")
1434 SECTION(
"invalid target qubits" ) {
1436 int badTargs[] = {0, 1, qureg.numQubits};
1437 REQUIRE_THROWS_WITH(
1439 ContainsSubstring(
"target")
1443 SECTION(
"duplicate target qubits" ) {
1445 int dupTargs[] = {0, 1, 1};
1446 REQUIRE_THROWS_WITH(
1448 ContainsSubstring(
"duplicate")
1452 SECTION(
"invalid number of targets" ) {
1454 int badNumTargs = GENERATE_COPY( -1, 0 );
1455 REQUIRE_THROWS_WITH(
1457 ContainsSubstring(
"targets") || ContainsSubstring(
"target qubits")
1460 badNumTargs = qureg.numQubits+1;
1461 REQUIRE_THROWS_WITH(
1463 ContainsSubstring(
"exceeds the number of qubits in the Qureg")
1470TEST_CASE(
"applyFullQuantumFourierTransform", TEST_CATEGORY_OPS ) {
1472 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1474 SECTION( LABEL_CORRECTNESS ) {
1476 GENERATE( range(0,10) );
1477 bool inverse = GENERATE(
false,
true);
1479 SECTION( LABEL_STATEVEC ) {
1481 auto testFunc = [&](
Qureg qureg, qvector& ref) {
1483 ref = getDiscreteFourierTransform(ref, inverse);
1487 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc);
1490 SECTION( LABEL_DENSMATR ) {
1493 auto states = getRandomOrthonormalStateVectors(numQubits,
getRandomInt(1,10));
1496 auto testFunc = [&](
Qureg qureg, qmatrix& ref) {
1499 setQuregToReference(qureg, getMixture(states, probs));
1503 for (
size_t i=0; i<states.size(); i++) {
1504 qvector vec = getDiscreteFourierTransform(states[i], inverse);
1505 ref += probs[i] * getOuterProduct(vec, vec);
1510 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc);
1514 SECTION( LABEL_VALIDATION ) {
1516 Qureg qureg = getArbitraryCachedStatevec();
1517 bool inverse =
false;
1519 SECTION(
"qureg uninitialised" ) {
1521 Qureg badQureg = qureg;
1522 badQureg.numQubits = -1;
1523 REQUIRE_THROWS_WITH(
1525 ContainsSubstring(
"invalid Qureg")
1532TEST_CASE(
"applyQubitProjector", TEST_CATEGORY_OPS ) {
1534 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1536 SECTION( LABEL_CORRECTNESS ) {
1538 GENERATE( range(0,10) );
1539 int target = GENERATE_COPY( range(0,numQubits) );
1540 int outcome = GENERATE( 0, 1 );
1542 qmatrix projector = getProjector(outcome);
1544 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1546 applyReferenceOperator(ref, {target}, projector);
1549 CAPTURE( target, outcome );
1550 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1551 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1554 SECTION( LABEL_VALIDATION ) {
1556 Qureg qureg = getArbitraryCachedStatevec();
1558 SECTION(
"qureg uninitialised" ) {
1560 Qureg badQureg = qureg;
1561 badQureg.numQubits = -1;
1562 REQUIRE_THROWS_WITH(
1564 ContainsSubstring(
"invalid Qureg")
1568 SECTION(
"invalid target qubit" ) {
1570 int badTarget = GENERATE_COPY( -1, qureg.numQubits );
1571 REQUIRE_THROWS_WITH(
1573 ContainsSubstring(
"target")
1577 SECTION(
"invalid outcome" ) {
1579 int badOutcome = GENERATE_COPY( -1, 2 );
1580 REQUIRE_THROWS_WITH(
1582 ContainsSubstring(
"outcome")
1591TEST_CASE(
"applyMultiQubitProjector", TEST_CATEGORY_OPS ) {
1593 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1595 SECTION( LABEL_CORRECTNESS ) {
1597 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1598 auto targets = GENERATE_TARGS( numQubits, numTargs );
1599 auto outcomes = getRandomOutcomes(numTargs);
1601 qmatrix projector = getProjector(targets, outcomes, numQubits);
1603 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1605 applyReferenceOperator(ref, projector);
1608 CAPTURE( targets, outcomes );
1609 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1610 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1613 SECTION( LABEL_VALIDATION ) {
1615 Qureg qureg = getArbitraryCachedStatevec();
1616 int targets[] = {0, 1, 2};
1617 int outcomes[] = {0, 1, 0};
1620 SECTION(
"qureg uninitialised" ) {
1622 Qureg badQureg = qureg;
1623 badQureg.numQubits = -1;
1624 REQUIRE_THROWS_WITH(
1626 ContainsSubstring(
"invalid Qureg")
1630 SECTION(
"invalid target qubits" ) {
1632 int badTargets[] = {0, 1, GENERATE_COPY( -1, qureg.numQubits) };
1633 REQUIRE_THROWS_WITH(
1635 ContainsSubstring(
"target")
1639 SECTION(
"duplicate target qubits" ) {
1641 int dupTargets[] = {0, 1, 1};
1642 REQUIRE_THROWS_WITH(
1644 ContainsSubstring(
"duplicate")
1648 SECTION(
"invalid number of targets" ) {
1650 int badNumTargs = GENERATE( 0, -1 );
1651 REQUIRE_THROWS_WITH(
1653 ContainsSubstring(
"targets")
1656 badNumTargs = qureg.numQubits + 1;
1657 REQUIRE_THROWS_WITH(
1659 ContainsSubstring(
"exceeds the number of qubits in the Qureg")
1663 SECTION(
"invalid outcomes" ) {
1665 int badOutcomes[] = {0, 1, GENERATE( -1, 2 ) };
1666 REQUIRE_THROWS_WITH(
1668 ContainsSubstring(
"outcome")
1672 SECTION(
"targets mismatch outcomes (C++ only)" ) {
1674 REQUIRE_THROWS_WITH(
1676 ContainsSubstring(
"outcomes") && ContainsSubstring(
"inconsistent with the given number of qubits")
1685TEST_CASE(
"applyForcedQubitMeasurement", TEST_CATEGORY_OPS ) {
1687 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1689 SECTION( LABEL_CORRECTNESS ) {
1691 GENERATE( range(0,10) );
1692 int target = GENERATE_COPY( range(0,numQubits) );
1693 int outcome = GENERATE( 0, 1 );
1695 qmatrix projector = getProjector(outcome);
1697 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1701 setToRandomState(ref);
1702 setQuregToReference(qureg, ref);
1706 qreal refProb = getReferenceProbability(ref, {target}, {outcome});
1707 REQUIRE_AGREE( apiProb, refProb );
1710 applyReferenceOperator(ref, {target}, projector);
1711 ref /= (qureg.isDensityMatrix)?
1712 refProb : std::sqrt(refProb);
1715 CAPTURE( target, outcome );
1716 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1717 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1720 SECTION( LABEL_VALIDATION ) {
1722 Qureg qureg = getArbitraryCachedStatevec();
1730 SECTION(
"qureg uninitialised" ) {
1732 Qureg badQureg = qureg;
1733 badQureg.numQubits = -1;
1734 REQUIRE_THROWS_WITH(
1736 ContainsSubstring(
"invalid Qureg")
1740 SECTION(
"invalid target qubit" ) {
1742 int badTarget = GENERATE_COPY( -1, qureg.numQubits );
1743 REQUIRE_THROWS_WITH(
1745 ContainsSubstring(
"target")
1749 SECTION(
"invalid outcome" ) {
1751 int badOutcome = GENERATE_COPY( -1, 2 );
1752 REQUIRE_THROWS_WITH(
1754 ContainsSubstring(
"outcome")
1758 SECTION(
"improbable outcome" ) {
1763 REQUIRE_THROWS_WITH(
1765 ContainsSubstring(
"impossibly unlikely")
1769 qreal badTheta = 1E-8;
1771 REQUIRE_THROWS_WITH(
1773 ContainsSubstring(
"impossibly unlikely")
1778 qreal goodTheta = 0.1;
1794TEST_CASE(
"applyForcedMultiQubitMeasurement", TEST_CATEGORY_OPS ) {
1796 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1798 SECTION( LABEL_CORRECTNESS ) {
1800 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1801 auto targets = GENERATE_TARGS( numQubits, numTargs );
1802 auto outcomes = getRandomOutcomes(numTargs);
1804 qmatrix projector = getProjector(targets, outcomes, numQubits);
1811 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1815 setToRandomState(ref);
1816 setQuregToReference(qureg, ref);
1820 qreal refProb = getReferenceProbability(ref, targets, outcomes);
1821 REQUIRE_AGREE( apiProb, refProb );
1824 applyReferenceOperator(ref, projector);
1825 ref /= (qureg.isDensityMatrix)?
1826 refProb : std::sqrt(refProb);
1829 CAPTURE( targets, outcomes );
1830 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1831 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1836 SECTION( LABEL_VALIDATION ) {
1838 Qureg qureg = getArbitraryCachedStatevec();
1839 int targets[] = {0, 1, 2};
1840 int outcomes[] = {0, 1, 0};
1847 SECTION(
"qureg uninitialised" ) {
1849 Qureg badQureg = qureg;
1850 badQureg.numQubits = -1;
1851 REQUIRE_THROWS_WITH(
1853 ContainsSubstring(
"invalid Qureg")
1857 SECTION(
"invalid target qubits" ) {
1859 int badTargets[] = {0, 1, GENERATE_COPY( -1, qureg.numQubits )};
1860 REQUIRE_THROWS_WITH(
1862 ContainsSubstring(
"target")
1866 SECTION(
"duplicate target qubits" ) {
1868 int dupTargets[] = {0, 1, 1};
1869 REQUIRE_THROWS_WITH(
1871 ContainsSubstring(
"duplicate")
1875 SECTION(
"invalid number of targets" ) {
1877 int badNumTargs = GENERATE( -1, 0 );
1878 REQUIRE_THROWS_WITH(
1880 ContainsSubstring(
"targets")
1883 badNumTargs = qureg.numQubits + 1;
1884 REQUIRE_THROWS_WITH(
1886 ContainsSubstring(
"exceeds the number of qubits in the Qureg")
1890 SECTION(
"invalid outcomes" ) {
1892 int badOutcomes[] = {0, 1, GENERATE( -1, 2 )};
1893 REQUIRE_THROWS_WITH(
1895 ContainsSubstring(
"outcome")
1899 SECTION(
"improbable outcomes" ) {
1903 int badOutcomes[] = {0, 0, 1};
1904 REQUIRE_THROWS_WITH(
1906 ContainsSubstring(
"impossibly unlikely")
1910 qreal badTheta = 1E-8;
1912 REQUIRE_THROWS_WITH(
1914 ContainsSubstring(
"impossibly unlikely")
1919 qreal goodTheta = 0.1;
1921 int goodOutcomes[] = {0, 0, 1};
1933 SECTION(
"targets mismatch outcomes (C++ only)") {
1935 REQUIRE_THROWS_WITH(
1937 ContainsSubstring(
"inconsistent")
1944TEST_CASE(
"applyMultiQubitMeasurement", TEST_CATEGORY_OPS ) {
1946 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1948 SECTION( LABEL_CORRECTNESS ) {
1950 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1951 auto targets = GENERATE_TARGS( numQubits, numTargs );
1953 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1957 setToRandomState(ref);
1958 setQuregToReference(qureg, ref);
1964 auto apiOutBits = getBits(apiOut, numTargs);
1965 qmatrix projector = getProjector(targets, apiOutBits, numQubits);
1966 applyReferenceOperator(ref, projector);
1967 qreal refProb = getReferenceProbability(ref, targets, apiOutBits);
1968 ref /= (qureg.isDensityMatrix)?
1969 refProb : std::sqrt(refProb);
1973 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1974 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1977 SECTION( LABEL_VALIDATION ) {
1979 Qureg qureg = getArbitraryCachedStatevec();
1980 int targets[] = {0, 1, 2};
1983 SECTION(
"qureg uninitialised" ) {
1985 Qureg badQureg = qureg;
1986 badQureg.numQubits = -1;
1987 REQUIRE_THROWS_WITH(
1989 ContainsSubstring(
"invalid Qureg")
1993 SECTION(
"invalid target qubits" ) {
1995 int badTargets[] = {0, 1, GENERATE_COPY(-1, qureg.numQubits)};
1996 REQUIRE_THROWS_WITH(
1998 ContainsSubstring(
"target")
2002 SECTION(
"duplicate target qubits" ) {
2004 int dupTargets[] = {0, 1, 1};
2005 REQUIRE_THROWS_WITH(
2007 ContainsSubstring(
"duplicate")
2011 SECTION(
"invalid number of targets" ) {
2013 int badNumTargs = GENERATE( -1, 0 );
2014 REQUIRE_THROWS_WITH(
2016 ContainsSubstring(
"targets")
2019 badNumTargs = qureg.numQubits + 1;
2020 REQUIRE_THROWS_WITH(
2022 ContainsSubstring(
"exceeds the number of qubits in the Qureg")
2029TEST_CASE(
"applyMultiQubitMeasurementAndGetProb", TEST_CATEGORY_OPS ) {
2031 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2033 SECTION( LABEL_CORRECTNESS ) {
2035 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
2036 auto targets = GENERATE_TARGS( numQubits, numTargs );
2038 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2042 setToRandomState(ref);
2043 setQuregToReference(qureg, ref);
2048 auto apiOutBits = getBits(apiOut, numTargs);
2049 qreal refProb = getReferenceProbability(ref, targets, apiOutBits);
2050 REQUIRE_AGREE( apiProb, refProb );
2053 qmatrix projector = getProjector(targets, apiOutBits, numQubits);
2054 applyReferenceOperator(ref, projector);
2055 ref /= (qureg.isDensityMatrix)?
2056 refProb : std::sqrt(refProb);
2060 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
2061 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2064 SECTION( LABEL_VALIDATION ) {
2066 Qureg qureg = getArbitraryCachedStatevec();
2067 int targets[] = {0, 1, 2};
2071 SECTION(
"qureg uninitialised" ) {
2073 Qureg badQureg = qureg;
2074 badQureg.numQubits = -1;
2075 REQUIRE_THROWS_WITH(
2077 ContainsSubstring(
"invalid Qureg")
2081 SECTION(
"invalid target qubits" ) {
2083 int badTargets[] = {0, 1, GENERATE_COPY( -1, qureg.numQubits )};
2084 REQUIRE_THROWS_WITH(
2086 ContainsSubstring(
"target")
2090 SECTION(
"duplicate target qubits" ) {
2092 int dupTargets[] = {0, 1, 1};
2093 REQUIRE_THROWS_WITH(
2095 ContainsSubstring(
"duplicate")
2099 SECTION(
"invalid number of targets" ) {
2101 int badNumTargs = GENERATE( -1, 0 );
2102 REQUIRE_THROWS_WITH(
2104 ContainsSubstring(
"targets")
2107 badNumTargs = qureg.numQubits + 1;
2108 REQUIRE_THROWS_WITH(
2110 ContainsSubstring(
"exceeds the number of qubits in the Qureg")
2117TEST_CASE(
"applyQubitMeasurement", TEST_CATEGORY_OPS ) {
2119 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2121 SECTION( LABEL_CORRECTNESS ) {
2123 GENERATE( range(0,10) );
2124 int target = GENERATE_COPY( range(0,numQubits) );
2126 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2130 setToRandomState(ref);
2131 setQuregToReference(qureg, ref);
2137 qmatrix projector = getProjector(apiOut);
2138 applyReferenceOperator(ref, {target}, projector);
2139 qreal refProb = getReferenceProbability(ref, {target}, {apiOut});
2140 ref /= (qureg.isDensityMatrix)?
2141 refProb : std::sqrt(refProb);
2145 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
2146 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2149 SECTION( LABEL_VALIDATION ) {
2151 Qureg qureg = getArbitraryCachedStatevec();
2153 SECTION(
"qureg uninitialised" ) {
2155 Qureg badQureg = qureg;
2156 badQureg.numQubits = -1;
2157 REQUIRE_THROWS_WITH(
2159 ContainsSubstring(
"invalid Qureg")
2163 SECTION(
"invalid target qubit" ) {
2165 int badTarget = GENERATE_COPY( -1, qureg.numQubits );
2166 REQUIRE_THROWS_WITH(
2168 ContainsSubstring(
"target")
2175TEST_CASE(
"applyQubitMeasurementAndGetProb", TEST_CATEGORY_OPS ) {
2177 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2179 SECTION( LABEL_CORRECTNESS ) {
2181 GENERATE( range(0,10) );
2182 int target = GENERATE_COPY( range(0,numQubits) );
2184 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2188 setToRandomState(ref);
2189 setQuregToReference(qureg, ref);
2194 qreal refProb = getReferenceProbability(ref, {target}, {apiOut});
2195 REQUIRE_AGREE( apiProb, refProb );
2198 qmatrix projector = getProjector(apiOut);
2199 applyReferenceOperator(ref, {target}, projector);
2200 ref /= (qureg.isDensityMatrix)?
2201 refProb : std::sqrt(refProb);
2205 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
2206 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2209 SECTION( LABEL_VALIDATION ) {
2211 Qureg qureg = getArbitraryCachedStatevec();
2214 SECTION(
"qureg uninitialised" ) {
2216 Qureg badQureg = qureg;
2217 badQureg.numQubits = -1;
2218 REQUIRE_THROWS_WITH(
2220 ContainsSubstring(
"invalid Qureg")
2224 SECTION(
"invalid target qubit" ) {
2226 int badTarget = GENERATE_COPY( -1, qureg.numQubits );
2227 REQUIRE_THROWS_WITH(
2229 ContainsSubstring(
"target")
2236TEST_CASE(
"applyFullStateDiagMatr", TEST_CATEGORY_OPS LABEL_MIXED_DEPLOY_TAG ) {
2238 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
2240 auto cachedMatrs = getCachedFullStateDiagMatrs();
2242 SECTION( LABEL_CORRECTNESS ) {
2244 qmatrix refMatr = getRandomDiagonalUnitary(numQubits);
2247 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
2249 SECTION( LABEL_STATEVEC ) {
2251 auto refFunc = [&] (qvector& state, qmatrix matr) { applyReferenceOperator(state, matr); };
2253 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
2256 SECTION( LABEL_DENSMATR ) {
2258 auto refFunc = [&] (qmatrix& state, qmatrix matr) { applyReferenceOperator(state, matr); };
2260 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
2268TEST_CASE(
"applyFullStateDiagMatrPower", TEST_CATEGORY_OPS LABEL_MIXED_DEPLOY_TAG ) {
2270 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
2272 auto cachedMatrs = getCachedFullStateDiagMatrs();
2274 SECTION( LABEL_CORRECTNESS ) {
2276 qmatrix refMatr = getRandomDiagonalUnitary(numQubits);
2280 bool testRealExp = GENERATE(
true,
false );
2281 qcomp exponent = (testRealExp)?
2289 CAPTURE( exponent );
2291 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
2296 SECTION( LABEL_STATEVEC ) {
2298 auto refFunc = [&] (qvector& state, qmatrix matr) {
2299 matr = getPowerOfDiagonalMatrix(matr, exponent);
2300 applyReferenceOperator(state, matr);
2303 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
2306 SECTION( LABEL_DENSMATR ) {
2308 auto refFunc = [&] (qmatrix& state, qmatrix matr) {
2309 matr = getPowerOfDiagonalMatrix(matr, exponent);
2310 applyReferenceOperator(state, matr);
2313 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
2323TEST_CASE(
"applyNonUnitaryPauliGadget", TEST_CATEGORY_OPS ) {
2325 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2327 SECTION( LABEL_CORRECTNESS ) {
2330 int numTargs = GENERATE_COPY( range(1, numQubits+1) );
2331 auto targs = GENERATE_TARGS( numQubits, numTargs );
2332 PauliStr str = getRandomPauliStr(targs);
2336 auto matrRef = getExponentialOfPauliMatrix(angle, getMatrix(str, numQubits));
2338 auto testFunc = [&](
Qureg qureg,
auto& stateRef) {
2340 applyReferenceOperator(stateRef, matrRef);
2343 CAPTURE( targs, angle );
2344 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
2345 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2348 SECTION( LABEL_VALIDATION ) {
2350 Qureg qureg = getArbitraryCachedStatevec();
2353 SECTION(
"qureg uninitialised" ) {
2355 Qureg badQureg = qureg;
2356 badQureg.numQubits = -1;
2357 REQUIRE_THROWS_WITH(
2359 ContainsSubstring(
"invalid Qureg")
2380TEST_CASE(
"leftapplySwap", TEST_CATEGORY_MULT ) { testOperation<zero,two,none,leftapply>(
leftapplySwap, FixedMatrices::SWAP); }
2381TEST_CASE(
"leftapplyPauliX", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,leftapply>(
leftapplyPauliX, FixedMatrices::X); }
2382TEST_CASE(
"leftapplyPauliY", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,leftapply>(
leftapplyPauliY, FixedMatrices::Y); }
2383TEST_CASE(
"leftapplyPauliZ", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,leftapply>(
leftapplyPauliZ, FixedMatrices::Z); }
2384TEST_CASE(
"leftapplyPauliStr", TEST_CATEGORY_MULT ) { testOperation<zero,any,paulistr,leftapply>(
leftapplyPauliStr,
nullptr); }
2391TEST_CASE(
"rightapplySwap", TEST_CATEGORY_MULT ) { testOperation<zero,two,none,rightapply>(
rightapplySwap, FixedMatrices::SWAP); }
2392TEST_CASE(
"rightapplyPauliX", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,rightapply>(
rightapplyPauliX, FixedMatrices::X); }
2393TEST_CASE(
"rightapplyPauliY", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,rightapply>(
rightapplyPauliY, FixedMatrices::Y); }
2394TEST_CASE(
"rightapplyPauliZ", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,rightapply>(
rightapplyPauliZ, FixedMatrices::Z); }
2395TEST_CASE(
"rightapplyPauliStr", TEST_CATEGORY_MULT ) { testOperation<zero,any,paulistr,rightapply>(
rightapplyPauliStr,
nullptr); }
2410TEST_CASE(
"leftapplyCompMatr", TEST_CATEGORY_MULT ) {
2412 testOperation<zero,any,compmatr,leftapply>(func,
nullptr);
2415TEST_CASE(
"leftapplyDiagMatr", TEST_CATEGORY_MULT ) {
2417 testOperation<zero,any,diagmatr,leftapply>(func,
nullptr);
2420TEST_CASE(
"leftapplyDiagMatrPower", TEST_CATEGORY_MULT ) {
2422 testOperation<zero,any,diagpower,leftapply>(func,
nullptr);
2425TEST_CASE(
"leftapplyMultiQubitNot", TEST_CATEGORY_MULT ) {
2427 testOperation<zero,any,none,leftapply>(func, VariableSizeMatrices::X);
2430TEST_CASE(
"leftapplyPhaseGadget", TEST_CATEGORY_MULT ) {
2432 testOperation<zero,any,scalar,leftapply>(func, VariableSizeParameterisedMatrices::Z);
2436TEST_CASE(
"rightapplyCompMatr", TEST_CATEGORY_MULT ) {
2438 testOperation<zero,any,compmatr,rightapply>(func,
nullptr);
2441TEST_CASE(
"rightapplyDiagMatr", TEST_CATEGORY_MULT ) {
2443 testOperation<zero,any,diagmatr,rightapply>(func,
nullptr);
2446TEST_CASE(
"rightapplyDiagMatrPower", TEST_CATEGORY_MULT ) {
2448 testOperation<zero,any,diagpower,rightapply>(func,
nullptr);
2451TEST_CASE(
"rightapplyMultiQubitNot", TEST_CATEGORY_MULT ) {
2453 testOperation<zero,any,none,rightapply>(func, VariableSizeMatrices::X);
2456TEST_CASE(
"rightapplyPhaseGadget", TEST_CATEGORY_MULT ) {
2458 testOperation<zero,any,scalar,rightapply>(func, VariableSizeParameterisedMatrices::Z);
2467TEST_CASE(
"leftapplyFullStateDiagMatr", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
2469 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
2471 auto cachedMatrs = getCachedFullStateDiagMatrs();
2473 SECTION( LABEL_CORRECTNESS ) {
2475 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(numQubits));
2478 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
2480 SECTION( LABEL_STATEVEC ) {
2482 auto refFunc = [&] (qvector& state, qmatrix matr) { leftapplyReferenceOperator(state, matr); };
2484 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
2487 SECTION( LABEL_DENSMATR ) {
2489 auto refFunc = [&] (qmatrix& state, qmatrix matr) { leftapplyReferenceOperator(state, matr); };
2491 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
2499TEST_CASE(
"rightapplyFullStateDiagMatr", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
2501 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
2503 auto cachedMatrs = getCachedFullStateDiagMatrs();
2505 SECTION( LABEL_CORRECTNESS ) {
2507 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(numQubits));
2510 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
2512 SECTION( LABEL_DENSMATR ) {
2514 auto refFunc = [&] (qmatrix& state, qmatrix matr) { rightapplyReferenceOperator(state, matr); };
2516 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
2524TEST_CASE(
"leftapplyFullStateDiagMatrPower", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
2526 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
2528 auto cachedMatrs = getCachedFullStateDiagMatrs();
2530 SECTION( LABEL_CORRECTNESS ) {
2532 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(numQubits));
2539 CAPTURE( exponent );
2541 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
2543 SECTION( LABEL_STATEVEC ) {
2545 auto refFunc = [&] (qvector& state, qmatrix matr) {
2546 matr = getPowerOfDiagonalMatrix(matr, exponent);
2547 leftapplyReferenceOperator(state, matr);
2550 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
2553 SECTION( LABEL_DENSMATR ) {
2555 auto refFunc = [&] (qmatrix& state, qmatrix matr) {
2556 matr = getPowerOfDiagonalMatrix(matr, exponent);
2557 leftapplyReferenceOperator(state, matr);
2560 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
2568TEST_CASE(
"rightapplyFullStateDiagMatrPower", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
2570 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
2572 auto cachedMatrs = getCachedFullStateDiagMatrs();
2574 SECTION( LABEL_CORRECTNESS ) {
2576 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(numQubits));
2583 CAPTURE( exponent );
2585 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
2587 SECTION( LABEL_DENSMATR ) {
2589 auto refFunc = [&] (qmatrix& state, qmatrix matr) {
2590 matr = getPowerOfDiagonalMatrix(matr, exponent);
2591 rightapplyReferenceOperator(state, matr);
2594 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
2602TEST_CASE(
"leftapplyQubitProjector", TEST_CATEGORY_MULT ) {
2604 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2606 SECTION( LABEL_CORRECTNESS ) {
2608 GENERATE( range(0,10) );
2609 int target = GENERATE_COPY( range(0,numQubits) );
2610 int outcome = GENERATE( 0, 1 );
2612 qmatrix projector = getProjector(outcome);
2614 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2616 leftapplyReferenceOperator(ref, {target}, projector);
2619 CAPTURE( target, outcome );
2620 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
2621 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2624 SECTION( LABEL_VALIDATION ) {
2626 Qureg qureg = getArbitraryCachedStatevec();
2628 SECTION(
"qureg uninitialised" ) {
2630 Qureg badQureg = qureg;
2631 badQureg.numQubits = -1;
2632 REQUIRE_THROWS_WITH(
2634 ContainsSubstring(
"invalid Qureg")
2638 SECTION(
"invalid target qubit" ) {
2640 int badTarget = GENERATE_COPY( -1, qureg.numQubits );
2641 REQUIRE_THROWS_WITH(
2643 ContainsSubstring(
"target")
2647 SECTION(
"invalid outcome" ) {
2649 int badOutcome = GENERATE_COPY( -1, 2 );
2650 REQUIRE_THROWS_WITH(
2652 ContainsSubstring(
"outcome")
2661TEST_CASE(
"rightapplyQubitProjector", TEST_CATEGORY_MULT ) {
2663 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2665 SECTION( LABEL_CORRECTNESS ) {
2667 GENERATE( range(0,10) );
2668 int target = GENERATE_COPY( range(0,numQubits) );
2669 int outcome = GENERATE( 0, 1 );
2671 qmatrix projector = getProjector(outcome);
2673 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2675 rightapplyReferenceOperator(ref, {target}, projector);
2678 CAPTURE( target, outcome );
2679 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2682 SECTION( LABEL_VALIDATION ) {
2684 Qureg qureg = getArbitraryCachedDensmatr();
2686 SECTION(
"qureg uninitialised" ) {
2688 Qureg badQureg = qureg;
2689 badQureg.numQubits = -1;
2690 REQUIRE_THROWS_WITH(
2692 ContainsSubstring(
"invalid Qureg")
2696 SECTION(
"qureg is not density matrix" ) {
2698 Qureg badQureg = getArbitraryCachedStatevec();
2699 REQUIRE_THROWS_WITH(
2701 ContainsSubstring(
"received a statevector")
2705 SECTION(
"invalid target qubit" ) {
2707 int badTarget = GENERATE_COPY( -1, qureg.numQubits );
2708 REQUIRE_THROWS_WITH(
2710 ContainsSubstring(
"target")
2714 SECTION(
"invalid outcome" ) {
2716 int badOutcome = GENERATE_COPY( -1, 2 );
2717 REQUIRE_THROWS_WITH(
2719 ContainsSubstring(
"outcome")
2728TEST_CASE(
"leftapplyMultiQubitProjector", TEST_CATEGORY_MULT ) {
2730 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2732 SECTION( LABEL_CORRECTNESS ) {
2734 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
2735 auto targets = GENERATE_TARGS( numQubits, numTargs );
2736 auto outcomes = getRandomOutcomes(numTargs);
2738 qmatrix projector = getProjector(targets, outcomes, numQubits);
2740 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2742 leftapplyReferenceOperator(ref, projector);
2745 CAPTURE( targets, outcomes );
2746 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
2747 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2750 SECTION( LABEL_VALIDATION ) {
2752 Qureg qureg = getArbitraryCachedStatevec();
2753 int targets[] = {0, 1, 2};
2754 int outcomes[] = {0, 1, 0};
2757 SECTION(
"qureg uninitialised" ) {
2759 Qureg badQureg = qureg;
2760 badQureg.numQubits = -1;
2761 REQUIRE_THROWS_WITH(
2763 ContainsSubstring(
"invalid Qureg")
2767 SECTION(
"invalid target qubits" ) {
2769 int badTargets[] = {0, 1, GENERATE_COPY( -1, qureg.numQubits) };
2770 REQUIRE_THROWS_WITH(
2772 ContainsSubstring(
"target")
2776 SECTION(
"duplicate target qubits" ) {
2778 int dupTargets[] = {0, 1, 1};
2779 REQUIRE_THROWS_WITH(
2781 ContainsSubstring(
"duplicate")
2785 SECTION(
"invalid number of targets" ) {
2787 int badNumTargs = GENERATE( 0, -1 );
2788 REQUIRE_THROWS_WITH(
2790 ContainsSubstring(
"targets")
2793 badNumTargs = qureg.numQubits + 1;
2794 REQUIRE_THROWS_WITH(
2796 ContainsSubstring(
"exceeds the number of qubits in the Qureg")
2800 SECTION(
"invalid outcomes" ) {
2802 int badOutcomes[] = {0, 1, GENERATE( -1, 2 ) };
2803 REQUIRE_THROWS_WITH(
2805 ContainsSubstring(
"outcome")
2809 SECTION(
"targets mismatch outcomes (C++ only)" ) {
2811 REQUIRE_THROWS_WITH(
2813 ContainsSubstring(
"inconsistent")
2822TEST_CASE(
"rightapplyMultiQubitProjector", TEST_CATEGORY_MULT ) {
2824 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2826 SECTION( LABEL_CORRECTNESS ) {
2828 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
2829 auto targets = GENERATE_TARGS( numQubits, numTargs );
2830 auto outcomes = getRandomOutcomes(numTargs);
2832 qmatrix projector = getProjector(targets, outcomes, numQubits);
2834 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2836 rightapplyReferenceOperator(ref, projector);
2839 CAPTURE( targets, outcomes );
2840 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2843 SECTION( LABEL_VALIDATION ) {
2845 Qureg qureg = getArbitraryCachedDensmatr();
2846 int targets[] = {0, 1, 2};
2847 int outcomes[] = {0, 1, 0};
2850 SECTION(
"qureg uninitialised" ) {
2852 Qureg badQureg = qureg;
2853 badQureg.numQubits = -1;
2854 REQUIRE_THROWS_WITH(
2856 ContainsSubstring(
"invalid Qureg")
2860 SECTION(
"qureg is not density matrix" ) {
2862 Qureg badQureg = getArbitraryCachedStatevec();
2863 REQUIRE_THROWS_WITH(
2865 ContainsSubstring(
"received a statevector")
2869 SECTION(
"invalid target qubits" ) {
2871 int badTargets[] = {0, 1, GENERATE_COPY( -1, qureg.numQubits) };
2872 REQUIRE_THROWS_WITH(
2874 ContainsSubstring(
"target")
2878 SECTION(
"duplicate target qubits" ) {
2880 int dupTargets[] = {0, 1, 1};
2881 REQUIRE_THROWS_WITH(
2883 ContainsSubstring(
"duplicate")
2887 SECTION(
"invalid number of targets" ) {
2889 int badNumTargs = GENERATE( 0, -1 );
2890 REQUIRE_THROWS_WITH(
2892 ContainsSubstring(
"targets")
2895 badNumTargs = qureg.numQubits + 1;
2896 REQUIRE_THROWS_WITH(
2898 ContainsSubstring(
"exceeds the number of qubits in the Qureg")
2902 SECTION(
"invalid outcomes" ) {
2904 int badOutcomes[] = {0, 1, GENERATE( -1, 2 ) };
2905 REQUIRE_THROWS_WITH(
2907 ContainsSubstring(
"outcome")
2911 SECTION(
"targets mismatch outcomes (C++ only)" ) {
2913 REQUIRE_THROWS_WITH(
2915 ContainsSubstring(
"inconsistent")
2924TEST_CASE(
"leftapplyPauliStrSum", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
2926 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2928 SECTION( LABEL_CORRECTNESS ) {
2930 int numQubits = getNumCachedQubits();
2931 int numTerms = GENERATE_COPY( 1, 2, 10 );
2933 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
2935 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2942 ref = getMatrix(sum, numQubits) * ref;
2945 CAPTURE( numTerms );
2946 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
2947 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2950 SECTION( LABEL_VALIDATION ) {
2952 Qureg qureg = getArbitraryCachedStatevec();
2953 PauliStrSum sum = createRandomPauliStrSum(numQubits, 2);
2955 SECTION(
"qureg uninitialised" ) {
2957 Qureg badQureg = qureg;
2958 badQureg.numQubits = -1;
2960 REQUIRE_THROWS_WITH(
2962 ContainsSubstring(
"invalid Qureg")
2974TEST_CASE(
"rightapplyPauliStrSum", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
2976 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2978 SECTION( LABEL_CORRECTNESS ) {
2980 int numQubits = getNumCachedQubits();
2981 int numTerms = GENERATE_COPY( 1, 2, 10 );
2983 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
2985 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2992 ref = ref * getMatrix(sum, numQubits);
2995 CAPTURE( numTerms );
2996 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2999 SECTION( LABEL_VALIDATION ) {
3001 Qureg qureg = getArbitraryCachedStatevec();
3002 PauliStrSum sum = createRandomPauliStrSum(numQubits, 2);
3004 SECTION(
"qureg uninitialised" ) {
3006 Qureg badQureg = qureg;
3007 badQureg.numQubits = -1;
3009 REQUIRE_THROWS_WITH(
3011 ContainsSubstring(
"invalid Qureg")
qreal calcProbOfQubitOutcome(Qureg qureg, int qubit, int outcome)
qreal calcProbOfMultiQubitOutcome(Qureg qureg, int *qubits, int *outcomes, int numQubits)
void setQuESTValidationEpsilonToDefault()
qreal getQuESTValidationEpsilon()
void setQuESTValidationEpsilon(qreal eps)
void initZeroState(Qureg qureg)
void initDebugState(Qureg qureg)
CompMatr createCompMatr(int numQubits)
DiagMatr createDiagMatr(int numQubits)
void destroyDiagMatr(DiagMatr matrix)
void destroyCompMatr(CompMatr matrix)
static CompMatr2 getCompMatr2(qcomp **in)
static CompMatr1 getCompMatr1(qcomp **in)
static DiagMatr2 getDiagMatr2(qcomp *in)
static DiagMatr1 getDiagMatr1(qcomp *in)
void setDiagMatr(DiagMatr out, qcomp *in)
void setCompMatr(CompMatr matr, qcomp **vals)
void setFullStateDiagMatr(FullStateDiagMatr out, qindex startInd, qcomp *in, qindex numElems)
void rightapplyCompMatr1(Qureg qureg, int target, CompMatr1 matrix)
void leftapplyCompMatr1(Qureg qureg, int target, CompMatr1 matrix)
void rightapplyCompMatr2(Qureg qureg, int target1, int target2, CompMatr2 matrix)
void leftapplyCompMatr2(Qureg qureg, int target1, int target2, CompMatr2 matr)
void leftapplyCompMatr(Qureg qureg, int *targets, int numTargets, CompMatr matrix)
void rightapplyCompMatr(Qureg qureg, int *targets, int numTargets, CompMatr matrix)
void leftapplyDiagMatr1(Qureg qureg, int target, DiagMatr1 matr)
void rightapplyDiagMatr1(Qureg qureg, int target, DiagMatr1 matrix)
void leftapplyDiagMatr2(Qureg qureg, int target1, int target2, DiagMatr2 matr)
void rightapplyDiagMatr2(Qureg qureg, int target1, int target2, DiagMatr2 matrix)
void rightapplyDiagMatr(Qureg qureg, int *targets, int numTargets, DiagMatr matrix)
void leftapplyDiagMatrPower(Qureg qureg, int *targets, int numTargets, DiagMatr matrix, qcomp exponent)
void rightapplyDiagMatrPower(Qureg qureg, int *targets, int numTargets, DiagMatr matrix, qcomp exponent)
void leftapplyDiagMatr(Qureg qureg, int *targets, int numTargets, DiagMatr matrix)
void rightapplyFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matrix)
void leftapplyFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matrix)
void rightapplyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent)
void leftapplyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent)
void leftapplyMultiQubitNot(Qureg qureg, int *targets, int numTargets)
void rightapplyMultiQubitNot(Qureg qureg, int *targets, int numTargets)
void leftapplyPauliX(Qureg qureg, int target)
void rightapplyPauliY(Qureg qureg, int target)
void leftapplyPauliY(Qureg qureg, int target)
void leftapplyPauliZ(Qureg qureg, int target)
void rightapplyPauliX(Qureg qureg, int target)
void rightapplyPauliZ(Qureg qureg, int target)
void leftapplyPauliGadget(Qureg qureg, PauliStr str, qreal angle)
void rightapplyPauliGadget(Qureg qureg, PauliStr str, qreal angle)
void rightapplyPauliStr(Qureg qureg, PauliStr str)
void leftapplyPauliStr(Qureg qureg, PauliStr str)
void rightapplyPauliStrSum(Qureg qureg, PauliStrSum sum, Qureg workspace)
void leftapplyPauliStrSum(Qureg qureg, PauliStrSum sum, Qureg workspace)
void rightapplyPhaseGadget(Qureg qureg, int *targets, int numTargets, qreal angle)
void leftapplyPhaseGadget(Qureg qureg, int *targets, int numTargets, qreal angle)
void leftapplyMultiQubitProjector(Qureg qureg, int *qubits, int *outcomes, int numQubits)
void rightapplyQubitProjector(Qureg qureg, int qubit, int outcome)
void rightapplyMultiQubitProjector(Qureg qureg, int *qubits, int *outcomes, int numQubits)
void leftapplyQubitProjector(Qureg qureg, int qubit, int outcome)
void leftapplySwap(Qureg qureg, int qubit1, int qubit2)
void rightapplySwap(Qureg qureg, int qubit1, int qubit2)
void applyFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matrix)
void applyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent)
qreal applyForcedQubitMeasurement(Qureg qureg, int target, int outcome)
qindex applyMultiQubitMeasurement(Qureg qureg, int *qubits, int numQubits)
int applyQubitMeasurement(Qureg qureg, int target)
qreal applyForcedMultiQubitMeasurement(Qureg qureg, int *qubits, int *outcomes, int numQubits)
qindex applyMultiQubitMeasurementAndGetProb(Qureg qureg, int *qubits, int numQubits, qreal *probability)
int applyQubitMeasurementAndGetProb(Qureg qureg, int target, qreal *probability)
void applyNonUnitaryPauliGadget(Qureg qureg, PauliStr str, qcomp angle)
void applyMultiQubitPhaseShift(Qureg qureg, int *targets, int numTargets, qreal angle)
void applyTwoQubitPhaseShift(Qureg qureg, int target1, int target2, qreal angle)
void applyTwoQubitPhaseFlip(Qureg qureg, int target1, int target2)
void applyPhaseShift(Qureg qureg, int target, qreal angle)
void applyPhaseFlip(Qureg qureg, int target)
void applyMultiQubitPhaseFlip(Qureg qureg, int *targets, int numTargets)
void applyMultiQubitProjector(Qureg qureg, int *qubits, int *outcomes, int numQubits)
void applyQubitProjector(Qureg qureg, int target, int outcome)
void applyQuantumFourierTransform(Qureg qureg, int *targets, int numTargets, bool inverse)
void applyFullQuantumFourierTransform(Qureg qureg, bool inverse)
void applyRotateX(Qureg qureg, int target, qreal angle)
PauliStr getPauliStr(const char *paulis, int *indices, int numPaulis)
void destroyPauliStrSum(PauliStrSum sum)
Qureg createCloneQureg(Qureg qureg)
void destroyQureg(Qureg qureg)
qmatrix getKroneckerProduct(qmatrix a, qmatrix b)
qmatrix getIdentityMatrix(size_t dim)
qmatrix getZeroMatrix(size_t dim)
qmatrix getRandomUnitary(int numQb)
qreal getRandomReal(qreal min, qreal maxExcl)
vector< qreal > getRandomProbabilities(int numProbs)
int getRandomInt(int min, int maxExcl)
TEST_CASE("calcExpecPauliStr", TEST_CATEGORY)
TEST_ALL_CTRL_OPERATIONS(PauliStr, any, paulistr, nullptr)