#include "catch.hpp" #include "QuEST.h" #include "utilities.hpp" /* allows concise use of Contains in catch's REQUIRE_THROWS_WITH */ using Catch::Matchers::Contains; /** @sa calcDensityInnerProduct * @ingroup unittest * @author Tyson Jones */ TEST_CASE( "calcDensityInnerProduct", "[calculations]" ) { Qureg mat1 = createDensityQureg(NUM_QUBITS, QUEST_ENV); Qureg mat2 = createDensityQureg(NUM_QUBITS, QUEST_ENV); SECTION( "correctness" ) { // repeat these random tests 10 times GENERATE( range(0,10) ); SECTION( "density-matrix" ) { SECTION( "pure" ) { // mat1 = |r1>|^2 qcomp prod = 0; for (size_t i=0; i */ QVector prodRef = vecRef; applyReferenceOp(prodRef, targs, numTargs, pauliProd); qcomp prod = 0; for (size_t i=0; i */ QVector sumRef = pauliSum * vecRef; qcomp prod = 0; for (size_t i=0; i|^2 */ SECTION( "normalised" ) { // random L2 vectors QVector vecRef = getRandomStateVector(NUM_QUBITS); QVector pureRef = getRandomStateVector(NUM_QUBITS); toQureg(vec, vecRef); toQureg(pure, pureRef); // ||^2 = |1|^2 = 1 REQUIRE( calcFidelity(vec,vec) == Approx(1) ); // ||^2 = |sum_j conj(vec_j) * pure_j|^2 qcomp dotProd = 0; for (size_t i=0; i = 1/sqrt(nv)|vec> qreal nv = 0; for (size_t i=0; i = sqrt(nv)*sqrt(nv) = nv, // hence ||^2 = nv*nv REQUIRE( calcFidelity(vec,vec) == Approx( nv*nv ) ); qcomp dotProd = 0; for (size_t i=0; i */ SECTION( "pure" ) { QVector pureRef = getRandomStateVector(NUM_QUBITS); toQureg(pure, pureRef); // test when density matrix is the same pure state QMatrix matRef = getKetBra(pureRef, pureRef); toQureg(mat, matRef); REQUIRE( calcFidelity(mat,pure) == Approx(1) ); // test when density matrix is a random pure state QVector r1 = getRandomStateVector(NUM_QUBITS); matRef = getKetBra(r1, r1); // actually pure |r1> = ||^2 = |sum_j conj(r1_j) * pure_j|^2 qcomp dotProd = 0; for (size_t i=0; i = ) QVector rhs = matRef * pureRef; qcomp dotProd = 0; for (size_t i=0; i ] = real[ ) ] QVector rhs = matRef * pureRef; qcomp dotProd = 0; for (size_t i=0; i = sum_j conj(r1_j) * r2_j QVector r1 = getRandomStateVector(NUM_QUBITS); QVector r2 = getRandomStateVector(NUM_QUBITS); qcomp prod = 0; for (size_t i=0; i = sum_j conj(r1_j) * r2_j QVector r1 = getRandomQVector(1<> target) & 1; // target-th bit if (bit == outcome) prob += pow(abs(ref[ind]), 2); } REQUIRE( calcProbOfOutcome(vec, target, outcome) == Approx(prob) ); } SECTION( "unnormalised" ) { QVector ref = getRandomQVector(1<> target) & 1; // target-th bit if (bit == 0) prob += pow(abs(ref[ind]), 2); } if (outcome == 1) prob = 1 - prob; REQUIRE( calcProbOfOutcome(vec, target, outcome) == Approx(prob) ); } } SECTION( "density-matrix" ) { SECTION( "pure" ) { // set mat to a random |r>> target) & 1; // target-th bit if (bit == outcome) prob += pow(abs(ref[ind]), 2); } REQUIRE( calcProbOfOutcome(mat, target, outcome) == Approx(prob) ); } SECTION( "mixed" ) { QMatrix ref = getRandomDensityMatrix(NUM_QUBITS); toQureg(mat, ref); // prob is sum of diagonal amps (should be real) where target bit is outcome qcomp tr = 0; for (size_t ind=0; ind> target) & 1; // target-th bit if (bit == outcome) tr += ref[ind][ind]; } REQUIRE( imag(tr) == Approx(0).margin(REAL_EPS) ); REQUIRE( calcProbOfOutcome(mat, target, outcome) == Approx(real(tr)) ); } SECTION( "unnormalised" ) { QMatrix ref = getRandomQMatrix(1<> target) & 1; // target-th bit if (bit == 0) tr += real(ref[ind][ind]); } if (outcome == 1) tr = 1 - tr; REQUIRE( calcProbOfOutcome(mat, target, outcome) == Approx(tr) ); } } } SECTION( "validation" ) { SECTION( "qubit indices" ) { int target = GENERATE( -1, NUM_QUBITS ); REQUIRE_THROWS_WITH( calcProbOfOutcome(vec, target, 0), Contains("Invalid target qubit") ); } SECTION( "outcome value" ) { int outcome = GENERATE( -1, 2 ); REQUIRE_THROWS_WITH( calcProbOfOutcome(vec, 0, outcome), Contains("Invalid measurement outcome") ); } } destroyQureg(vec, QUEST_ENV); destroyQureg(mat, QUEST_ENV); } /** @sa calcPurity * @ingroup unittest * @author Tyson Jones */ TEST_CASE( "calcPurity", "[calculations]" ) { Qureg mat = createDensityQureg(NUM_QUBITS, QUEST_ENV); SECTION( "correctness" ) { // perform the following random tests 10 times GENERATE( range(1,10) ); SECTION( "density-matrix" ) { SECTION( "pure" ) { // pure states have unity purity initZeroState(mat); REQUIRE( calcPurity(mat) == 1 ); // (try also a pure random L2-vector) QVector r1 = getRandomStateVector(NUM_QUBITS); // |r> QMatrix m1 = getKetBra(r1, r1); // |r>= 1/pow(2.,NUM_QUBITS) ); // compare to Tr(rho^2) QMatrix prod = ref*ref; qreal tr = 0; for (size_t i=0; i= NUM_QUBITS so as not to limit distribution size int numQb = GENERATE( range(NUM_QUBITS, NUM_QUBITS+10) ); SECTION( "state-vector" ) { Qureg vec = createQureg(numQb, QUEST_ENV); REQUIRE( getNumAmps(vec) == (1<= NUM_QUBITS so as not to limit distribution size int numQb = GENERATE( range(NUM_QUBITS, NUM_QUBITS+10) ); SECTION( "state-vector" ) { Qureg vec = createQureg(numQb, QUEST_ENV); REQUIRE( getNumQubits(vec) == numQb ); destroyQureg(vec, QUEST_ENV); } SECTION( "density-matrix" ) { Qureg mat = createDensityQureg(numQb, QUEST_ENV); REQUIRE( getNumQubits(mat) == numQb ); destroyQureg(mat, QUEST_ENV); } } SECTION( "input validation" ) { // no validation SUCCEED(); } } /** @sa getProbAmp * @ingroup unittest * @author Tyson Jones */ TEST_CASE( "getProbAmp", "[calculations]" ) { Qureg vec = createQureg(NUM_QUBITS, QUEST_ENV); SECTION( "correctness" ) { SECTION( "state-vector" ) { initDebugState(vec); QVector ref = toQVector(vec); int ind = GENERATE( range(0,1<