12#include <catch2/catch_test_macros.hpp>
13#include <catch2/matchers/catch_matchers_string.hpp>
14#include <catch2/generators/catch_generators_range.hpp>
16#include "tests/utils/macros.hpp"
17#include "tests/utils/linalg.hpp"
18#include "tests/utils/convert.hpp"
19#include "tests/utils/compare.hpp"
20#include "tests/utils/random.hpp"
24using Catch::Matchers::ContainsSubstring;
33#define TEST_CATEGORY \
34 LABEL_UNIT_TAG "[channels]"
48 SECTION( LABEL_CORRECTNESS ) {
50 int numQubits = GENERATE( range(1,4) );
51 int numMatrices = GENERATE( 1, 2, 10 );
52 CAPTURE( numQubits, numMatrices );
57 REQUIRE( map.numQubits == numQubits );
58 REQUIRE( map.numMatrices == numMatrices );
59 REQUIRE( map.numRows == getPow2(numQubits) );
62 REQUIRE( map.superop.numQubits == numQubits );
63 REQUIRE( map.superop.numRows == getPow2(2 * numQubits) );
66 REQUIRE( *(map.isApproxCPTP) == -1 );
67 REQUIRE( *(map.superop.wasGpuSynced) == 0 );
70 REQUIRE( map.matrices !=
nullptr );
71 REQUIRE( map.superop.cpuElems !=
nullptr );
72 REQUIRE( map.superop.cpuElemsFlat !=
nullptr );
74 REQUIRE( map.superop.gpuElemsFlat !=
nullptr );
76 REQUIRE( map.superop.gpuElemsFlat ==
nullptr );
80 for (qindex i=0; i<map.numMatrices && isZero; i++)
81 for (qindex r=0; r<map.numRows && isZero; r++)
82 for (qindex c=0; c<map.numRows && isZero; c++)
83 isZero = (map.matrices[i][r][c] == qcomp(0,0));
88 for (qindex r=0; r<map.superop.numRows && isZero; r++)
89 for (qindex c=0; c<map.superop.numRows && isZero; c++)
90 isZero = (map.superop.cpuElems[r][c] == qcomp(0,0));
96 SECTION( LABEL_VALIDATION ) {
98 SECTION(
"env is init" ) {
104 SECTION(
"too few qubits" ) {
106 int numQubits = GENERATE( -1, 0 );
108 REQUIRE_THROWS_WITH(
createKrausMap(numQubits,1), ContainsSubstring(
"one or more qubits") );
111 SECTION(
"too few operators" ) {
113 int numOpers = GENERATE( -1, 0 );
115 REQUIRE_THROWS_WITH(
createKrausMap(1,numOpers), ContainsSubstring(
"strictly positive number of matrices") );
118 SECTION(
"too many qubits" ) {
120 REQUIRE_THROWS_WITH(
createKrausMap(100,1), ContainsSubstring(
"can be addressed by the qindex type") );
122 REQUIRE_THROWS_WITH(
createKrausMap(15,1), ContainsSubstring(
"necessary memory") && ContainsSubstring(
"would overflow") );
128 #ifndef SANITIZER_IS_ACTIVE
130 ContainsSubstring(
"failed") ||
131 ContainsSubstring(
"insufficient available memory") ||
132 ContainsSubstring(
"exceeds the available memory") ||
133 ContainsSubstring(
"available GPU memory") );
137 SECTION(
"too many operators" ) {
150TEST_CASE(
"destroyKrausMap", TEST_CATEGORY ) {
152 SECTION( LABEL_CORRECTNESS ) {
158 SECTION( LABEL_VALIDATION ) {
161 #ifndef SANITIZER_IS_ACTIVE
162 SECTION(
"not created" ) {
165 REQUIRE_THROWS_WITH(
destroyKrausMap(m), ContainsSubstring(
"Invalid KrausMap") && ContainsSubstring(
"not created") );
174 SECTION( LABEL_CORRECTNESS ) {
176 int numTargs = GENERATE( range(1,4) );
177 int numMatrs = GENERATE( 1, 2, 10 );
178 CAPTURE( numTargs, numMatrs );
181 REQUIRE( *(map.superop.wasGpuSynced) == 0 );
183 *(map.isApproxCPTP) = 0;
187 REQUIRE( *(map.superop.wasGpuSynced) == 1 );
188 REQUIRE( *(map.isApproxCPTP) == -1 );
194 REQUIRE_AGREE( map.superop, getSuperOperator(matrices) );
204 SECTION( LABEL_VALIDATION ) {
209 #ifndef SANITIZER_IS_ACTIVE
210 SECTION(
"not created" ) {
213 REQUIRE_THROWS_WITH(
syncKrausMap(m), ContainsSubstring(
"Invalid KrausMap") && ContainsSubstring(
"not created") );
223 SECTION( LABEL_CORRECTNESS ) {
225 int numQubits = GENERATE( range(1,4) );
226 int numOps = GENERATE( 1, 2, 10 );
227 CAPTURE( numQubits, numOps );
232 SECTION( LABEL_C_INTERFACE ) {
234 qcomp*** ptrs = (qcomp***) malloc(numOps *
sizeof *ptrs);
235 for (
int n=0; n<numOps; n++) {
236 ptrs[n] = (qcomp**) malloc(map.numRows *
sizeof **ptrs);
237 for (
int r=0; r<map.numRows; r++)
238 ptrs[n][r] = matrices[n][r].data();
242 REQUIRE( *(map.superop.wasGpuSynced) == 1 );
243 REQUIRE_AGREE( map.superop, getSuperOperator(matrices) );
245 for (
int n=0; n<numOps; n++)
250 SECTION( LABEL_CPP_INTERFACE ) {
252 *(map.superop.wasGpuSynced) = 0;
255 REQUIRE( *(map.superop.wasGpuSynced) == 1 );
256 REQUIRE_AGREE( map.superop, getSuperOperator(matrices) );
267 SECTION( LABEL_VALIDATION ) {
275 int err = GENERATE( -1, +1 );
280 #ifndef SANITIZER_IS_ACTIVE
281 SECTION(
"not created" ) {
289 SECTION(
"inconsistent dimensions" ) {
294 SECTION(
"inconsistent number of matrices" ) {
306 SECTION( LABEL_CORRECTNESS ) {
308 int numQubits = GENERATE( range(1,4) );
309 int numOps = GENERATE( 1, 2, 10 );
310 CAPTURE( numQubits, numOps );
317 SECTION( LABEL_CPP_INTERFACE ) {
319 *(map.superop.wasGpuSynced) = 0;
322 REQUIRE( *(map.superop.wasGpuSynced) == 1 );
323 REQUIRE_AGREE( map.superop, getSuperOperator(matrices) );
331 SECTION( LABEL_VALIDATION ) {
339 int err = GENERATE( -1, +1 );
344 #ifndef SANITIZER_IS_ACTIVE
345 SECTION(
"not created" ) {
353 SECTION(
"macro parameters" ) {
356 REQUIRE_THROWS_WITH(
setInlineKrausMap(map, numQubits+err, numOps,
getRandomKrausMap(numQubits, numOps)), ContainsSubstring(
"number of Kraus operators") && ContainsSubstring(
"qubits") );
357 REQUIRE_THROWS_WITH(
setInlineKrausMap(map, numQubits, numOps+err,
getRandomKrausMap(numQubits, numOps)), ContainsSubstring(
"number of Kraus operators") && ContainsSubstring(
"qubits") );
360 SECTION(
"dimensions" ) {
374 SECTION( LABEL_CORRECTNESS ) {
376 int numQubits = GENERATE( range(1,4) );
377 int numOps = GENERATE( 1, 2, 10 );
378 CAPTURE( numQubits, numOps );
384 SECTION( LABEL_CPP_INTERFACE ) {
388 REQUIRE( *(map.superop.wasGpuSynced) == 1 );
389 REQUIRE_AGREE( map.superop, getSuperOperator(matrices) );
397 SECTION( LABEL_VALIDATION ) {
401 SECTION(
"env not created" ) {
407 SECTION(
"incomaptible number of matrices" ) {
409 int err = GENERATE( -1, +1 );
414 SECTION(
"incompatible dimensions" ) {
416 int err = GENERATE( -1, +1 );
421 SECTION(
"too few qubits" ) {
423 int numQubits = GENERATE( -1, 0 );
425 REQUIRE_THROWS_WITH(
createInlineKrausMap(numQubits,1,{{{}}}), ContainsSubstring(
"one or more qubits") );
428 SECTION(
"too few operators" ) {
430 int numOpers = GENERATE( -1, 0 );
432 REQUIRE_THROWS_WITH(
createInlineKrausMap(1,numOpers,{{{}}}), ContainsSubstring(
"strictly positive number of matrices") );
435 SECTION(
"too many qubits" ) {
437 REQUIRE_THROWS_WITH(
createInlineKrausMap(100,1,{{{}}}), ContainsSubstring(
"can be addressed by the qindex type") );
439 REQUIRE_THROWS_WITH(
createInlineKrausMap(15,1,{{{}}}), ContainsSubstring(
"necessary memory") && ContainsSubstring(
"would overflow") );
445 SECTION(
"too many operators" ) {
459TEST_CASE(
"createSuperOp", TEST_CATEGORY ) {
461 SECTION( LABEL_CORRECTNESS ) {
463 int numQubits = GENERATE( range(1,4) );
464 CAPTURE( numQubits );
469 REQUIRE( op.numQubits == numQubits );
470 REQUIRE( op.numRows == getPow2(2*numQubits) );
473 REQUIRE( *(op.wasGpuSynced) == 0 );
476 REQUIRE( op.cpuElems !=
nullptr );
477 REQUIRE( op.cpuElemsFlat !=
nullptr );
479 REQUIRE( op.gpuElemsFlat !=
nullptr );
481 REQUIRE( op.gpuElemsFlat ==
nullptr );
485 for (qindex r=0; r<op.numRows && isZero; r++)
486 for (qindex c=0; c<op.numRows && isZero; c++)
487 isZero = (op.cpuElems[r][c] == qcomp(0,0));
493 SECTION( LABEL_VALIDATION ) {
495 SECTION(
"env is init" ) {
501 SECTION(
"too few qubits" ) {
503 int numQubits = GENERATE( -1, 0 );
505 REQUIRE_THROWS_WITH(
createSuperOp(numQubits), ContainsSubstring(
"one or more qubits") );
508 SECTION(
"too many qubits" ) {
510 REQUIRE_THROWS_WITH(
createSuperOp(100), ContainsSubstring(
"qindex") );
512 REQUIRE_THROWS_WITH(
createSuperOp(15), ContainsSubstring(
"size_t") );
518 #ifndef SANITIZER_IS_ACTIVE
520 ContainsSubstring(
"failed") ||
521 ContainsSubstring(
"insufficient available memory") ||
522 ContainsSubstring(
"available GPU memory") ||
523 ContainsSubstring(
"exceeds that available") );
532 SECTION( LABEL_CORRECTNESS ) {
535 REQUIRE( *(op.wasGpuSynced) == 0 );
538 REQUIRE( *(op.wasGpuSynced) == 1 );
548 SECTION( LABEL_VALIDATION ) {
553 #ifndef SANITIZER_IS_ACTIVE
554 SECTION(
"not created" ) {
557 REQUIRE_THROWS_WITH(
syncSuperOp(m), ContainsSubstring(
"invalid fields") );
565TEST_CASE(
"destroySuperOp", TEST_CATEGORY ) {
567 SECTION( LABEL_CORRECTNESS ) {
573 SECTION( LABEL_VALIDATION ) {
576 #ifndef SANITIZER_IS_ACTIVE
577 SECTION(
"not created" ) {
580 REQUIRE_THROWS_WITH(
destroySuperOp(m), ContainsSubstring(
"invalid fields") );
589 SECTION( LABEL_CORRECTNESS ) {
591 int numQubits = GENERATE( range(1,4) );
592 CAPTURE( numQubits );
595 REQUIRE( *(op.wasGpuSynced) == 0 );
597 int dim = getPow2(2 * numQubits);
598 qmatrix ref = getRandomMatrix(dim);
600 SECTION( LABEL_C_INTERFACE ) {
603 qcomp** ptrs = (qcomp**) malloc(dim *
sizeof *ptrs);
604 for (
int i=0; i<dim; i++) {
605 ptrs[i] = (qcomp*) malloc(dim *
sizeof **ptrs);
606 for (
int j=0; j<dim; j++)
607 ptrs[i][j] = ref[i][j];
610 REQUIRE_AGREE( op, ref );
611 REQUIRE( *(op.wasGpuSynced) == 1 );
616 for (
int i=0; i<dim; i++)
621 SECTION( LABEL_CPP_INTERFACE ) {
626 REQUIRE_AGREE( op, ref );
627 REQUIRE( *(op.wasGpuSynced) == 1 );
633 SECTION( LABEL_VALIDATION ) {
640 #ifndef SANITIZER_IS_ACTIVE
641 SECTION(
"not created" ) {
645 REQUIRE_THROWS_WITH(
setSuperOp(bad, dummy), ContainsSubstring(
"invalid fields") );
650 SECTION(
"null pointer" ) {
652 qcomp** ptr =
nullptr;
653 REQUIRE_THROWS_WITH(
setSuperOp(op, ptr), ContainsSubstring(
"was a null pointer") );
655 qcomp* arr[1] = {
nullptr};
656 REQUIRE_THROWS_WITH(
setSuperOp(op, arr), ContainsSubstring(
"contained a null pointer") );
659 SECTION(
"invalid dimensions" ) {
663 REQUIRE_NOTHROW(
setSuperOp(op, qmatrix(4, qvector(4))) );
665 REQUIRE_THROWS_WITH(
setSuperOp(op, qmatrix(3, qvector(4))), ContainsSubstring(
"Incompatible number of rows") );
666 REQUIRE_THROWS_WITH(
setSuperOp(op, qmatrix(5, qvector(4))), ContainsSubstring(
"Incompatible number of rows") );
668 REQUIRE_THROWS_WITH(
setSuperOp(op, qmatrix(4, qvector(3))), ContainsSubstring(
"Incompatible number of columns") );
669 REQUIRE_THROWS_WITH(
setSuperOp(op, qmatrix(4, qvector(5))), ContainsSubstring(
"Incompatible number of columns") );
679 SECTION( LABEL_CORRECTNESS ) {
682 REQUIRE( *(op.wasGpuSynced) == 0 );
686 setInlineSuperOp( op, 1, {{1,2,3,4},{5,6,7,8},{-9,-8,-7,-6},{5_i,4_i,3_i,2_i}} );
687 REQUIRE_AGREE( op, {{1,2,3,4},{5,6,7,8},{-9,-8,-7,-6},{5_i,4_i,3_i,2_i}} );
688 REQUIRE( *(op.wasGpuSynced) == 1 );
693 SECTION( LABEL_VALIDATION ) {
700 #ifndef SANITIZER_IS_ACTIVE
701 SECTION(
"not created" ) {
704 REQUIRE_THROWS_WITH(
setInlineSuperOp(bad, 1, {{}}), ContainsSubstring(
"invalid fields") );
709 SECTION(
"mismatching dimension" ) {
711 REQUIRE_THROWS_WITH(
setInlineSuperOp(op, 2, {{}}), ContainsSubstring(
"specified number of qubits") && ContainsSubstring(
"differs") );
714 SECTION(
"invalid dimensions" ) {
720 REQUIRE_THROWS_WITH(
setInlineSuperOp(op, 1, qmatrix(3, qvector(4))), ContainsSubstring(
"Incompatible number of rows") );
721 REQUIRE_THROWS_WITH(
setInlineSuperOp(op, 1, qmatrix(5, qvector(4))), ContainsSubstring(
"Incompatible number of rows") );
723 REQUIRE_THROWS_WITH(
setInlineSuperOp(op, 1, qmatrix(4, qvector(3))), ContainsSubstring(
"Incompatible number of columns") );
724 REQUIRE_THROWS_WITH(
setInlineSuperOp(op, 1, qmatrix(4, qvector(5))), ContainsSubstring(
"Incompatible number of columns") );
732TEST_CASE(
"createInlineSuperOp", TEST_CATEGORY ) {
734 SECTION( LABEL_CORRECTNESS ) {
736 SuperOp op =
createInlineSuperOp(1, {{1,2,3,4}, {5,6,7,8}, {-9,-8,-7,-6}, {-5_i,-4_i,-3_i,-2_i}});
737 REQUIRE_AGREE( op, {{1,2,3,4}, {5,6,7,8}, {-9,-8,-7,-6}, {-5_i,-4_i,-3_i,-2_i}});
738 REQUIRE( *(op.wasGpuSynced) == 1 );
743 SECTION( LABEL_VALIDATION ) {
745 SECTION(
"env not initialised" ) {
751 SECTION(
"too few qubits" ) {
753 int numQubits = GENERATE( -1, 0 );
755 REQUIRE_THROWS_WITH(
createInlineSuperOp(numQubits, {{}}), ContainsSubstring(
"must act upon one or more qubits") );
758 SECTION(
"mismatching dimension" ) {
760 REQUIRE_THROWS_WITH(
createInlineSuperOp(1, {{1,2},{3,4}}), ContainsSubstring(
"inconsistent with the number of rows") );
KrausMap createInlineKrausMap(int numQubits, int numOperators, std::vector< std::vector< std::vector< qcomp > > > matrices)
SuperOp createInlineSuperOp(int numQubits, std::vector< std::vector< qcomp > > matrix)
KrausMap createKrausMap(int numQubits, int numOperators)
SuperOp createSuperOp(int numQubits)
void destroySuperOp(SuperOp op)
void destroyKrausMap(KrausMap map)
void reportKrausMap(KrausMap map)
void reportSuperOp(SuperOp op)
void setInlineSuperOp(SuperOp op, int numQb, std::vector< std::vector< qcomp > > matrix)
void setInlineKrausMap(KrausMap map, int numQb, int numOps, std::vector< std::vector< std::vector< qcomp > > > matrices)
void setSuperOp(SuperOp op, qcomp **matrix)
void setKrausMap(KrausMap map, qcomp ***matrices)
void syncSuperOp(SuperOp op)
void syncKrausMap(KrausMap map)
qmatrix getZeroMatrix(size_t dim)
vector< qmatrix > getRandomKrausMap(int numQb, int numOps)
TEST_CASE("createKrausMap", TEST_CATEGORY)