48 PREPARE_TEST(qureg, ref);
50 SECTION(
"correctness" ) {
52 int target = GENERATE( range(0, NUM_QUBITS) );
57 QMatrix kraus0{{1,0},{0,sqrt(1-prob)}};
60 QMatrix kraus1{{0,sqrt(prob)},{0,0}};
67 SECTION(
"validation ") {
69 SECTION(
"qubit index" ) {
71 int target = GENERATE( -1, NUM_QUBITS );
72 REQUIRE_THROWS_WITH(
mixDamping(qureg, target, 0), ContainsSubstring(
"Invalid target") );
75 SECTION(
"probability" ) {
77 REQUIRE_THROWS_WITH(
mixDamping(qureg, 0, -.1), ContainsSubstring(
"probability is invalid") );
78 REQUIRE_THROWS_WITH(
mixDamping(qureg, 0, 1.1), ContainsSubstring(
"probability is invalid") );
80 SECTION(
"density-matrix" ) {
84 REQUIRE_THROWS_WITH(
mixDamping(vec, 0, .1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
106 SECTION(
"correctness" ) {
109 qreal prob = GENERATE( 0., 1., take(10, random(0.,1.)) );
110 mixDensityMatrix(qureg1, prob, qureg2);
113 ref1 = (1-prob)*ref1 + (prob)*ref2;
119 SECTION(
"input validation" ) {
121 SECTION(
"probabilities" ) {
123 qreal prob = GENERATE( -0.1, 1.1 );
124 REQUIRE_THROWS_WITH( mixDensityMatrix(qureg1, prob, qureg2), ContainsSubstring(
"probability is invalid") );
126 SECTION(
"density matrices" ) {
130 REQUIRE_THROWS_WITH( mixDensityMatrix(state1, 0, qureg1), ContainsSubstring(
"The first Qureg") && ContainsSubstring(
"must be a density matrix") );
138 REQUIRE_THROWS_WITH( mixDensityMatrix(state1, 0, state2), ContainsSubstring(
"The first Qureg") && ContainsSubstring(
"must be a density matrix") );
143 SECTION(
"matching dimensions" ) {
146 REQUIRE_THROWS_WITH( mixDensityMatrix(qureg1, 0, qureg3), ContainsSubstring(
"inconsistent number of qubits") );
147 REQUIRE_THROWS_WITH( mixDensityMatrix(qureg3, 0, qureg1), ContainsSubstring(
"inconsistent number of qubits") );
163 PREPARE_TEST(qureg, ref);
165 SECTION(
"correctness" ) {
167 int target = GENERATE( range(0,NUM_QUBITS) );
174 ref = ((1 - prob) * ref) + (prob * phaseRef);
178 SECTION(
"validation" ) {
180 SECTION(
"qubit index" ) {
182 int target = GENERATE( -1, NUM_QUBITS );
183 REQUIRE_THROWS_WITH(
mixDephasing(qureg, target, 0), ContainsSubstring(
"Invalid target") );
186 SECTION(
"probability" ) {
188 REQUIRE_THROWS_WITH(
mixDephasing(qureg, 0, -.1), ContainsSubstring(
"probability is invalid") );
189 REQUIRE_THROWS_WITH(
mixDephasing(qureg, 0, .6), ContainsSubstring(
"probability") && ContainsSubstring(
"1/2") );
191 SECTION(
"density-matrix" ) {
195 REQUIRE_THROWS_WITH(
mixDephasing(vec, 0, 0.1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
210 PREPARE_TEST(qureg, ref);
212 SECTION(
"correctness " ) {
214 int target = GENERATE( range(0,NUM_QUBITS) );
224 ref = ((1 - prob) * ref) + ((prob/3.) * ( xRef + yRef + zRef));
228 SECTION(
"validation ") {
230 SECTION(
"qubit index" ) {
232 int target = GENERATE( -1, NUM_QUBITS );
233 REQUIRE_THROWS_WITH(
mixDepolarising(qureg, target, 0), ContainsSubstring(
"Invalid target") );
236 SECTION(
"probability" ) {
238 REQUIRE_THROWS_WITH(
mixDepolarising(qureg, 0, -.1), ContainsSubstring(
"probability is invalid") );
239 REQUIRE_THROWS_WITH(
mixDepolarising(qureg, 0, .76), ContainsSubstring(
"probability") && ContainsSubstring(
"3/4") );
241 SECTION(
"density-matrix" ) {
245 REQUIRE_THROWS_WITH(
mixDepolarising(vec, 0, 0.1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
260 PREPARE_TEST(qureg, ref);
264 int maxNumTargs = qureg.logNumAmpsPerNode / 2;
266 SECTION(
"correctness" ) {
273 int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
278 GENERATE( range(0, 10) );
279 vector<int> targs(numTargs);
284 int maxNumOps = (2*numTargs)*(2*numTargs);
285 int numOps = GENERATE_COPY( 1, maxNumOps, take(2,random(1,maxNumOps)) );
291 vector<ComplexMatrixN> ops(numOps);
292 for (
int i=0; i<numOps; i++) {
297 mixMultiQubitKrausMap(qureg, targs.data(), numTargs, ops.data(), numOps);
300 vector<QMatrix> matrRefs(numOps);
301 for (
int i=0; i<numOps; i++) {
306 for (
int i=0; i<numOps; i++)
309 REQUIRE(
areEqual(qureg, ref, 1E2*REAL_EPS) );
312 for (
int i=0; i<numOps; i++)
315 SECTION(
"input validation" ) {
320 ComplexMatrixN spoofOps[NUM_QUBITS];
321 for (
int i=0; i<NUM_QUBITS; i++) {
322 spoofOps[i] = createComplexMatrixN(NUM_QUBITS);
326 SECTION(
"repetition of target" ) {
329 int targs[NUM_QUBITS];
330 for (
int i=0; i<NUM_QUBITS; i++)
334 int badInd = GENERATE( range(0,NUM_QUBITS) );
335 int copyInd = GENERATE_COPY( filter([=](
int i){
return i!=badInd; }, range(0,NUM_QUBITS)) );
336 targs[badInd] = targs[copyInd];
338 REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"target qubits") && ContainsSubstring(
"unique") );
340 SECTION(
"qubit indices" ) {
343 int targs[NUM_QUBITS];
344 for (
int i=0; i<NUM_QUBITS; i++)
348 targs[GENERATE( range(0,NUM_QUBITS) )] = GENERATE( -1, NUM_QUBITS );
350 REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
428 SECTION(
"trace preserving" ) {
430 int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
431 int maxNumOps = (2*numTargs) * (2*numTargs);
432 int numOps = GENERATE_COPY( 1, 2, maxNumOps );
436 vector<ComplexMatrixN> ops(numOps);
437 for (
int i=0; i<numOps; i++) {
438 ops[i] = createComplexMatrixN(numTargs);
443 ops[GENERATE_COPY( 0, numOps - 1)].cpuElems[0][0] = -123456789;
446 vector<int> targs(numTargs);
447 for (
int i=0; i<numTargs; i++)
450 REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs.data(), numTargs, ops.data(), numOps), ContainsSubstring(
"trace preserving") );
452 for (
int i=0; i<numOps; i++)
453 destroyComplexMatrixN(ops[i]);
455 SECTION(
"density-matrix" ) {
460 int targs[NUM_QUBITS];
461 for (
int i=0; i<NUM_QUBITS; i++)
464 REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(statevec, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
468 SECTION(
"operator fits in node" ) {
471 int minAmps = (2*NUM_QUBITS) * (2*NUM_QUBITS);
474 int targs[NUM_QUBITS];
475 for (
int i=0; i<NUM_QUBITS; i++)
479 ComplexMatrixN ops[] = {createComplexMatrixN(NUM_QUBITS)};
480 for (
int i=0; i<(1<<NUM_QUBITS); i++)
481 ops[0].cpuElems[i][i] = 1;
485 qureg.isDistributed = 1;
486 qureg.numAmpsPerNode = minAmps - 1;
487 qureg.logNumAmpsPerNode = log2(minAmps) - 1;
488 REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, ops, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );
490 destroyComplexMatrixN(ops[0]);
493 for (
int i=0; i<NUM_QUBITS; i++)
507 PREPARE_TEST(qureg, ref);
509 SECTION(
"correctness" ) {
511 int target = GENERATE( range(0,NUM_QUBITS) );
517 qreal max1 = (max0 - probs[0])/2.;
519 qreal max2 = (max1 - probs[1])/2.;
523 int inds[3] = {0,1,2};
524 std::shuffle(inds,inds+3, std::default_random_engine(1E5 * target));
525 qreal probX = probs[inds[0]];
526 qreal probY = probs[inds[1]];
527 qreal probZ = probs[inds[2]];
529 mixPauli(qureg, target, probX, probY, probZ);
537 ref = ((1 - probX - probY - probZ) * ref) +
538 (probX * xRef) + (probY * yRef) + (probZ * zRef);
542 SECTION(
"input validation" ) {
544 SECTION(
"qubit index" ) {
546 int target = GENERATE( -1, NUM_QUBITS );
547 REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, 0), ContainsSubstring(
"Invalid target") );
550 SECTION(
"probability" ) {
555 REQUIRE_THROWS_WITH( mixPauli(qureg, target, -.1, 0, 0), ContainsSubstring(
"probability is invalid") );
556 REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, -.1, 0), ContainsSubstring(
"probability is invalid") );
557 REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, -.1), ContainsSubstring(
"probability is invalid") );
560 REQUIRE_THROWS_WITH( mixPauli(qureg, target, .6, 0, 0), ContainsSubstring(
"probabilities exceed that which induce maximal mixing") );
561 REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, .6, 0), ContainsSubstring(
"probabilities exceed that which induce maximal mixing") );
562 REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, .6), ContainsSubstring(
"probabilities exceed that which induce maximal mixing") );
565 REQUIRE_THROWS_WITH( mixPauli(qureg, target, .3, .3, .3), ContainsSubstring(
"probabilities exceed that which induce maximal mixing") );
567 SECTION(
"density-matrix" ) {
570 REQUIRE_NOTHROW( mixPauli(vec, 0, 0, 0, 0) );
571 REQUIRE_THROWS_WITH( mixPauli(vec, 0, 0.1, 0, 0), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
572 REQUIRE_THROWS_WITH( mixPauli(vec, 0, 0, 0.1, 0), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
573 REQUIRE_THROWS_WITH( mixPauli(vec, 0, 0, 0, 0.1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
588 PREPARE_TEST(qureg, ref);
590 SECTION(
"correctness" ) {
592 int target = GENERATE( range(0,NUM_QUBITS) );
593 int numOps = GENERATE( range(1,5) );
596 vector<ComplexMatrix2> ops(numOps);
597 for (
int i=0; i<numOps; i++)
600 v3_mixKrausMap(qureg, target, ops.data(), numOps);
603 vector<QMatrix> matrRefs(numOps);
604 for (
int i=0; i<numOps; i++) {
609 for (
int i=0; i<numOps; i++)
612 REQUIRE(
areEqual(qureg, ref, 10*REAL_EPS) );
614 SECTION(
"input validation" ) {
619 SECTION(
"number of operators" ) {
623 REQUIRE_THROWS_WITH( v3_mixKrausMap(qureg, 0, spoofOps, numOps), ContainsSubstring(
"must be given a strictly positive number of matrices") );
625 SECTION(
"trace preserving" ) {
628 int numOps = GENERATE( range(1,5) );
630 vector<ComplexMatrix2> ops(numOps);
631 for (
int i=0; i<numOps; i++)
635 ops[GENERATE_REF( range(0,numOps) )].real[0][0] = 9999;
636 REQUIRE_THROWS_WITH( v3_mixKrausMap(qureg, 0, ops.data(), numOps), ContainsSubstring(
"trace preserving") );
638 SECTION(
"qubit index" ) {
640 int target = GENERATE( -1, NUM_QUBITS );
641 REQUIRE_THROWS_WITH( v3_mixKrausMap(qureg, target, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
643 SECTION(
"density-matrix" ) {
646 REQUIRE_THROWS_WITH( v3_mixKrausMap(vec, 0, spoofOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
649 SECTION(
"operators fit in node" ) {
651 qureg.isDistributed = 1;
652 qureg.numAmpsPerNode = 3;
653 qureg.logNumAmpsPerNode = 1;
655 REQUIRE_THROWS_WITH( v3_mixKrausMap(qureg, 0, spoofOps, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );
669 PREPARE_TEST(qureg, ref);
671 SECTION(
"correctness" ) {
673 int target = GENERATE( range(0,NUM_QUBITS) );
674 int numOps = GENERATE( range(1,5) );
677 vector<QMatrix> matrs;
678 for (
int i=0; i<numOps; i++)
681 vector<ComplexMatrix2> ops(numOps);
682 for (
int i=0; i<numOps; i++)
684 mixNonTPKrausMap(qureg, target, ops.data(), numOps);
687 vector<QMatrix> matrRefs(numOps);
688 for (
int i=0; i<numOps; i++) {
693 for (
int i=0; i<numOps; i++)
696 REQUIRE(
areEqual(qureg, ref, 1E2*REAL_EPS) );
698 SECTION(
"input validation" ) {
703 SECTION(
"number of operators" ) {
706 REQUIRE_THROWS_WITH( mixNonTPKrausMap(qureg, 0, spoofOps, numOps), ContainsSubstring(
"must be given a strictly positive number of matrices") );
708 SECTION(
"qubit index" ) {
710 int target = GENERATE( -1, NUM_QUBITS );
711 REQUIRE_THROWS_WITH( mixNonTPKrausMap(qureg, target, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
713 SECTION(
"density-matrix" ) {
716 REQUIRE_THROWS_WITH( mixNonTPKrausMap(vec, 0, spoofOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
719 SECTION(
"operators fit in node" ) {
721 qureg.isDistributed = 1;
722 qureg.numAmpsPerNode = 3;
723 qureg.logNumAmpsPerNode = 1;
724 REQUIRE_THROWS_WITH( mixNonTPKrausMap(qureg, 0, spoofOps, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );
736TEST_CASE(
"mixNonTPMultiQubitKrausMap",
"[decoherence]" ) {
738 PREPARE_TEST(qureg, ref);
742 int maxNumTargs =
calcLog2(qureg.numAmpsPerNode) / 2;
744 SECTION(
"correctness" ) {
750 int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
755 GENERATE( range(0, 10) );
756 vector<int> targs(numTargs);
761 int maxNumOps = (2*numTargs)*(2*numTargs);
762 int numOps = GENERATE_COPY( 1, maxNumOps, take(2,random(1,maxNumOps)) );
765 vector<QMatrix> matrs;
766 for (
int i=0; i<numOps; i++)
770 vector<ComplexMatrixN> ops(numOps);
771 for (
int i=0; i<numOps; i++) {
772 ops[i] = createComplexMatrixN(numTargs);
776 mixNonTPMultiQubitKrausMap(qureg, targs.data(), numTargs, ops.data(), numOps);
779 vector<QMatrix> matrRefs(numOps);
780 for (
int i=0; i<numOps; i++) {
785 for (
int i=0; i<numOps; i++)
788 REQUIRE(
areEqual(qureg, ref, 1E5*REAL_EPS) );
791 for (
int i=0; i<numOps; i++)
792 destroyComplexMatrixN(ops[i]);
794 SECTION(
"input validation" ) {
799 ComplexMatrixN spoofOps[NUM_QUBITS];
800 for (
int i=0; i<NUM_QUBITS; i++) {
801 spoofOps[i] = createComplexMatrixN(NUM_QUBITS);
805 SECTION(
"repetition of target" ) {
808 int targs[NUM_QUBITS];
809 for (
int i=0; i<NUM_QUBITS; i++)
813 int badInd = GENERATE( range(0,NUM_QUBITS) );
814 int copyInd = GENERATE_COPY( filter([=](
int i){
return i!=badInd; }, range(0,NUM_QUBITS)) );
815 targs[badInd] = targs[copyInd];
817 REQUIRE_THROWS_WITH( mixNonTPMultiQubitKrausMap(qureg, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"target qubits") && ContainsSubstring(
"unique") );
819 SECTION(
"qubit indices" ) {
822 int targs[NUM_QUBITS];
823 for (
int i=0; i<NUM_QUBITS; i++)
827 targs[GENERATE( range(0,NUM_QUBITS) )] = GENERATE( -1, NUM_QUBITS );
829 REQUIRE_THROWS_WITH( mixNonTPMultiQubitKrausMap(qureg, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
904 SECTION(
"density-matrix" ) {
909 int targs[NUM_QUBITS];
910 for (
int i=0; i<NUM_QUBITS; i++)
913 REQUIRE_THROWS_WITH( mixNonTPMultiQubitKrausMap(statevec, targs, NUM_QUBITS, spoofOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
917 SECTION(
"operator fits in node" ) {
920 int minAmps = (2*NUM_QUBITS) * (2*NUM_QUBITS);
923 int targs[NUM_QUBITS];
924 for (
int i=0; i<NUM_QUBITS; i++)
928 ComplexMatrixN ops[] = {createComplexMatrixN(NUM_QUBITS)};
929 for (
int i=0; i<(1<<NUM_QUBITS); i++)
930 ops[0].cpuElems[i][i] = 1;
934 qureg.isDistributed = 1;
935 qureg.numAmpsPerNode = minAmps - 1;
936 qureg.logNumAmpsPerNode = log2(minAmps) - 1;
937 REQUIRE_THROWS_WITH( mixNonTPMultiQubitKrausMap(qureg, targs, NUM_QUBITS, ops, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );
939 destroyComplexMatrixN(ops[0]);
942 for (
int i=0; i<NUM_QUBITS; i++)
943 destroyComplexMatrixN(spoofOps[i]);
954TEST_CASE(
"mixNonTPTwoQubitKrausMap",
"[decoherence]" ) {
956 PREPARE_TEST(qureg, ref);
958 SECTION(
"correctness" ) {
960 int targ1 = GENERATE( range(0,NUM_QUBITS) );
961 int targ2 = GENERATE_COPY( filter([=](
int t){
return t!=targ1; }, range(0,NUM_QUBITS)) );
962 int numOps = GENERATE( range(1,17) );
965 vector<QMatrix> matrs;
966 for (
int i=0; i<numOps; i++)
969 vector<ComplexMatrix4> ops(numOps);
970 for (
int i=0; i<numOps; i++)
972 mixNonTPTwoQubitKrausMap(qureg, targ1, targ2, ops.data(), numOps);
975 int targs[2] = {targ1, targ2};
976 vector<QMatrix> matrRefs(numOps);
977 for (
int i=0; i<numOps; i++) {
982 for (
int i=0; i<numOps; i++)
985 REQUIRE(
areEqual(qureg, ref, 1E4*REAL_EPS) );
987 SECTION(
"input validation" ) {
1000 SECTION(
"target collision" ) {
1002 int target = GENERATE( range(0,NUM_QUBITS) );
1003 REQUIRE_THROWS_WITH( mixNonTPTwoQubitKrausMap(qureg, target, target, spoofOps, 1), ContainsSubstring(
"target qubits") && ContainsSubstring(
"unique") );
1005 SECTION(
"qubit index" ) {
1007 int target = GENERATE( -1, NUM_QUBITS );
1008 REQUIRE_THROWS_WITH( mixNonTPTwoQubitKrausMap(qureg, 0,target, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
1009 REQUIRE_THROWS_WITH( mixNonTPTwoQubitKrausMap(qureg, target,0, spoofOps, 1), ContainsSubstring(
"Invalid target qubit") );
1011 SECTION(
"density-matrix" ) {
1014 REQUIRE_THROWS_WITH( mixNonTPTwoQubitKrausMap(vec, 0,1, spoofOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
1017 SECTION(
"operators fit in node" ) {
1019 qureg.isDistributed = 1;
1020 qureg.numAmpsPerNode = 15;
1021 qureg.logNumAmpsPerNode = 3;
1022 REQUIRE_THROWS_WITH( mixNonTPTwoQubitKrausMap(qureg, 0,1, spoofOps, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );
1036 PREPARE_TEST(qureg, ref);
1038 SECTION(
"correctness" ) {
1040 int targ1 = GENERATE( range(0,NUM_QUBITS) );
1041 int targ2 = GENERATE_COPY( filter([=](
int t){
return t!=targ1; }, range(0,NUM_QUBITS)) );
1055 ref = ((1 - prob) * ref) + (prob/3.) * (z1Ref + z2Ref + z1z2Ref);
1059 SECTION(
"input validation" ) {
1061 SECTION(
"qubit indices" ) {
1063 int targ = GENERATE( -1, NUM_QUBITS );
1064 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(qureg, 0, targ, 0), ContainsSubstring(
"Invalid target") );
1065 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(qureg, targ, 0, 0), ContainsSubstring(
"Invalid target") );
1067 SECTION(
"target collision" ) {
1069 int targ = GENERATE( range(0,NUM_QUBITS) );
1070 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(qureg, targ, targ, 0), ContainsSubstring(
"target") && ContainsSubstring(
"unique") );
1072 SECTION(
"probability" ) {
1074 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(qureg, 0, 1, -.1), ContainsSubstring(
"probability is invalid") );
1075 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(qureg, 0, 1, 3/4. + .01), ContainsSubstring(
"probability") && ContainsSubstring(
"3/4") );
1077 SECTION(
"density-matrix" ) {
1081 REQUIRE_THROWS_WITH(
mixTwoQubitDephasing(vec, 0, 1, 0.1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
1096 PREPARE_TEST(qureg, ref);
1098 SECTION(
"correctness" ) {
1100 int targ1 = GENERATE( range(0,NUM_QUBITS) );
1101 int targ2 = GENERATE_COPY( filter([=](
int t){
return t!=targ1; }, range(0,NUM_QUBITS)) );
1109 QMatrix{{0,-qcomp(0,1)},{qcomp(0,1),0}},
1113 int targs[2] = {targ1, targ2};
1115 ref = (1 - (16/15.)*prob) * ref;
1116 for (
int i=0; i<4; i++) {
1117 for (
int j=0; j<4; j++) {
1121 ref += (prob/15.) * term;
1125 REQUIRE(
areEqual(qureg, ref, 1E4*REAL_EPS) );
1127 SECTION(
"input validation" ) {
1129 SECTION(
"qubit indices" ) {
1131 int targ = GENERATE( -1, NUM_QUBITS );
1135 SECTION(
"target collision" ) {
1137 int targ = GENERATE( range(0,NUM_QUBITS) );
1138 REQUIRE_THROWS_WITH(
mixTwoQubitDepolarising(qureg, targ, targ, 0), ContainsSubstring(
"target") && ContainsSubstring(
"unique") );
1140 SECTION(
"probability" ) {
1142 REQUIRE_THROWS_WITH(
mixTwoQubitDepolarising(qureg, 0, 1, -.1), ContainsSubstring(
"probability is invalid") );
1143 REQUIRE_THROWS_WITH(
mixTwoQubitDepolarising(qureg, 0, 1, 15/16. + .01), ContainsSubstring(
"probability") && ContainsSubstring(
"15/16") );
1145 SECTION(
"density-matrix" ) {
1149 REQUIRE_THROWS_WITH(
mixTwoQubitDepolarising(vec, 0, 1, 0.1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
1164 PREPARE_TEST(qureg, ref);
1166 SECTION(
"correctness" ) {
1168 int targ1 = GENERATE( range(0,NUM_QUBITS) );
1169 int targ2 = GENERATE_COPY( filter([=](
int t){
return t!=targ1; }, range(0,NUM_QUBITS)) );
1170 int numOps = GENERATE( range(1,17) );
1173 vector<ComplexMatrix4> ops(numOps);
1174 for (
int i=0; i<numOps; i++)
1176 mixTwoQubitKrausMap(qureg, targ1, targ2, ops.data(), numOps);
1179 int targs[2] = {targ1, targ2};
1180 vector<QMatrix> matrRefs(numOps);
1181 for (
int i=0; i<numOps; i++) {
1186 for (
int i=0; i<numOps; i++)
1189 REQUIRE(
areEqual(qureg, ref, 10*REAL_EPS) );
1191 SECTION(
"input validation" ) {
1195 SECTION(
"number of operators" ) {
1199 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, emptyOps, numOps), ContainsSubstring(
"must be given a strictly positive number of matrices") );
1201 SECTION(
"trace preserving" ) {
1204 int numOps = GENERATE( range(1,16) );
1206 vector<ComplexMatrix4> ops(numOps);
1207 for (
int i=0; i<numOps; i++)
1211 ops[GENERATE_REF( range(0,numOps) )].real[0][0] = 999;
1213 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, ops.data(), numOps), ContainsSubstring(
"trace preserving") );
1215 SECTION(
"target collision" ) {
1217 int target = GENERATE( range(0,NUM_QUBITS) );
1218 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, target, target, emptyOps, 1), ContainsSubstring(
"target qubits") && ContainsSubstring(
"unique") );
1220 SECTION(
"qubit index" ) {
1222 int target = GENERATE( -1, NUM_QUBITS );
1223 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,target, emptyOps, 1), ContainsSubstring(
"Invalid target qubit") );
1224 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, target,0, emptyOps, 1), ContainsSubstring(
"Invalid target qubit") );
1226 SECTION(
"density-matrix" ) {
1229 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(vec, 0,1, emptyOps, 1), ContainsSubstring(
"Expected a density matrix Qureg but received a statevector") );
1232 SECTION(
"operators fit in node" ) {
1234 qureg.isDistributed = 1;
1235 qureg.numAmpsPerNode = 15;
1236 qureg.logNumAmpsPerNode = 3;
1237 REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, emptyOps, 1), ContainsSubstring(
"each node's communication buffer") && ContainsSubstring(
"cannot simultaneously store") );