53 PREPARE_TEST(qureg, ref);
55 SECTION(
"correctness" ) {
57 int target = GENERATE( range(0, NUM_QUBITS) );
62 QMatrix kraus0{{1,0},{0,sqrt(1-prob)}};
65 QMatrix kraus1{{0,sqrt(prob)},{0,0}};
72 SECTION(
"validation ") {
74 SECTION(
"qubit index" ) {
76 int target = GENERATE( -1, NUM_QUBITS );
77 REQUIRE_THROWS_WITH(
mixDamping(qureg, target, 0), ContainsSubstring(
"Invalid target") );
80 SECTION(
"probability" ) {
82 REQUIRE_THROWS_WITH(
mixDamping(qureg, 0, -.1), ContainsSubstring(
"probability is invalid") );
83 REQUIRE_THROWS_WITH(
mixDamping(qureg, 0, 1.1), ContainsSubstring(
"probability is invalid") );
85 SECTION(
"density-matrix" ) {
89 REQUIRE_THROWS_WITH(
mixDamping(vec, 0, .1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
111 SECTION(
"correctness" ) {
114 qreal prob = GENERATE( 0., 1., take(10, random(0.,1.)) );
115 mixDensityMatrix(qureg1, prob, qureg2);
118 ref1 = (1-prob)*ref1 + (prob)*ref2;
124 SECTION(
"input validation" ) {
126 SECTION(
"probabilities" ) {
128 qreal prob = GENERATE( -0.1, 1.1 );
129 REQUIRE_THROWS_WITH( mixDensityMatrix(qureg1, prob, qureg2), ContainsSubstring(
"probability is invalid") );
131 SECTION(
"density matrices" ) {
135 REQUIRE_THROWS_WITH( mixDensityMatrix(state1, 0, qureg1), ContainsSubstring(
"The first Qureg") && ContainsSubstring(
"must be a density matrix") );
143 REQUIRE_THROWS_WITH( mixDensityMatrix(state1, 0, state2), ContainsSubstring(
"The first Qureg") && ContainsSubstring(
"must be a density matrix") );
148 SECTION(
"matching dimensions" ) {
151 REQUIRE_THROWS_WITH( mixDensityMatrix(qureg1, 0, qureg3), ContainsSubstring(
"inconsistent number of qubits") );
152 REQUIRE_THROWS_WITH( mixDensityMatrix(qureg3, 0, qureg1), ContainsSubstring(
"inconsistent number of qubits") );
168 PREPARE_TEST(qureg, ref);
170 SECTION(
"correctness" ) {
172 int target = GENERATE( range(0,NUM_QUBITS) );
179 ref = ((1 - prob) * ref) + (prob * phaseRef);
183 SECTION(
"validation" ) {
185 SECTION(
"qubit index" ) {
187 int target = GENERATE( -1, NUM_QUBITS );
188 REQUIRE_THROWS_WITH(
mixDephasing(qureg, target, 0), ContainsSubstring(
"Invalid target") );
191 SECTION(
"probability" ) {
193 REQUIRE_THROWS_WITH(
mixDephasing(qureg, 0, -.1), ContainsSubstring(
"probability is invalid") );
194 REQUIRE_THROWS_WITH(
mixDephasing(qureg, 0, .6), ContainsSubstring(
"probability") && ContainsSubstring(
"1/2") );
196 SECTION(
"density-matrix" ) {
200 REQUIRE_THROWS_WITH(
mixDephasing(vec, 0, 0.1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
215 PREPARE_TEST(qureg, ref);
217 SECTION(
"correctness " ) {
219 int target = GENERATE( range(0,NUM_QUBITS) );
229 ref = ((1 - prob) * ref) + ((prob/3.) * ( xRef + yRef + zRef));
233 SECTION(
"validation ") {
235 SECTION(
"qubit index" ) {
237 int target = GENERATE( -1, NUM_QUBITS );
238 REQUIRE_THROWS_WITH(
mixDepolarising(qureg, target, 0), ContainsSubstring(
"Invalid target") );
241 SECTION(
"probability" ) {
243 REQUIRE_THROWS_WITH(
mixDepolarising(qureg, 0, -.1), ContainsSubstring(
"probability is invalid") );
244 REQUIRE_THROWS_WITH(
mixDepolarising(qureg, 0, .76), ContainsSubstring(
"probability") && ContainsSubstring(
"3/4") );
246 SECTION(
"density-matrix" ) {
250 REQUIRE_THROWS_WITH(
mixDepolarising(vec, 0, 0.1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
265 PREPARE_TEST(qureg, ref);
269 int maxNumTargs = qureg.logNumAmpsPerNode / 2;
271 SECTION(
"correctness" ) {
278 int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
283 GENERATE( range(0, 10) );
284 vector<int> targs(numTargs);
289 int maxNumOps = (2*numTargs)*(2*numTargs);
290 int numOps = GENERATE_COPY( 1, maxNumOps, take(2,random(1,maxNumOps)) );
296 vector<ComplexMatrixN> ops(numOps);
297 for (
int i=0; i<numOps; i++) {
302 mixMultiQubitKrausMap(qureg, targs.data(), numTargs, ops.data(), numOps);
305 vector<QMatrix> matrRefs(numOps);
306 for (
int i=0; i<numOps; i++) {
311 for (
int i=0; i<numOps; i++)
314 REQUIRE(
areEqual(qureg, ref, 1E2*REAL_EPS) );
317 for (
int i=0; i<numOps; i++)
320 SECTION(
"input validation" ) {
325 ComplexMatrixN spoofOps[NUM_QUBITS];
326 for (
int i=0; i<NUM_QUBITS; i++) {
327 spoofOps[i] = createComplexMatrixN(NUM_QUBITS);
331 SECTION(
"repetition of target" ) {
334 int targs[NUM_QUBITS];
335 for (
int i=0; i<NUM_QUBITS; i++)
339 int badInd = GENERATE( range(0,NUM_QUBITS) );
340 int copyInd = GENERATE_COPY( filter([=](
int i){
return i!=badInd; }, range(0,NUM_QUBITS)) );
341 targs[badInd] = targs[copyInd];
343 REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"target qubits") && ContainsSubstring(
"unique") );
345 SECTION(
"qubit indices" ) {
348 int targs[NUM_QUBITS];
349 for (
int i=0; i<NUM_QUBITS; i++)
353 targs[GENERATE( range(0,NUM_QUBITS) )] = GENERATE( -1, NUM_QUBITS );
355 REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
433 SECTION(
"trace preserving" ) {
435 int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
436 int maxNumOps = (2*numTargs) * (2*numTargs);
437 int numOps = GENERATE_COPY( 1, 2, maxNumOps );
441 vector<ComplexMatrixN> ops(numOps);
442 for (
int i=0; i<numOps; i++) {
443 ops[i] = createComplexMatrixN(numTargs);
448 ops[GENERATE_COPY( 0, numOps - 1)].cpuElems[0][0] = -123456789;
451 vector<int> targs(numTargs);
452 for (
int i=0; i<numTargs; i++)
455 REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs.data(), numTargs, ops.data(), numOps), ContainsSubstring(
"trace preserving") );
457 for (
int i=0; i<numOps; i++)
458 destroyComplexMatrixN(ops[i]);
460 SECTION(
"density-matrix" ) {
465 int targs[NUM_QUBITS];
466 for (
int i=0; i<NUM_QUBITS; i++)
469 REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(statevec, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
473 SECTION(
"operator fits in node" ) {
476 int minAmps = (2*NUM_QUBITS) * (2*NUM_QUBITS);
479 int targs[NUM_QUBITS];
480 for (
int i=0; i<NUM_QUBITS; i++)
484 ComplexMatrixN ops[] = {createComplexMatrixN(NUM_QUBITS)};
485 for (
int i=0; i<(1<<NUM_QUBITS); i++)
486 ops[0].cpuElems[i][i] = 1;
490 qureg.isDistributed = 1;
491 qureg.numAmpsPerNode = minAmps - 1;
492 qureg.logNumAmpsPerNode = log2(minAmps) - 1;
493 REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, ops, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );
495 destroyComplexMatrixN(ops[0]);
498 for (
int i=0; i<NUM_QUBITS; i++)
512 PREPARE_TEST(qureg, ref);
514 SECTION(
"correctness" ) {
516 int target = GENERATE( range(0,NUM_QUBITS) );
522 qreal max1 = (max0 - probs[0])/2.;
524 qreal max2 = (max1 - probs[1])/2.;
528 int inds[3] = {0,1,2};
529 std::shuffle(inds,inds+3, std::default_random_engine(1E5 * target));
530 qreal probX = probs[inds[0]];
531 qreal probY = probs[inds[1]];
532 qreal probZ = probs[inds[2]];
534 mixPauli(qureg, target, probX, probY, probZ);
542 ref = ((1 - probX - probY - probZ) * ref) +
543 (probX * xRef) + (probY * yRef) + (probZ * zRef);
547 SECTION(
"input validation" ) {
549 SECTION(
"qubit index" ) {
551 int target = GENERATE( -1, NUM_QUBITS );
552 REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, 0), ContainsSubstring(
"Invalid target") );
555 SECTION(
"probability" ) {
560 REQUIRE_THROWS_WITH( mixPauli(qureg, target, -.1, 0, 0), ContainsSubstring(
"probability is invalid") );
561 REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, -.1, 0), ContainsSubstring(
"probability is invalid") );
562 REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, -.1), ContainsSubstring(
"probability is invalid") );
565 REQUIRE_THROWS_WITH( mixPauli(qureg, target, .6, 0, 0), ContainsSubstring(
"probabilities exceed that which induce maximal mixing") );
566 REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, .6, 0), ContainsSubstring(
"probabilities exceed that which induce maximal mixing") );
567 REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, .6), ContainsSubstring(
"probabilities exceed that which induce maximal mixing") );
570 REQUIRE_THROWS_WITH( mixPauli(qureg, target, .3, .3, .3), ContainsSubstring(
"probabilities exceed that which induce maximal mixing") );
572 SECTION(
"density-matrix" ) {
575 REQUIRE_NOTHROW( mixPauli(vec, 0, 0, 0, 0) );
576 REQUIRE_THROWS_WITH( mixPauli(vec, 0, 0.1, 0, 0), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
577 REQUIRE_THROWS_WITH( mixPauli(vec, 0, 0, 0.1, 0), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
578 REQUIRE_THROWS_WITH( mixPauli(vec, 0, 0, 0, 0.1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
593 PREPARE_TEST(qureg, ref);
595 SECTION(
"correctness" ) {
597 int target = GENERATE( range(0,NUM_QUBITS) );
598 int numOps = GENERATE( range(1,5) );
601 vector<ComplexMatrix2> ops(numOps);
602 for (
int i=0; i<numOps; i++)
605 v3_mixKrausMap(qureg, target, ops.data(), numOps);
608 vector<QMatrix> matrRefs(numOps);
609 for (
int i=0; i<numOps; i++) {
614 for (
int i=0; i<numOps; i++)
617 REQUIRE(
areEqual(qureg, ref, 10*REAL_EPS) );
619 SECTION(
"input validation" ) {
624 SECTION(
"number of operators" ) {
628 REQUIRE_THROWS_WITH( v3_mixKrausMap(qureg, 0, spoofOps, numOps), ContainsSubstring(
"must be given a strictly positive number of matrices") );
630 SECTION(
"trace preserving" ) {
633 int numOps = GENERATE( range(1,5) );
635 vector<ComplexMatrix2> ops(numOps);
636 for (
int i=0; i<numOps; i++)
640 ops[GENERATE_REF( range(0,numOps) )].real[0][0] = 9999;
641 REQUIRE_THROWS_WITH( v3_mixKrausMap(qureg, 0, ops.data(), numOps), ContainsSubstring(
"trace preserving") );
643 SECTION(
"qubit index" ) {
645 int target = GENERATE( -1, NUM_QUBITS );
646 REQUIRE_THROWS_WITH( v3_mixKrausMap(qureg, target, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
648 SECTION(
"density-matrix" ) {
651 REQUIRE_THROWS_WITH( v3_mixKrausMap(vec, 0, spoofOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
654 SECTION(
"operators fit in node" ) {
656 qureg.isDistributed = 1;
657 qureg.numAmpsPerNode = 3;
658 qureg.logNumAmpsPerNode = 1;
660 REQUIRE_THROWS_WITH( v3_mixKrausMap(qureg, 0, spoofOps, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );
674 PREPARE_TEST(qureg, ref);
676 SECTION(
"correctness" ) {
678 int target = GENERATE( range(0,NUM_QUBITS) );
679 int numOps = GENERATE( range(1,5) );
682 vector<QMatrix> matrs;
683 for (
int i=0; i<numOps; i++)
686 vector<ComplexMatrix2> ops(numOps);
687 for (
int i=0; i<numOps; i++)
689 mixNonTPKrausMap(qureg, target, ops.data(), numOps);
692 vector<QMatrix> matrRefs(numOps);
693 for (
int i=0; i<numOps; i++) {
698 for (
int i=0; i<numOps; i++)
701 REQUIRE(
areEqual(qureg, ref, 1E2*REAL_EPS) );
703 SECTION(
"input validation" ) {
708 SECTION(
"number of operators" ) {
711 REQUIRE_THROWS_WITH( mixNonTPKrausMap(qureg, 0, spoofOps, numOps), ContainsSubstring(
"must be given a strictly positive number of matrices") );
713 SECTION(
"qubit index" ) {
715 int target = GENERATE( -1, NUM_QUBITS );
716 REQUIRE_THROWS_WITH( mixNonTPKrausMap(qureg, target, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
718 SECTION(
"density-matrix" ) {
721 REQUIRE_THROWS_WITH( mixNonTPKrausMap(vec, 0, spoofOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
724 SECTION(
"operators fit in node" ) {
726 qureg.isDistributed = 1;
727 qureg.numAmpsPerNode = 3;
728 qureg.logNumAmpsPerNode = 1;
729 REQUIRE_THROWS_WITH( mixNonTPKrausMap(qureg, 0, spoofOps, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );
741TEST_CASE(
"mixNonTPMultiQubitKrausMap",
"[decoherence]" ) {
743 PREPARE_TEST(qureg, ref);
747 int maxNumTargs =
calcLog2(qureg.numAmpsPerNode) / 2;
749 SECTION(
"correctness" ) {
755 int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
760 GENERATE( range(0, 10) );
761 vector<int> targs(numTargs);
766 int maxNumOps = (2*numTargs)*(2*numTargs);
767 int numOps = GENERATE_COPY( 1, maxNumOps, take(2,random(1,maxNumOps)) );
770 vector<QMatrix> matrs;
771 for (
int i=0; i<numOps; i++)
775 vector<ComplexMatrixN> ops(numOps);
776 for (
int i=0; i<numOps; i++) {
777 ops[i] = createComplexMatrixN(numTargs);
781 mixNonTPMultiQubitKrausMap(qureg, targs.data(), numTargs, ops.data(), numOps);
784 vector<QMatrix> matrRefs(numOps);
785 for (
int i=0; i<numOps; i++) {
790 for (
int i=0; i<numOps; i++)
793 REQUIRE(
areEqual(qureg, ref, 1E5*REAL_EPS) );
796 for (
int i=0; i<numOps; i++)
797 destroyComplexMatrixN(ops[i]);
799 SECTION(
"input validation" ) {
804 ComplexMatrixN spoofOps[NUM_QUBITS];
805 for (
int i=0; i<NUM_QUBITS; i++) {
806 spoofOps[i] = createComplexMatrixN(NUM_QUBITS);
810 SECTION(
"repetition of target" ) {
813 int targs[NUM_QUBITS];
814 for (
int i=0; i<NUM_QUBITS; i++)
818 int badInd = GENERATE( range(0,NUM_QUBITS) );
819 int copyInd = GENERATE_COPY( filter([=](
int i){
return i!=badInd; }, range(0,NUM_QUBITS)) );
820 targs[badInd] = targs[copyInd];
822 REQUIRE_THROWS_WITH( mixNonTPMultiQubitKrausMap(qureg, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"target qubits") && ContainsSubstring(
"unique") );
824 SECTION(
"qubit indices" ) {
827 int targs[NUM_QUBITS];
828 for (
int i=0; i<NUM_QUBITS; i++)
832 targs[GENERATE( range(0,NUM_QUBITS) )] = GENERATE( -1, NUM_QUBITS );
834 REQUIRE_THROWS_WITH( mixNonTPMultiQubitKrausMap(qureg, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
909 SECTION(
"density-matrix" ) {
914 int targs[NUM_QUBITS];
915 for (
int i=0; i<NUM_QUBITS; i++)
918 REQUIRE_THROWS_WITH( mixNonTPMultiQubitKrausMap(statevec, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
922 SECTION(
"operator fits in node" ) {
925 int minAmps = (2*NUM_QUBITS) * (2*NUM_QUBITS);
928 int targs[NUM_QUBITS];
929 for (
int i=0; i<NUM_QUBITS; i++)
933 ComplexMatrixN ops[] = {createComplexMatrixN(NUM_QUBITS)};
934 for (
int i=0; i<(1<<NUM_QUBITS); i++)
935 ops[0].cpuElems[i][i] = 1;
939 qureg.isDistributed = 1;
940 qureg.numAmpsPerNode = minAmps - 1;
941 qureg.logNumAmpsPerNode = log2(minAmps) - 1;
942 REQUIRE_THROWS_WITH( mixNonTPMultiQubitKrausMap(qureg, targs, NUM_QUBITS, ops, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );
944 destroyComplexMatrixN(ops[0]);
947 for (
int i=0; i<NUM_QUBITS; i++)
948 destroyComplexMatrixN(spoofOps[i]);
959TEST_CASE(
"mixNonTPTwoQubitKrausMap",
"[decoherence]" ) {
961 PREPARE_TEST(qureg, ref);
963 SECTION(
"correctness" ) {
965 int targ1 = GENERATE( range(0,NUM_QUBITS) );
966 int targ2 = GENERATE_COPY( filter([=](
int t){
return t!=targ1; }, range(0,NUM_QUBITS)) );
967 int numOps = GENERATE( range(1,17) );
970 vector<QMatrix> matrs;
971 for (
int i=0; i<numOps; i++)
974 vector<ComplexMatrix4> ops(numOps);
975 for (
int i=0; i<numOps; i++)
977 mixNonTPTwoQubitKrausMap(qureg, targ1, targ2, ops.data(), numOps);
980 int targs[2] = {targ1, targ2};
981 vector<QMatrix> matrRefs(numOps);
982 for (
int i=0; i<numOps; i++) {
987 for (
int i=0; i<numOps; i++)
990 REQUIRE(
areEqual(qureg, ref, 1E4*REAL_EPS) );
992 SECTION(
"input validation" ) {
1005 SECTION(
"target collision" ) {
1007 int target = GENERATE( range(0,NUM_QUBITS) );
1008 REQUIRE_THROWS_WITH( mixNonTPTwoQubitKrausMap(qureg, target, target, spoofOps, 1), ContainsSubstring(
"target qubits") && ContainsSubstring(
"unique") );
1010 SECTION(
"qubit index" ) {
1012 int target = GENERATE( -1, NUM_QUBITS );
1013 REQUIRE_THROWS_WITH( mixNonTPTwoQubitKrausMap(qureg, 0,target, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
1014 REQUIRE_THROWS_WITH( mixNonTPTwoQubitKrausMap(qureg, target,0, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
1016 SECTION(
"density-matrix" ) {
1019 REQUIRE_THROWS_WITH( mixNonTPTwoQubitKrausMap(vec, 0,1, spoofOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
1022 SECTION(
"operators fit in node" ) {
1024 qureg.isDistributed = 1;
1025 qureg.numAmpsPerNode = 15;
1026 qureg.logNumAmpsPerNode = 3;
1027 REQUIRE_THROWS_WITH( mixNonTPTwoQubitKrausMap(qureg, 0,1, spoofOps, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );
1041 PREPARE_TEST(qureg, ref);
1043 SECTION(
"correctness" ) {
1045 int targ1 = GENERATE( range(0,NUM_QUBITS) );
1046 int targ2 = GENERATE_COPY( filter([=](
int t){
return t!=targ1; }, range(0,NUM_QUBITS)) );
1060 ref = ((1 - prob) * ref) + (prob/3.) * (z1Ref + z2Ref + z1z2Ref);
1064 SECTION(
"input validation" ) {
1066 SECTION(
"qubit indices" ) {
1068 int targ = GENERATE( -1, NUM_QUBITS );
1069 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(qureg, 0, targ, 0), ContainsSubstring(
"Invalid target") );
1070 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(qureg, targ, 0, 0), ContainsSubstring(
"Invalid target") );
1072 SECTION(
"target collision" ) {
1074 int targ = GENERATE( range(0,NUM_QUBITS) );
1075 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(qureg, targ, targ, 0), ContainsSubstring(
"target") && ContainsSubstring(
"unique") );
1077 SECTION(
"probability" ) {
1079 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(qureg, 0, 1, -.1), ContainsSubstring(
"probability is invalid") );
1080 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(qureg, 0, 1, 3/4. + .01), ContainsSubstring(
"probability") && ContainsSubstring(
"3/4") );
1082 SECTION(
"density-matrix" ) {
1086 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(vec, 0, 1, 0.1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
1101 PREPARE_TEST(qureg, ref);
1103 SECTION(
"correctness" ) {
1105 int targ1 = GENERATE( range(0,NUM_QUBITS) );
1106 int targ2 = GENERATE_COPY( filter([=](
int t){
return t!=targ1; }, range(0,NUM_QUBITS)) );
1114 QMatrix{{0,-qcomp(0,1)},{qcomp(0,1),0}},
1118 int targs[2] = {targ1, targ2};
1120 ref = (1 - (16/15.)*prob) * ref;
1121 for (
int i=0; i<4; i++) {
1122 for (
int j=0; j<4; j++) {
1126 ref += (prob/15.) * term;
1130 REQUIRE(
areEqual(qureg, ref, 1E4*REAL_EPS) );
1132 SECTION(
"input validation" ) {
1134 SECTION(
"qubit indices" ) {
1136 int targ = GENERATE( -1, NUM_QUBITS );
1140 SECTION(
"target collision" ) {
1142 int targ = GENERATE( range(0,NUM_QUBITS) );
1143 REQUIRE_THROWS_WITH(
mixTwoQubitDepolarising(qureg, targ, targ, 0), ContainsSubstring(
"target") && ContainsSubstring(
"unique") );
1145 SECTION(
"probability" ) {
1147 REQUIRE_THROWS_WITH(
mixTwoQubitDepolarising(qureg, 0, 1, -.1), ContainsSubstring(
"probability is invalid") );
1148 REQUIRE_THROWS_WITH(
mixTwoQubitDepolarising(qureg, 0, 1, 15/16. + .01), ContainsSubstring(
"probability") && ContainsSubstring(
"15/16") );
1150 SECTION(
"density-matrix" ) {
1154 REQUIRE_THROWS_WITH(
mixTwoQubitDepolarising(vec, 0, 1, 0.1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
1169 PREPARE_TEST(qureg, ref);
1171 SECTION(
"correctness" ) {
1173 int targ1 = GENERATE( range(0,NUM_QUBITS) );
1174 int targ2 = GENERATE_COPY( filter([=](
int t){
return t!=targ1; }, range(0,NUM_QUBITS)) );
1175 int numOps = GENERATE( range(1,17) );
1178 vector<ComplexMatrix4> ops(numOps);
1179 for (
int i=0; i<numOps; i++)
1181 mixTwoQubitKrausMap(qureg, targ1, targ2, ops.data(), numOps);
1184 int targs[2] = {targ1, targ2};
1185 vector<QMatrix> matrRefs(numOps);
1186 for (
int i=0; i<numOps; i++) {
1191 for (
int i=0; i<numOps; i++)
1194 REQUIRE(
areEqual(qureg, ref, 10*REAL_EPS) );
1196 SECTION(
"input validation" ) {
1200 SECTION(
"number of operators" ) {
1204 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, emptyOps, numOps), ContainsSubstring(
"must be given a strictly positive number of matrices") );
1206 SECTION(
"trace preserving" ) {
1209 int numOps = GENERATE( range(1,16) );
1211 vector<ComplexMatrix4> ops(numOps);
1212 for (
int i=0; i<numOps; i++)
1216 ops[GENERATE_REF( range(0,numOps) )].real[0][0] = 999;
1218 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, ops.data(), numOps), ContainsSubstring(
"trace preserving") );
1220 SECTION(
"target collision" ) {
1222 int target = GENERATE( range(0,NUM_QUBITS) );
1223 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, target, target, emptyOps, 1), ContainsSubstring(
"target qubits") && ContainsSubstring(
"unique") );
1225 SECTION(
"qubit index" ) {
1227 int target = GENERATE( -1, NUM_QUBITS );
1228 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,target, emptyOps, 1), ContainsSubstring(
"Invalid target qubit") );
1229 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, target,0, emptyOps, 1), ContainsSubstring(
"Invalid target qubit") );
1231 SECTION(
"density-matrix" ) {
1234 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(vec, 0,1, emptyOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
1237 SECTION(
"operators fit in node" ) {
1239 qureg.isDistributed = 1;
1240 qureg.numAmpsPerNode = 15;
1241 qureg.logNumAmpsPerNode = 3;
1242 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, emptyOps, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );