18#include "quest/include/quest.h"
20#include <catch2/catch_test_macros.hpp>
21#include <catch2/catch_template_test_macros.hpp>
22#include <catch2/matchers/catch_matchers_string.hpp>
23#include <catch2/generators/catch_generators_range.hpp>
25#include "tests/utils/cache.hpp"
26#include "tests/utils/qvector.hpp"
27#include "tests/utils/qmatrix.hpp"
28#include "tests/utils/compare.hpp"
29#include "tests/utils/convert.hpp"
30#include "tests/utils/evolve.hpp"
31#include "tests/utils/linalg.hpp"
32#include "tests/utils/lists.hpp"
33#include "tests/utils/measure.hpp"
34#include "tests/utils/macros.hpp"
35#include "tests/utils/random.hpp"
40using Catch::Matchers::ContainsSubstring;
48#define TEST_CATEGORY \
49 LABEL_UNIT_TAG "[operations]"
56namespace FixedMatrices {
59 {1/std::sqrt(2), 1/std::sqrt(2)},
60 {1/std::sqrt(2), -1/std::sqrt(2)}};
62 qmatrix X = getPauliMatrix(1);
63 qmatrix Y = getPauliMatrix(2);
64 qmatrix Z = getPauliMatrix(3);
66 qreal PI = 3.14159265358979323846;
69 {0, std::exp(1_i * PI/4)}};
83 {0, (1+1_i)/2, (1-1_i)/2, 0},
84 {0, (1-1_i)/2, (1+1_i)/2, 0},
88namespace ParameterisedMatrices {
94 auto PS = [](qreal p) {
return qmatrix{{1, 0}, {0, std::exp(p*1_i)}}; };
95 auto PS2 = [](qreal p) {
return getControlledMatrix(PS(p), 1); };
98namespace VariableSizeMatrices {
101 auto PF = [](
int n) {
return getControlledMatrix(FixedMatrices::Z, n - 1); };
104namespace VariableSizeParameterisedMatrices {
106 auto Z = [](qreal p,
int n) {
111 auto PS = [](qreal p,
int n) {
112 qmatrix m = ParameterisedMatrices::PS(p);
113 return getControlledMatrix(m, n - 1);
128void TEST_ON_CACHED_QUREGS(quregCache quregs,
auto& reference,
auto& function) {
130 for (
auto& [label, qureg]: quregs) {
132 DYNAMIC_SECTION( label ) {
138 setToDebugState(reference);
140 function(qureg, reference);
141 REQUIRE_AGREE( qureg, reference );
146void TEST_ON_CACHED_QUREG_AND_MATRIX(quregCache quregs, matrixCache matrices,
auto apiFunc,
auto refState,
auto refMatr,
auto refFunc) {
148 for (
auto& [labelA, qureg]: quregs) {
149 for (
auto& [labelB, matrix]: matrices) {
152 if (matrix.isDistributed && ! qureg.isDistributed)
155 DYNAMIC_SECTION( labelA + LABEL_DELIMITER + labelB ) {
159 setToDebugState(refState);
165 apiFunc(qureg, matrix);
166 refFunc(refState, refMatr);
167 REQUIRE_AGREE( qureg, refState );
178#define PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef ) \
179 int numQubits = getNumCachedQubits(); \
180 auto statevecQuregs = getCachedStatevecs(); \
181 auto densmatrQuregs = getCachedDensmatrs(); \
182 qvector statevecRef = getZeroVector(getPow2(numQubits)); \
183 qmatrix densmatrRef = getZeroMatrix(getPow2(numQubits));
206enum ArgsFlag { none, scalar, axisrots, diagmatr, diagpower, compmatr, paulistr, pauligad };
223enum NumQubitsFlag { zero, one, two, any, anystates };
225void assertNumQubitsFlagsAreValid(NumQubitsFlag ctrlsFlag, NumQubitsFlag targsFlag) {
231 ctrlsFlag == anystates );
240void assertNumQubitsFlagsValid(
241 NumQubitsFlag ctrlsFlag, NumQubitsFlag targsFlag,
242 vector<int> ctrls, vector<int> states, vector<int> targs
244 assertNumQubitsFlagsAreValid(ctrlsFlag, targsFlag);
251 if (targsFlag == one)
252 DEMAND( targs.size() == 1 );
254 if (targsFlag == two)
255 DEMAND( targs.size() == 2 );
257 if (ctrlsFlag == zero)
258 DEMAND( ctrls.size() == 0 );
260 if (ctrlsFlag == one)
261 DEMAND( ctrls.size() == 1 );
263 if (ctrlsFlag == anystates)
264 DEMAND( states.size() == ctrls.size() );
266 DEMAND( states.size() == 0 );
279template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
280int GENERATE_NUM_TARGS(
int numQuregQubits) {
282 assertNumQubitsFlagsAreValid(zero, Targs);
283 DEMAND( Targs != one || numQuregQubits >= 1 );
284 DEMAND( Targs != two || numQuregQubits >= 2 );
285 DEMAND( numQuregQubits > 0 );
288 if constexpr (Targs == one)
290 if constexpr (Targs == two)
293 if constexpr (Targs == any) {
296 int maxNumTargs = numQuregQubits;
302 if (Args == compmatr)
303 maxNumTargs = numQuregQubits - getLog2(
getQuESTEnv().numNodes);
306 if (Ctrls == one && maxNumTargs == numQuregQubits)
309 return GENERATE_COPY( range(1, maxNumTargs+1) );
313template <NumQubitsFlag Ctrls>
314int GENERATE_NUM_CTRLS(
int numFreeQubits) {
316 assertNumQubitsFlagsAreValid(Ctrls, one);
317 DEMAND( Ctrls != one || numFreeQubits >= 1 );
318 DEMAND( numFreeQubits >= 0 );
320 if constexpr (Ctrls == zero)
323 if constexpr (Ctrls == one)
326 if constexpr (Ctrls == any || Ctrls == anystates)
327 return GENERATE_COPY( range(0, numFreeQubits+1) );
348template <NumQubitsFlag Ctrls, NumQubitsFlag Targs>
349void invokeApiOperation(
350 auto operation,
Qureg qureg,
351 vector<int> ctrls, vector<int> states,
int numCtrls,
352 vector<int> targs,
int numTargs,
355 assertNumQubitsFlagsValid(Ctrls, Targs, ctrls, states, targs);
357 if constexpr (Ctrls == zero) {
358 if constexpr (Targs == zero) operation(qureg, args...);
359 if constexpr (Targs == one) operation(qureg, targs[0], args...);
360 if constexpr (Targs == two) operation(qureg, targs[0], targs[1], args...);
361 if constexpr (Targs == any) operation(qureg, targs.data(), numTargs, args...);
363 if constexpr (Ctrls == one) {
364 if constexpr (Targs == zero) operation(qureg, ctrls[0], args...);
365 if constexpr (Targs == one) operation(qureg, ctrls[0], targs[0], args...);
366 if constexpr (Targs == two) operation(qureg, ctrls[0], targs[0], targs[1], args...);
367 if constexpr (Targs == any) operation(qureg, ctrls[0], targs.data(), numTargs, args...);
369 if constexpr (Ctrls == any) {
370 if constexpr (Targs == zero) operation(qureg, ctrls.data(), numCtrls, args...);
371 if constexpr (Targs == one) operation(qureg, ctrls.data(), numCtrls, targs[0], args...);
372 if constexpr (Targs == two) operation(qureg, ctrls.data(), numCtrls, targs[0], targs[1], args...);
373 if constexpr (Targs == any) operation(qureg, ctrls.data(), numCtrls, targs.data(), numTargs, args...);
375 if constexpr (Ctrls == anystates) {
376 if constexpr (Targs == zero) operation(qureg, ctrls.data(), states.data(), numCtrls, args...);
377 if constexpr (Targs == one) operation(qureg, ctrls.data(), states.data(), numCtrls, targs[0], args...);
378 if constexpr (Targs == two) operation(qureg, ctrls.data(), states.data(), numCtrls, targs[0], targs[1], args...);
379 if constexpr (Targs == any) operation(qureg, ctrls.data(), states.data(), numCtrls, targs.data(), numTargs, args...);
385template <NumQubitsFlag Ctrls, NumQubitsFlag Targs>
386void invokeApiOperation(
auto operation,
Qureg qureg, vector<int> ctrls, vector<int> states, vector<int> targs,
auto&... args) {
387 invokeApiOperation<Ctrls,Targs>(operation, qureg, ctrls, states, ctrls.size(), targs, targs.size(), args...);
400template <NumQubitsFlag Targs, ArgsFlag Args>
401auto getRandomOrIdentityApiMatrix(
int numTargs,
int elemsFlag) {
418 qm = (Args == compmatr)?
420 getRandomDiagonalUnitary(numTargs);
422 if constexpr (Args == compmatr && Targs == one)
425 if constexpr (Args == compmatr && Targs == two)
428 if constexpr (Args == compmatr && Targs == any) {
434 qvector dv = getDiagonals(qm);
435 constexpr bool diag = (Args == diagmatr || Args == diagpower);
437 if constexpr (diag && Targs == one)
440 if constexpr (diag && Targs == two)
443 if constexpr (diag && Targs == any) {
450template <NumQubitsFlag Targs, ArgsFlag Args>
auto getZeroApiMatrix (
int numTargs) {
return getRandomOrIdentityApiMatrix<Targs,Args>(numTargs, 0); }
451template <NumQubitsFlag Targs, ArgsFlag Args>
auto getIdentityApiMatrix(
int numTargs) {
return getRandomOrIdentityApiMatrix<Targs,Args>(numTargs, 1); }
452template <NumQubitsFlag Targs, ArgsFlag Args>
auto getRandomApiMatrix (
int numTargs) {
return getRandomOrIdentityApiMatrix<Targs,Args>(numTargs, 2); }
465template <NumQubitsFlag Targs, ArgsFlag Args>
466auto getRandomRemainingArgs(vector<int> targs) {
468 if constexpr (Args == none)
471 if constexpr (Args == scalar) {
472 qreal angle = getRandomPhase();
473 return tuple{ angle };
476 if constexpr (Args == axisrots) {
477 qreal angle = getRandomPhase();
481 return tuple{ angle, x, y, z };
484 if constexpr (Args == compmatr || Args == diagmatr) {
485 auto matrix = getRandomApiMatrix<Targs,Args>(targs.size());
486 return tuple{ matrix };
489 if constexpr (Args == diagpower) {
490 DiagMatr matrix = getRandomApiMatrix<Targs,Args>(targs.size());
492 return tuple{ matrix, exponent };
495 if constexpr (Args == paulistr) {
496 PauliStr str = getRandomPauliStr(targs);
500 if constexpr (Args == pauligad) {
501 PauliStr str = getRandomPauliStr(targs);
502 qreal angle = getRandomPhase();
503 return tuple{ str, angle };
508template <NumQubitsFlag Targs, ArgsFlag Args>
509void freeRemainingArgs(
auto args) {
511 if constexpr (Targs == any && Args == compmatr)
514 if constexpr (Targs == any && Args == diagmatr)
517 if constexpr (Targs == any && Args == diagpower)
530template <NumQubitsFlag Targs, ArgsFlag Args>
531qmatrix getReferenceMatrix(
auto matrixRefGen, vector<int> targs,
auto additionalArgs) {
533 if constexpr (Args == none && Targs != any)
536 if constexpr (Args == none && Targs == any)
537 return matrixRefGen(targs.size());
539 if constexpr (Args == scalar && Targs != any) {
540 qreal angle = std::get<0>(additionalArgs);
541 return matrixRefGen(angle);
544 if constexpr (Args == scalar && Targs == any) {
545 qreal angle = std::get<0>(additionalArgs);
546 return matrixRefGen(angle, targs.size());
549 if constexpr (Args == axisrots) {
550 qreal angle = std::get<0>(additionalArgs);
551 qreal x = std::get<1>(additionalArgs);
552 qreal y = std::get<2>(additionalArgs);
553 qreal z = std::get<3>(additionalArgs);
554 return getExponentialOfNormalisedPauliVector(angle, x, y, z);
557 if constexpr (Args == compmatr || Args == diagmatr) {
558 auto apiMatrix = std::get<0>(additionalArgs);
559 return getMatrix(apiMatrix);
562 if constexpr (Args == diagpower) {
563 auto apiMatrix = std::get<0>(additionalArgs);
564 qmatrix diag = getMatrix(apiMatrix);
565 qcomp power = std::get<1>(additionalArgs);
566 return getPowerOfDiagonalMatrix(diag, power);
569 if constexpr (Args == paulistr) {
570 PauliStr str = std::get<0>(additionalArgs);
571 return getMatrix(str, targs);
574 if constexpr (Args == pauligad) {
575 PauliStr str = std::get<0>(additionalArgs);
576 qreal angle = std::get<1>(additionalArgs);
577 qmatrix matr = getMatrix(str, targs);
596std::string toString(vector<int> list) {
598 std::string out =
"{ ";
600 out += std::to_string(e) +
" ";
605extern int paulis_getPauliAt(
PauliStr str,
int ind);
607std::string toString(
PauliStr str, vector<int> targs) {
609 std::string labels =
"IXYZ";
612 std::string out =
"";
613 for (
int i=targs.size()-1; i>=0; i--)
614 out += labels[paulis_getPauliAt(str, targs[i])];
619template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
620void CAPTURE_RELEVANT( vector<int> ctrls, vector<int> states, vector<int> targs,
auto& args ) {
624 UNSCOPED_INFO(
"control := " << ctrls[0] );
625 if (Ctrls == any || Ctrls == anystates )
626 UNSCOPED_INFO(
"controls := " << toString(ctrls) );
629 if (Ctrls == anystates)
630 UNSCOPED_INFO(
"states := " << toString(states) );
634 UNSCOPED_INFO(
"target := " << targs[0] );
637 UNSCOPED_INFO(
"target A := " << targs[0] );
638 UNSCOPED_INFO(
"target B := " << targs[1] );
641 UNSCOPED_INFO(
"targets := " << toString(targs) );
644 if constexpr (Args == scalar)
645 UNSCOPED_INFO(
"angle := " << std::get<0>(args) );
648 if constexpr (Args == axisrots) {
649 UNSCOPED_INFO(
"angle := " << std::get<0>(args) );
650 UNSCOPED_INFO(
"x := " << std::get<1>(args) );
651 UNSCOPED_INFO(
"y := " << std::get<2>(args) );
652 UNSCOPED_INFO(
"z := " << std::get<3>(args) );
656 if constexpr (Args == compmatr || Args == diagmatr || Args == diagpower)
657 UNSCOPED_INFO(
"matrix := (omitted)" );
660 if constexpr (Args == diagpower) {
661 qcomp p = std::get<1>(args);
662 UNSCOPED_INFO(
"exponent := " << std::real(p) <<
" + (" << std::imag(p) <<
")i" );
666 if constexpr (Args == paulistr || Args == pauligad)
667 UNSCOPED_INFO(
"paulis := " << toString(std::get<0>(args), targs) );
670 if constexpr (Args == pauligad)
671 UNSCOPED_INFO(
"angle := " << std::get<1>(args) );
683template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
684void testOperationCorrectness(
auto operation,
auto matrixRefGen,
bool multiplyOnly) {
686 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
689 int numTargs = GENERATE_NUM_TARGS<Ctrls,Targs,Args>(numQubits);
690 int numCtrls = GENERATE_NUM_CTRLS<Ctrls>(numQubits - numTargs);
693 auto ctrlsAndTargs = GENERATE_CTRLS_AND_TARGS( numQubits, numCtrls, numTargs );
694 vector<int> ctrls = std::get<0>(ctrlsAndTargs);
695 vector<int> targs = std::get<1>(ctrlsAndTargs);
698 vector<int> states = getRandomOutcomes(numCtrls * (Ctrls == anystates));
701 auto primaryArgs = tuple{ ctrls, states, targs };
702 auto furtherArgs = getRandomRemainingArgs<Targs,Args>(targs);
705 qmatrix matrixRef = getReferenceMatrix<Targs,Args>(matrixRefGen, targs, furtherArgs);
708 constexpr NumQubitsFlag RevTargs = (Args==paulistr||Args==pauligad)? zero : Targs;
719 auto testFunc = [&](
Qureg qureg,
auto& stateRef) ->
void {
722 auto apiFunc = [](
auto&&... args) {
return invokeApiOperation<Ctrls,RevTargs>(args...); };
723 auto allArgs = std::tuple_cat(tuple{operation, qureg}, primaryArgs, furtherArgs);
724 std::apply(apiFunc, allArgs);
728 multiplyReferenceOperator(stateRef, ctrls, states, targs, matrixRef):
729 applyReferenceOperator(stateRef, ctrls, states, targs, matrixRef);
733 CAPTURE_RELEVANT<Ctrls,Targs,Args>( ctrls, states, targs, furtherArgs );
736 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
737 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
740 freeRemainingArgs<Targs,Args>(furtherArgs);
751template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
752auto getFixedCtrlsStatesTargs(
int numQubits) {
755 vector<int> targs, ctrls, states;
758 if constexpr (Targs == one) targs = {0};
759 if constexpr (Targs == two) targs = {0,1};
760 if constexpr (Targs == any) targs = {0,1,2};
761 if constexpr (Ctrls == one) ctrls = {3};
762 if constexpr (Ctrls == any) ctrls = {3,4};
763 if constexpr (Ctrls == anystates) ctrls = {3,4};
764 if constexpr (Ctrls == anystates) states = {0,0};
766 DEMAND( numQubits >= targs.size() + ctrls.size() );
768 return tuple{ ctrls, states, targs };
771template <NumQubitsFlag Targs, ArgsFlag Args>
772auto getFixedRemainingArgs(vector<int> targs) {
775 if constexpr (Args == paulistr || Args == pauligad)
776 DEMAND( targs.size() == 3 );
778 if constexpr (Args == none)
return tuple{ };
779 if constexpr (Args == scalar)
return tuple{ 0 };
780 if constexpr (Args == axisrots)
return tuple{ 0, 1,1,1 };
781 if constexpr (Args == compmatr)
return tuple{ getIdentityApiMatrix<Targs,Args>(targs.size()) };
782 if constexpr (Args == diagmatr)
return tuple{ getIdentityApiMatrix<Targs,Args>(targs.size()) };
783 if constexpr (Args == diagpower)
return tuple{ getIdentityApiMatrix<Targs,Args>(targs.size()), qcomp(1,0) };
784 if constexpr (Args == paulistr)
return tuple{
getPauliStr(
"XXX", targs) };
785 if constexpr (Args == pauligad)
return tuple{
getPauliStr(
"XXX", targs), 0 };
788template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
789void testOperationValidation(
auto operation,
bool multiplyOnly) {
792 Qureg qureg = getCachedStatevecs().begin()->second;
796 auto [ctrls,states,targs] = getFixedCtrlsStatesTargs<Ctrls,Targs,Args>(qureg.numQubits);
797 auto furtherArgs = getFixedRemainingArgs<Targs,Args>(targs);
800 auto apiFunc = [&]() {
801 constexpr NumQubitsFlag RevTargs = (Args==paulistr||Args==pauligad)? zero : Targs;
802 auto func = [](
auto&&... allArgs) {
return invokeApiOperation<Ctrls,RevTargs>(allArgs...); };
803 std::apply(func, std::tuple_cat(tuple{operation, qureg, ctrls, states, targs}, furtherArgs));
807 int numQubits = qureg.numQubits;
808 int numTargs = (int) targs.size();
809 int numCtrls = (int) ctrls.size();
817 SECTION(
"qureg uninitialised" ) {
820 qureg.numQubits = -123;
821 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"invalid Qureg") );
824 SECTION(
"invalid target" ) {
827 if (Args == paulistr || Args == pauligad)
831 int ind = GENERATE_COPY( range(0,numTargs) );
832 int val = GENERATE_COPY( -1, numQubits );
835 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Invalid target qubit") );
838 SECTION(
"invalid non-Identity Pauli index" ) {
840 if (Args != paulistr && Args != pauligad)
844 if constexpr (Args == paulistr) furtherArgs = tuple{ badStr };
845 if constexpr (Args == pauligad) furtherArgs = tuple{ badStr, 1 };
847 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"highest-index non-identity Pauli operator") && ContainsSubstring(
"exceeds the maximum target") );
850 SECTION(
"invalid control" ) {
856 int ind = GENERATE_COPY( range(0,numCtrls) );
857 int val = GENERATE_COPY( -1, numQubits );
860 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Invalid control qubit") );
863 SECTION(
"control and target collision" ) {
869 int targInd = GENERATE_COPY( range(0,numTargs) );
870 int ctrlInd = GENERATE_COPY( range(0,numCtrls) );
871 ctrls[ctrlInd] = targs[targInd];
873 if (Args==paulistr||Args==pauligad)
874 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"control qubit overlaps a non-identity Pauli operator") );
876 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"qubit appeared among both the control and target qubits") );
879 SECTION(
"control states" ) {
884 int ind = GENERATE_COPY( range(0,numCtrls) );
885 int val = GENERATE( -1, 2 );
888 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"invalid control-state") );
891 SECTION(
"repetition in controls" ) {
896 int ind = GENERATE_COPY( range(1,numCtrls) );
897 ctrls[ind] = ctrls[0];
899 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"control qubits contained duplicates") );
902 SECTION(
"repetition in targets" ) {
905 if (Args==paulistr||Args==pauligad)
911 int ind = GENERATE_COPY( range(1,numTargs) );
912 targs[ind] = targs[0];
914 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"target qubits contained duplicates") );
917 SECTION(
"number of targets" ) {
921 if (Args == paulistr || Args == pauligad)
929 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Must specify one or more targets") );
932 targs = getRange(qureg.numQubits+1);
933 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"number of target qubits") && ContainsSubstring(
"exceeds the number of qubits in the Qureg") );
939 SECTION(
"mismatching matrix size" ) {
944 if (!(Args == compmatr || Args == diagmatr || Args == diagpower))
947 DEMAND( numTargs > 1 );
948 DEMAND( numCtrls + numTargs < numQubits );
950 targs.push_back(numQubits - 1);
951 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"matrix has an inconsistent size") );
955 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"matrix has an inconsistent size") );
958 SECTION(
"matrix unitarity" ) {
961 if (Args != compmatr && Args != diagmatr && Args != diagpower)
968 if constexpr (Args == compmatr || Args == diagmatr)
969 furtherArgs = tuple{ getZeroApiMatrix<Targs,Args>(targs.size()) };
970 if constexpr (Args == diagpower)
971 furtherArgs = tuple{ getZeroApiMatrix<Targs,Args>(targs.size()), 1 };
973 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"unitary") );
976 SECTION(
"matrix uninitialised" ) {
979 if constexpr (Args == compmatr || Args == diagmatr || Args == diagpower)
980 std::get<0>(furtherArgs).numQubits = -1;
984 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"Invalid") );
987 if constexpr (Args == compmatr || Args == diagmatr || Args == diagpower)
988 std::get<0>(furtherArgs).numQubits = numTargs;
991 SECTION(
"matrix unsynced" ) {
997 if constexpr (Targs == any && (Args == compmatr || Args == diagmatr || Args == diagpower))
998 *(std::get<0>(furtherArgs).wasGpuSynced) = 0;
1002 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"sync") );
1005 SECTION(
"targeted amps fit in node" ) {
1009 if (qureg.numNodes < 2)
1014 int minNumCtrls = (Ctrls == one)? 1 : 0;
1015 int minNumTargs = numQubits - qureg.logNumNodes + 1;
1016 int maxNumTargs = numQubits - minNumCtrls;
1017 if (minNumTargs > maxNumTargs)
1023 if constexpr (Args == compmatr && Targs == any) {
1029 int numNewTargs = GENERATE_COPY( range(minNumTargs, maxNumTargs+1) );
1030 targs = getRange(numNewTargs);
1034 ctrls = vector<int>(minNumCtrls, numQubits - 1);
1038 CompMatr matr = getIdentityApiMatrix<Targs,Args>(numNewTargs);
1039 furtherArgs = tuple{ matr };
1041 CAPTURE( minNumCtrls, numNewTargs, numQubits - minNumCtrls, ctrls, targs );
1042 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"cannot simultaneously store") && ContainsSubstring(
"remote amplitudes") );
1049 SECTION(
"non-unitary exponent" ) {
1055 if constexpr (Args == diagpower)
1056 furtherArgs = tuple{ std::get<0>(furtherArgs), qcomp(1,1) };
1060 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"exponent was not approximately real") );
1063 SECTION(
"diverging exponent" ) {
1070 if constexpr (Args == diagpower)
1071 furtherArgs = tuple{ getZeroApiMatrix<Targs,Args>(numTargs), qcomp(-1,0) };
1075 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"divergences") );
1078 SECTION(
"zero axis rotation" ) {
1080 if constexpr (Args == axisrots) {
1081 furtherArgs = tuple{ 0, 0, 0, 0 };
1085 REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring(
"zero vector") );
1088 freeRemainingArgs<Targs,Args>(furtherArgs);
1097template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
1098void testOperation(
auto operation,
auto matrixRefGen,
bool multiplyOnly) {
1100 assertNumQubitsFlagsAreValid(Ctrls, Targs);
1102 SECTION( LABEL_CORRECTNESS ) {
1103 testOperationCorrectness<Ctrls,Targs,Args>(operation, matrixRefGen, multiplyOnly);
1106 SECTION( LABEL_VALIDATION ) {
1107 testOperationValidation<Ctrls,Targs,Args>(operation, multiplyOnly);
1111template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args>
1112void testOperation(
auto operation,
auto matrixRefGen) {
1114 bool multiplyOnly =
false;
1115 testOperation<Ctrls,Targs,Args>(operation, matrixRefGen, multiplyOnly);
1154#define GET_FUNC_CTRL_SUB_SIG( numctrls ) GET_FUNC_CTRL_SUB_SIG_##numctrls
1155#define GET_FUNC_CTRL_SUB_SIG_zero
1156#define GET_FUNC_CTRL_SUB_SIG_one int,
1157#define GET_FUNC_CTRL_SUB_SIG_any int*,int,
1158#define GET_FUNC_CTRL_SUB_SIG_anystates int*,int*,int,
1164#define GET_FUNC_TARG_SUB_SIG( numtargs, argtype ) GET_FUNC_TARG_SUB_SIG_##argtype( numtargs )
1165#define GET_FUNC_TARG_SUB_SIG_none( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs
1166#define GET_FUNC_TARG_SUB_SIG_scalar( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1167#define GET_FUNC_TARG_SUB_SIG_axisrots( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1168#define GET_FUNC_TARG_SUB_SIG_compmatr( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1169#define GET_FUNC_TARG_SUB_SIG_diagmatr( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1170#define GET_FUNC_TARG_SUB_SIG_diagpower( numtargs ) GET_FUNC_TARG_SUB_SIG_##numtargs ,
1171#define GET_FUNC_TARG_SUB_SIG_paulistr( numtargs )
1172#define GET_FUNC_TARG_SUB_SIG_pauligad( numtargs )
1173#define GET_FUNC_TARG_SUB_SIG_one int
1174#define GET_FUNC_TARG_SUB_SIG_two int,int
1175#define GET_FUNC_TARG_SUB_SIG_any int*,int
1178#define GET_FUNC_ARGS_SUB_SIG( numtargs, argtype ) GET_FUNC_ARGS_SUB_SIG_##numtargs##_##argtype
1179#define GET_FUNC_ARGS_SUB_SIG_one_none
1180#define GET_FUNC_ARGS_SUB_SIG_two_none
1181#define GET_FUNC_ARGS_SUB_SIG_any_none
1182#define GET_FUNC_ARGS_SUB_SIG_one_scalar qreal
1183#define GET_FUNC_ARGS_SUB_SIG_two_scalar qreal
1184#define GET_FUNC_ARGS_SUB_SIG_any_scalar qreal
1185#define GET_FUNC_ARGS_SUB_SIG_one_compmatr CompMatr1
1186#define GET_FUNC_ARGS_SUB_SIG_two_compmatr CompMatr2
1187#define GET_FUNC_ARGS_SUB_SIG_any_compmatr CompMatr
1188#define GET_FUNC_ARGS_SUB_SIG_one_diagmatr DiagMatr1
1189#define GET_FUNC_ARGS_SUB_SIG_two_diagmatr DiagMatr2
1190#define GET_FUNC_ARGS_SUB_SIG_any_diagmatr DiagMatr
1191#define GET_FUNC_ARGS_SUB_SIG_one_diagpower DiagMatr1,qcomp
1192#define GET_FUNC_ARGS_SUB_SIG_two_diagpower DiagMatr2,qcomp
1193#define GET_FUNC_ARGS_SUB_SIG_any_diagpower DiagMatr, qcomp
1194#define GET_FUNC_ARGS_SUB_SIG_one_axisrots qreal,qreal,qreal,qreal
1195#define GET_FUNC_ARGS_SUB_SIG_any_paulistr PauliStr
1196#define GET_FUNC_ARGS_SUB_SIG_any_pauligad PauliStr,qreal
1199#define GET_FUNC_NAME_PREFIX( numctrls ) GET_FUNC_NAME_PREFIX_##numctrls
1200#define GET_FUNC_NAME_PREFIX_zero apply
1201#define GET_FUNC_NAME_PREFIX_one applyControlled
1202#define GET_FUNC_NAME_PREFIX_any applyMultiControlled
1203#define GET_FUNC_NAME_PREFIX_anystates applyMultiStateControlled
1206#define GET_FUNC_NAME(numctrls, suffix) GET_FUNC_NAME_INNER(GET_FUNC_NAME_PREFIX(numctrls), suffix)
1207#define GET_FUNC_NAME_INNER(A, B) GET_FUNC_NAME_INNER_INNER(A, B)
1208#define GET_FUNC_NAME_INNER_INNER(A, B) A##B
1211#define GET_FUNC_NAME_STR(numctrls, suffix) GET_FUNC_NAME_STR_INNER( GET_FUNC_NAME(numctrls,suffix) )
1212#define GET_FUNC_NAME_STR_INNER(expr) GET_FUNC_NAME_STR_INNER_INNER(expr)
1213#define GET_FUNC_NAME_STR_INNER_INNER(symbol) #symbol
1219#define GET_FUNC_SIG( numctrls, numtargs, argtype ) \
1222 GET_FUNC_CTRL_SUB_SIG( numctrls ) \
1223 GET_FUNC_TARG_SUB_SIG( numtargs, argtype ) \
1224 GET_FUNC_ARGS_SUB_SIG( numtargs, argtype ) \
1229#define GET_CASTED_FUNC( namesuffix, numctrls, numtargs, argtype ) \
1230 static_cast< GET_FUNC_SIG(numctrls, numtargs, argtype) > ( \
1231 GET_FUNC_NAME(numctrls, namesuffix) )
1234#define TEST_CASE_OPERATION( namesuffix, numctrls, numtargs, argtype, matrixgen ) \
1235 TEST_CASE( GET_FUNC_NAME_STR(numctrls, namesuffix), TEST_CATEGORY ) { \
1236 testOperation<numctrls, numtargs, argtype>( \
1237 GET_CASTED_FUNC(namesuffix, numctrls, numtargs, argtype), \
1242#define TEST_ALL_CTRL_OPERATIONS( namesuffix, numtargs, argtype, matrixgen ) \
1243 TEST_CASE_OPERATION( namesuffix, zero, numtargs, argtype, matrixgen ) \
1244 TEST_CASE_OPERATION( namesuffix, one, numtargs, argtype, matrixgen ) \
1245 TEST_CASE_OPERATION( namesuffix, any, numtargs, argtype, matrixgen ) \
1246 TEST_CASE_OPERATION( namesuffix, anystates, numtargs, argtype, matrixgen )
1297TEST_CASE(
"applyPhaseFlip", TEST_CATEGORY ) { testOperation<zero,one,none> (
applyPhaseFlip, VariableSizeMatrices::PF(1)); }
1299TEST_CASE(
"applyPhaseShift", TEST_CATEGORY ) { testOperation<zero,one,scalar>(
applyPhaseShift, ParameterisedMatrices::PS); }
1310TEST_CASE(
"multiplyCompMatr", TEST_CATEGORY ) {
1312 testOperation<zero,any,compmatr>(func,
nullptr,
true);
1315TEST_CASE(
"multiplyDiagMatr", TEST_CATEGORY ) {
1317 testOperation<zero,any,diagmatr>(func,
nullptr,
true);
1320TEST_CASE(
"multiplyDiagMatrPower", TEST_CATEGORY ) {
1322 testOperation<zero,any,diagpower>(func,
nullptr,
true);
1325TEST_CASE(
"multiplyMultiQubitNot", TEST_CATEGORY ) {
1327 testOperation<zero,any,none>(func, VariableSizeMatrices::X,
true);
1330TEST_CASE(
"multiplyPhaseGadget", TEST_CATEGORY ) {
1332 testOperation<zero,any,scalar>(func, VariableSizeParameterisedMatrices::Z,
true);
1335TEST_CASE(
"applyMultiQubitPhaseFlip", TEST_CATEGORY ) {
1337 testOperation<zero,any,none>(func, VariableSizeMatrices::PF);
1340TEST_CASE(
"applyMultiQubitPhaseShift", TEST_CATEGORY ) {
1342 testOperation<zero,any,scalar>(func, VariableSizeParameterisedMatrices::PS);
1352 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1354 SECTION( LABEL_CORRECTNESS ) {
1356 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1357 auto targs = GENERATE_TARGS( numQubits, numTargs );
1361 SECTION( LABEL_STATEVEC ) {
1363 auto testFunc = [&](
Qureg qureg, qvector& ref) {
1365 ref = getDisceteFourierTransform(ref, targs);
1368 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc);
1371 SECTION( LABEL_DENSMATR ) {
1374 auto states = getRandomOrthonormalStateVectors(numQubits,
getRandomInt(1,10));
1377 auto testFunc = [&](
Qureg qureg, qmatrix& ref) {
1380 setQuregToReference(qureg, getMixture(states, probs));
1384 for (
size_t i=0; i<states.size(); i++) {
1385 qvector vec = getDisceteFourierTransform(states[i], targs);
1386 ref += probs[i] * getOuterProduct(vec, vec);
1390 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc);
1398TEST_CASE(
"applyFullQuantumFourierTransform", TEST_CATEGORY ) {
1400 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1402 SECTION( LABEL_CORRECTNESS ) {
1404 GENERATE( range(0,10) );
1406 SECTION( LABEL_STATEVEC ) {
1408 auto testFunc = [&](
Qureg qureg, qvector& ref) {
1410 ref = getDisceteFourierTransform(ref);
1413 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc);
1416 SECTION( LABEL_DENSMATR ) {
1419 auto states = getRandomOrthonormalStateVectors(numQubits,
getRandomInt(1,10));
1422 auto testFunc = [&](
Qureg qureg, qmatrix& ref) {
1425 setQuregToReference(qureg, getMixture(states, probs));
1429 for (
size_t i=0; i<states.size(); i++) {
1430 qvector vec = getDisceteFourierTransform(states[i]);
1431 ref += probs[i] * getOuterProduct(vec, vec);
1435 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc);
1445 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1447 SECTION( LABEL_CORRECTNESS ) {
1449 GENERATE( range(0,10) );
1450 int target = GENERATE_COPY( range(0,numQubits) );
1451 int outcome = GENERATE( 0, 1 );
1453 qmatrix projector = getProjector(outcome);
1455 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1457 applyReferenceOperator(ref, {target}, projector);
1460 CAPTURE( target, outcome );
1461 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1462 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1471 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1473 SECTION( LABEL_CORRECTNESS ) {
1475 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1476 auto targets = GENERATE_TARGS( numQubits, numTargs );
1477 auto outcomes = getRandomOutcomes(numTargs);
1479 qmatrix projector = getProjector(targets, outcomes, numQubits);
1481 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1483 applyReferenceOperator(ref, projector);
1486 CAPTURE( targets, outcomes );
1487 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1488 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1497 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1499 SECTION( LABEL_CORRECTNESS ) {
1501 GENERATE( range(0,10) );
1502 int target = GENERATE_COPY( range(0,numQubits) );
1503 int outcome = GENERATE( 0, 1 );
1505 qmatrix projector = getProjector(outcome);
1507 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1511 setToRandomState(ref);
1512 setQuregToReference(qureg, ref);
1516 qreal refProb = getReferenceProbability(ref, {target}, {outcome});
1517 REQUIRE_AGREE( apiProb, refProb );
1520 applyReferenceOperator(ref, {target}, projector);
1521 ref /= (qureg.isDensityMatrix)?
1522 refProb : std::sqrt(refProb);
1525 CAPTURE( target, outcome );
1526 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1527 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1534TEST_CASE(
"applyForcedMultiQubitMeasurement", TEST_CATEGORY ) {
1536 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1538 SECTION( LABEL_CORRECTNESS ) {
1540 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1541 auto targets = GENERATE_TARGS( numQubits, numTargs );
1542 auto outcomes = getRandomOutcomes(numTargs);
1544 qmatrix projector = getProjector(targets, outcomes, numQubits);
1551 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1555 setToRandomState(ref);
1556 setQuregToReference(qureg, ref);
1560 qreal refProb = getReferenceProbability(ref, targets, outcomes);
1561 REQUIRE_AGREE( apiProb, refProb );
1564 applyReferenceOperator(ref, projector);
1565 ref /= (qureg.isDensityMatrix)?
1566 refProb : std::sqrt(refProb);
1569 CAPTURE( targets, outcomes );
1570 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1571 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1582 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1584 SECTION( LABEL_CORRECTNESS ) {
1586 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1587 auto targets = GENERATE_TARGS( numQubits, numTargs );
1589 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1593 setToRandomState(ref);
1594 setQuregToReference(qureg, ref);
1600 auto apiOutBits = getBits(apiOut, numTargs);
1601 qmatrix projector = getProjector(targets, apiOutBits, numQubits);
1602 applyReferenceOperator(ref, projector);
1603 qreal refProb = getReferenceProbability(ref, targets, apiOutBits);
1604 ref /= (qureg.isDensityMatrix)?
1605 refProb : std::sqrt(refProb);
1609 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1610 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1617TEST_CASE(
"applyMultiQubitMeasurementAndGetProb", TEST_CATEGORY ) {
1619 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1621 SECTION( LABEL_CORRECTNESS ) {
1623 int numTargs = GENERATE_COPY( range(1,numQubits+1) );
1624 auto targets = GENERATE_TARGS( numQubits, numTargs );
1626 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1630 setToRandomState(ref);
1631 setQuregToReference(qureg, ref);
1636 auto apiOutBits = getBits(apiOut, numTargs);
1637 qreal refProb = getReferenceProbability(ref, targets, apiOutBits);
1638 REQUIRE_AGREE( apiProb, refProb );
1641 qmatrix projector = getProjector(targets, apiOutBits, numQubits);
1642 applyReferenceOperator(ref, projector);
1643 ref /= (qureg.isDensityMatrix)?
1644 refProb : std::sqrt(refProb);
1648 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1649 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1658 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1660 SECTION( LABEL_CORRECTNESS ) {
1662 GENERATE( range(0,10) );
1663 int target = GENERATE_COPY( range(0,numQubits) );
1665 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1669 setToRandomState(ref);
1670 setQuregToReference(qureg, ref);
1676 qmatrix projector = getProjector(apiOut);
1677 applyReferenceOperator(ref, {target}, projector);
1678 qreal refProb = getReferenceProbability(ref, {target}, {apiOut});
1679 ref /= (qureg.isDensityMatrix)?
1680 refProb : std::sqrt(refProb);
1684 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1685 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1692TEST_CASE(
"applyQubitMeasurementAndGetProb", TEST_CATEGORY ) {
1694 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1696 SECTION( LABEL_CORRECTNESS ) {
1698 GENERATE( range(0,10) );
1699 int target = GENERATE_COPY( range(0,numQubits) );
1701 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1705 setToRandomState(ref);
1706 setQuregToReference(qureg, ref);
1711 qreal refProb = getReferenceProbability(ref, {target}, {apiOut});
1712 REQUIRE_AGREE( apiProb, refProb );
1715 qmatrix projector = getProjector(apiOut);
1716 applyReferenceOperator(ref, {target}, projector);
1717 ref /= (qureg.isDensityMatrix)?
1718 refProb : std::sqrt(refProb);
1722 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1723 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, testFunc); }
1730TEST_CASE(
"multiplyFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
1732 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
1734 auto cachedMatrs = getCachedFullStateDiagMatrs();
1736 SECTION( LABEL_CORRECTNESS ) {
1738 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(numQubits));
1743 SECTION( LABEL_STATEVEC ) {
1745 auto refFunc = [&] (qvector& state, qmatrix matr) { multiplyReferenceOperator(state, matr); };
1747 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
1750 SECTION( LABEL_DENSMATR ) {
1752 auto refFunc = [&] (qmatrix& state, qmatrix matr) { multiplyReferenceOperator(state, matr); };
1754 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
1762TEST_CASE(
"multiplyFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
1764 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
1766 auto cachedMatrs = getCachedFullStateDiagMatrs();
1768 SECTION( LABEL_CORRECTNESS ) {
1770 qmatrix refMatr = getRandomDiagonalMatrix(getPow2(numQubits));
1777 CAPTURE( exponent );
1781 SECTION( LABEL_STATEVEC ) {
1783 auto refFunc = [&] (qvector& state, qmatrix matr) {
1784 matr = getPowerOfDiagonalMatrix(matr, exponent);
1785 multiplyReferenceOperator(state, matr);
1788 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
1791 SECTION( LABEL_DENSMATR ) {
1793 auto refFunc = [&] (qmatrix& state, qmatrix matr) {
1794 matr = getPowerOfDiagonalMatrix(matr, exponent);
1795 multiplyReferenceOperator(state, matr);
1798 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
1806TEST_CASE(
"applyFullStateDiagMatr", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
1808 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
1810 auto cachedMatrs = getCachedFullStateDiagMatrs();
1812 SECTION( LABEL_CORRECTNESS ) {
1814 qmatrix refMatr = getRandomDiagonalUnitary(numQubits);
1819 SECTION( LABEL_STATEVEC ) {
1821 auto refFunc = [&] (qvector& state, qmatrix matr) { applyReferenceOperator(state, matr); };
1823 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
1826 SECTION( LABEL_DENSMATR ) {
1828 auto refFunc = [&] (qmatrix& state, qmatrix matr) { applyReferenceOperator(state, matr); };
1830 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
1838TEST_CASE(
"applyFullStateDiagMatrPower", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
1840 PREPARE_TEST( numQubits, cachedSV, cachedDM, refSV, refDM );
1842 auto cachedMatrs = getCachedFullStateDiagMatrs();
1844 SECTION( LABEL_CORRECTNESS ) {
1846 qmatrix refMatr = getRandomDiagonalUnitary(numQubits);
1850 bool testRealExp = GENERATE(
true,
false );
1851 qcomp exponent = (testRealExp)?
1859 CAPTURE( exponent );
1866 SECTION( LABEL_STATEVEC ) {
1868 auto refFunc = [&] (qvector& state, qmatrix matr) {
1869 matr = getPowerOfDiagonalMatrix(matr, exponent);
1870 applyReferenceOperator(state, matr);
1873 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedSV, cachedMatrs, apiFunc, refSV, refMatr, refFunc);
1876 SECTION( LABEL_DENSMATR ) {
1878 auto refFunc = [&] (qmatrix& state, qmatrix matr) {
1879 matr = getPowerOfDiagonalMatrix(matr, exponent);
1880 applyReferenceOperator(state, matr);
1883 TEST_ON_CACHED_QUREG_AND_MATRIX( cachedDM, cachedMatrs, apiFunc, refDM, refMatr, refFunc);
1893TEST_CASE(
"multiplyPauliStrSum", TEST_CATEGORY LABEL_MIXED_DEPLOY_TAG ) {
1895 PREPARE_TEST( numQubits, statevecQuregs, densmatrQuregs, statevecRef, densmatrRef );
1897 SECTION( LABEL_CORRECTNESS ) {
1899 int numQubits = getNumCachedQubits();
1900 int numTerms = GENERATE_COPY( 1, 2, 10 );
1902 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
1904 auto testFunc = [&](
Qureg qureg,
auto& ref) {
1911 ref = getMatrix(sum, numQubits) * ref;
1914 CAPTURE( numTerms );
1915 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, testFunc); }
1916 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 multiplyCompMatr1(Qureg qureg, int target, CompMatr1 matrix)
void multiplyCompMatr2(Qureg qureg, int target1, int target2, CompMatr2 matr)
void multiplyCompMatr(Qureg qureg, int *targets, int numTargets, CompMatr matr)
void multiplyDiagMatr1(Qureg qureg, int target, DiagMatr1 matr)
void multiplyDiagMatr2(Qureg qureg, int target1, int target2, DiagMatr2 matr)
void multiplyDiagMatr(Qureg qureg, int *targets, int numTargets, DiagMatr matrix)
void multiplyDiagMatrPower(Qureg qureg, int *targets, int numTargets, DiagMatr matrix, qcomp exponent)
void applyFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matrix)
void multiplyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent)
void applyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent)
void multiplyFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matrix)
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 multiplyMultiQubitNot(Qureg qureg, int *targets, int numTargets)
void multiplyPauliGadget(Qureg qureg, PauliStr str, qreal angle)
void multiplyPauliStr(Qureg qureg, PauliStr str)
void multiplyPauliStrSum(Qureg qureg, PauliStrSum sum, Qureg workspace)
void applyTrotterizedPauliStrSumGadget(Qureg qureg, PauliStrSum sum, qreal angle, int order, int reps)
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 multiplyPhaseGadget(Qureg qureg, int *targets, int numTargets, qreal angle)
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 getExponentialOfPauliMatrix(qreal arg, qmatrix m)
const int TEST_NUM_MIXED_DEPLOYMENT_REPETITIONS
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)