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 );
59 REQUIRE( map.
numRows == getPow2(numQubits) );
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));
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 );
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();
243 REQUIRE_AGREE( map.
superop, getSuperOperator(matrices) );
245 for (
int n=0; n<numOps; n++)
250 SECTION( LABEL_CPP_INTERFACE ) {
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 ) {
321 setInlineKrausMap(map, numQubits, numOps, matrices);
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" ) {
348 REQUIRE_THROWS_WITH( setInlineKrausMap(bad, numQubits, numOps,
getRandomKrausMap(numQubits, numOps)), ContainsSubstring(
"invalid") );
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" ) {
363 REQUIRE_THROWS_WITH( setInlineKrausMap(map, numQubits, numOps,
getRandomKrausMap(numQubits+err, numOps )), ContainsSubstring(
"dimension") );
364 REQUIRE_THROWS_WITH( setInlineKrausMap(map, numQubits, numOps,
getRandomKrausMap(numQubits, numOps+err)), ContainsSubstring(
"number of matrices") );
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 ) {
386 KrausMap map = createInlineKrausMap(numQubits, numOps, matrices);
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 );
411 REQUIRE_THROWS_WITH( createInlineKrausMap(3, 3,
getRandomKrausMap(3, 3+err)), ContainsSubstring(
"matrices") );
414 SECTION(
"incompatible dimensions" ) {
416 int err = GENERATE( -1, +1 );
418 REQUIRE_THROWS_WITH( createInlineKrausMap(3, 3,
getRandomKrausMap(3+err, 3)), ContainsSubstring(
"rows") );
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 );
470 REQUIRE( op.
numRows == getPow2(2*numQubits) );
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 ) {
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 );
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 );
616 for (
int i=0; i<dim; i++)
621 SECTION( LABEL_CPP_INTERFACE ) {
626 REQUIRE_AGREE( op, ref );
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 ) {
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}} );
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" ) {
718 REQUIRE_NOTHROW( setInlineSuperOp(op, 1, qmatrix(4, qvector(4))) );
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}});
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 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 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)