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/generators/catch_generators_range.hpp>
29#include "tests/utils/config.hpp"
30#include "tests/utils/cache.hpp"
31#include "tests/utils/qvector.hpp"
32#include "tests/utils/qmatrix.hpp"
33#include "tests/utils/compare.hpp"
34#include "tests/utils/convert.hpp"
35#include "tests/utils/evolve.hpp"
36#include "tests/utils/linalg.hpp"
37#include "tests/utils/lists.hpp"
38#include "tests/utils/measure.hpp"
39#include "tests/utils/macros.hpp"
40#include "tests/utils/random.hpp"
45using Catch::Matchers::ContainsSubstring;
52extern int paulis_getPauliAt(
PauliStr str,
int ind);
59#define TEST_CATEGORY_OPS \
60 LABEL_UNIT_TAG "[operations]"
62#define TEST_CATEGORY_MULT \
63 LABEL_UNIT_TAG "[multiplication]"
70namespace FixedMatrices {
73 {1/std::sqrt(2), 1/std::sqrt(2)},
74 {1/std::sqrt(2), -1/std::sqrt(2)}};
76 qmatrix X = getPauliMatrix(1);
77 qmatrix Y = getPauliMatrix(2);
78 qmatrix Z = getPauliMatrix(3);
80 qreal PI = 3.14159265358979323846;
83 {0, std::exp(1_i * PI/4)}};
97 {0, (1+1_i)/2, (1-1_i)/2, 0},
98 {0, (1-1_i)/2, (1+1_i)/2, 0},
102namespace ParameterisedMatrices {
104 auto Rx = [](qreal p) {
return getExponentialOfPauliMatrix(p, FixedMatrices::X); };
105 auto Ry = [](qreal p) {
return getExponentialOfPauliMatrix(p, FixedMatrices::Y); };
106 auto Rz = [](qreal p) {
return getExponentialOfPauliMatrix(p, FixedMatrices::Z); };
108 auto PS = [](qreal p) {
return qmatrix{{1, 0}, {0, std::exp(p*1_i)}}; };
109 auto PS2 = [](qreal p) {
return getControlledMatrix(PS(p), 1); };
112namespace VariableSizeMatrices {
115 auto PF = [](
int n) {
return getControlledMatrix(FixedMatrices::Z, n - 1); };
118namespace VariableSizeParameterisedMatrices {
120 auto Z = [](qreal p,
int n) {
122 return getExponentialOfPauliMatrix(p, m);
125 auto PS = [](qreal p,
int n) {
126 qmatrix m = ParameterisedMatrices::PS(p);
127 return getControlledMatrix(m, n - 1);
142void TEST_ON_CACHED_QUREGS(quregCache quregs,
auto& reference,
auto& function) {
144 for (
auto& [label, qureg]: quregs) {
146 DYNAMIC_SECTION( label ) {
152 setToDebugState(reference);
154 function(qureg, reference);
155 REQUIRE_AGREE( qureg, reference );
160void TEST_ON_CACHED_QUREG_AND_MATRIX(quregCache quregs, matrixCache matrices,
auto apiFunc,
auto refState,
auto refMatr,
auto refFunc) {
162 for (
auto& [labelA, qureg]: quregs) {
163 for (
auto& [labelB, matrix]: matrices) {
166 if (matrix.isDistributed && ! qureg.isDistributed)
169 DYNAMIC_SECTION( labelA + LABEL_DELIMITER + labelB ) {
173 setToDebugState(refState);
179 apiFunc(qureg, matrix);
180 refFunc(refState, refMatr);
181 REQUIRE_AGREE( qureg, refState );
192#define PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef ) \
193 int numQubits = getNumCachedQubits(); \
194 auto statevecQuregs = getCachedStatevecs(); \
195 auto densmatrQuregs = getCachedDensmatrs(); \
196 qvector statevecRef = getZeroVector(getPow2(numQubits)); \
197 qmatrix densmatrRef = getZeroMatrix(getPow2(numQubits));
220enum ArgsFlag { none, scalar, axisrots, diagmatr, diagpower, compmatr, paulistr, pauligad };
237enum NumQubitsFlag { zero, one, two, any, anystates };
239void assertNumQubitsFlagsAreValid(NumQubitsFlag ctrlsFlag, NumQubitsFlag targsFlag) {
245 ctrlsFlag == anystates );
254void assertNumQubitsFlagsValid(
255 NumQubitsFlag ctrlsFlag, NumQubitsFlag targsFlag,
256 vector<int> ctrls, vector<int> states, vector<int> targs
258 assertNumQubitsFlagsAreValid(ctrlsFlag, targsFlag);
265 if (targsFlag == one)
266 DEMAND( targs.size() == 1 );
268 if (targsFlag == two)
269 DEMAND( targs.size() == 2 );
271 if (ctrlsFlag == zero)
272 DEMAND( ctrls.size() == 0 );
274 if (ctrlsFlag == one)
275 DEMAND( ctrls.size() == 1 );
277 if (ctrlsFlag == anystates)
278 DEMAND( states.size() == ctrls.size() );
280 DEMAND( states.size() == 0 );
293template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
294int GENERATE_NUM_TARGS(
int numQuregQubits) {
296 assertNumQubitsFlagsAreValid(zero, Targs);
297 DEMAND( Targs != one || numQuregQubits >= 1 );
298 DEMAND( Targs != two || numQuregQubits >= 2 );
299 DEMAND( numQuregQubits > 0 );
302 if constexpr (Targs == one)
304 if constexpr (Targs == two)
307 if constexpr (Targs == any) {
310 int maxNumTargs = numQuregQubits;
316 if (Args == compmatr)
317 maxNumTargs = numQuregQubits - getLog2(
getQuESTEnv().numNodes);
320 if (Ctrls == one && maxNumTargs == numQuregQubits)
323 return GENERATE_COPY( range(1, maxNumTargs+1) );
327template <NumQubitsFlag Ctrls>
328int GENERATE_NUM_CTRLS(
int numFreeQubits) {
330 assertNumQubitsFlagsAreValid(Ctrls, one);
331 DEMAND( Ctrls != one || numFreeQubits >= 1 );
332 DEMAND( numFreeQubits >= 0 );
334 if constexpr (Ctrls == zero)
337 if constexpr (Ctrls == one)
340 if constexpr (Ctrls == any || Ctrls == anystates)
341 return GENERATE_COPY( range(0, numFreeQubits+1) );
362template <NumQubitsFlag Ctrls, NumQubitsFlag Targs>
363void invokeApiOperation(
364 auto operation,
Qureg qureg,
365 vector<int> ctrls, vector<int> states,
int numCtrls,
366 vector<int> targs,
int numTargs,
369 assertNumQubitsFlagsValid(Ctrls, Targs, ctrls, states, targs);
371 if constexpr (Ctrls == zero) {
372 if constexpr (Targs == zero) operation(qureg, args...);
373 if constexpr (Targs == one) operation(qureg, targs[0], args...);
374 if constexpr (Targs == two) operation(qureg, targs[0], targs[1], args...);
375 if constexpr (Targs == any) operation(qureg, targs.data(), numTargs, args...);
377 if constexpr (Ctrls == one) {
378 if constexpr (Targs == zero) operation(qureg, ctrls[0], args...);
379 if constexpr (Targs == one) operation(qureg, ctrls[0], targs[0], args...);
380 if constexpr (Targs == two) operation(qureg, ctrls[0], targs[0], targs[1], args...);
381 if constexpr (Targs == any) operation(qureg, ctrls[0], targs.data(), numTargs, args...);
383 if constexpr (Ctrls == any) {
384 if constexpr (Targs == zero) operation(qureg, ctrls.data(), numCtrls, args...);
385 if constexpr (Targs == one) operation(qureg, ctrls.data(), numCtrls, targs[0], args...);
386 if constexpr (Targs == two) operation(qureg, ctrls.data(), numCtrls, targs[0], targs[1], args...);
387 if constexpr (Targs == any) operation(qureg, ctrls.data(), numCtrls, targs.data(), numTargs, args...);
389 if constexpr (Ctrls == anystates) {
390 if constexpr (Targs == zero) operation(qureg, ctrls.data(), states.data(), numCtrls, args...);
391 if constexpr (Targs == one) operation(qureg, ctrls.data(), states.data(), numCtrls, targs[0], args...);
392 if constexpr (Targs == two) operation(qureg, ctrls.data(), states.data(), numCtrls, targs[0], targs[1], args...);
393 if constexpr (Targs == any) operation(qureg, ctrls.data(), states.data(), numCtrls, targs.data(), numTargs, args...);
399template <NumQubitsFlag Ctrls, NumQubitsFlag Targs>
400void invokeApiOperation(
auto operation,
Qureg qureg, vector<int> ctrls, vector<int> states, vector<int> targs,
auto&... args) {
401 invokeApiOperation<Ctrls,Targs>(operation, qureg, ctrls, states, ctrls.size(), targs, targs.size(), args...);
414template <NumQubitsFlag Targs, ArgsFlag Args>
415auto getRandomOrIdentityApiMatrix(
int numTargs,
int elemsFlag) {
432 qm = (Args == compmatr)?
434 getRandomDiagonalUnitary(numTargs);
436 if constexpr (Args == compmatr && Targs == one)
439 if constexpr (Args == compmatr && Targs == two)
442 if constexpr (Args == compmatr && Targs == any) {
448 qvector dv = getDiagonals(qm);
449 constexpr bool diag = (Args == diagmatr || Args == diagpower);
451 if constexpr (diag && Targs == one)
454 if constexpr (diag && Targs == two)
457 if constexpr (diag && Targs == any) {
464template <NumQubitsFlag Targs, ArgsFlag Args>
auto getZeroApiMatrix (
int numTargs) {
return getRandomOrIdentityApiMatrix<Targs,Args>(numTargs, 0); }
465template <NumQubitsFlag Targs, ArgsFlag Args>
auto getIdentityApiMatrix(
int numTargs) {
return getRandomOrIdentityApiMatrix<Targs,Args>(numTargs, 1); }
466template <NumQubitsFlag Targs, ArgsFlag Args>
auto getRandomApiMatrix (
int numTargs) {
return getRandomOrIdentityApiMatrix<Targs,Args>(numTargs, 2); }
479template <NumQubitsFlag Targs, ArgsFlag Args>
480auto getRandomRemainingArgs(vector<int> targs) {
482 if constexpr (Args == none)
485 if constexpr (Args == scalar) {
486 qreal angle = getRandomPhase();
487 return tuple{ angle };
490 if constexpr (Args == axisrots) {
491 qreal angle = getRandomPhase();
495 return tuple{ angle, x, y, z };
498 if constexpr (Args == compmatr || Args == diagmatr) {
499 auto matrix = getRandomApiMatrix<Targs,Args>(targs.size());
500 return tuple{ matrix };
503 if constexpr (Args == diagpower) {
504 DiagMatr matrix = getRandomApiMatrix<Targs,Args>(targs.size());
506 return tuple{ matrix, exponent };
509 if constexpr (Args == paulistr) {
510 PauliStr str = getRandomPauliStr(targs);
514 if constexpr (Args == pauligad) {
515 PauliStr str = getRandomPauliStr(targs);
516 qreal angle = getRandomPhase();
517 return tuple{ str, angle };
522template <NumQubitsFlag Targs, ArgsFlag Args>
523void freeRemainingArgs(
auto args) {
525 if constexpr (Targs == any && Args == compmatr)
528 if constexpr (Targs == any && Args == diagmatr)
531 if constexpr (Targs == any && Args == diagpower)
544template <NumQubitsFlag Targs, ArgsFlag Args>
545qmatrix getReferenceMatrix(
auto matrixRefGen, vector<int> targs,
auto additionalArgs) {
547 if constexpr (Args == none && Targs != any)
550 if constexpr (Args == none && Targs == any)
551 return matrixRefGen(targs.size());
553 if constexpr (Args == scalar && Targs != any) {
554 qreal angle = std::get<0>(additionalArgs);
555 return matrixRefGen(angle);
558 if constexpr (Args == scalar && Targs == any) {
559 qreal angle = std::get<0>(additionalArgs);
560 return matrixRefGen(angle, targs.size());
563 if constexpr (Args == axisrots) {
564 qreal angle = std::get<0>(additionalArgs);
565 qreal x = std::get<1>(additionalArgs);
566 qreal y = std::get<2>(additionalArgs);
567 qreal z = std::get<3>(additionalArgs);
568 return getExponentialOfNormalisedPauliVector(angle, x, y, z);
571 if constexpr (Args == compmatr || Args == diagmatr) {
572 auto apiMatrix = std::get<0>(additionalArgs);
573 return getMatrix(apiMatrix);
576 if constexpr (Args == diagpower) {
577 auto apiMatrix = std::get<0>(additionalArgs);
578 qmatrix diag = getMatrix(apiMatrix);
579 qcomp power = std::get<1>(additionalArgs);
580 return getPowerOfDiagonalMatrix(diag, power);
583 if constexpr (Args == paulistr) {
584 PauliStr str = std::get<0>(additionalArgs);
585 return getMatrix(str, targs);
588 if constexpr (Args == pauligad) {
589 PauliStr str = std::get<0>(additionalArgs);
590 qreal angle = std::get<1>(additionalArgs);
591 qmatrix matr = getMatrix(str, targs);
592 return getExponentialOfPauliMatrix(angle, matr);
613enum ApplyFlag { apply, leftapply, rightapply };
629std::string toString(vector<int> list) {
631 std::string out =
"{ ";
633 out += std::to_string(e) +
" ";
638std::string toString(
PauliStr str, vector<int> targs) {
640 std::string labels =
"IXYZ";
643 std::string out =
"";
644 for (
int i=targs.size()-1; i>=0; i--)
645 out += labels[paulis_getPauliAt(str, targs[i])];
650template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
651void CAPTURE_RELEVANT( vector<int> ctrls, vector<int> states, vector<int> targs,
auto& args ) {
655 UNSCOPED_INFO(
"control := " << ctrls[0] );
656 if (Ctrls == any || Ctrls == anystates )
657 UNSCOPED_INFO(
"controls := " << toString(ctrls) );
660 if (Ctrls == anystates)
661 UNSCOPED_INFO(
"states := " << toString(states) );
665 UNSCOPED_INFO(
"target := " << targs[0] );
668 UNSCOPED_INFO(
"target A := " << targs[0] );
669 UNSCOPED_INFO(
"target B := " << targs[1] );
672 UNSCOPED_INFO(
"targets := " << toString(targs) );
675 if constexpr (Args == scalar)
676 UNSCOPED_INFO(
"angle := " << std::get<0>(args) );
679 if constexpr (Args == axisrots) {
680 UNSCOPED_INFO(
"angle := " << std::get<0>(args) );
681 UNSCOPED_INFO(
"x := " << std::get<1>(args) );
682 UNSCOPED_INFO(
"y := " << std::get<2>(args) );
683 UNSCOPED_INFO(
"z := " << std::get<3>(args) );
687 if constexpr (Args == compmatr || Args == diagmatr || Args == diagpower)
688 UNSCOPED_INFO(
"matrix := (omitted)" );
691 if constexpr (Args == diagpower) {
692 qcomp p = std::get<1>(args);
693 UNSCOPED_INFO(
"exponent := " << std::real(p) <<
" + (" << std::imag(p) <<
")i" );
697 if constexpr (Args == paulistr || Args == pauligad)
698 UNSCOPED_INFO(
"paulis := " << toString(std::get<0>(args), targs) );
701 if constexpr (Args == pauligad)
702 UNSCOPED_INFO(
"angle := " << std::get<1>(args) );
714template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args, ApplyFlag Apply>
715void testOperationCorrectness(
auto operation,
auto matrixRefGen) {
717 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
720 int numTargs = GENERATE_NUM_TARGS<Ctrls,Targs,Args>(numQubits);
721 int numCtrls = GENERATE_NUM_CTRLS<Ctrls>(numQubits - numTargs);
724 auto ctrlsAndTargs = GENERATE_CTRLS_AND_TARGS( numQubits, numCtrls, numTargs );
725 vector<int> ctrls = std::get<0>(ctrlsAndTargs);
726 vector<int> targs = std::get<1>(ctrlsAndTargs);
729 vector<int> states = getRandomOutcomes(numCtrls * (Ctrls == anystates));
732 auto primaryArgs = tuple{ ctrls, states, targs };
733 auto furtherArgs = getRandomRemainingArgs<Targs,Args>(targs);
736 qmatrix matrixRef = getReferenceMatrix<Targs,Args>(matrixRefGen, targs, furtherArgs);
739 constexpr NumQubitsFlag RevTargs = (Args==paulistr||Args==pauligad)? zero : Targs;
750 auto testFunc = [&](
Qureg qureg,
auto& stateRef) ->
void {
753 auto apiFunc = [](
auto&&... args) {
return invokeApiOperation<Ctrls,RevTargs>(args...); };
754 auto allArgs = std::tuple_cat(tuple{operation, qureg}, primaryArgs, furtherArgs);
755 std::apply(apiFunc, allArgs);
758 if constexpr (Apply == apply) applyReferenceOperator( stateRef, ctrls, states, targs, matrixRef);
759 if constexpr (Apply == leftapply) leftapplyReferenceOperator( stateRef, ctrls, states, targs, matrixRef);
760 if constexpr (Apply == rightapply) rightapplyReferenceOperator(stateRef, ctrls, states, targs, matrixRef);
764 CAPTURE_RELEVANT<Ctrls,Targs,Args>( ctrls, states, targs, furtherArgs );
768 if constexpr (Apply != rightapply) {
769 SECTION( LABEL_STATEVEC ) {
770 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc);
773 SECTION( LABEL_DENSMATR ) {
774 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc);
778 freeRemainingArgs<Targs,Args>(furtherArgs);
789template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
790auto getFixedCtrlsStatesTargs(
int numQubits) {
793 vector<int> targs, ctrls, states;
796 if constexpr (Targs == one) targs = {0};
797 if constexpr (Targs == two) targs = {0,1};
798 if constexpr (Targs == any) targs = {0,1,2};
799 if constexpr (Ctrls == one) ctrls = {3};
800 if constexpr (Ctrls == any) ctrls = {3,4};
801 if constexpr (Ctrls == anystates) ctrls = {3,4};
802 if constexpr (Ctrls == anystates) states = {0,0};
804 DEMAND( numQubits >= targs.size() + ctrls.size() );
806 return tuple{ ctrls, states, targs };
809template <NumQubitsFlag Targs, ArgsFlag Args>
810auto getFixedRemainingArgs(vector<int> targs) {
813 if constexpr (Args == paulistr || Args == pauligad)
814 DEMAND( targs.size() == 3 );
816 if constexpr (Args == none)
return tuple{ };
817 if constexpr (Args == scalar)
return tuple{ 0 };
818 if constexpr (Args == axisrots)
return tuple{ 0, 1,1,1 };
819 if constexpr (Args == compmatr)
return tuple{ getIdentityApiMatrix<Targs,Args>(targs.size()) };
820 if constexpr (Args == diagmatr)
return tuple{ getIdentityApiMatrix<Targs,Args>(targs.size()) };
821 if constexpr (Args == diagpower)
return tuple{ getIdentityApiMatrix<Targs,Args>(targs.size()), qcomp(1,0) };
822 if constexpr (Args == paulistr)
return tuple{
getPauliStr(
"XXX", targs) };
823 if constexpr (Args == pauligad)
return tuple{
getPauliStr(
"XXX", targs), 0 };
826template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args, ApplyFlag Apply>
827void testOperationValidation(
auto operation) {
830 Qureg qureg = getCachedDensmatrs().begin()->second;
834 auto [ctrls,states,targs] = getFixedCtrlsStatesTargs<Ctrls,Targs,Args>(qureg.numQubits);
835 auto furtherArgs = getFixedRemainingArgs<Targs,Args>(targs);
838 auto apiFunc = [&]() {
839 constexpr NumQubitsFlag RevTargs = (Args==paulistr||Args==pauligad)? zero : Targs;
840 auto func = [](
auto&&... allArgs) {
return invokeApiOperation<Ctrls,RevTargs>(allArgs...); };
841 std::apply(func, std::tuple_cat(tuple{operation, qureg, ctrls, states, targs}, furtherArgs));
845 int numQubits = qureg.numQubits;
846 int numTargs = (int) targs.size();
847 int numCtrls = (int) ctrls.size();
855 SECTION(
"qureg uninitialised" ) {
858 qureg.numQubits = -123;
859 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"invalid Qureg") );
862 SECTION(
"invalid target" ) {
865 if (Args == paulistr || Args == pauligad)
869 int ind = GENERATE_COPY( range(0,numTargs) );
870 int val = GENERATE_COPY( -1, numQubits );
873 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Invalid target qubit") );
876 SECTION(
"invalid non-Identity Pauli index" ) {
878 if (Args != paulistr && Args != pauligad)
882 if constexpr (Args == paulistr) furtherArgs = tuple{ badStr };
883 if constexpr (Args == pauligad) furtherArgs = tuple{ badStr, 1 };
885 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"highest-index non-identity Pauli operator") && ContainsSubstring(
"exceeds the maximum target") );
888 SECTION(
"invalid control" ) {
894 int ind = GENERATE_COPY( range(0,numCtrls) );
895 int val = GENERATE_COPY( -1, numQubits );
898 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Invalid control qubit") );
901 SECTION(
"control and target collision" ) {
907 int targInd = GENERATE_COPY( range(0,numTargs) );
908 int ctrlInd = GENERATE_COPY( range(0,numCtrls) );
909 ctrls[ctrlInd] = targs[targInd];
911 if (Args==paulistr||Args==pauligad)
912 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"control qubit overlaps a non-identity Pauli operator") );
914 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"qubit appeared among both the control and target qubits") );
917 SECTION(
"control states" ) {
922 int ind = GENERATE_COPY( range(0,numCtrls) );
923 int val = GENERATE( -1, 2 );
926 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"invalid control-state") );
929 SECTION(
"repetition in controls" ) {
934 int ind = GENERATE_COPY( range(1,numCtrls) );
935 ctrls[ind] = ctrls[0];
937 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"control qubits contained duplicates") );
940 SECTION(
"repetition in targets" ) {
943 if (Args==paulistr||Args==pauligad)
949 int ind = GENERATE_COPY( range(1,numTargs) );
950 targs[ind] = targs[0];
952 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"target qubits contained duplicates") );
955 SECTION(
"number of targets" ) {
959 if (Args == paulistr || Args == pauligad)
967 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Must specify one or more targets") );
970 targs = getRange(qureg.numQubits+1);
971 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"number of target qubits") && ContainsSubstring(
"exceeds the number of qubits in the Qureg") );
977 SECTION(
"mismatching matrix size" ) {
982 if (!(Args == compmatr || Args == diagmatr || Args == diagpower))
985 DEMAND( numTargs > 1 );
986 DEMAND( numCtrls + numTargs < numQubits );
988 targs.push_back(numQubits - 1);
989 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"matrix has an inconsistent size") );
993 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"matrix has an inconsistent size") );
996 SECTION(
"matrix unitarity" ) {
999 if (Args != compmatr && Args != diagmatr && Args != diagpower)
1006 if constexpr (Args == compmatr || Args == diagmatr)
1007 furtherArgs = tuple{ getZeroApiMatrix<Targs,Args>(targs.size()) };
1008 if constexpr (Args == diagpower)
1009 furtherArgs = tuple{ getZeroApiMatrix<Targs,Args>(targs.size()), 1 };
1011 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"unitary") );
1014 SECTION(
"matrix uninitialised" ) {
1017 if constexpr (Args == compmatr || Args == diagmatr || Args == diagpower)
1018 std::get<0>(furtherArgs).numQubits = -1;
1022 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Invalid") );
1025 if constexpr (Args == compmatr || Args == diagmatr || Args == diagpower)
1026 std::get<0>(furtherArgs).numQubits = numTargs;
1029 SECTION(
"matrix unsynced" ) {
1035 if constexpr (Targs == any && (Args == compmatr || Args == diagmatr || Args == diagpower))
1036 *(std::get<0>(furtherArgs).wasGpuSynced) = 0;
1040 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"sync") );
1043 SECTION(
"targeted amps fit in node" ) {
1046 qureg = getCachedStatevecs().begin()->second;
1050 if (qureg.numNodes < 2)
1055 int minNumCtrls = (Ctrls == one)? 1 : 0;
1056 int minNumTargs = numQubits - qureg.logNumNodes + 1;
1057 int maxNumTargs = numQubits - minNumCtrls;
1058 if (minNumTargs > maxNumTargs)
1064 if constexpr (Args == compmatr && Targs == any) {
1070 int numNewTargs = GENERATE_COPY( range(minNumTargs, maxNumTargs+1) );
1071 targs = getRange(numNewTargs);
1075 ctrls = vector<int>(minNumCtrls, numQubits - 1);
1079 CompMatr matr = getIdentityApiMatrix<Targs,Args>(numNewTargs);
1080 furtherArgs = tuple{ matr };
1082 CAPTURE( minNumCtrls, numNewTargs, numQubits - minNumCtrls, ctrls, targs );
1083 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"cannot simultaneously store") && ContainsSubstring(
"remote amplitudes") );
1090 SECTION(
"non-unitary exponent" ) {
1096 if constexpr (Args == diagpower)
1097 furtherArgs = tuple{ std::get<0>(furtherArgs), qcomp(1,1) };
1101 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"exponent was not approximately real") );
1104 SECTION(
"diverging exponent" ) {
1111 if constexpr (Args == diagpower)
1112 furtherArgs = tuple{ getZeroApiMatrix<Targs,Args>(numTargs), qcomp(-1,0) };
1116 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"divergences") );
1119 SECTION(
"zero axis rotation" ) {
1121 if constexpr (Args == axisrots) {
1122 furtherArgs = tuple{ 0, 0, 0, 0 };
1126 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"zero vector") );
1129 SECTION(
"qureg type" ) {
1132 if (Apply != rightapply)
1136 qureg = getCachedStatevecs().begin()->second;
1138 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Expected a density matrix") );
1141 freeRemainingArgs<Targs,Args>(furtherArgs);
1150template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args, ApplyFlag Apply>
1151void testOperation(
auto operation,
auto matrixRefGen) {
1153 assertNumQubitsFlagsAreValid(Ctrls, Targs);
1155 SECTION( LABEL_CORRECTNESS ) {
1156 testOperationCorrectness<Ctrls,Targs,Args,Apply>(operation, matrixRefGen);
1159 SECTION( LABEL_VALIDATION ) {
1160 testOperationValidation<Ctrls,Targs,Args,Apply>(operation);
1200#define GET_FUNC_CTRL_SUB_SIG( numctrls ) GET_FUNC_CTRL_SUB_SIG_##numctrls
1201#define GET_FUNC_CTRL_SUB_SIG_zero
1202#define GET_FUNC_CTRL_SUB_SIG_one int,
1203#define GET_FUNC_CTRL_SUB_SIG_any int*,int,
1204#define GET_FUNC_CTRL_SUB_SIG_anystates int*,int*,int,
1210#define GET_FUNC_TARG_SUB_SIG( numtargs, argtype ) GET_FUNC_TARG_SUB_SIG_##argtype( numtargs )
1211#define GET_FUNC_TARG_SUB_SIG_none( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs
1212#define GET_FUNC_TARG_SUB_SIG_scalar( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1213#define GET_FUNC_TARG_SUB_SIG_axisrots( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1214#define GET_FUNC_TARG_SUB_SIG_compmatr( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1215#define GET_FUNC_TARG_SUB_SIG_diagmatr( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1216#define GET_FUNC_TARG_SUB_SIG_diagpower( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1217#define GET_FUNC_TARG_SUB_SIG_paulistr( numtargs )
1218#define GET_FUNC_TARG_SUB_SIG_pauligad( numtargs )
1219#define GET_FUNC_TARG_SUB_SIG_one int
1220#define GET_FUNC_TARG_SUB_SIG_two int,int
1221#define GET_FUNC_TARG_SUB_SIG_any int*,int
1224#define GET_FUNC_ARGS_SUB_SIG( numtargs, argtype ) GET_FUNC_ARGS_SUB_SIG_##numtargs##_##argtype
1225#define GET_FUNC_ARGS_SUB_SIG_one_none
1226#define GET_FUNC_ARGS_SUB_SIG_two_none
1227#define GET_FUNC_ARGS_SUB_SIG_any_none
1228#define GET_FUNC_ARGS_SUB_SIG_one_scalar qreal
1229#define GET_FUNC_ARGS_SUB_SIG_two_scalar qreal
1230#define GET_FUNC_ARGS_SUB_SIG_any_scalar qreal
1231#define GET_FUNC_ARGS_SUB_SIG_one_compmatr CompMatr1
1232#define GET_FUNC_ARGS_SUB_SIG_two_compmatr CompMatr2
1233#define GET_FUNC_ARGS_SUB_SIG_any_compmatr CompMatr
1234#define GET_FUNC_ARGS_SUB_SIG_one_diagmatr DiagMatr1
1235#define GET_FUNC_ARGS_SUB_SIG_two_diagmatr DiagMatr2
1236#define GET_FUNC_ARGS_SUB_SIG_any_diagmatr DiagMatr
1237#define GET_FUNC_ARGS_SUB_SIG_one_diagpower DiagMatr1,qcomp
1238#define GET_FUNC_ARGS_SUB_SIG_two_diagpower DiagMatr2,qcomp
1239#define GET_FUNC_ARGS_SUB_SIG_any_diagpower DiagMatr, qcomp
1240#define GET_FUNC_ARGS_SUB_SIG_one_axisrots qreal,qreal,qreal,qreal
1241#define GET_FUNC_ARGS_SUB_SIG_any_paulistr PauliStr
1242#define GET_FUNC_ARGS_SUB_SIG_any_pauligad PauliStr,qreal
1245#define GET_FUNC_NAME_PREFIX( numctrls ) GET_FUNC_NAME_PREFIX_##numctrls
1246#define GET_FUNC_NAME_PREFIX_zero apply
1247#define GET_FUNC_NAME_PREFIX_one applyControlled
1248#define GET_FUNC_NAME_PREFIX_any applyMultiControlled
1249#define GET_FUNC_NAME_PREFIX_anystates applyMultiStateControlled
1252#define GET_FUNC_NAME(numctrls, suffix) GET_FUNC_NAME_INNER(GET_FUNC_NAME_PREFIX(numctrls), suffix)
1253#define GET_FUNC_NAME_INNER(A, B) GET_FUNC_NAME_INNER_INNER(A, B)
1254#define GET_FUNC_NAME_INNER_INNER(A, B) A##B
1257#define GET_FUNC_NAME_STR(numctrls, suffix) GET_FUNC_NAME_STR_INNER( GET_FUNC_NAME(numctrls,suffix) )
1258#define GET_FUNC_NAME_STR_INNER(expr) GET_FUNC_NAME_STR_INNER_INNER(expr)
1259#define GET_FUNC_NAME_STR_INNER_INNER(symbol) #symbol
1265#define GET_FUNC_SIG( numctrls, numtargs, argtype ) \
1268 GET_FUNC_CTRL_SUB_SIG( numctrls ) \
1269 GET_FUNC_TARG_SUB_SIG( numtargs, argtype ) \
1270 GET_FUNC_ARGS_SUB_SIG( numtargs, argtype ) \
1275#define GET_CASTED_FUNC( namesuffix, numctrls, numtargs, argtype ) \
1276 static_cast< GET_FUNC_SIG(numctrls, numtargs, argtype) > ( \
1277 GET_FUNC_NAME(numctrls, namesuffix) )
1280#define TEST_CASE_OPERATION( namesuffix, numctrls, numtargs, argtype, matrixgen ) \
1281 TEST_CASE( GET_FUNC_NAME_STR(numctrls, namesuffix), TEST_CATEGORY_OPS ) { \
1282 testOperation<numctrls, numtargs, argtype, apply>( \
1283 GET_CASTED_FUNC(namesuffix, numctrls, numtargs, argtype), \
1288#define TEST_ALL_CTRL_OPERATIONS( namesuffix, numtargs, argtype, matrixgen ) \
1289 TEST_CASE_OPERATION( namesuffix, zero, numtargs, argtype, matrixgen ) \
1290 TEST_CASE_OPERATION( namesuffix, one, numtargs, argtype, matrixgen ) \
1291 TEST_CASE_OPERATION( namesuffix, any, numtargs, argtype, matrixgen ) \
1292 TEST_CASE_OPERATION( namesuffix, anystates, numtargs, argtype, matrixgen )
1337TEST_CASE(
"applyPhaseFlip", TEST_CATEGORY_OPS ) { testOperation<zero,one,none,apply> (
applyPhaseFlip, VariableSizeMatrices::PF(1)); }
1339TEST_CASE(
"applyPhaseShift", TEST_CATEGORY_OPS ) { testOperation<zero,one,scalar,apply>(
applyPhaseShift, ParameterisedMatrices::PS ); }
1350TEST_CASE(
"applyMultiQubitPhaseFlip", TEST_CATEGORY_OPS ) {
1352 testOperation<zero,any,none,apply>(func, VariableSizeMatrices::PF);
1355TEST_CASE(
"applyMultiQubitPhaseShift", TEST_CATEGORY_OPS ) {
1357 testOperation<zero,any,scalar,apply>(func, VariableSizeParameterisedMatrices::PS);
1365TEST_CASE(
"applyQuantumFourierTransform", TEST_CATEGORY_OPS ) {
1367 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1369 SECTION( LABEL_CORRECTNESS ) {
1371 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1372 auto targs = GENERATE_TARGS( numQubits, numTargs );
1376 SECTION( LABEL_STATEVEC ) {
1378 auto testFunc = [&](
Qureg qureg, qvector& ref) {
1380 ref = getDisceteFourierTransform(ref, targs);
1383 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc);
1386 SECTION( LABEL_DENSMATR ) {
1389 auto states = getRandomOrthonormalStateVectors(numQubits,
getRandomInt(1,10));
1392 auto testFunc = [&](
Qureg qureg, qmatrix& ref) {
1395 setQuregToReference(qureg, getMixture(states, probs));
1399 for (
size_t i=0; i<states.size(); i++) {
1400 qvector vec = getDisceteFourierTransform(states[i], targs);
1401 ref += probs[i] * getOuterProduct(vec, vec);
1405 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc);
1413TEST_CASE(
"applyFullQuantumFourierTransform", TEST_CATEGORY_OPS ) {
1415 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1417 SECTION( LABEL_CORRECTNESS ) {
1419 GENERATE( range(0,10) );
1421 SECTION( LABEL_STATEVEC ) {
1423 auto testFunc = [&](
Qureg qureg, qvector& ref) {
1425 ref = getDisceteFourierTransform(ref);
1428 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc);
1431 SECTION( LABEL_DENSMATR ) {
1434 auto states = getRandomOrthonormalStateVectors(numQubits,
getRandomInt(1,10));
1437 auto testFunc = [&](
Qureg qureg, qmatrix& ref) {
1440 setQuregToReference(qureg, getMixture(states, probs));
1444 for (
size_t i=0; i<states.size(); i++) {
1445 qvector vec = getDisceteFourierTransform(states[i]);
1446 ref += probs[i] * getOuterProduct(vec, vec);
1450 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc);
1460 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1462 SECTION( LABEL_CORRECTNESS ) {
1464 GENERATE( range(0,10) );
1465 int target = GENERATE_COPY( range(0,numQubits) );
1466 int outcome = GENERATE( 0, 1 );
1468 qmatrix projector = getProjector(outcome);
1470 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1472 applyReferenceOperator(ref, {target}, projector);
1475 CAPTURE( target, outcome );
1476 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1477 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1486 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1488 SECTION( LABEL_CORRECTNESS ) {
1490 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1491 auto targets = GENERATE_TARGS( numQubits, numTargs );
1492 auto outcomes = getRandomOutcomes(numTargs);
1494 qmatrix projector = getProjector(targets, outcomes, numQubits);
1496 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1498 applyReferenceOperator(ref, projector);
1501 CAPTURE( targets, outcomes );
1502 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1503 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1510TEST_CASE(
"applyForcedQubitMeasurement", TEST_CATEGORY_OPS ) {
1512 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1514 SECTION( LABEL_CORRECTNESS ) {
1516 GENERATE( range(0,10) );
1517 int target = GENERATE_COPY( range(0,numQubits) );
1518 int outcome = GENERATE( 0, 1 );
1520 qmatrix projector = getProjector(outcome);
1522 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1526 setToRandomState(ref);
1527 setQuregToReference(qureg, ref);
1531 qreal refProb = getReferenceProbability(ref, {target}, {outcome});
1532 REQUIRE_AGREE( apiProb, refProb );
1535 applyReferenceOperator(ref, {target}, projector);
1536 ref /= (qureg.isDensityMatrix)?
1537 refProb : std::sqrt(refProb);
1540 CAPTURE( target, outcome );
1541 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1542 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1549TEST_CASE(
"applyForcedMultiQubitMeasurement", TEST_CATEGORY_OPS ) {
1551 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1553 SECTION( LABEL_CORRECTNESS ) {
1555 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1556 auto targets = GENERATE_TARGS( numQubits, numTargs );
1557 auto outcomes = getRandomOutcomes(numTargs);
1559 qmatrix projector = getProjector(targets, outcomes, numQubits);
1566 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1570 setToRandomState(ref);
1571 setQuregToReference(qureg, ref);
1575 qreal refProb = getReferenceProbability(ref, targets, outcomes);
1576 REQUIRE_AGREE( apiProb, refProb );
1579 applyReferenceOperator(ref, projector);
1580 ref /= (qureg.isDensityMatrix)?
1581 refProb : std::sqrt(refProb);
1584 CAPTURE( targets, outcomes );
1585 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1586 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1595TEST_CASE(
"applyMultiQubitMeasurement", TEST_CATEGORY_OPS ) {
1597 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1599 SECTION( LABEL_CORRECTNESS ) {
1601 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1602 auto targets = GENERATE_TARGS( numQubits, numTargs );
1604 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1608 setToRandomState(ref);
1609 setQuregToReference(qureg, ref);
1615 auto apiOutBits = getBits(apiOut, numTargs);
1616 qmatrix projector = getProjector(targets, apiOutBits, numQubits);
1617 applyReferenceOperator(ref, projector);
1618 qreal refProb = getReferenceProbability(ref, targets, apiOutBits);
1619 ref /= (qureg.isDensityMatrix)?
1620 refProb : std::sqrt(refProb);
1624 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1625 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1632TEST_CASE(
"applyMultiQubitMeasurementAndGetProb", TEST_CATEGORY_OPS ) {
1634 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1636 SECTION( LABEL_CORRECTNESS ) {
1638 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1639 auto targets = GENERATE_TARGS( numQubits, numTargs );
1641 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1645 setToRandomState(ref);
1646 setQuregToReference(qureg, ref);
1651 auto apiOutBits = getBits(apiOut, numTargs);
1652 qreal refProb = getReferenceProbability(ref, targets, apiOutBits);
1653 REQUIRE_AGREE( apiProb, refProb );
1656 qmatrix projector = getProjector(targets, apiOutBits, numQubits);
1657 applyReferenceOperator(ref, projector);
1658 ref /= (qureg.isDensityMatrix)?
1659 refProb : std::sqrt(refProb);
1663 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1664 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1673 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1675 SECTION( LABEL_CORRECTNESS ) {
1677 GENERATE( range(0,10) );
1678 int target = GENERATE_COPY( range(0,numQubits) );
1680 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1684 setToRandomState(ref);
1685 setQuregToReference(qureg, ref);
1691 qmatrix projector = getProjector(apiOut);
1692 applyReferenceOperator(ref, {target}, projector);
1693 qreal refProb = getReferenceProbability(ref, {target}, {apiOut});
1694 ref /= (qureg.isDensityMatrix)?
1695 refProb : std::sqrt(refProb);
1699 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1700 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1707TEST_CASE(
"applyQubitMeasurementAndGetProb", TEST_CATEGORY_OPS ) {
1709 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1711 SECTION( LABEL_CORRECTNESS ) {
1713 GENERATE( range(0,10) );
1714 int target = GENERATE_COPY( range(0,numQubits) );
1716 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1720 setToRandomState(ref);
1721 setQuregToReference(qureg, ref);
1726 qreal refProb = getReferenceProbability(ref, {target}, {apiOut});
1727 REQUIRE_AGREE( apiProb, refProb );
1730 qmatrix projector = getProjector(apiOut);
1731 applyReferenceOperator(ref, {target}, projector);
1732 ref /= (qureg.isDensityMatrix)?
1733 refProb : std::sqrt(refProb);
1737 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1738 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1745TEST_CASE(
"applyFullStateDiagMatr", TEST_CATEGORY_OPS LABEL_MIXED_DEPLOY_TAG ) {
1747 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
1749 auto cachedMatrs = getCachedFullStateDiagMatrs();
1751 SECTION( LABEL_CORRECTNESS ) {
1753 qmatrix refMatr = getRandomDiagonalUnitary(numQubits);
1756 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
1758 SECTION( LABEL_STATEVEC ) {
1760 auto refFunc = [&] (qvector& state, qmatrix matr) { applyReferenceOperator(state, matr); };
1762 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
1765 SECTION( LABEL_DENSMATR ) {
1767 auto refFunc = [&] (qmatrix& state, qmatrix matr) { applyReferenceOperator(state, matr); };
1769 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
1777TEST_CASE(
"applyFullStateDiagMatrPower", TEST_CATEGORY_OPS LABEL_MIXED_DEPLOY_TAG ) {
1779 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
1781 auto cachedMatrs = getCachedFullStateDiagMatrs();
1783 SECTION( LABEL_CORRECTNESS ) {
1785 qmatrix refMatr = getRandomDiagonalUnitary(numQubits);
1789 bool testRealExp = GENERATE(
true,
false );
1790 qcomp exponent = (testRealExp)?
1798 CAPTURE( exponent );
1800 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
1805 SECTION( LABEL_STATEVEC ) {
1807 auto refFunc = [&] (qvector& state, qmatrix matr) {
1808 matr = getPowerOfDiagonalMatrix(matr, exponent);
1809 applyReferenceOperator(state, matr);
1812 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
1815 SECTION( LABEL_DENSMATR ) {
1817 auto refFunc = [&] (qmatrix& state, qmatrix matr) {
1818 matr = getPowerOfDiagonalMatrix(matr, exponent);
1819 applyReferenceOperator(state, matr);
1822 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
1832TEST_CASE(
"applyNonUnitaryPauliGadget", TEST_CATEGORY_OPS ) {
1834 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1836 SECTION( LABEL_CORRECTNESS ) {
1839 int numTargs = GENERATE_COPY( range(1, numQubits+1) );
1840 auto targs = GENERATE_TARGS( numQubits, numTargs );
1841 PauliStr str = getRandomPauliStr(targs);
1845 auto matrRef = getExponentialOfPauliMatrix(angle, getMatrix(str, numQubits));
1847 auto testFunc = [&](
Qureg qureg,
auto& stateRef) {
1849 applyReferenceOperator(stateRef, matrRef);
1852 CAPTURE( targs, angle );
1853 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1854 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1873TEST_CASE(
"leftapplySwap", TEST_CATEGORY_MULT ) { testOperation<zero,two,none,leftapply>(
leftapplySwap, FixedMatrices::SWAP); }
1874TEST_CASE(
"leftapplyPauliX", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,leftapply>(
leftapplyPauliX, FixedMatrices::X); }
1875TEST_CASE(
"leftapplyPauliY", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,leftapply>(
leftapplyPauliY, FixedMatrices::Y); }
1876TEST_CASE(
"leftapplyPauliZ", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,leftapply>(
leftapplyPauliZ, FixedMatrices::Z); }
1877TEST_CASE(
"leftapplyPauliStr", TEST_CATEGORY_MULT ) { testOperation<zero,any,paulistr,leftapply>(
leftapplyPauliStr,
nullptr); }
1884TEST_CASE(
"rightapplySwap", TEST_CATEGORY_MULT ) { testOperation<zero,two,none,rightapply>(
rightapplySwap, FixedMatrices::SWAP); }
1885TEST_CASE(
"rightapplyPauliX", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,rightapply>(
rightapplyPauliX, FixedMatrices::X); }
1886TEST_CASE(
"rightapplyPauliY", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,rightapply>(
rightapplyPauliY, FixedMatrices::Y); }
1887TEST_CASE(
"rightapplyPauliZ", TEST_CATEGORY_MULT ) { testOperation<zero,one,none,rightapply>(
rightapplyPauliZ, FixedMatrices::Z); }
1888TEST_CASE(
"rightapplyPauliStr", TEST_CATEGORY_MULT ) { testOperation<zero,any,paulistr,rightapply>(
rightapplyPauliStr,
nullptr); }
1903TEST_CASE(
"leftapplyCompMatr", TEST_CATEGORY_MULT ) {
1905 testOperation<zero,any,compmatr,leftapply>(func,
nullptr);
1908TEST_CASE(
"leftapplyDiagMatr", TEST_CATEGORY_MULT ) {
1910 testOperation<zero,any,diagmatr,leftapply>(func,
nullptr);
1913TEST_CASE(
"leftapplyDiagMatrPower", TEST_CATEGORY_MULT ) {
1915 testOperation<zero,any,diagpower,leftapply>(func,
nullptr);
1918TEST_CASE(
"leftapplyMultiQubitNot", TEST_CATEGORY_MULT ) {
1920 testOperation<zero,any,none,leftapply>(func, VariableSizeMatrices::X);
1923TEST_CASE(
"leftapplyPhaseGadget", TEST_CATEGORY_MULT ) {
1925 testOperation<zero,any,scalar,leftapply>(func, VariableSizeParameterisedMatrices::Z);
1929TEST_CASE(
"rightapplyCompMatr", TEST_CATEGORY_MULT ) {
1931 testOperation<zero,any,compmatr,rightapply>(func,
nullptr);
1934TEST_CASE(
"rightapplyDiagMatr", TEST_CATEGORY_MULT ) {
1936 testOperation<zero,any,diagmatr,rightapply>(func,
nullptr);
1939TEST_CASE(
"rightapplyDiagMatrPower", TEST_CATEGORY_MULT ) {
1941 testOperation<zero,any,diagpower,rightapply>(func,
nullptr);
1944TEST_CASE(
"rightapplyMultiQubitNot", TEST_CATEGORY_MULT ) {
1946 testOperation<zero,any,none,rightapply>(func, VariableSizeMatrices::X);
1949TEST_CASE(
"rightapplyPhaseGadget", TEST_CATEGORY_MULT ) {
1951 testOperation<zero,any,scalar,rightapply>(func, VariableSizeParameterisedMatrices::Z);
1960TEST_CASE(
"leftapplyFullStateDiagMatr", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
1962 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
1964 auto cachedMatrs = getCachedFullStateDiagMatrs();
1966 SECTION( LABEL_CORRECTNESS ) {
1968 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(numQubits));
1971 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
1973 SECTION( LABEL_STATEVEC ) {
1975 auto refFunc = [&] (qvector& state, qmatrix matr) { leftapplyReferenceOperator(state, matr); };
1977 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
1980 SECTION( LABEL_DENSMATR ) {
1982 auto refFunc = [&] (qmatrix& state, qmatrix matr) { leftapplyReferenceOperator(state, matr); };
1984 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
1992TEST_CASE(
"rightapplyFullStateDiagMatr", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
1994 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
1996 auto cachedMatrs = getCachedFullStateDiagMatrs();
1998 SECTION( LABEL_CORRECTNESS ) {
2000 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(numQubits));
2003 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
2005 SECTION( LABEL_DENSMATR ) {
2007 auto refFunc = [&] (qmatrix& state, qmatrix matr) { rightapplyReferenceOperator(state, matr); };
2009 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
2017TEST_CASE(
"leftapplyFullStateDiagMatrPower", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
2019 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
2021 auto cachedMatrs = getCachedFullStateDiagMatrs();
2023 SECTION( LABEL_CORRECTNESS ) {
2025 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(numQubits));
2032 CAPTURE( exponent );
2034 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
2036 SECTION( LABEL_STATEVEC ) {
2038 auto refFunc = [&] (qvector& state, qmatrix matr) {
2039 matr = getPowerOfDiagonalMatrix(matr, exponent);
2040 leftapplyReferenceOperator(state, matr);
2043 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
2046 SECTION( LABEL_DENSMATR ) {
2048 auto refFunc = [&] (qmatrix& state, qmatrix matr) {
2049 matr = getPowerOfDiagonalMatrix(matr, exponent);
2050 leftapplyReferenceOperator(state, matr);
2053 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
2061TEST_CASE(
"rightapplyFullStateDiagMatrPower", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
2063 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
2065 auto cachedMatrs = getCachedFullStateDiagMatrs();
2067 SECTION( LABEL_CORRECTNESS ) {
2069 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(numQubits));
2076 CAPTURE( exponent );
2078 GENERATE( range(0, getNumTestedMixedDeploymentRepetitions()) );
2080 SECTION( LABEL_DENSMATR ) {
2082 auto refFunc = [&] (qmatrix& state, qmatrix matr) {
2083 matr = getPowerOfDiagonalMatrix(matr, exponent);
2084 rightapplyReferenceOperator(state, matr);
2087 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
2097 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2099 SECTION( LABEL_CORRECTNESS ) {
2101 GENERATE( range(0,10) );
2102 int target = GENERATE_COPY( range(0,numQubits) );
2103 int outcome = GENERATE( 0, 1 );
2105 qmatrix projector = getProjector(outcome);
2107 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2109 leftapplyReferenceOperator(ref, {target}, projector);
2112 CAPTURE( target, outcome );
2113 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
2114 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2123 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2125 SECTION( LABEL_CORRECTNESS ) {
2127 GENERATE( range(0,10) );
2128 int target = GENERATE_COPY( range(0,numQubits) );
2129 int outcome = GENERATE( 0, 1 );
2131 qmatrix projector = getProjector(outcome);
2133 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2135 rightapplyReferenceOperator(ref, {target}, projector);
2138 CAPTURE( target, outcome );
2139 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2146TEST_CASE(
"leftapplyMultiQubitProjector", TEST_CATEGORY_OPS ) {
2148 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2150 SECTION( LABEL_CORRECTNESS ) {
2152 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
2153 auto targets = GENERATE_TARGS( numQubits, numTargs );
2154 auto outcomes = getRandomOutcomes(numTargs);
2156 qmatrix projector = getProjector(targets, outcomes, numQubits);
2158 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2160 leftapplyReferenceOperator(ref, projector);
2163 CAPTURE( targets, outcomes );
2164 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
2165 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2172TEST_CASE(
"rightapplyMultiQubitProjector", TEST_CATEGORY_OPS ) {
2174 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2176 SECTION( LABEL_CORRECTNESS ) {
2178 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
2179 auto targets = GENERATE_TARGS( numQubits, numTargs );
2180 auto outcomes = getRandomOutcomes(numTargs);
2182 qmatrix projector = getProjector(targets, outcomes, numQubits);
2184 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2186 rightapplyReferenceOperator(ref, projector);
2189 CAPTURE( targets, outcomes );
2190 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2197TEST_CASE(
"leftapplyPauliStrSum", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
2199 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2201 SECTION( LABEL_CORRECTNESS ) {
2203 int numQubits = getNumCachedQubits();
2204 int numTerms = GENERATE_COPY( 1, 2, 10 );
2206 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
2208 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2215 ref = getMatrix(sum, numQubits) * ref;
2218 CAPTURE( numTerms );
2219 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
2220 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
2227TEST_CASE(
"rightapplyPauliStrSum", TEST_CATEGORY_MULT LABEL_MIXED_DEPLOY_TAG ) {
2229 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
2231 SECTION( LABEL_CORRECTNESS ) {
2233 int numQubits = getNumCachedQubits();
2234 int numTerms = GENERATE_COPY( 1, 2, 10 );
2236 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
2238 auto testFunc = [&](
Qureg qureg,
auto& ref) {
2245 ref = ref * getMatrix(sum, numQubits);
2248 CAPTURE( numTerms );
2249 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
void setValidationEpsilonToDefault()
void setValidationEpsilon(qreal eps)
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 applyFullQuantumFourierTransform(Qureg qureg)
void applyQuantumFourierTransform(Qureg qureg, int *targets, int numTargets)
PauliStr getPauliStr(const char *paulis, int *indices, int numPaulis)
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)