Unit tests

Unit tests of the QuEST API, using Catch2 in C++14. More...

Functions

 TEST_CASE ("applyPauliSum", "[operators]")
 
 TEST_CASE ("calcDensityInnerProduct", "[calculations]")
 
 TEST_CASE ("calcExpecPauliProd", "[calculations]")
 
 TEST_CASE ("calcExpecPauliSum", "[calculations]")
 
 TEST_CASE ("calcFidelity", "[calculations]")
 
 TEST_CASE ("calcHilbertSchmidtDistance", "[calculations]")
 
 TEST_CASE ("calcInnerProduct", "[calculations]")
 
 TEST_CASE ("calcProbOfOutcome", "[calculations]")
 
 TEST_CASE ("calcPurity", "[calculations]")
 
 TEST_CASE ("calcTotalProb", "[calculations]")
 
 TEST_CASE ("cloneQureg", "[state_initialisations]")
 
 TEST_CASE ("collapseToOutcome", "[gates]")
 
 TEST_CASE ("compactUnitary", "[unitaries]")
 
 TEST_CASE ("controlledCompactUnitary", "[unitaries]")
 
 TEST_CASE ("controlledMultiQubitUnitary", "[unitaries]")
 
 TEST_CASE ("controlledNot", "[unitaries]")
 
 TEST_CASE ("controlledPauliY", "[unitaries]")
 
 TEST_CASE ("controlledPhaseFlip", "[unitaries]")
 
 TEST_CASE ("controlledPhaseShift", "[unitaries]")
 
 TEST_CASE ("controlledRotateAroundAxis", "[unitaries]")
 
 TEST_CASE ("controlledRotateX", "[unitaries]")
 
 TEST_CASE ("controlledRotateY", "[unitaries]")
 
 TEST_CASE ("controlledRotateZ", "[unitaries]")
 
 TEST_CASE ("controlledTwoQubitUnitary", "[unitaries]")
 
 TEST_CASE ("controlledUnitary", "[unitaries]")
 
 TEST_CASE ("createCloneQureg", "[data_structures]")
 
 TEST_CASE ("createComplexMatrixN", "[data_structures]")
 
 TEST_CASE ("createDensityQureg", "[data_structures]")
 
 TEST_CASE ("createQuESTEnv", "[data_structures]")
 
 TEST_CASE ("createQureg", "[data_structures]")
 
 TEST_CASE ("destroyComplexMatrixN", "[data_structures]")
 
 TEST_CASE ("destroyQuESTEnv", "[data_structures]")
 
 TEST_CASE ("destroyQureg", "[data_structures]")
 
 TEST_CASE ("fromComplex", "[data_structures]")
 
 TEST_CASE ("getAmp", "[calculations]")
 
 TEST_CASE ("getDensityAmp", "[calculations]")
 
 TEST_CASE ("getImagAmp", "[calculations]")
 
 TEST_CASE ("getNumAmps", "[calculations]")
 
 TEST_CASE ("getNumQubits", "[calculations]")
 
 TEST_CASE ("getProbAmp", "[calculations]")
 
 TEST_CASE ("getRealAmp", "[calculations]")
 
 TEST_CASE ("getStaticComplexMatrixN", "[data_structures]")
 
 TEST_CASE ("hadamard", "[unitaries]")
 
 TEST_CASE ("initBlankState", "[state_initialisations]")
 
 TEST_CASE ("initClassicalState", "[state_initialisations]")
 
 TEST_CASE ("initComplexMatrixN", "[data_structures]")
 
 TEST_CASE ("initPlusState", "[state_initialisations]")
 
 TEST_CASE ("initPureState", "[state_initialisations]")
 
 TEST_CASE ("initStateFromAmps", "[state_initialisations]")
 
 TEST_CASE ("initZeroState", "[state_initialisations]")
 
 TEST_CASE ("measure", "[gates]")
 
 TEST_CASE ("measureWithStats", "[gates]")
 
 TEST_CASE ("mixDamping", "[decoherence]")
 
 TEST_CASE ("mixDensityMatrix", "[decoherence]")
 
 TEST_CASE ("mixDephasing", "[decoherence]")
 
 TEST_CASE ("mixDepolarising", "[decoherence]")
 
 TEST_CASE ("mixKrausMap", "[decoherence]")
 
 TEST_CASE ("mixMultiQubitKrausMap", "[decoherence]")
 
 TEST_CASE ("mixPauli", "[decoherence]")
 
 TEST_CASE ("mixTwoQubitDephasing", "[decoherence]")
 
 TEST_CASE ("mixTwoQubitDepolarising", "[decoherence]")
 
 TEST_CASE ("mixTwoQubitKrausMap", "[decoherence]")
 
 TEST_CASE ("multiControlledMultiQubitUnitary", "[unitaries]")
 
 TEST_CASE ("multiControlledPhaseFlip", "[unitaries]")
 
 TEST_CASE ("multiControlledPhaseShift", "[unitaries]")
 
 TEST_CASE ("multiControlledTwoQubitUnitary", "[unitaries]")
 
 TEST_CASE ("multiControlledUnitary", "[unitaries]")
 
 TEST_CASE ("multiQubitUnitary", "[unitaries]")
 
 TEST_CASE ("multiRotatePauli", "[unitaries]")
 
 TEST_CASE ("multiRotateZ", "[unitaries]")
 
 TEST_CASE ("multiStateControlledUnitary", "[unitaries]")
 
 TEST_CASE ("pauliX", "[unitaries]")
 
 TEST_CASE ("pauliY", "[unitaries]")
 
 TEST_CASE ("pauliZ", "[unitaries]")
 
 TEST_CASE ("phaseShift", "[unitaries]")
 
 TEST_CASE ("rotateAroundAxis", "[unitaries]")
 
 TEST_CASE ("rotateX", "[unitaries]")
 
 TEST_CASE ("rotateY", "[unitaries]")
 
 TEST_CASE ("rotateZ", "[unitaries]")
 
 TEST_CASE ("setAmps", "[state_initialisations]")
 
 TEST_CASE ("setWeightedQureg", "[state_initialisations]")
 
 TEST_CASE ("sGate", "[unitaries]")
 
 TEST_CASE ("sqrtSwapGate", "[unitaries]")
 
 TEST_CASE ("swapGate", "[unitaries]")
 
 TEST_CASE ("tGate", "[unitaries]")
 
 TEST_CASE ("toComplex", "[data_structures]")
 
 TEST_CASE ("twoQubitUnitary", "[unitaries]")
 
 TEST_CASE ("unitary", "[unitaries]")
 

Detailed Description

Unit tests of the QuEST API, using Catch2 in C++14.

Function Documentation

◆ TEST_CASE() [1/88]

TEST_CASE ( "applyPauliSum"  ,
""  [operators] 
)
See also
applyPauliSum
Author
Tyson Jones

Definition at line 15 of file test_operators.cpp.

15  {
16 
21 
22  initDebugState(vecIn);
23  initDebugState(matIn);
24 
25  SECTION( "correctness" ) {
26 
27  int numTerms = GENERATE( 1, 2, 10, 15);
28  int numPaulis = numTerms * NUM_QUBITS;
29 
30  // each test will use random coefficients
31  qreal coeffs[numTerms];
32  for (int i=0; i<numTerms; i++)
33  coeffs[i] = getRandomReal(-5, 5);
34 
35  /* it's too expensive to try ALL Pauli sequences, via
36  * pauliOpType* paulis = GENERATE_COPY( pauliseqs(numPaulis) );.
37  * Furthermore, take(10, pauliseqs(numTargs)) will try the same pauli codes.
38  * Hence, we instead opt to repeatedly randomly generate pauliseqs
39  */
40  GENERATE( range(0,10) ); // gen 10 random pauli-codes
41  pauliOpType paulis[numPaulis];
42  for (int i=0; i<numPaulis; i++)
43  paulis[i] = (pauliOpType) getRandomInt(0,4);
44 
45  // build the resulting Pauli sum; sum_j coeffs[j] * paulis[n*j : (n+1)j]
46  QMatrix iMatr{{1,0},{0,1}};
47  QMatrix xMatr{{0,1},{1,0}};
48  QMatrix yMatr{{0,-1i},{1i,0}};
49  QMatrix zMatr{{1,0},{0,-1}};
50  QMatrix pauliSum = getZeroMatrix(1<<NUM_QUBITS);
51 
52  for (int t=0; t<numTerms; t++) {
53  QMatrix pauliProd = QMatrix{{1}};
54 
55  for (int q=0; q<NUM_QUBITS; q++) {
56  int i = q + t*NUM_QUBITS;
57 
58  QMatrix fac;
59  if (paulis[i] == PAULI_I) fac = iMatr;
60  if (paulis[i] == PAULI_X) fac = xMatr;
61  if (paulis[i] == PAULI_Y) fac = yMatr;
62  if (paulis[i] == PAULI_Z) fac = zMatr;
63  pauliProd = getKroneckerProduct(fac, pauliProd);
64  }
65  pauliSum += coeffs[t] * pauliProd;
66  }
67 
68  SECTION( "state-vector" ) {
69 
70  QVector vecRef = toQVector(vecIn);
71  applyPauliSum(vecIn, paulis, coeffs, numTerms, vecOut);
72 
73  // ensure vecIn barely changes under precision
74  REQUIRE( areEqual(vecIn, vecRef) );
75 
76  // ensure vecOut changed correctly
77  REQUIRE( areEqual(vecOut, pauliSum * vecRef) );
78  }
79  SECTION( "density-matrix" ) {
80 
81  QMatrix matRef = toQMatrix(matIn);
82  applyPauliSum(matIn, paulis, coeffs, numTerms, matOut);
83 
84  // ensure matIn barely changes under precision
85  REQUIRE( areEqual(matIn, matRef) );
86 
87  // ensure matOut changed correctly
88  REQUIRE( areEqual(matOut, pauliSum * matRef, 1E2*REAL_EPS) );
89  }
90  }
91  SECTION( "input validation" ) {
92 
93  SECTION( "number of terms" ) {
94 
95  int numTerms = GENERATE( -1, 0 );
96  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, NULL, NULL, numTerms, vecOut), Contains("Invalid number of terms") );
97  }
98  SECTION( "pauli codes" ) {
99 
100  // valid codes
101  int numTerms = 3;
102  int numPaulis = numTerms*NUM_QUBITS;
103  pauliOpType paulis[numPaulis];
104  for (int i=0; i<numPaulis; i++)
105  paulis[i] = PAULI_I;
106 
107  // make one invalid
108  paulis[GENERATE_COPY( range(0,numPaulis) )] = (pauliOpType) GENERATE( -1, 4 );
109  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, numTerms, vecOut), Contains("Invalid Pauli code") );
110  }
111  SECTION( "qureg dimensions" ) {
112 
113  Qureg badVec = createQureg(NUM_QUBITS+1, QUEST_ENV);
114  pauliOpType paulis[NUM_QUBITS];
115  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, badVec), Contains("Dimensions of the qubit registers don't match") );
116  destroyQureg(badVec, QUEST_ENV);
117  }
118  SECTION( "qureg types" ) {
119 
120  pauliOpType paulis[NUM_QUBITS];
121  REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, matOut), Contains("Registers must both be state-vectors or both be density matrices") );
122  }
123  }
124  destroyQureg(vecIn, QUEST_ENV);
125  destroyQureg(vecOut, QUEST_ENV);
126  destroyQureg(matIn, QUEST_ENV);
127  destroyQureg(matOut, QUEST_ENV);
128 }

References applyPauliSum(), areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getKroneckerProduct(), getRandomInt(), getRandomReal(), getZeroMatrix(), initDebugState(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, qreal, QUEST_ENV, toQMatrix(), and toQVector().

◆ TEST_CASE() [2/88]

TEST_CASE ( "calcDensityInnerProduct"  ,
""  [calculations] 
)
See also
calcDensityInnerProduct
Author
Tyson Jones

Definition at line 15 of file test_calculations.cpp.

15  {
16 
19 
20  SECTION( "correctness" ) {
21 
22  // repeat these random tests 10 times
23  GENERATE( range(0,10) );
24 
25  SECTION( "density-matrix" ) {
26 
27  SECTION( "pure" ) {
28 
29  // mat1 = |r1><r1|
31  toQureg(mat1, getKetBra(r1,r1));
32 
33  // mat2 = |r2><r2|
35  toQureg(mat2, getKetBra(r2,r2));
36 
37  // prod( |r1><r1|, |r2><r2| ) = |<r1|r2>|^2
38  qcomp prod = 0;
39  for (size_t i=0; i<r1.size(); i++)
40  prod += conj(r1[i]) * r2[i];
41  qreal densProd = pow(abs(prod),2);
42 
43  REQUIRE( calcDensityInnerProduct(mat1,mat2) == Approx(densProd) );
44  }
45  SECTION( "mixed" ) {
46 
49  toQureg(mat1, ref1);
50  toQureg(mat2, ref2);
51 
52  // prod(mat1, mat2) = sum_{ij} conj(mat1_{ij}) * mat2_{ij}
53  qcomp refProd = 0;
54  for (size_t i=0; i<ref1.size(); i++)
55  for (size_t j=0; j<ref1.size(); j++)
56  refProd += conj(ref1[i][j]) * ref2[i][j];
57  REQUIRE( imag(refProd) == Approx(0).margin(REAL_EPS) );
58 
59  REQUIRE( calcDensityInnerProduct(mat1,mat2) == Approx(real(refProd)) );
60 
61  // should be invariant under ordering
62  REQUIRE( calcDensityInnerProduct(mat1,mat2) == Approx(calcDensityInnerProduct(mat2,mat1)) );
63  }
64  SECTION( "unnormalised" ) {
65 
66  // set both to random (non-Hermitian) complex matrices
69  toQureg(mat1, ref1);
70  toQureg(mat2, ref2);
71 
72  // prod(mat1, mat2) = real(sum_{ij} conj(mat1_{ij}) * mat2_{ij})
73  qcomp refProd = 0;
74  for (size_t i=0; i<ref1.size(); i++)
75  for (size_t j=0; j<ref1.size(); j++)
76  refProd += conj(ref1[i][j]) * ref2[i][j];
77 
78  REQUIRE( calcDensityInnerProduct(mat1,mat2) == Approx(real(refProd)) );
79  }
80  }
81  }
82  SECTION( "input validation" ) {
83 
84  SECTION( "dimensions" ) {
85 
87  REQUIRE_THROWS_WITH( calcDensityInnerProduct(mat1,mat3), Contains("Dimensions") && Contains("don't match") );
88  destroyQureg(mat3, QUEST_ENV);
89  }
90  SECTION( "state-vectors" ) {
91 
93 
94  REQUIRE_THROWS_WITH( calcDensityInnerProduct(mat1,vec), Contains("valid only for density matrices") );
95  REQUIRE_THROWS_WITH( calcDensityInnerProduct(vec,mat1), Contains("valid only for density matrices") );
96  REQUIRE_THROWS_WITH( calcDensityInnerProduct(vec,vec), Contains("valid only for density matrices") );
97 
98  destroyQureg(vec, QUEST_ENV);
99  }
100  }
101  destroyQureg(mat1, QUEST_ENV);
102  destroyQureg(mat2, QUEST_ENV);
103 }

References calcDensityInnerProduct(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

◆ TEST_CASE() [3/88]

TEST_CASE ( "calcExpecPauliProd"  ,
""  [calculations] 
)
See also
calcExpecPauliProd
Author
Tyson Jones

Definition at line 111 of file test_calculations.cpp.

111  {
112 
115  initDebugState(vec);
116  initDebugState(mat);
117  QVector vecRef = toQVector(vec);
118  QMatrix matRef = toQMatrix(mat);
119 
122 
123  SECTION( "correctness" ) {
124 
125  int numTargs = GENERATE( range(1,NUM_QUBITS+1) );
126  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
127 
128  /* it's too expensive to try ALL Pauli sequences, via
129  * pauliOpType* paulis = GENERATE_COPY( pauliseqs(numTargs) );.
130  * Furthermore, take(10, pauliseqs(numTargs)) will try the same pauli codes.
131  * Hence, we instead opt to repeatedlyrandomly generate pauliseqs
132  */
133  GENERATE( range(0,10) ); // gen 10 random pauli-codes for every targs
134  pauliOpType paulis[numTargs];
135  for (int i=0; i<numTargs; i++)
136  paulis[i] = (pauliOpType) getRandomInt(0,4);
137 
138  // produce a numTargs-big matrix 'pauliProd' by pauli-matrix tensoring
139  QMatrix iMatr{{1,0},{0,1}};
140  QMatrix xMatr{{0,1},{1,0}};
141  QMatrix yMatr{{0,-1i},{1i,0}};
142  QMatrix zMatr{{1,0},{0,-1}};
143  QMatrix pauliProd{{1}};
144  for (int i=0; i<numTargs; i++) {
145  QMatrix fac;
146  if (paulis[i] == PAULI_I) fac = iMatr;
147  if (paulis[i] == PAULI_X) fac = xMatr;
148  if (paulis[i] == PAULI_Y) fac = yMatr;
149  if (paulis[i] == PAULI_Z) fac = zMatr;
150  pauliProd = getKroneckerProduct(fac, pauliProd);
151  }
152 
153  SECTION( "state-vector" ) {
154 
155  /* calcExpecPauliProd calculates <qureg|pauliProd|qureg> */
156 
157  QVector prodRef = vecRef;
158  applyReferenceOp(prodRef, targs, numTargs, pauliProd);
159  qcomp prod = 0;
160  for (size_t i=0; i<vecRef.size(); i++)
161  prod += conj(vecRef[i]) * prodRef[i];
162  REQUIRE( imag(prod) == Approx(0).margin(REAL_EPS) );
163 
164  qreal res = calcExpecPauliProd(vec, targs, paulis, numTargs, vecWork);
165  REQUIRE( res == Approx(real(prod)).margin(REAL_EPS) );
166  }
167  SECTION( "density matrix" ) {
168 
169  /* calcExpecPauliProd calculates Trace( pauliProd * qureg ) */
170 
171  // produce (pauliProd * mat)
172  QMatrix fullOp = getFullOperatorMatrix(NULL, 0, targs, numTargs, pauliProd, NUM_QUBITS);
173  matRef = fullOp * matRef;
174 
175  // compute real(trace(pauliProd * mat))
176  qreal tr = 0;
177  for (size_t i=0; i<matRef.size(); i++)
178  tr += real(matRef[i][i]);
179  // (get real, since we start in a non-Hermitian state, hence diagonal isn't real)
180 
181  qreal res = calcExpecPauliProd(mat, targs, paulis, numTargs, matWork);
182  REQUIRE( res == Approx(tr).margin(10*REAL_EPS) );
183  }
184  }
185  SECTION( "validation" ) {
186 
187  SECTION( "number of targets" ) {
188 
189  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
190  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, NULL, NULL, numTargs, vecWork), Contains("Invalid number of target") );
191  }
192  SECTION( "target indices" ) {
193 
194  int numTargs = 3;
195  int targs[3] = {0, 1, 2};
196 
197  // make one index wrong
198  targs[GENERATE( range(0,3) )] = GENERATE( -1, NUM_QUBITS );
199  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, targs, NULL, numTargs, vecWork), Contains("Invalid target qubit") );
200  }
201  SECTION( "repetition in targets" ) {
202 
203  int numTargs = 3;
204  int targs[3] = {0, 1, 1};
205  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, targs, NULL, numTargs, vecWork), Contains("target qubits must be unique") );
206  }
207  SECTION( "pauli codes" ) {
208 
209  int numTargs = 3;
210  int targs[3] = {0, 1, 2};
211  pauliOpType codes[3] = {PAULI_X, PAULI_Y, PAULI_Z};
212 
213  // make one pauli wrong
214  codes[GENERATE( range(0,3) )] = (pauliOpType) GENERATE( -1, 4 );
215  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, targs, codes, numTargs, vecWork), Contains("Invalid Pauli code") );
216  }
217  SECTION( "workspace type" ) {
218 
219  int numTargs = 1;
220  int targs[1] = {0};
221  pauliOpType codes[1] = {PAULI_I};
222 
223  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, targs, codes, numTargs, matWork), Contains("Registers must both be state-vectors or both be density matrices") );
224  REQUIRE_THROWS_WITH( calcExpecPauliProd(mat, targs, codes, numTargs, vecWork), Contains("Registers must both be state-vectors or both be density matrices") );
225  }
226  SECTION( "workspace dimensions" ) {
227 
228  int numTargs = 1;
229  int targs[1] = {0};
230  pauliOpType codes[1] = {PAULI_I};
231 
232  Qureg vec2 = createQureg(NUM_QUBITS + 1, QUEST_ENV);
233  REQUIRE_THROWS_WITH( calcExpecPauliProd(vec, targs, codes, numTargs, vec2), Contains("Dimensions") && Contains("don't match") );
234  destroyQureg(vec2, QUEST_ENV);
235 
237  REQUIRE_THROWS_WITH( calcExpecPauliProd(mat, targs, codes, numTargs, mat2), Contains("Dimensions") && Contains("don't match") );
238  destroyQureg(mat2, QUEST_ENV);
239  }
240  }
241  destroyQureg(vec, QUEST_ENV);
242  destroyQureg(mat, QUEST_ENV);
243  destroyQureg(vecWork, QUEST_ENV);
244  destroyQureg(matWork, QUEST_ENV);
245 }

References applyReferenceOp(), calcExpecPauliProd(), createDensityQureg(), createQureg(), destroyQureg(), getFullOperatorMatrix(), getKroneckerProduct(), getRandomInt(), initDebugState(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, qcomp, qreal, QUEST_ENV, sublists(), toQMatrix(), and toQVector().

◆ TEST_CASE() [4/88]

TEST_CASE ( "calcExpecPauliSum"  ,
""  [calculations] 
)
See also
calcExpecPauliSum
Author
Tyson Jones

Definition at line 253 of file test_calculations.cpp.

253  {
254 
257  initDebugState(vec);
258  initDebugState(mat);
259  QVector vecRef = toQVector(vec);
260  QMatrix matRef = toQMatrix(mat);
261 
264 
265  SECTION( "correctness" ) {
266 
267  int numSumTerms = GENERATE( 1, 2, 10, 15 );
268 
269  /* it's too expensive to try every possible Pauli configuration, so
270  * we'll try 10 random codes, and for each, random coefficients
271  */
272  GENERATE( range(0,10) );
273  int totNumCodes = numSumTerms*NUM_QUBITS;
274  pauliOpType paulis[totNumCodes];
275  for (int i=0; i<totNumCodes; i++)
276  paulis[i] = (pauliOpType) getRandomInt(0,4);
277 
278  // for every above param configuration, try random coefficients
279  qreal coeffs[numSumTerms];
280  for (int i=0; i<numSumTerms; i++)
281  coeffs[i] = getRandomReal(-5, 5);
282 
283  // produce a numTargs-big matrix 'pauliSum' by pauli-matrix tensoring and summing
284  QMatrix iMatr{{1,0},{0,1}};
285  QMatrix xMatr{{0,1},{1,0}};
286  QMatrix yMatr{{0,-1i},{1i,0}};
287  QMatrix zMatr{{1,0},{0,-1}};
288  QMatrix pauliSum = getZeroMatrix(1<<NUM_QUBITS);
289 
290  for (int t=0; t<numSumTerms; t++) {
291  QMatrix pauliProd = QMatrix{{1}};
292 
293  for (int q=0; q<NUM_QUBITS; q++) {
294  int i = q + t*NUM_QUBITS;
295 
296  QMatrix fac;
297  if (paulis[i] == PAULI_I) fac = iMatr;
298  if (paulis[i] == PAULI_X) fac = xMatr;
299  if (paulis[i] == PAULI_Y) fac = yMatr;
300  if (paulis[i] == PAULI_Z) fac = zMatr;
301  pauliProd = getKroneckerProduct(fac, pauliProd);
302  }
303  pauliSum += coeffs[t] * pauliProd;
304  }
305  SECTION( "state-vector" ) {
306 
307  /* calcExpecPauliSum calculates <qureg|pauliSum|qureg> */
308 
309  QVector sumRef = pauliSum * vecRef;
310  qcomp prod = 0;
311  for (size_t i=0; i<vecRef.size(); i++)
312  prod += conj(vecRef[i]) * sumRef[i];
313  REQUIRE( imag(prod) == Approx(0).margin(10*REAL_EPS) );
314 
315  qreal res = calcExpecPauliSum(vec, paulis, coeffs, numSumTerms, vecWork);
316  REQUIRE( res == Approx(real(prod)).margin(10*REAL_EPS) );
317  }
318  SECTION( "density matrix" ) {
319 
320  /* calcExpecPauliSum calculates Trace( pauliSum * qureg ) */
321  matRef = pauliSum * matRef;
322  qreal tr = 0;
323  for (size_t i=0; i<matRef.size(); i++)
324  tr += real(matRef[i][i]);
325  // (get real, since we start in a non-Hermitian state, hence diagonal isn't real)
326 
327  qreal res = calcExpecPauliSum(mat, paulis, coeffs, numSumTerms, matWork);
328  REQUIRE( res == Approx(tr).margin(1E2*REAL_EPS) );
329  }
330  }
331  SECTION( "validation" ) {
332 
333  SECTION( "number of sum terms" ) {
334 
335  int numSumTerms = GENERATE( -1, 0 );
336  REQUIRE_THROWS_WITH( calcExpecPauliSum(vec, NULL, NULL, numSumTerms, vecWork), Contains("Invalid number of terms in the Pauli sum") );
337  }
338  SECTION( "pauli codes" ) {
339 
340  // make valid params
341  int numSumTerms = 3;
342  qreal coeffs[numSumTerms];
343  pauliOpType codes[numSumTerms*NUM_QUBITS];
344  for (int i=0; i<numSumTerms*NUM_QUBITS; i++)
345  codes[i] = PAULI_I;
346 
347  // make one pauli wrong
348  codes[GENERATE_COPY( range(0,numSumTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
349  REQUIRE_THROWS_WITH( calcExpecPauliSum(vec, codes, coeffs, numSumTerms, vecWork), Contains("Invalid Pauli code") );
350  }
351  SECTION( "workspace type" ) {
352 
353  // make valid params
354  int numSumTerms = 1;
355  qreal coeffs[1] = {0};
356  pauliOpType codes[NUM_QUBITS];
357  for (int i=0; i<NUM_QUBITS; i++)
358  codes[i] = PAULI_I;
359 
360  REQUIRE_THROWS_WITH( calcExpecPauliSum(vec, codes, coeffs, numSumTerms, mat), Contains("Registers must both be state-vectors or both be density matrices") );
361  REQUIRE_THROWS_WITH( calcExpecPauliSum(mat, codes, coeffs, numSumTerms, vec), Contains("Registers must both be state-vectors or both be density matrices") );
362  }
363  SECTION( "workspace dimensions" ) {
364 
365  // make valid params
366  int numSumTerms = 1;
367  qreal coeffs[1] = {0};
368  pauliOpType codes[NUM_QUBITS];
369  for (int i=0; i<NUM_QUBITS; i++)
370  codes[i] = PAULI_I;
371 
372  Qureg vec2 = createQureg(NUM_QUBITS + 1, QUEST_ENV);
373  REQUIRE_THROWS_WITH( calcExpecPauliSum(vec, codes, coeffs, numSumTerms, vec2), Contains("Dimensions") && Contains("don't match") );
374  destroyQureg(vec2, QUEST_ENV);
375 
377  REQUIRE_THROWS_WITH( calcExpecPauliSum(mat, codes, coeffs, numSumTerms, mat2), Contains("Dimensions") && Contains("don't match") );
378  destroyQureg(mat2, QUEST_ENV);
379  }
380  }
381  destroyQureg(vec, QUEST_ENV);
382  destroyQureg(mat, QUEST_ENV);
383  destroyQureg(vecWork, QUEST_ENV);
384  destroyQureg(matWork, QUEST_ENV);
385 }

References calcExpecPauliSum(), createDensityQureg(), createQureg(), destroyQureg(), getKroneckerProduct(), getRandomInt(), getRandomReal(), getZeroMatrix(), initDebugState(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, qcomp, qreal, QUEST_ENV, toQMatrix(), and toQVector().

◆ TEST_CASE() [5/88]

TEST_CASE ( "calcFidelity"  ,
""  [calculations] 
)
See also
calcFidelity
Author
Tyson Jones

Definition at line 393 of file test_calculations.cpp.

393  {
394 
398 
399  SECTION( "correctness" ) {
400 
401  // repeat the below random tests 10 times
402  GENERATE( range(0,10) );
403 
404  SECTION( "state-vector" ) {
405 
406  /* calcFidelity computes |<vec|pure>|^2 */
407 
408  SECTION( "normalised" ) {
409 
410  // random L2 vectors
413  toQureg(vec, vecRef);
414  toQureg(pure, pureRef);
415 
416  // |<vec|vec>|^2 = |1|^2 = 1
417  REQUIRE( calcFidelity(vec,vec) == Approx(1) );
418 
419  // |<vec|pure>|^2 = |sum_j conj(vec_j) * pure_j|^2
420  qcomp dotProd = 0;
421  for (size_t i=0; i<vecRef.size(); i++)
422  dotProd += conj(vecRef[i]) * pureRef[i];
423  qreal refFid = pow(abs(dotProd), 2);
424 
425  REQUIRE( calcFidelity(vec,pure) == Approx(refFid) );
426  }
427  SECTION( "unnormalised" ) {
428 
429  // random unnormalised vectors
430  QVector vecRef = getRandomQVector(1<<NUM_QUBITS);
431  QVector pureRef = getRandomQVector(1<<NUM_QUBITS);
432  toQureg(vec, vecRef);
433  toQureg(pure, pureRef);
434 
435  // Let nv be magnitude of vec, hence |unit-vec> = 1/sqrt(nv)|vec>
436  qreal nv = 0;
437  for (size_t i=0; i<vecRef.size(); i++)
438  nv += pow(abs(vecRef[i]), 2);
439  // then <vec|vec> = sqrt(nv)*sqrt(nv) <unit-vec|unit-vec> = nv,
440  // hence |<vec|vec>|^2 = nv*nv
441  REQUIRE( calcFidelity(vec,vec) == Approx( nv*nv ) );
442 
443  qcomp dotProd = 0;
444  for (size_t i=0; i<vecRef.size(); i++)
445  dotProd += conj(vecRef[i]) * pureRef[i];
446  qreal refFid = pow(abs(dotProd), 2);
447 
448  REQUIRE( calcFidelity(vec,pure) == Approx(refFid) );
449  }
450  }
451  SECTION( "density-matrix" ) {
452 
453  /* calcFidelity computes <pure|mat|pure> */
454 
455  SECTION( "pure" ) {
456 
458  toQureg(pure, pureRef);
459 
460  // test when density matrix is the same pure state
461  QMatrix matRef = getKetBra(pureRef, pureRef);
462  toQureg(mat, matRef);
463  REQUIRE( calcFidelity(mat,pure) == Approx(1) );
464 
465  // test when density matrix is a random pure state
467  matRef = getKetBra(r1, r1); // actually pure |r1><r1|
468  toQureg(mat, matRef);
469 
470  // <pure|r1><r1|pure> = |<r1|pure>|^2 = |sum_j conj(r1_j) * pure_j|^2
471  qcomp dotProd = 0;
472  for (size_t i=0; i<r1.size(); i++)
473  dotProd += conj(r1[i]) * pureRef[i];
474  qreal refFid = pow(abs(dotProd), 2);
475 
476  REQUIRE( calcFidelity(mat,pure) == Approx(refFid) );
477  }
478  SECTION( "mixed" ) {
479 
481  toQureg(pure, pureRef);
482 
483  // test when density matrix is mixed
485  toQureg(mat, matRef);
486 
487  // <pure|mat|pure> = <pure| (Mat|pure>)
488  QVector rhs = matRef * pureRef;
489  qcomp dotProd = 0;
490  for (size_t i=0; i<rhs.size(); i++)
491  dotProd += conj(pureRef[i]) * rhs[i];
492 
493  REQUIRE( imag(dotProd) == Approx(0).margin(REAL_EPS) );
494  REQUIRE( calcFidelity(mat,pure) == Approx(real(dotProd)) );
495  }
496  SECTION( "unnormalised" ) {
497 
498  // test when both density matrix and pure state are unnormalised
499  QVector pureRef = getRandomQVector(1<<NUM_QUBITS);
500  QMatrix matRef = getRandomQMatrix(1<<NUM_QUBITS);
501  toQureg(pure, pureRef);
502  toQureg(mat, matRef);
503 
504  // real[ <pure|mat|pure> ] = real[ <pure| (Mat|pure>) ]
505  QVector rhs = matRef * pureRef;
506  qcomp dotProd = 0;
507  for (size_t i=0; i<rhs.size(); i++)
508  dotProd += conj(pureRef[i]) * rhs[i];
509 
510  REQUIRE( calcFidelity(mat,pure) == Approx(real(dotProd)) );
511  }
512  }
513  }
514  SECTION( "input validation" ) {
515 
516  SECTION( "dimensions" ) {
517 
518  // two state-vectors
520  REQUIRE_THROWS_WITH( calcFidelity(vec2,vec), Contains("Dimensions") && Contains("don't match") );
521  destroyQureg(vec2, QUEST_ENV);
522 
523  // density-matrix and state-vector
525  REQUIRE_THROWS_WITH( calcFidelity(mat2,vec), Contains("Dimensions") && Contains("don't match") );
526  destroyQureg(mat2, QUEST_ENV);
527  }
528  SECTION( "density-matrices" ) {
529 
530  // two mixed statess
531  REQUIRE_THROWS_WITH( calcFidelity(mat,mat), Contains("Second argument must be a state-vector") );
532  }
533  }
534  destroyQureg(vec, QUEST_ENV);
535  destroyQureg(mat, QUEST_ENV);
536  destroyQureg(pure, QUEST_ENV);
537 }

References calcFidelity(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomQVector(), getRandomStateVector(), NUM_QUBITS, Qureg::numQubitsRepresented, qcomp, qreal, QUEST_ENV, and toQureg().

◆ TEST_CASE() [6/88]

TEST_CASE ( "calcHilbertSchmidtDistance"  ,
""  [calculations] 
)
See also
calcHilbertSchmidtDistance
Author
Tyson Jones

Definition at line 545 of file test_calculations.cpp.

545  {
546 
549 
550  SECTION( "correctness" ) {
551 
552  // perform these random tests 10 times
553  GENERATE( range(0,10) );
554 
555  SECTION( "density-matrix" ) {
556 
557  SECTION( "pure" ) {
558 
559  // create random |r1><r1| and |r2><r2| states
561  QMatrix m1 = getKetBra(r1,r1);
562  toQureg(mat1, m1);
564  QMatrix m2 = getKetBra(r2,r2);
565  toQureg(mat2, m2);
566 
567  // Tr{ (a-b)(a-b)^dagger } = sum_{ij} |a_{ij} - b_{ij}|^2
568  qreal tr = 0;
569  for (size_t i=0; i<m1.size(); i++)
570  for (size_t j=0; j<m1.size(); j++)
571  tr += pow(abs(m1[i][j] - m2[i][j]), 2);
572 
573  qreal res = calcHilbertSchmidtDistance(mat1, mat2);
574  REQUIRE( res == Approx(sqrt(tr)) );
575 
576  }
577  SECTION( "normalised" ) {
578 
581  toQureg(mat1, ref1);
582  toQureg(mat2, ref2);
583 
584  // Tr{ (a-b)(a-b)^dagger } = sum_{ij} |a_{ij} - b_{ij}|^2
585  qreal tr = 0;
586  for (size_t i=0; i<ref1.size(); i++)
587  for (size_t j=0; j<ref1.size(); j++)
588  tr += pow(abs(ref1[i][j] - ref2[i][j]), 2);
589 
590  qreal res = calcHilbertSchmidtDistance(mat1, mat2);
591  REQUIRE( res == Approx(sqrt(tr)) );
592  }
593  SECTION( "unnormalised" ) {
594 
595  // mat1 and mat2 are both random matrices
598  toQureg(mat1, ref1);
599  toQureg(mat2, ref2);
600 
601  // Tr{ (a-b)(a-b)^dagger } = sum_{ij} |a_{ij} - b_{ij}|^2
602  qreal tr = 0;
603  for (size_t i=0; i<ref1.size(); i++)
604  for (size_t j=0; j<ref1.size(); j++)
605  tr += pow(abs(ref1[i][j] - ref2[i][j]), 2);
606 
607  qreal res = calcHilbertSchmidtDistance(mat1, mat2);
608  REQUIRE( res == Approx(sqrt(tr)) );
609  }
610  }
611  }
612  SECTION( "input validation") {
613 
614  SECTION( "dimensions" ) {
615 
617  REQUIRE_THROWS_WITH( calcHilbertSchmidtDistance(mat1,mat3), Contains("Dimensions") && Contains("don't match") );
618  destroyQureg(mat3, QUEST_ENV);
619  }
620  SECTION( "state-vector" ) {
621 
623 
624  REQUIRE_THROWS_WITH( calcHilbertSchmidtDistance(vec,mat1), Contains("valid only for density matrices") );
625  REQUIRE_THROWS_WITH( calcHilbertSchmidtDistance(mat1,vec), Contains("valid only for density matrices") );
626  REQUIRE_THROWS_WITH( calcHilbertSchmidtDistance(vec,vec), Contains("valid only for density matrices") );
627 
628  destroyQureg(vec, QUEST_ENV);
629  }
630  }
631  destroyQureg(mat1, QUEST_ENV);
632  destroyQureg(mat2, QUEST_ENV);
633 }

References calcHilbertSchmidtDistance(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

◆ TEST_CASE() [7/88]

TEST_CASE ( "calcInnerProduct"  ,
""  [calculations] 
)
See also
calcInnerProduct
Author
Tyson Jones

Definition at line 641 of file test_calculations.cpp.

641  {
642 
645 
646  SECTION( "correctness" ) {
647 
648  // perform these random tests 10 times
649  GENERATE( range(0,10) );
650 
651  SECTION( "state-vector" ) {
652 
653  SECTION( "normalised" ) {
654 
655  // <r1|r2> = sum_j conj(r1_j) * r2_j
658  qcomp prod = 0;
659  for (size_t i=0; i<r1.size(); i++)
660  prod += conj(r1[i]) * r2[i];
661 
662  toQureg(vec1, r1);
663  toQureg(vec2, r2);
664  Complex res = calcInnerProduct(vec1,vec2);
665 
666  REQUIRE( res.real == Approx(real(prod)) );
667  REQUIRE( res.imag == Approx(imag(prod)) );
668  }
669  SECTION( "unnormalised" ) {
670 
671  // <r1|r2> = sum_j conj(r1_j) * r2_j
674  qcomp prod = 0;
675  for (size_t i=0; i<r1.size(); i++)
676  prod += conj(r1[i]) * r2[i];
677 
678  toQureg(vec1, r1);
679  toQureg(vec2, r2);
680  Complex res = calcInnerProduct(vec1,vec2);
681 
682  REQUIRE( res.real == Approx(real(prod)) );
683  REQUIRE( res.imag == Approx(imag(prod)) );
684  }
685  }
686  }
687  SECTION( "input validation" ) {
688 
689  SECTION( "dimensions" ) {
690 
691  Qureg vec3 = createQureg(NUM_QUBITS + 1, QUEST_ENV);
692  REQUIRE_THROWS_WITH( calcInnerProduct(vec1,vec3), Contains("Dimensions") && Contains("don't match") );
693  destroyQureg(vec3, QUEST_ENV);
694  }
695  SECTION( "density-matrix" ) {
696 
698 
699  REQUIRE_THROWS_WITH( calcInnerProduct(vec1,mat), Contains("valid only for state-vectors") );
700  REQUIRE_THROWS_WITH( calcInnerProduct(mat,vec1), Contains("valid only for state-vectors") );
701  REQUIRE_THROWS_WITH( calcInnerProduct(mat,mat), Contains("valid only for state-vectors") );
702 
703  destroyQureg(mat, QUEST_ENV);
704  }
705  }
706  destroyQureg(vec1, QUEST_ENV);
707  destroyQureg(vec2, QUEST_ENV);
708 }

References calcInnerProduct(), createDensityQureg(), createQureg(), destroyQureg(), getRandomQVector(), getRandomStateVector(), Complex::imag, NUM_QUBITS, qcomp, QUEST_ENV, Complex::real, and toQureg().

◆ TEST_CASE() [8/88]

TEST_CASE ( "calcProbOfOutcome"  ,
""  [calculations] 
)
See also
calcProbOfOutcome
Author
Tyson Jones

Definition at line 716 of file test_calculations.cpp.

716  {
717 
720 
721  SECTION( "correctness" ) {
722 
723  int target = GENERATE( range(0,NUM_QUBITS) );
724  int outcome = GENERATE( 0, 1 );
725 
726  SECTION( "state-vector" ) {
727 
728  SECTION( "normalised" ) {
729 
731  toQureg(vec, ref);
732 
733  // prob is sum of |amp|^2 of amplitudes where target bit is outcome
734  qreal prob = 0;
735  for (size_t ind=0; ind<ref.size(); ind++) {
736  int bit = (ind >> target) & 1; // target-th bit
737  if (bit == outcome)
738  prob += pow(abs(ref[ind]), 2);
739  }
740 
741  REQUIRE( calcProbOfOutcome(vec, target, outcome) == Approx(prob) );
742  }
743  SECTION( "unnormalised" ) {
744 
746  toQureg(vec, ref);
747 
748  // prob is (sum of |amp|^2 of amplitudes where target bit is zero)
749  // or 1 - (this) if outcome == 1
750  qreal prob = 0;
751  for (size_t ind=0; ind<ref.size(); ind++) {
752  int bit = (ind >> target) & 1; // target-th bit
753  if (bit == 0)
754  prob += pow(abs(ref[ind]), 2);
755  }
756  if (outcome == 1)
757  prob = 1 - prob;
758 
759  REQUIRE( calcProbOfOutcome(vec, target, outcome) == Approx(prob) );
760  }
761  }
762  SECTION( "density-matrix" ) {
763 
764  SECTION( "pure" ) {
765 
766  // set mat to a random |r><r|
768  toQureg(mat, getKetBra(ref, ref));
769 
770  // calc prob of the state-vector
771  qreal prob = 0;
772  for (size_t ind=0; ind<ref.size(); ind++) {
773  int bit = (ind >> target) & 1; // target-th bit
774  if (bit == outcome)
775  prob += pow(abs(ref[ind]), 2);
776  }
777 
778  REQUIRE( calcProbOfOutcome(mat, target, outcome) == Approx(prob) );
779  }
780  SECTION( "mixed" ) {
781 
783  toQureg(mat, ref);
784 
785  // prob is sum of diagonal amps (should be real) where target bit is outcome
786  qcomp tr = 0;
787  for (size_t ind=0; ind<ref.size(); ind++) {
788  int bit = (ind >> target) & 1; // target-th bit
789  if (bit == outcome)
790  tr += ref[ind][ind];
791  }
792  REQUIRE( imag(tr) == Approx(0).margin(REAL_EPS) );
793 
794  REQUIRE( calcProbOfOutcome(mat, target, outcome) == Approx(real(tr)) );
795  }
796  SECTION( "unnormalised" ) {
797 
799  toQureg(mat, ref);
800 
801  // prob is (sum of real of diagonal amps where target bit is outcome)
802  // or 1 - (this) if outcome == 1
803  qreal tr = 0;
804  for (size_t ind=0; ind<ref.size(); ind++) {
805  int bit = (ind >> target) & 1; // target-th bit
806  if (bit == 0)
807  tr += real(ref[ind][ind]);
808  }
809  if (outcome == 1)
810  tr = 1 - tr;
811 
812  REQUIRE( calcProbOfOutcome(mat, target, outcome) == Approx(tr) );
813  }
814  }
815  }
816  SECTION( "validation" ) {
817 
818  SECTION( "qubit indices" ) {
819 
820  int target = GENERATE( -1, NUM_QUBITS );
821  REQUIRE_THROWS_WITH( calcProbOfOutcome(vec, target, 0), Contains("Invalid target qubit") );
822  }
823  SECTION( "outcome value" ) {
824 
825  int outcome = GENERATE( -1, 2 );
826  REQUIRE_THROWS_WITH( calcProbOfOutcome(vec, 0, outcome), Contains("Invalid measurement outcome") );
827  }
828  }
829  destroyQureg(vec, QUEST_ENV);
830  destroyQureg(mat, QUEST_ENV);
831 }

References calcProbOfOutcome(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomQVector(), getRandomStateVector(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

◆ TEST_CASE() [9/88]

TEST_CASE ( "calcPurity"  ,
""  [calculations] 
)
See also
calcPurity
Author
Tyson Jones

Definition at line 839 of file test_calculations.cpp.

839  {
840 
842 
843  SECTION( "correctness" ) {
844 
845  // perform the following random tests 10 times
846  GENERATE( range(1,10) );
847 
848  SECTION( "density-matrix" ) {
849 
850  SECTION( "pure" ) {
851 
852  // pure states have unity purity
853  initZeroState(mat);
854  REQUIRE( calcPurity(mat) == 1 );
855 
856  // (try also a pure random L2-vector)
858  QMatrix m1 = getKetBra(r1, r1); // |r><r|
859  toQureg(mat, m1);
860  REQUIRE( calcPurity(mat) == Approx(1) );
861 
862  }
863  SECTION( "mixed" ) {
864 
865  // mixed states have 1/2^N < purity < 1
867  toQureg(mat, ref);
868  qreal purity = calcPurity(mat);
869  REQUIRE( purity < 1 );
870  REQUIRE( purity >= 1/pow(2.,NUM_QUBITS) );
871 
872  // compare to Tr(rho^2)
873  QMatrix prod = ref*ref;
874  qreal tr = 0;
875  for (size_t i=0; i<prod.size(); i++)
876  tr += real(prod[i][i]);
877  REQUIRE( purity == Approx(tr) );
878  }
879  SECTION( "unnormalised" ) {
880 
881  // unphysical states give sum_{ij} |rho_ij|^2
883  qreal tot = 0;
884  for (size_t i=0; i<ref.size(); i++)
885  for (size_t j=0; j<ref.size(); j++)
886  tot += pow(abs(ref[i][j]), 2);
887 
888  toQureg(mat, ref);
889  REQUIRE( calcPurity(mat) == Approx(tot) );
890  }
891  }
892  }
893  SECTION( "input validation" ) {
894 
895  SECTION( "state-vector" ) {
896 
898  REQUIRE_THROWS_WITH( calcPurity(vec), Contains("valid only for density matrices") );
899  destroyQureg(vec, QUEST_ENV);
900  }
901  }
902  destroyQureg(mat, QUEST_ENV);
903 }

References calcPurity(), createDensityQureg(), createQureg(), destroyQureg(), getKetBra(), getRandomDensityMatrix(), getRandomQMatrix(), getRandomStateVector(), initZeroState(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

◆ TEST_CASE() [10/88]

TEST_CASE ( "calcTotalProb"  ,
""  [calculations] 
)
See also
calcTotalProb
Author
Tyson Jones

Definition at line 911 of file test_calculations.cpp.

911  {
912 
915 
916  SECTION( "correctness" ) {
917 
918  SECTION( "state-vector" ) {
919 
920  // normalised: prob(vec) = 1
921  initPlusState(vec);
922  REQUIRE( calcTotalProb(vec) == Approx(1) );
923 
924  // zero norm: prob(vec) = 0
925  initBlankState(vec);
926  REQUIRE( calcTotalProb(vec) == 0 );
927 
928  // random L2 state: prob(vec) = 1
930  REQUIRE( calcTotalProb(vec) == Approx(1) );
931 
932  // unnormalised: prob(vec) = sum_i |vec_i|^2
933  initDebugState(vec);
934  QVector ref = toQVector(vec);
935  qreal refProb = 0;
936  for (size_t i=0; i<ref.size(); i++)
937  refProb += pow(abs(ref[i]), 2);
938  REQUIRE( calcTotalProb(vec) == Approx(refProb) );
939  }
940  SECTION( "density-matrix" ) {
941 
942  // normalised: prob(mat) = 1
943  initPlusState(mat);
944  REQUIRE( calcTotalProb(mat) == Approx(1) );
945 
946  // zero norm: prob(mat) = 0
947  initBlankState(mat);
948  REQUIRE( calcTotalProb(mat) == 0 );
949 
950  // random density matrix: prob(mat) = 1
952  REQUIRE( calcTotalProb(mat) == Approx(1) );
953 
954  // unnormalised: prob(mat) = sum_i real(mat_{ii})
955  initDebugState(mat);
956  QMatrix ref = toQMatrix(mat);
957  qreal refProb = 0;
958  for (size_t i=0; i<ref.size(); i++)
959  refProb += real(ref[i][i]);
960  REQUIRE( calcTotalProb(mat) == Approx(refProb) );
961  }
962  }
963  SECTION( "input validation" ) {
964 
965  // no validation
966  SUCCEED();
967  }
968  destroyQureg(vec, QUEST_ENV);
969  destroyQureg(mat, QUEST_ENV);
970 }

References calcTotalProb(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), initBlankState(), initDebugState(), initPlusState(), NUM_QUBITS, qreal, QUEST_ENV, toQMatrix(), toQureg(), and toQVector().

◆ TEST_CASE() [11/88]

TEST_CASE ( "cloneQureg"  ,
""  [state_initialisations] 
)
See also
cloneQureg
Author
Tyson Jones

Definition at line 15 of file test_state_initialisations.cpp.

15  {
16 
19 
20  SECTION( "correctness" ) {
21 
22  SECTION( "state-vector" ) {
23 
25 
26  // make sure states start differently
27  initDebugState(vec1);
28  initBlankState(vec2);
29  REQUIRE( !areEqual(vec1, vec2) );
30 
31  // make sure vec2 is changed
32  QVector copy1 = toQVector(vec1);
33  cloneQureg(vec2, vec1);
34  REQUIRE( areEqual(vec1, vec2) );
35 
36  // make sure vec1 unaffected
37  REQUIRE( areEqual(vec1, copy1) );
38 
39  destroyQureg(vec2, QUEST_ENV);
40  }
41  SECTION( "density-matrix" ) {
42 
44 
45  // make sure states start differently
46  initDebugState(mat1);
47  initBlankState(mat2);
48  REQUIRE( !areEqual(mat1, mat2) );
49 
50  // make sure vec2 is changed
51  QMatrix copy1 = toQMatrix(mat1);
52  cloneQureg(mat2, mat1);
53  REQUIRE( areEqual(mat1, mat2) );
54 
55  // make sure vec1 unaffected
56  REQUIRE( areEqual(mat1, copy1) );
57 
58  destroyQureg(mat2, QUEST_ENV);
59  }
60  }
61  SECTION( "input validation" ) {
62 
63  SECTION( "qureg type" ) {
64 
65  REQUIRE_THROWS_WITH( cloneQureg(mat1, vec1), Contains("both be state-vectors") && Contains("density matrices") );
66  REQUIRE_THROWS_WITH( cloneQureg(vec1, mat1), Contains("both be state-vectors") && Contains("density matrices") );
67  }
68  SECTION( "qureg dimensions" ) {
69 
72 
73  REQUIRE_THROWS_WITH( cloneQureg(vec1, vec3), Contains("Dimensions") && Contains("don't match") );
74  REQUIRE_THROWS_WITH( cloneQureg(mat1, mat3), Contains("Dimensions") && Contains("don't match") );
75 
76  destroyQureg(vec3, QUEST_ENV);
77  destroyQureg(mat3, QUEST_ENV);
78  }
79  }
80  destroyQureg(vec1, QUEST_ENV);
81  destroyQureg(mat1, QUEST_ENV);
82 }

References areEqual(), cloneQureg(), createDensityQureg(), createQureg(), destroyQureg(), initBlankState(), initDebugState(), NUM_QUBITS, Qureg::numQubitsRepresented, QUEST_ENV, toQMatrix(), and toQVector().

◆ TEST_CASE() [12/88]

TEST_CASE ( "collapseToOutcome"  ,
""  [gates] 
)
See also
collapseToOutcome
Author
Tyson Jones

Definition at line 15 of file test_gates.cpp.

15  {
16 
19 
20  SECTION( "correctness" ) {
21 
22  int qubit = GENERATE( range(0,NUM_QUBITS) );
23  int outcome = GENERATE( 0, 1 );
24 
25  // repeat these random tests 10 times on every qubit, and for both outcomes
26  GENERATE( range(0,10) );
27 
28  SECTION( "state-vector" ) {
29 
30  // use a random L2 state for every qubit & outcome
32  toQureg(vec, vecRef);
33 
34  // calculate prob of outcome
35  qreal prob = 0;
36  for (size_t ind=0; ind<vecRef.size(); ind++) {
37  int bit = (ind >> qubit) & 1; // target-th bit
38  if (bit == outcome)
39  prob += pow(abs(vecRef[ind]), 2);
40  }
41 
42  // renormalise by the outcome prob
43  for (size_t ind=0; ind<vecRef.size(); ind++) {
44  int bit = (ind >> qubit) & 1; // target-th bit
45  if (bit == outcome)
46  vecRef[ind] /= sqrt(prob);
47  else
48  vecRef[ind] = 0;
49  }
50 
51  qreal res = collapseToOutcome(vec, qubit, outcome);
52  REQUIRE( res == Approx(prob) );
53  REQUIRE( areEqual(vec, vecRef) );
54  }
55  SECTION( "density-matrix" ) {
56 
57  // use a random density matrix for every qubit & outcome
59  toQureg(mat, matRef);
60 
61  // prob is sum of diagonal amps (should be real) where target bit is outcome
62  qcomp tr = 0;
63  for (size_t ind=0; ind<matRef.size(); ind++) {
64  int bit = (ind >> qubit) & 1; // qubit-th bit
65  if (bit == outcome)
66  tr += matRef[ind][ind];
67  }
68  REQUIRE( imag(tr) == Approx(0).margin(REAL_EPS) );
69  qreal prob = real(tr);
70 
71  // renorm (/prob) every |*outcome*><*outcome*| state, zeroing all others
72  for (size_t r=0; r<matRef.size(); r++) {
73  for (size_t c=0; c<matRef.size(); c++) {
74  int ketBit = (c >> qubit) & 1;
75  int braBit = (r >> qubit) & 1;
76 
77  if (ketBit == outcome && braBit == outcome)
78  matRef[r][c] /= prob;
79  else
80  matRef[r][c] = 0;
81  }
82  }
83 
84  qreal res = collapseToOutcome(mat, qubit, outcome);
85  REQUIRE( res == Approx(prob) );
86  REQUIRE( areEqual(mat, matRef) );
87  }
88  }
89  SECTION( "input validation" ) {
90 
91  SECTION( "qubit index" ) {
92 
93  int qubit = GENERATE( -1, NUM_QUBITS );
94  int outcome = 0;
95  REQUIRE_THROWS_WITH( collapseToOutcome(mat, qubit, outcome), Contains("Invalid target qubit") );
96  }
97  SECTION( "outcome value" ) {
98 
99  int qubit = 0;
100  int outcome = GENERATE( -1, 2 );
101  REQUIRE_THROWS_WITH( collapseToOutcome(mat, qubit, outcome), Contains("Invalid measurement outcome") );
102  }
103  SECTION( "outcome probability" ) {
104 
105  initZeroState(vec);
106  REQUIRE_THROWS_WITH( collapseToOutcome(vec, 0, 1), Contains("Can't collapse to state with zero probability") );
107  initClassicalState(vec, 1);
108  REQUIRE_THROWS_WITH( collapseToOutcome(vec, 0, 0), Contains("Can't collapse to state with zero probability") );
109  }
110  }
111  destroyQureg(vec, QUEST_ENV);
112  destroyQureg(mat, QUEST_ENV);
113 }

References areEqual(), collapseToOutcome(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), initClassicalState(), initZeroState(), NUM_QUBITS, qcomp, qreal, QUEST_ENV, and toQureg().

◆ TEST_CASE() [13/88]

TEST_CASE ( "compactUnitary"  ,
""  [unitaries] 
)
See also
compactUnitary
Author
Tyson Jones

Definition at line 46 of file test_unitaries.cpp.

46  {
47 
48  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
49 
50  qcomp a = getRandomReal(-1,1) * expI(getRandomReal(0,2*M_PI));
51  qcomp b = sqrt(1-abs(a)*abs(a)) * expI(getRandomReal(0,2*M_PI));
52  Complex alpha = toComplex( a );
53  Complex beta = toComplex( b );
54  QMatrix op = toQMatrix(alpha, beta);
55 
56  SECTION( "correctness" ) {
57 
58  int target = GENERATE( range(0,NUM_QUBITS) );
59 
60  SECTION( "state-vector" ) {
61 
62  compactUnitary(quregVec, target, alpha, beta);
63  applyReferenceOp(refVec, target, op);
64  REQUIRE( areEqual(quregVec, refVec) );
65  }
66  SECTION( "density-matrix" ) {
67 
68  compactUnitary(quregMatr, target, alpha, beta);
69  applyReferenceOp(refMatr, target, op);
70  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
71  }
72  }
73  SECTION( "input validation" ) {
74 
75  SECTION( "qubit indices" ) {
76 
77  int target = GENERATE( -1, NUM_QUBITS );
78  REQUIRE_THROWS_WITH( compactUnitary(quregVec, target, alpha, beta), Contains("Invalid target") );
79  }
80  SECTION( "unitarity" ) {
81 
82  // unitary when |alpha|^2 + |beta|^2 = 1
83  alpha = {.real=1, .imag=2};
84  beta = {.real=3, .imag=4};
85  REQUIRE_THROWS_WITH( compactUnitary(quregVec, 0, alpha, beta), Contains("unitary") );
86  }
87  }
88  CLEANUP_TEST( quregVec, quregMatr );
89 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, compactUnitary(), expI(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, qcomp, Complex::real, toComplex, and toQMatrix().

◆ TEST_CASE() [14/88]

TEST_CASE ( "controlledCompactUnitary"  ,
""  [unitaries] 
)
See also
controlledCompactUnitary
Author
Tyson Jones

Definition at line 97 of file test_unitaries.cpp.

97  {
98 
99  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
100 
101  qcomp a = getRandomReal(-1,1) * expI(getRandomReal(0,2*M_PI));
102  qcomp b = sqrt(1-abs(a)*abs(a)) * expI(getRandomReal(0,2*M_PI));
103  Complex alpha = toComplex( a );
104  Complex beta = toComplex( b );
105  QMatrix op = toQMatrix(alpha, beta);
106 
107  SECTION( "correctness" ) {
108 
109  int target = GENERATE( range(0,NUM_QUBITS) );
110  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
111 
112  SECTION( "state-vector" ) {
113 
114  controlledCompactUnitary(quregVec, control, target, alpha, beta);
115  applyReferenceOp(refVec, control, target, op);
116  REQUIRE( areEqual(quregVec, refVec) );
117  }
118  SECTION( "density-matrix" ) {
119 
120  controlledCompactUnitary(quregMatr, control, target, alpha, beta);
121  applyReferenceOp(refMatr, control, target, op);
122  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
123  }
124  }
125  SECTION( "input validation" ) {
126 
127  SECTION( "control and target collision" ) {
128 
129  int qb = 0;
130  REQUIRE_THROWS_WITH( controlledCompactUnitary(quregVec, qb, qb, alpha, beta), Contains("Control") && Contains("target") );
131  }
132  SECTION( "qubit indices" ) {
133 
134  int qb = GENERATE( -1, NUM_QUBITS );
135  REQUIRE_THROWS_WITH( controlledCompactUnitary(quregVec, qb, 0, alpha, beta), Contains("Invalid control") );
136  REQUIRE_THROWS_WITH( controlledCompactUnitary(quregVec, 0, qb, alpha, beta), Contains("Invalid target") );
137  }
138  SECTION( "unitarity" ) {
139 
140  // unitary when |a|^2 + |b^2 = 1
141  alpha = {.real=1, .imag=2};
142  beta = {.real=3, .imag=4};
143  REQUIRE_THROWS_WITH( controlledCompactUnitary(quregVec, 0, 1, alpha, beta), Contains("unitary") );
144  }
145  }
146  CLEANUP_TEST( quregVec, quregMatr );
147 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledCompactUnitary(), expI(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, qcomp, Complex::real, toComplex, and toQMatrix().

◆ TEST_CASE() [15/88]

TEST_CASE ( "controlledMultiQubitUnitary"  ,
""  [unitaries] 
)
See also
controlledMultiQubitUnitary
Author
Tyson Jones

Definition at line 155 of file test_unitaries.cpp.

155  {
156 
157  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
158 
159  // figure out max-num targs (inclusive) allowed by hardware backend
160  int maxNumTargs = calcLog2(quregVec.numAmpsPerChunk);
161  if (maxNumTargs >= NUM_QUBITS)
162  maxNumTargs = NUM_QUBITS - 1; // make space for control qubit
163 
164  SECTION( "correctness" ) {
165 
166  // generate all possible qubit arrangements
167  int ctrl = GENERATE( range(0,NUM_QUBITS) );
168  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
169  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs, ctrl) );
170 
171  // for each qubit arrangement, use a new random unitary
172  QMatrix op = getRandomUnitary(numTargs);
173  ComplexMatrixN matr = createComplexMatrixN(numTargs);
174  toComplexMatrixN(op, matr);
175 
176  SECTION( "state-vector" ) {
177 
178  controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr);
179  applyReferenceOp(refVec, ctrl, targs, numTargs, op);
180  REQUIRE( areEqual(quregVec, refVec) );
181  }
182  SECTION( "density-matrix" ) {
183 
184  controlledMultiQubitUnitary(quregMatr, ctrl, targs, numTargs, matr);
185  applyReferenceOp(refMatr, ctrl, targs, numTargs, op);
186  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
187  }
188  destroyComplexMatrixN(matr);
189  }
190  SECTION( "input validation" ) {
191 
192  SECTION( "number of targets" ) {
193 
194  // there cannot be more targets than qubits in register
195  // (numTargs=NUM_QUBITS is caught elsewhere, because that implies ctrl is invalid)
196  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
197  int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
198  ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
199  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, 0, targs, numTargs, matr), Contains("Invalid number of target"));
200  destroyComplexMatrixN(matr);
201  }
202  SECTION( "repetition in targets" ) {
203 
204  int ctrl = 0;
205  int numTargs = 3;
206  int targs[] = {1,2,2};
207  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
208 
209  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr), Contains("target") && Contains("unique"));
210  destroyComplexMatrixN(matr);
211  }
212  SECTION( "control and target collision" ) {
213 
214  int numTargs = 3;
215  int targs[] = {0,1,2};
216  int ctrl = targs[GENERATE_COPY( range(0,numTargs) )];
217  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
218 
219  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr), Contains("Control") && Contains("target"));
220  destroyComplexMatrixN(matr);
221  }
222  SECTION( "qubit indices" ) {
223 
224  int ctrl = 0;
225  int numTargs = 3;
226  int targs[] = {1,2,3};
227  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
228 
229  int inv = GENERATE( -1, NUM_QUBITS );
230  ctrl = inv;
231  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr), Contains("Invalid control") );
232 
233  ctrl = 0; // restore valid ctrl
234  targs[GENERATE_COPY( range(0,numTargs) )] = inv; // make invalid target
235  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr), Contains("Invalid target") );
236 
237  destroyComplexMatrixN(matr);
238  }
239  SECTION( "unitarity" ) {
240 
241  int ctrl = 0;
242  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
243  ComplexMatrixN matr = createComplexMatrixN(numTargs); // initially zero, hence not-unitary
244 
245  int targs[numTargs];
246  for (int i=0; i<numTargs; i++)
247  targs[i] = i+1;
248 
249  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, numTargs, matr), Contains("unitary") );
250  destroyComplexMatrixN(matr);
251  }
252  SECTION( "unitary creation" ) {
253 
254  int numTargs = 3;
255  int targs[] = {1,2,3};
256 
257  /* compilers don't auto-initialise to NULL; the below circumstance
258  * only really occurs when 'malloc' returns NULL in createComplexMatrixN,
259  * which actually triggers its own validation. Hence this test is useless
260  * currently.
261  */
262  ComplexMatrixN matr;
263  matr.real = NULL;
264  matr.imag = NULL;
265  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, 0, targs, numTargs, matr), Contains("created") );
266  }
267  SECTION( "unitary dimensions" ) {
268 
269  int ctrl = 0;
270  int targs[2] = {1,2};
272 
273  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, ctrl, targs, 2, matr), Contains("matrix size"));
274  destroyComplexMatrixN(matr);
275  }
276  SECTION( "unitary fits in node" ) {
277 
278  // pretend we have a very limited distributed memory (judged by matr size)
279  quregVec.numAmpsPerChunk = 1;
280  int qb[] = {1,2};
281  ComplexMatrixN matr = createComplexMatrixN(2); // prevents seg-fault if validation doesn't trigger
282  REQUIRE_THROWS_WITH( controlledMultiQubitUnitary(quregVec, 0, qb, 2, matr), Contains("targets too many qubits"));
283  destroyComplexMatrixN(matr);
284  }
285  }
286  CLEANUP_TEST( quregVec, quregMatr );
287 }

References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, controlledMultiQubitUnitary(), createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

◆ TEST_CASE() [16/88]

TEST_CASE ( "controlledNot"  ,
""  [unitaries] 
)
See also
controlledNot
Author
Tyson Jones

Definition at line 295 of file test_unitaries.cpp.

295  {
296 
297  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
298  QMatrix op{{0,1},{1,0}};
299 
300  SECTION( "correctness" ) {
301 
302  int target = GENERATE( range(0,NUM_QUBITS) );
303  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
304 
305  SECTION( "state-vector" ) {
306 
307  controlledNot(quregVec, control, target);
308  applyReferenceOp(refVec, control, target, op);
309  REQUIRE( areEqual(quregVec, refVec) );
310  }
311  SECTION( "density-matrix" ) {
312 
313  controlledNot(quregMatr, control, target);
314  applyReferenceOp(refMatr, control, target, op);
315  REQUIRE( areEqual(quregMatr, refMatr) );
316  }
317  }
318  SECTION( "input validation" ) {
319 
320  SECTION( "control and target collision" ) {
321 
322  int qb = GENERATE( range(0,NUM_QUBITS) );
323  REQUIRE_THROWS_WITH( controlledNot(quregVec, qb, qb), Contains("Control") && Contains("target") );
324  }
325  SECTION( "qubit indices" ) {
326 
327  int qb = GENERATE( -1, NUM_QUBITS );
328  REQUIRE_THROWS_WITH( controlledNot(quregVec, qb, 0), Contains("Invalid control") );
329  REQUIRE_THROWS_WITH( controlledNot(quregVec, 0, qb), Contains("Invalid target") );
330  }
331  }
332  CLEANUP_TEST( quregVec, quregMatr );
333 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledNot(), NUM_QUBITS, and PREPARE_TEST.

◆ TEST_CASE() [17/88]

TEST_CASE ( "controlledPauliY"  ,
""  [unitaries] 
)
See also
controlledPauliY
Author
Tyson Jones

Definition at line 341 of file test_unitaries.cpp.

341  {
342 
343  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
344  QMatrix op{{0,-1i},{1i,0}};
345 
346  SECTION( "correctness" ) {
347 
348  int target = GENERATE( range(0,NUM_QUBITS) );
349  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
350 
351  SECTION( "state-vector" ) {
352 
353  controlledPauliY(quregVec, control, target);
354  applyReferenceOp(refVec, control, target, op);
355  REQUIRE( areEqual(quregVec, refVec) );
356  }
357  SECTION( "density-matrix" ) {
358 
359  controlledPauliY(quregMatr, control, target);
360  applyReferenceOp(refMatr, control, target, op);
361  REQUIRE( areEqual(quregMatr, refMatr) );
362  }
363  }
364  SECTION( "input validation" ) {
365 
366  SECTION( "control and target collision" ) {
367 
368  int qb = GENERATE( range(0,NUM_QUBITS) );
369  REQUIRE_THROWS_WITH( controlledPauliY(quregVec, qb, qb), Contains("Control") && Contains("target") );
370  }
371  SECTION( "qubit indices" ) {
372 
373  int qb = GENERATE( -1, NUM_QUBITS );
374  REQUIRE_THROWS_WITH( controlledPauliY(quregVec, qb, 0), Contains("Invalid control") );
375  REQUIRE_THROWS_WITH( controlledPauliY(quregVec, 0, qb), Contains("Invalid target") );
376  }
377  }
378  CLEANUP_TEST( quregVec, quregMatr );
379 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPauliY(), NUM_QUBITS, and PREPARE_TEST.

◆ TEST_CASE() [18/88]

TEST_CASE ( "controlledPhaseFlip"  ,
""  [unitaries] 
)
See also
controlledPhaseFlip
Author
Tyson Jones

Definition at line 387 of file test_unitaries.cpp.

387  {
388 
389  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
390  QMatrix op{{1,0},{0,-1}};
391 
392  SECTION( "correctness" ) {
393 
394  int target = GENERATE( range(0,NUM_QUBITS) );
395  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
396 
397  SECTION( "state-vector" ) {
398 
399  controlledPhaseFlip(quregVec, control, target);
400  applyReferenceOp(refVec, control, target, op);
401  REQUIRE( areEqual(quregVec, refVec) );
402  }
403  SECTION( "density-matrix" ) {
404 
405  controlledPhaseFlip(quregMatr, control, target);
406  applyReferenceOp(refMatr, control, target, op);
407  REQUIRE( areEqual(quregMatr, refMatr) );
408  }
409  }
410  SECTION( "input validation" ) {
411 
412  SECTION( "control and target collision" ) {
413 
414  int qb = GENERATE( range(0,NUM_QUBITS) );
415  REQUIRE_THROWS_WITH( controlledPhaseFlip(quregVec, qb, qb), Contains("Control") && Contains("target") );
416  }
417  SECTION( "qubit indices" ) {
418 
419  int qb = GENERATE( -1, NUM_QUBITS );
420  REQUIRE_THROWS_WITH( controlledPhaseFlip(quregVec, qb, 0), Contains("Invalid control") );
421  REQUIRE_THROWS_WITH( controlledPhaseFlip(quregVec, 0, qb), Contains("Invalid target") );
422  }
423  }
424  CLEANUP_TEST( quregVec, quregMatr );
425 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPhaseFlip(), NUM_QUBITS, and PREPARE_TEST.

◆ TEST_CASE() [19/88]

TEST_CASE ( "controlledPhaseShift"  ,
""  [unitaries] 
)
See also
controlledPhaseShift
Author
Tyson Jones

Definition at line 433 of file test_unitaries.cpp.

433  {
434 
435  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
436  qreal param = getRandomReal(-2*M_PI, 2*M_PI);
437  QMatrix op{{1,0},{0,expI(param)}};
438 
439  SECTION( "correctness" ) {
440 
441  int target = GENERATE( range(0,NUM_QUBITS) );
442  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
443 
444  SECTION( "state-vector" ) {
445 
446  controlledPhaseShift(quregVec, control, target, param);
447  applyReferenceOp(refVec, control, target, op);
448  REQUIRE( areEqual(quregVec, refVec) );
449  }
450  SECTION( "density-matrix" ) {
451 
452  controlledPhaseShift(quregMatr, control, target, param);
453  applyReferenceOp(refMatr, control, target, op);
454  REQUIRE( areEqual(quregMatr, refMatr) );
455  }
456  }
457  SECTION( "input validation" ) {
458 
459  SECTION( "control and target collision" ) {
460 
461  int qb = GENERATE( range(0,NUM_QUBITS) );
462  REQUIRE_THROWS_WITH( controlledPhaseShift(quregVec, qb, qb, param), Contains("Control") && Contains("target") );
463  }
464  SECTION( "qubit indices" ) {
465 
466  int qb = GENERATE( -1, NUM_QUBITS );
467  REQUIRE_THROWS_WITH( controlledPhaseShift(quregVec, qb, 0, param), Contains("Invalid control") );
468  REQUIRE_THROWS_WITH( controlledPhaseShift(quregVec, 0, qb, param), Contains("Invalid target") );
469  }
470  }
471  CLEANUP_TEST( quregVec, quregMatr );
472 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledPhaseShift(), expI(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, and qreal.

◆ TEST_CASE() [20/88]

TEST_CASE ( "controlledRotateAroundAxis"  ,
""  [unitaries] 
)
See also
controlledRotateAroundAxis
Author
Tyson Jones

Definition at line 480 of file test_unitaries.cpp.

480  {
481 
482  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
483 
484  // each test will use a random parameter and axis vector
485  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
486  Vector vec = {.x=getRandomReal(-1,1), .y=getRandomReal(-1,1), .z=getRandomReal(-1,1)};
487 
488  // Rn(a) = cos(a/2)I - i sin(a/2) n . paulivector
489  // (pg 24 of vcpc.univie.ac.at/~ian/hotlist/qc/talks/bloch-sphere-rotations.pdf)
490  qreal c = cos(param/2);
491  qreal s = sin(param/2);
492  qreal m = sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z);
493  QMatrix op{{c - 1i*vec.z*s/m, -(vec.y + 1i*vec.x)*s/m},
494  {(vec.y - 1i*vec.x)*s/m, c + 1i*vec.z*s/m}};
495 
496  SECTION( "correctness" ) {
497 
498  int target = GENERATE( range(0,NUM_QUBITS) );
499  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
500 
501  SECTION( "state-vector" ) {
502 
503  controlledRotateAroundAxis(quregVec, control, target, param, vec);
504  applyReferenceOp(refVec, control, target, op);
505  REQUIRE( areEqual(quregVec, refVec) );
506  }
507  SECTION( "density-matrix" ) {
508 
509  controlledRotateAroundAxis(quregMatr, control, target, param, vec);
510  applyReferenceOp(refMatr, control, target, op);
511  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
512  }
513  }
514  SECTION( "input validation" ) {
515 
516  SECTION( "control and target collision" ) {
517 
518  int qb = GENERATE( range(0,NUM_QUBITS) );
519  REQUIRE_THROWS_WITH( controlledRotateAroundAxis(quregVec, qb, qb, param, vec), Contains("Control") && Contains("target") );
520  }
521  SECTION( "qubit indices" ) {
522 
523  int qb = GENERATE( -1, NUM_QUBITS );
524  REQUIRE_THROWS_WITH( controlledRotateAroundAxis(quregVec, qb, 0, param, vec), Contains("Invalid control") );
525  REQUIRE_THROWS_WITH( controlledRotateAroundAxis(quregVec, 0, qb, param, vec), Contains("Invalid target") );
526  }
527  SECTION( "zero rotation axis" ) {
528 
529  vec = {.x=0, .y=0, .z=0};
530  REQUIRE_THROWS_WITH( controlledRotateAroundAxis(quregVec, 0, 1, param, vec), Contains("Invalid axis") && Contains("zero") );
531  }
532  }
533  CLEANUP_TEST( quregVec, quregMatr );
534 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateAroundAxis(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, qreal, Vector::x, Vector::y, and Vector::z.

◆ TEST_CASE() [21/88]

TEST_CASE ( "controlledRotateX"  ,
""  [unitaries] 
)
See also
controlledRotateX
Author
Tyson Jones

Definition at line 542 of file test_unitaries.cpp.

542  {
543 
544  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
545  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
546  QMatrix op{{cos(param/2), -1i*sin(param/2)}, {-1i*sin(param/2), cos(param/2)}};
547 
548  SECTION( "correctness" ) {
549 
550  int target = GENERATE( range(0,NUM_QUBITS) );
551  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
552 
553  SECTION( "state-vector" ) {
554 
555  controlledRotateX(quregVec, control, target, param);
556  applyReferenceOp(refVec, control, target, op);
557  REQUIRE( areEqual(quregVec, refVec) );
558  }
559  SECTION( "density-matrix" ) {
560 
561  controlledRotateX(quregMatr, control, target, param);
562  applyReferenceOp(refMatr, control, target, op);
563  REQUIRE( areEqual(quregMatr, refMatr) );
564  }
565  }
566  SECTION( "input validation" ) {
567 
568  SECTION( "control and target collision" ) {
569 
570  int qb = GENERATE( range(0,NUM_QUBITS) );
571  REQUIRE_THROWS_WITH( controlledRotateX(quregVec, qb, qb, param), Contains("Control") && Contains("target") );
572  }
573  SECTION( "qubit indices" ) {
574 
575  int qb = GENERATE( -1, NUM_QUBITS );
576  REQUIRE_THROWS_WITH( controlledRotateX(quregVec, qb, 0, param), Contains("Invalid control") );
577  REQUIRE_THROWS_WITH( controlledRotateX(quregVec, 0, qb, param), Contains("Invalid target") );
578  }
579  }
580  CLEANUP_TEST( quregVec, quregMatr );
581 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateX(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, and qreal.

◆ TEST_CASE() [22/88]

TEST_CASE ( "controlledRotateY"  ,
""  [unitaries] 
)
See also
controlledRotateY
Author
Tyson Jones

Definition at line 589 of file test_unitaries.cpp.

589  {
590 
591  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
592  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
593  QMatrix op{{cos(param/2), -sin(param/2)},{sin(param/2), cos(param/2)}};
594 
595  SECTION( "correctness" ) {
596 
597  int target = GENERATE( range(0,NUM_QUBITS) );
598  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
599 
600  SECTION( "state-vector" ) {
601 
602  controlledRotateY(quregVec, control, target, param);
603  applyReferenceOp(refVec, control, target, op);
604  REQUIRE( areEqual(quregVec, refVec) );
605  }
606  SECTION( "density-matrix" ) {
607 
608  controlledRotateY(quregMatr, control, target, param);
609  applyReferenceOp(refMatr, control, target, op);
610  REQUIRE( areEqual(quregMatr, refMatr, 2*REAL_EPS) );
611  }
612  }
613  SECTION( "input validation" ) {
614 
615  SECTION( "control and target collision" ) {
616 
617  int qb = GENERATE( range(0,NUM_QUBITS) );
618  REQUIRE_THROWS_WITH( controlledRotateY(quregVec, qb, qb, param), Contains("Control") && Contains("target") );
619  }
620  SECTION( "qubit indices" ) {
621 
622  int qb = GENERATE( -1, NUM_QUBITS );
623  REQUIRE_THROWS_WITH( controlledRotateY(quregVec, qb, 0, param), Contains("Invalid control") );
624  REQUIRE_THROWS_WITH( controlledRotateY(quregVec, 0, qb, param), Contains("Invalid target") );
625  }
626  }
627  CLEANUP_TEST( quregVec, quregMatr );
628 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateY(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, and qreal.

◆ TEST_CASE() [23/88]

TEST_CASE ( "controlledRotateZ"  ,
""  [unitaries] 
)
See also
controlledRotateZ
Author
Tyson Jones

Definition at line 636 of file test_unitaries.cpp.

636  {
637 
638  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
639  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
640  QMatrix op{{expI(-param/2.),0},{0,expI(param/2.)}};
641 
642  SECTION( "correctness" ) {
643 
644  int target = GENERATE( range(0,NUM_QUBITS) );
645  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
646 
647  SECTION( "state-vector" ) {
648 
649  controlledRotateZ(quregVec, control, target, param);
650  applyReferenceOp(refVec, control, target, op);
651  REQUIRE( areEqual(quregVec, refVec) );
652  }
653  SECTION( "density-matrix" ) {
654 
655  controlledRotateZ(quregMatr, control, target, param);
656  applyReferenceOp(refMatr, control, target, op);
657  REQUIRE( areEqual(quregMatr, refMatr) );
658  }
659  }
660  SECTION( "input validation" ) {
661 
662  SECTION( "control and target collision" ) {
663 
664  int qb = GENERATE( range(0,NUM_QUBITS) );
665  REQUIRE_THROWS_WITH( controlledRotateZ(quregVec, qb, qb, param), Contains("Control") && Contains("target") );
666  }
667  SECTION( "qubit indices" ) {
668 
669  int qb = GENERATE( -1, NUM_QUBITS );
670  REQUIRE_THROWS_WITH( controlledRotateZ(quregVec, qb, 0, param), Contains("Invalid control") );
671  REQUIRE_THROWS_WITH( controlledRotateZ(quregVec, 0, qb, param), Contains("Invalid target") );
672  }
673  }
674  CLEANUP_TEST( quregVec, quregMatr );
675 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledRotateZ(), expI(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, and qreal.

◆ TEST_CASE() [24/88]

TEST_CASE ( "controlledTwoQubitUnitary"  ,
""  [unitaries] 
)
See also
controlledTwoQubitUnitary
Author
Tyson Jones

Definition at line 683 of file test_unitaries.cpp.

683  {
684 
685  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
686 
687  // in distributed mode, each node must be able to fit all amps modified by unitary
688  REQUIRE( quregVec.numAmpsPerChunk >= 4 );
689 
690  // every test will use a unique random matrix
691  QMatrix op = getRandomUnitary(2);
692  ComplexMatrix4 matr = toComplexMatrix4(op);
693 
694  SECTION( "correctness" ) {
695 
696  int targ1 = GENERATE( range(0,NUM_QUBITS) );
697  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
698  int control = GENERATE_COPY( filter([=](int c){ return c!=targ1 && c!=targ2; }, range(0,NUM_QUBITS)) );
699 
700  SECTION( "state-vector" ) {
701 
702  controlledTwoQubitUnitary(quregVec, control, targ1, targ2, matr);
703  applyReferenceOp(refVec, control, targ1, targ2, op);
704  REQUIRE( areEqual(quregVec, refVec) );
705  }
706  SECTION( "density-matrix" ) {
707 
708  controlledTwoQubitUnitary(quregMatr, control, targ1, targ2, matr);
709  applyReferenceOp(refMatr, control, targ1, targ2, op);
710  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
711  }
712  }
713  SECTION( "input validation" ) {
714 
715  SECTION( "repetition of targets" ) {
716  int targ = 0;
717  int ctrl = 1;
718  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, ctrl, targ, targ, matr), Contains("target") && Contains("unique") );
719  }
720  SECTION( "control and target collision" ) {
721 
722  int targ1 = 1;
723  int targ2 = 2;
724  int ctrl = GENERATE( 1,2 ); // catch2 bug; can't do GENERATE_COPY( targ1, targ2 )
725  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, ctrl, targ1, targ2, matr), Contains("Control") && Contains("target") );
726  }
727  SECTION( "qubit indices" ) {
728 
729  // valid config
730  int ctrl = 0;
731  int targ1 = 1;
732  int targ2 = 2;
733 
734  int qb = GENERATE( -1, NUM_QUBITS );
735  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, qb, targ1, targ2, matr), Contains("Invalid control") );
736  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, ctrl, qb, targ2, matr), Contains("Invalid target") );
737  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, ctrl, targ1, qb, matr), Contains("Invalid target") );
738  }
739  SECTION( "unitarity" ) {
740 
741  matr.real[0][0] = 0; // break matr unitarity
742  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, 0, 1, 2, matr), Contains("unitary") );
743  }
744  SECTION( "unitary fits in node" ) {
745 
746  // pretend we have a very limited distributed memory
747  quregVec.numAmpsPerChunk = 1;
748  REQUIRE_THROWS_WITH( controlledTwoQubitUnitary(quregVec, 0, 1, 2, matr), Contains("targets too many qubits"));
749  }
750  }
751  CLEANUP_TEST( quregVec, quregMatr );
752 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledTwoQubitUnitary(), getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, and toComplexMatrix4().

◆ TEST_CASE() [25/88]

TEST_CASE ( "controlledUnitary"  ,
""  [unitaries] 
)
See also
controlledUnitary
Author
Tyson Jones

Definition at line 760 of file test_unitaries.cpp.

760  {
761 
762  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
763  QMatrix op = getRandomUnitary(1);
764  ComplexMatrix2 matr = toComplexMatrix2(op);
765 
766  SECTION( "correctness" ) {
767 
768  int target = GENERATE( range(0,NUM_QUBITS) );
769  int control = GENERATE_COPY( filter([=](int c){ return c!=target; }, range(0,NUM_QUBITS)) );
770 
771  SECTION( "state-vector" ) {
772 
773  controlledUnitary(quregVec, control, target, matr);
774  applyReferenceOp(refVec, control, target, op);
775  REQUIRE( areEqual(quregVec, refVec) );
776  }
777  SECTION( "density-matrix" ) {
778 
779  controlledUnitary(quregMatr, control, target, matr);
780  applyReferenceOp(refMatr, control, target, op);
781  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
782  }
783  }
784  SECTION( "input validation" ) {
785 
786  SECTION( "control and target collision" ) {
787 
788  int qb = GENERATE( range(0,NUM_QUBITS) );
789  REQUIRE_THROWS_WITH( controlledUnitary(quregVec, qb, qb, matr), Contains("Control") && Contains("target") );
790  }
791  SECTION( "qubit indices" ) {
792 
793  int qb = GENERATE( -1, NUM_QUBITS );
794  REQUIRE_THROWS_WITH( controlledUnitary(quregVec, qb, 0, matr), Contains("Invalid control") );
795  REQUIRE_THROWS_WITH( controlledUnitary(quregVec, 0, qb, matr), Contains("Invalid target") );
796  }
797  SECTION( "unitarity" ) {
798 
799  matr.real[0][0] = 0; // break unitarity
800  REQUIRE_THROWS_WITH( controlledUnitary(quregVec, 0, 1, matr), Contains("unitary") );
801  }
802  }
803  CLEANUP_TEST( quregVec, quregMatr );
804 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, controlledUnitary(), getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, and toComplexMatrix2().

◆ TEST_CASE() [26/88]

TEST_CASE ( "createCloneQureg"  ,
""  [data_structures] 
)
See also
createCloneQureg
Author
Tyson Jones

Definition at line 57 of file test_data_structures.cpp.

57  {
58 
59  SECTION( "state-vector" ) {
60 
63 
64  // check properties are the same
65  REQUIRE( b.isDensityMatrix == a.isDensityMatrix );
67  REQUIRE( b.numQubitsInStateVec == a.numQubitsInStateVec );
68  REQUIRE( b.numAmpsPerChunk == a.numAmpsPerChunk );
69  REQUIRE( b.numAmpsTotal == a.numAmpsTotal );
70 
71  // check state-vector is the same (works for GPU and distributed)
72  REQUIRE( areEqual(a, b) );
73 
76  }
77  SECTION( "density-matrix" ) {
78 
81 
82  // check properties are the same
83  REQUIRE( b.isDensityMatrix == a.isDensityMatrix );
85  REQUIRE( b.numQubitsInStateVec == a.numQubitsInStateVec );
86  REQUIRE( b.numAmpsPerChunk == a.numAmpsPerChunk );
87  REQUIRE( b.numAmpsTotal == a.numAmpsTotal );
88 
89  // check state-vector is the same (works for GPU and distributed)
90  REQUIRE( areEqual(a, b) );
91 
94  }
95 }

References areEqual(), createCloneQureg(), createDensityQureg(), createQureg(), destroyQureg(), Qureg::isDensityMatrix, NUM_QUBITS, Qureg::numAmpsPerChunk, Qureg::numAmpsTotal, Qureg::numQubitsInStateVec, Qureg::numQubitsRepresented, and QUEST_ENV.

◆ TEST_CASE() [27/88]

TEST_CASE ( "createComplexMatrixN"  ,
""  [data_structures] 
)
See also
createComplexMatrixN
Author
Tyson Jones

Definition at line 103 of file test_data_structures.cpp.

103  {
104 
105  SECTION( "correctness" ) {
106 
107  int numQb = GENERATE( range(1,10+1) );
109 
110  // ensure elems are created and initialised to 0
111  REQUIRE( areEqual(toQMatrix(m), getZeroMatrix(1<<numQb)) );
112 
114  }
115  SECTION( "input validation" ) {
116 
117  SECTION( "number of qubits" ) {
118 
119  int numQb = GENERATE( -1, 0 );
120  REQUIRE_THROWS_WITH( createComplexMatrixN(numQb), Contains("Invalid number of qubits") );
121  }
122  }
123 }

References areEqual(), createComplexMatrixN(), destroyComplexMatrixN(), getZeroMatrix(), and toQMatrix().

◆ TEST_CASE() [28/88]

TEST_CASE ( "createDensityQureg"  ,
""  [data_structures] 
)
See also
createDensityQureg
Author
Tyson Jones

Definition at line 131 of file test_data_structures.cpp.

131  {
132 
133  // must be at least one amplitude per node
134  int minNumQb = calcLog2(QUEST_ENV.numRanks) - 1; // density matrix has 2*numQb in state-vec
135  if (minNumQb <= 0)
136  minNumQb = 1;
137 
138  SECTION( "correctness" ) {
139 
140  // try 10 valid number of qubits
141  int numQb = GENERATE_COPY( range(minNumQb, minNumQb+10) );
142  Qureg reg = createDensityQureg(numQb, QUEST_ENV);
143 
144  // ensure elems (CPU and/or GPU) are created, and reg begins in |0><0|
145  QMatrix ref = getZeroMatrix(1<<numQb);
146  ref[0][0] = 1; // |0><0|
147  REQUIRE( areEqual(reg, ref) );
148 
149  destroyQureg(reg, QUEST_ENV);
150  }
151  SECTION( "input validation") {
152 
153  SECTION( "number of qubits" ) {
154 
155  int numQb = GENERATE( -1, 0 );
156  REQUIRE_THROWS_WITH( createDensityQureg(numQb, QUEST_ENV), Contains("Invalid number of qubits") );
157  }
158  SECTION( "number of amplitudes" ) {
159 
160  // use local QuESTEnv to safely modify
161  QuESTEnv env = QUEST_ENV;
162 
163  // too many amplitudes to store in type
164  int maxQb = (int) calcLog2(SIZE_MAX) - 1;
165  REQUIRE_THROWS_WITH( createDensityQureg(maxQb+1, env), Contains("Too many qubits") && Contains("size_t type") );
166 
167  /* n-qubit density matrix contains 2^(2n) amplitudes
168  * so can be spread between at most 2^(2n) ranks
169  */
170  int minQb = GENERATE( range(3,10) );
171  env.numRanks = (int) pow(2, 2*minQb);
172  int numQb = GENERATE_COPY( range(1,minQb) );
173  REQUIRE_THROWS_WITH( createDensityQureg(numQb, env), Contains("Too few qubits") );
174  }
175  SECTION( "available memory" ) {
176 
177  /* there is no reliable way to force the malloc statements to
178  * fail, and hence trigger the matrixInit validation */
179  SUCCEED( );
180  }
181  }
182 }

References areEqual(), calcLog2(), createDensityQureg(), destroyQureg(), getZeroMatrix(), QuESTEnv::numRanks, and QUEST_ENV.

◆ TEST_CASE() [29/88]

TEST_CASE ( "createQuESTEnv"  ,
""  [data_structures] 
)
See also
createQuESTEnv
Author
Tyson Jones

Definition at line 190 of file test_data_structures.cpp.

190  {
191 
192  /* there is no meaningful way to test this */
193  SUCCEED( );
194 }

◆ TEST_CASE() [30/88]

TEST_CASE ( "createQureg"  ,
""  [data_structures] 
)
See also
createQureg
Author
Tyson Jones

Definition at line 202 of file test_data_structures.cpp.

202  {
203 
204  // must be at least one amplitude per node
205  int minNumQb = calcLog2(QUEST_ENV.numRanks);
206  if (minNumQb == 0)
207  minNumQb = 1;
208 
209  SECTION( "correctness" ) {
210 
211  // try 10 valid number of qubits
212  int numQb = GENERATE_COPY( range(minNumQb, minNumQb+10) );
213  Qureg reg = createQureg(numQb, QUEST_ENV);
214 
215  // ensure elems (CPU and/or GPU) are created, and reg begins in |0>
216  QVector ref = QVector(1<<numQb);
217  ref[0] = 1; // |0>
218  REQUIRE( areEqual(reg, ref) );
219 
220  destroyQureg(reg, QUEST_ENV);
221  }
222  SECTION( "input validation") {
223 
224  SECTION( "number of qubits" ) {
225 
226  int numQb = GENERATE( -1, 0 );
227  REQUIRE_THROWS_WITH( createQureg(numQb, QUEST_ENV), Contains("Invalid number of qubits") );
228  }
229  SECTION( "number of amplitudes" ) {
230 
231  // use local QuESTEnv to safely modify
232  QuESTEnv env = QUEST_ENV;
233 
234  // too many amplitudes to store in type
235  int maxQb = (int) calcLog2(SIZE_MAX);
236  REQUIRE_THROWS_WITH( createQureg(maxQb+1, env), Contains("Too many qubits") && Contains("size_t type") );
237 
238  // too few amplitudes to distribute
239  int minQb = GENERATE( range(2,10) );
240  env.numRanks = (int) pow(2, minQb);
241  int numQb = GENERATE_COPY( range(1,minQb) );
242  REQUIRE_THROWS_WITH( createQureg(numQb, env), Contains("Too few qubits") );
243  }
244  SECTION( "available memory" ) {
245 
246  /* there is no reliable way to force the malloc statements to
247  * fail, and hence trigger the matrixInit validation */
248  SUCCEED( );
249  }
250  }
251 }

References areEqual(), calcLog2(), createQureg(), destroyQureg(), QuESTEnv::numRanks, and QUEST_ENV.

◆ TEST_CASE() [31/88]

TEST_CASE ( "destroyComplexMatrixN"  ,
""  [data_structures] 
)
See also
destroyComplexMatrixN
Author
Tyson Jones

Definition at line 259 of file test_data_structures.cpp.

259  {
260 
261  SECTION( "correctness" ) {
262 
263  /* there is no meaningful way to test this */
264  SUCCEED( );
265  }
266  SECTION( "input validation" ) {
267 
268  SECTION( "matrix not created" ) {
269 
270  /* this is an artificial test case since nothing in the QuEST API
271  * automatically sets un-initialised ComplexMatrixN fields to
272  * the NULL pointer.
273  */
274  ComplexMatrixN m;
275  m.real = NULL;
276 
277  /* the error message is also somewhat unrelated, but oh well
278  */
279  REQUIRE_THROWS_WITH( destroyComplexMatrixN(m), Contains("The ComplexMatrixN was not successfully created") );
280  }
281  }
282 }

References destroyComplexMatrixN(), and ComplexMatrixN::real.

◆ TEST_CASE() [32/88]

TEST_CASE ( "destroyQuESTEnv"  ,
""  [data_structures] 
)
See also
destroyQuESTEnv
Author
Tyson Jones

Definition at line 290 of file test_data_structures.cpp.

290  {
291 
292  /* there is no meaningful way to test this */
293  SUCCEED( );
294 }

◆ TEST_CASE() [33/88]

TEST_CASE ( "destroyQureg"  ,
""  [data_structures] 
)
See also
destroyQureg
Author
Tyson Jones

Definition at line 302 of file test_data_structures.cpp.

302  {
303 
304  /* there is no meaningful way to test this.
305  * We e.g. cannot check that the pointers are NULL because
306  * they are not updated; this function passes the struct by value,
307  * not by reference. We also cannot reliably monitor the
308  * memory used in the heap at runtime.
309  */
310  SUCCEED( );
311 }

◆ TEST_CASE() [34/88]

TEST_CASE ( "fromComplex"  ,
""  [data_structures] 
)
See also
fromComplex
Author
Tyson Jones

Definition at line 15 of file test_data_structures.cpp.

15  {
16 
17  Complex a = {.real=.5, .imag=-.2};
18  qcomp b = fromComplex(a);
19 
20  REQUIRE( a.real == real(b) );
21  REQUIRE( a.imag == imag(b) );
22 }

References fromComplex, Complex::imag, qcomp, and Complex::real.

◆ TEST_CASE() [35/88]

TEST_CASE ( "getAmp"  ,
""  [calculations] 
)
See also
getAmp
Author
Tyson Jones

Definition at line 978 of file test_calculations.cpp.

978  {
979 
981 
982  SECTION( "correctness" ) {
983 
984  SECTION( "state-vector" ) {
985 
986  initDebugState(vec);
987  QVector ref = toQVector(vec);
988 
989  int ind = GENERATE( range(0,1<<NUM_QUBITS) );
990  Complex amp = getAmp(vec,ind);
991  REQUIRE( fromComplex(amp) == ref[ind] );
992  }
993  }
994  SECTION( "input validation" ) {
995 
996  SECTION( "state index" ) {
997 
998  int ind = GENERATE( -1, 1<<NUM_QUBITS );
999  REQUIRE_THROWS_WITH( getAmp(vec,ind), Contains("Invalid amplitude index") );
1000  }
1001  SECTION( "density-matrix" ) {
1002 
1004  REQUIRE_THROWS_WITH( getAmp(mat,0), Contains("valid only for state-vectors") );
1005  destroyQureg(mat, QUEST_ENV);
1006  }
1007  }
1008  destroyQureg(vec, QUEST_ENV);
1009 }

References createDensityQureg(), createQureg(), destroyQureg(), fromComplex, getAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

◆ TEST_CASE() [36/88]

TEST_CASE ( "getDensityAmp"  ,
""  [calculations] 
)
See also
getDensityAmp
Author
Tyson Jones

Definition at line 1017 of file test_calculations.cpp.

1017  {
1018 
1020 
1021  SECTION( "correctness" ) {
1022 
1023  SECTION( "density-matrix" ) {
1024 
1025  initDebugState(mat);
1026  QMatrix ref = toQMatrix(mat);
1027 
1028  int row = GENERATE( range(0,1<<NUM_QUBITS) );
1029  int col = GENERATE( range(0,1<<NUM_QUBITS) );
1030 
1031  Complex amp = getDensityAmp(mat,row,col);
1032  REQUIRE( fromComplex(amp) == ref[row][col] );
1033  }
1034  }
1035  SECTION( "input validation" ) {
1036 
1037  SECTION( "state index" ) {
1038 
1039  int ind = GENERATE( -1, 1<<NUM_QUBITS );
1040  REQUIRE_THROWS_WITH( getDensityAmp(mat,ind,0), Contains("Invalid amplitude index") );
1041  REQUIRE_THROWS_WITH( getDensityAmp(mat,0,ind), Contains("Invalid amplitude index") );
1042 
1043  }
1044  SECTION( "state-vector" ) {
1045 
1047  REQUIRE_THROWS_WITH( getDensityAmp(vec,0,0), Contains("valid only for density matrices") );
1048  destroyQureg(vec, QUEST_ENV);
1049  }
1050  }
1051  destroyQureg(mat, QUEST_ENV);
1052 }

References createDensityQureg(), createQureg(), destroyQureg(), fromComplex, getDensityAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQMatrix().

◆ TEST_CASE() [37/88]

TEST_CASE ( "getImagAmp"  ,
""  [calculations] 
)
See also
getImagAmp
Author
Tyson Jones

Definition at line 1060 of file test_calculations.cpp.

1060  {
1061 
1063 
1064  SECTION( "correctness" ) {
1065 
1066  SECTION( "state-vector" ) {
1067 
1068  initDebugState(vec);
1069  QVector ref = toQVector(vec);
1070 
1071  int ind = GENERATE( range(0,1<<NUM_QUBITS) );
1072  REQUIRE( getImagAmp(vec,ind) == imag(ref[ind]) );
1073  }
1074  }
1075  SECTION( "input validation" ) {
1076 
1077  SECTION( "state index" ) {
1078 
1079  int ind = GENERATE( -1, 1<<NUM_QUBITS );
1080  REQUIRE_THROWS_WITH( getImagAmp(vec,ind), Contains("Invalid amplitude index") );
1081  }
1082  SECTION( "density-matrix" ) {
1083 
1085  REQUIRE_THROWS_WITH( getImagAmp(mat,0), Contains("valid only for state-vectors") );
1086  destroyQureg(mat, QUEST_ENV);
1087  }
1088  }
1089  destroyQureg(vec, QUEST_ENV);
1090 }

References createDensityQureg(), createQureg(), destroyQureg(), getImagAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

◆ TEST_CASE() [38/88]

TEST_CASE ( "getNumAmps"  ,
""  [calculations] 
)
See also
getNumAmps
Author
Tyson Jones

Definition at line 1098 of file test_calculations.cpp.

1098  {
1099 
1100  SECTION( "correctness" ) {
1101 
1102  // test >= NUM_QUBITS so as not to limit distribution size
1103  int numQb = GENERATE( range(NUM_QUBITS, NUM_QUBITS+10) );
1104 
1105  SECTION( "state-vector" ) {
1106 
1107  Qureg vec = createQureg(numQb, QUEST_ENV);
1108  REQUIRE( getNumAmps(vec) == (1<<numQb) );
1109  destroyQureg(vec, QUEST_ENV);
1110  }
1111  }
1112  SECTION( "input validation" ) {
1113 
1114  SECTION( "density-matrix" ) {
1116  REQUIRE_THROWS_WITH( getNumAmps(mat), Contains("valid only for state-vectors") );
1117  destroyQureg(mat, QUEST_ENV);
1118  }
1119  }
1120 }

References createDensityQureg(), createQureg(), destroyQureg(), getNumAmps(), NUM_QUBITS, and QUEST_ENV.

◆ TEST_CASE() [39/88]

TEST_CASE ( "getNumQubits"  ,
""  [calculations] 
)
See also
getNumQubits
Author
Tyson Jones

Definition at line 1128 of file test_calculations.cpp.

1128  {
1129 
1130  SECTION( "correctness" ) {
1131 
1132  // test >= NUM_QUBITS so as not to limit distribution size
1133  int numQb = GENERATE( range(NUM_QUBITS, NUM_QUBITS+10) );
1134 
1135  SECTION( "state-vector" ) {
1136 
1137  Qureg vec = createQureg(numQb, QUEST_ENV);
1138  REQUIRE( getNumQubits(vec) == numQb );
1139  destroyQureg(vec, QUEST_ENV);
1140  }
1141  SECTION( "density-matrix" ) {
1142 
1143  Qureg mat = createDensityQureg(numQb, QUEST_ENV);
1144  REQUIRE( getNumQubits(mat) == numQb );
1145  destroyQureg(mat, QUEST_ENV);
1146  }
1147  }
1148  SECTION( "input validation" ) {
1149 
1150  // no validation
1151  SUCCEED();
1152  }
1153 }

References createDensityQureg(), createQureg(), destroyQureg(), getNumQubits(), NUM_QUBITS, and QUEST_ENV.

◆ TEST_CASE() [40/88]

TEST_CASE ( "getProbAmp"  ,
""  [calculations] 
)
See also
getProbAmp
Author
Tyson Jones

Definition at line 1161 of file test_calculations.cpp.

1161  {
1162 
1164 
1165  SECTION( "correctness" ) {
1166 
1167  SECTION( "state-vector" ) {
1168 
1169  initDebugState(vec);
1170  QVector ref = toQVector(vec);
1171 
1172  int ind = GENERATE( range(0,1<<NUM_QUBITS) );
1173  qreal refCalc = pow(abs(ref[ind]), 2);
1174  REQUIRE( getProbAmp(vec,ind) == Approx(refCalc) );
1175  }
1176  }
1177  SECTION( "input validation" ) {
1178 
1179  SECTION( "state index" ) {
1180 
1181  int ind = GENERATE( -1, 1<<NUM_QUBITS );
1182  REQUIRE_THROWS_WITH( getProbAmp(vec,ind), Contains("Invalid amplitude index") );
1183  }
1184  SECTION( "density-matrix" ) {
1185 
1187  REQUIRE_THROWS_WITH( getProbAmp(mat,0), Contains("valid only for state-vectors") );
1188  destroyQureg(mat, QUEST_ENV);
1189  }
1190  }
1191  destroyQureg(vec, QUEST_ENV);
1192 }

References createDensityQureg(), createQureg(), destroyQureg(), getProbAmp(), initDebugState(), NUM_QUBITS, qreal, QUEST_ENV, and toQVector().

◆ TEST_CASE() [41/88]

TEST_CASE ( "getRealAmp"  ,
""  [calculations] 
)
See also
getRealAmp
Author
Tyson Jones

Definition at line 1200 of file test_calculations.cpp.

1200  {
1201 
1203 
1204  SECTION( "correctness" ) {
1205 
1206  SECTION( "state-vector" ) {
1207 
1208  initDebugState(vec);
1209  QVector ref = toQVector(vec);
1210 
1211  int ind = GENERATE( range(0,1<<NUM_QUBITS) );
1212  REQUIRE( getRealAmp(vec,ind) == real(ref[ind]) );
1213  }
1214  }
1215  SECTION( "input validation" ) {
1216 
1217  SECTION( "state index" ) {
1218 
1219  int ind = GENERATE( -1, 1<<NUM_QUBITS );
1220  REQUIRE_THROWS_WITH( getRealAmp(vec,ind), Contains("Invalid amplitude index") );
1221  }
1222  SECTION( "density-matrix" ) {
1223 
1225  REQUIRE_THROWS_WITH( getRealAmp(mat,0), Contains("valid only for state-vectors") );
1226  destroyQureg(mat, QUEST_ENV);
1227  }
1228  }
1229  destroyQureg(vec, QUEST_ENV);
1230 }

References createDensityQureg(), createQureg(), destroyQureg(), getRealAmp(), initDebugState(), NUM_QUBITS, QUEST_ENV, and toQVector().

◆ TEST_CASE() [42/88]

TEST_CASE ( "getStaticComplexMatrixN"  ,
""  [data_structures] 
)
See also
getStaticComplexMatrixN
Author
Tyson Jones

Definition at line 30 of file test_data_structures.cpp.

30  {
31 
32  /* use of this function is illegal in C++ */
33  SUCCEED( );
34 }

◆ TEST_CASE() [43/88]

TEST_CASE ( "hadamard"  ,
""  [unitaries] 
)
See also
hadamard
Author
Tyson Jones

Definition at line 812 of file test_unitaries.cpp.

812  {
813 
814  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
815  qreal a = 1/sqrt(2);
816  QMatrix op{{a,a},{a,-a}};
817 
818  SECTION( "correctness" ) {
819 
820  int target = GENERATE( range(0,NUM_QUBITS) );
821 
822  SECTION( "state-vector ") {
823 
824  hadamard(quregVec, target);
825  applyReferenceOp(refVec, target, op);
826  REQUIRE( areEqual(quregVec, refVec) );
827  }
828  SECTION( "density-matrix" ) {
829 
830  hadamard(quregMatr, target);
831  applyReferenceOp(refMatr, target, op);
832  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
833  }
834  }
835  SECTION( "input validation" ) {
836 
837  SECTION( "qubit indices" ) {
838 
839  int target = GENERATE( -1, NUM_QUBITS );
840  REQUIRE_THROWS_WITH( hadamard(quregVec, target), Contains("Invalid target") );
841  }
842  }
843  CLEANUP_TEST( quregVec, quregMatr );
844 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, hadamard(), NUM_QUBITS, PREPARE_TEST, and qreal.

◆ TEST_CASE() [44/88]

TEST_CASE ( "initBlankState"  ,
""  [state_initialisations] 
)
See also
initBlankState
Author
Tyson Jones

Definition at line 90 of file test_state_initialisations.cpp.

90  {
91 
94 
95  SECTION( "correctness" ) {
96 
97  SECTION( "state-vector" ) {
98 
99  initBlankState(vec);
100  REQUIRE( areEqual(vec, QVector(1<<NUM_QUBITS)) );
101  }
102  SECTION( "density-matrix" ) {
103 
104  initBlankState(mat);
105  REQUIRE( areEqual(mat, getZeroMatrix(1<<NUM_QUBITS)) );
106  }
107  }
108  SECTION( "input validation" ) {
109 
110  // no user validation
111  SUCCEED( );
112  }
113  destroyQureg(vec, QUEST_ENV);
114  destroyQureg(mat, QUEST_ENV);
115 }

References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getZeroMatrix(), initBlankState(), NUM_QUBITS, and QUEST_ENV.

◆ TEST_CASE() [45/88]

TEST_CASE ( "initClassicalState"  ,
""  [state_initialisations] 
)
See also
initClassicalState
Author
Tyson Jones

Definition at line 123 of file test_state_initialisations.cpp.

123  {
124 
127 
128  SECTION( "correctness" ) {
129 
130  int numInds = (1<<NUM_QUBITS);
131  int ind = GENERATE_COPY( range(0,numInds) );
132 
133  SECTION( "state-vector" ) {
134 
135  initClassicalState(vec, ind);
136  QVector vecRef = QVector(1<<NUM_QUBITS);
137  vecRef[ind] = 1;
138  REQUIRE( areEqual(vec, vecRef) );
139  }
140  SECTION( "density-matrix" ) {
141 
142  initClassicalState(mat, ind);
143  QMatrix matRef = getZeroMatrix(1<<NUM_QUBITS);
144  matRef[ind][ind] = 1;
145  REQUIRE( areEqual(mat, matRef) );
146  }
147  }
148  SECTION( "input validation" ) {
149 
150  SECTION( "state index" ) {
151 
152  int ind = GENERATE( -1, (1<<NUM_QUBITS) );
153  REQUIRE_THROWS_WITH( initClassicalState(vec, ind), Contains("Invalid state index") );
154  }
155  }
156  destroyQureg(vec, QUEST_ENV);
157  destroyQureg(mat, QUEST_ENV);
158 }

References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getZeroMatrix(), initClassicalState(), NUM_QUBITS, and QUEST_ENV.

◆ TEST_CASE() [46/88]

TEST_CASE ( "initComplexMatrixN"  ,
""  [data_structures] 
)
See also
initComplexMatrixN
Author
Tyson Jones

Definition at line 319 of file test_data_structures.cpp.

319  {
320 
321  /* use of this function is illegal in C++ */
322  SUCCEED( );
323 }

◆ TEST_CASE() [47/88]

TEST_CASE ( "initPlusState"  ,
""  [state_initialisations] 
)
See also
initPlusState
Author
Tyson Jones

Definition at line 166 of file test_state_initialisations.cpp.

166  {
167 
170 
171  SECTION( "correctness" ) {
172 
173  SECTION( "state-vector" ) {
174 
175  // |+> = 1/sqrt(N^2) sum_i |i>
176  // = 1/sqrt(N^2) {1, ..., 1}
177  initPlusState(vec);
178  QVector vecRef = QVector(1<<NUM_QUBITS);
179  for (size_t i=0; i<vecRef.size(); i++)
180  vecRef[i] = 1./sqrt(pow(2,NUM_QUBITS));
181  REQUIRE( areEqual(vec, vecRef) );
182  }
183  SECTION( "density-matrix" ) {
184 
185  // |+><+| = 1/sqrt(N^2) sum_i |i> 1/sqrt(N^2) sum_j <j|
186  // = 1/(N^2) sum_{ij} |i><j|
187  // = 1/(N^2) {{1, ..., 1}, ...}
188  initPlusState(mat);
189  QMatrix matRef = getZeroMatrix(1<<NUM_QUBITS);
190  for (size_t i=0; i<matRef.size(); i++)
191  for (size_t j=0; j<matRef.size(); j++)
192  matRef[i][j] = 1./pow(2, NUM_QUBITS);
193  REQUIRE( areEqual(mat, matRef) );
194  }
195  }
196  SECTION( "input validation" ) {
197 
198  // no user validation
199  SUCCEED( );
200  }
201  destroyQureg(vec, QUEST_ENV);
202  destroyQureg(mat, QUEST_ENV);
203 }

References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getZeroMatrix(), initPlusState(), NUM_QUBITS, and QUEST_ENV.

◆ TEST_CASE() [48/88]

TEST_CASE ( "initPureState"  ,
""  [state_initialisations] 
)
See also
initPureState
Author
Tyson Jones

Definition at line 211 of file test_state_initialisations.cpp.

211  {
212 
215 
216  SECTION( "correctness" ) {
217 
218  SECTION( "state-vector" ) {
219 
220  /* state-vector version just performs cloneQureg */
221 
223 
224  // make sure states start differently
225  initDebugState(vec1);
226  initBlankState(vec2);
227  REQUIRE( !areEqual(vec1, vec2) );
228 
229  // make sure vec2 is overwritten with vec1
230  QVector copy1 = toQVector(vec1);
231  initPureState(vec2, vec1);
232  REQUIRE( areEqual(vec1, vec2) );
233 
234  // make sure vec1 was not modified
235  REQUIRE( areEqual(vec1, copy1) );
236 
237  destroyQureg(vec2, QUEST_ENV);
238  }
239  SECTION( "density-matrix" ) {
240 
241  /* density matrix version initialises matrix in |pure><pure| */
242 
243  initDebugState(vec1); // |vec1> = sum_i a_i |i>
244  QVector copy1 = toQVector(vec1);
245 
246  // make sure mat1 is modified correctly
247  initBlankState(mat1);
248  initPureState(mat1, vec1); // mat1 = |vec1><vec1| = sum_{ij} a_i a_j* |i><j|
249 
250  QMatrix matRef = getZeroMatrix(1<<NUM_QUBITS);
251  for (size_t i=0; i<matRef.size(); i++)
252  for (size_t j=0; j<matRef.size(); j++)
253  matRef[i][j] = copy1[i] * conj(copy1[j]);
254  REQUIRE( areEqual(mat1, matRef) );
255 
256  // make sure vec1 was not modified
257  REQUIRE( areEqual(vec1, copy1) );
258  }
259  }
260  SECTION( "input validation" ) {
261 
262  SECTION( "qureg types" ) {
263 
264  // density matrix as second arg is illegal (regardless of first arg)
265  REQUIRE_THROWS_WITH( initPureState(vec1, mat1), Contains("Second argument must be a state-vector") );
266  REQUIRE_THROWS_WITH( initPureState(mat1, mat1), Contains("Second argument must be a state-vector") );
267  }
268  SECTION( "qureg dimensions" ) {
269 
270  Qureg vec2 = createQureg(NUM_QUBITS + 1, QUEST_ENV);
271  REQUIRE_THROWS_WITH( initPureState(vec1, vec2), Contains("Dimensions") && Contains("don't match") );
272  REQUIRE_THROWS_WITH( initPureState(mat1, vec2), Contains("Dimensions") && Contains("don't match") );
273  destroyQureg(vec2, QUEST_ENV);
274  }
275  }
276  destroyQureg(vec1, QUEST_ENV);
277  destroyQureg(mat1, QUEST_ENV);
278 }

References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getZeroMatrix(), initBlankState(), initDebugState(), initPureState(), NUM_QUBITS, QUEST_ENV, and toQVector().

◆ TEST_CASE() [49/88]

TEST_CASE ( "initStateFromAmps"  ,
""  [state_initialisations] 
)
See also
initStateFromAmps
Author
Tyson Jones

Definition at line 286 of file test_state_initialisations.cpp.

286  {
287 
289 
290  SECTION( "correctness" ) {
291 
292  SECTION( "state-vector" ) {
293 
294  // create arbitrary (but distinctly non-zero) amplitudes
295  qreal ampsRe[vec.numAmpsTotal];
296  qreal ampsIm[vec.numAmpsTotal];
297  QVector vecRef = QVector(vec.numAmpsTotal);
298  for (int i=0; i<vec.numAmpsTotal; i++) {
299  ampsRe[i] = 2*i;
300  ampsIm[i] = 2*i + 1;
301  vecRef[i] = (ampsRe[i]) + 1i*(ampsIm[i]);
302  }
303 
304  initBlankState(vec);
305  initStateFromAmps(vec, ampsRe, ampsIm);
306  REQUIRE( areEqual(vec, vecRef) );
307  }
308  }
309  SECTION( "input validation" ) {
310 
311  SECTION( "density-matrix" ) {
312 
314  REQUIRE_THROWS_WITH( initStateFromAmps(mat, NULL, NULL), Contains("valid only for state-vectors") );
315  destroyQureg(mat, QUEST_ENV);
316  }
317  }
318  destroyQureg(vec, QUEST_ENV);
319 }

References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), initBlankState(), initStateFromAmps(), NUM_QUBITS, Qureg::numAmpsTotal, qreal, and QUEST_ENV.

◆ TEST_CASE() [50/88]

TEST_CASE ( "initZeroState"  ,
""  [state_initialisations] 
)
See also
initZeroState
Author
Tyson Jones

Definition at line 327 of file test_state_initialisations.cpp.

327  {
328 
331 
332  SECTION( "correctness" ) {
333 
334  SECTION( "state-vector" ) {
335 
336  initBlankState(vec);
337  initZeroState(vec);
338 
339  QVector refVec = QVector(vec.numAmpsTotal);
340  refVec[0] = 1;
341  REQUIRE( areEqual(vec, refVec) );
342  }
343  SECTION( "density-matrix" ) {
344 
345  initBlankState(mat);
346  initZeroState(mat);
347 
348  QMatrix refMat = getZeroMatrix(1<<mat.numQubitsRepresented);
349  refMat[0][0] = 1;
350  REQUIRE( areEqual(mat, refMat) );
351  }
352  }
353  SECTION( "input validation" ) {
354 
355  // no input validation
356  SUCCEED( );
357  }
358  destroyQureg(vec, QUEST_ENV);
359  destroyQureg(mat, QUEST_ENV);
360 }

References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getZeroMatrix(), initBlankState(), initZeroState(), NUM_QUBITS, Qureg::numAmpsTotal, Qureg::numQubitsRepresented, and QUEST_ENV.

◆ TEST_CASE() [51/88]

TEST_CASE ( "measure"  ,
""  [gates] 
)
See also
measure
Author
Tyson Jones

Definition at line 121 of file test_gates.cpp.

121  {
122 
125 
126  SECTION( "correctness" ) {
127 
128  int qubit = GENERATE( range(0,NUM_QUBITS) );
129 
130  // repeat these random tests 10 times on every qubit
131  GENERATE( range(0,10) );
132 
133  SECTION( "state-vector" ) {
134 
136  toQureg(vec, vecRef);
137 
138  int outcome = measure(vec, qubit);
139  REQUIRE( (outcome == 0 || outcome == 1) );
140 
141  // calculate prob of this outcome
142  qreal prob = 0;
143  for (size_t ind=0; ind<vecRef.size(); ind++) {
144  int bit = (ind >> qubit) & 1; // target-th bit
145  if (bit == outcome)
146  prob += pow(abs(vecRef[ind]), 2);
147  }
148 
149  REQUIRE( prob > REAL_EPS );
150 
151  // renormalise by the outcome prob
152  for (size_t ind=0; ind<vecRef.size(); ind++) {
153  int bit = (ind >> qubit) & 1; // target-th bit
154  if (bit == outcome)
155  vecRef[ind] /= sqrt(prob);
156  else
157  vecRef[ind] = 0;
158  }
159  REQUIRE( areEqual(vec, vecRef) );
160  }
161  SECTION( "density-matrix" ) {
162 
164  toQureg(mat, matRef);
165 
166  int outcome = measure(mat, qubit);
167  REQUIRE( (outcome == 0 || outcome == 1) );
168 
169  // compute prob of this outcome
170  qreal prob = 0;
171  for (size_t ind=0; ind<matRef.size(); ind++) {
172  int bit = (ind >> qubit) & 1; // qubit-th bit
173  if (bit == outcome)
174  prob += real(matRef[ind][ind]);
175  }
176 
177  REQUIRE( prob > REAL_EPS );
178 
179  // renorm (/prob) every |*outcome*><*outcome*| state, zeroing all others
180  for (size_t r=0; r<matRef.size(); r++) {
181  for (size_t c=0; c<matRef.size(); c++) {
182  int ketBit = (c >> qubit) & 1;
183  int braBit = (r >> qubit) & 1;
184 
185  if (ketBit == outcome && braBit == outcome)
186  matRef[r][c] /= prob;
187  else
188  matRef[r][c] = 0;
189  }
190  }
191 
192  REQUIRE( areEqual(mat, matRef) );
193  }
194  }
195  SECTION( "input validation" ) {
196 
197  SECTION( "qubit index" ) {
198 
199  int qubit = GENERATE( -1, NUM_QUBITS );
200  REQUIRE_THROWS_WITH( measure(vec, qubit), Contains("Invalid target qubit") );
201  }
202  }
203  destroyQureg(vec, QUEST_ENV);
204  destroyQureg(mat, QUEST_ENV);
205 }

References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), measure(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

◆ TEST_CASE() [52/88]

TEST_CASE ( "measureWithStats"  ,
""  [gates] 
)
See also
measureWithStats
Author
Tyson Jones

Definition at line 213 of file test_gates.cpp.

213  {
214 
217 
218  SECTION( "correctness" ) {
219 
220  int qubit = GENERATE( range(0,NUM_QUBITS) );
221 
222  // repeat these random tests 10 times on every qubit
223  GENERATE( range(0,10) );
224 
225  SECTION( "state-vector" ) {
226 
228  toQureg(vec, vecRef);
229 
230  qreal res;
231  int outcome = measureWithStats(vec, qubit, &res);
232  REQUIRE( (outcome == 0 || outcome == 1) );
233 
234  // calculate prob of this outcome
235  qreal prob = 0;
236  for (size_t ind=0; ind<vecRef.size(); ind++) {
237  int bit = (ind >> qubit) & 1; // target-th bit
238  if (bit == outcome)
239  prob += pow(abs(vecRef[ind]), 2);
240  }
241 
242  REQUIRE( prob == Approx(res) );
243 
244  // renormalise by the outcome prob
245  for (size_t ind=0; ind<vecRef.size(); ind++) {
246  int bit = (ind >> qubit) & 1; // target-th bit
247  if (bit == outcome)
248  vecRef[ind] /= sqrt(prob);
249  else
250  vecRef[ind] = 0;
251  }
252  REQUIRE( areEqual(vec, vecRef) );
253  }
254  SECTION( "density-matrix" ) {
255 
257  toQureg(mat, matRef);
258 
259  qreal res;
260  int outcome = measureWithStats(mat, qubit, &res);
261  REQUIRE( (outcome == 0 || outcome == 1) );
262 
263  // compute prob of this outcome
264  qreal prob = 0;
265  for (size_t ind=0; ind<matRef.size(); ind++) {
266  int bit = (ind >> qubit) & 1; // qubit-th bit
267  if (bit == outcome)
268  prob += real(matRef[ind][ind]);
269  }
270 
271  REQUIRE( prob == Approx(res) );
272 
273  // renorm (/prob) every |*outcome*><*outcome*| state, zeroing all others
274  for (size_t r=0; r<matRef.size(); r++) {
275  for (size_t c=0; c<matRef.size(); c++) {
276  int ketBit = (c >> qubit) & 1;
277  int braBit = (r >> qubit) & 1;
278 
279  if (ketBit == outcome && braBit == outcome)
280  matRef[r][c] /= prob;
281  else
282  matRef[r][c] = 0;
283  }
284  }
285 
286  REQUIRE( areEqual(mat, matRef) );
287  }
288  }
289  SECTION( "input validation" ) {
290 
291  SECTION( "qubit index" ) {
292 
293  int qubit = GENERATE( -1, NUM_QUBITS );
294  qreal res;
295  REQUIRE_THROWS_WITH( measureWithStats(vec, qubit, &res), Contains("Invalid target qubit") );
296  }
297  }
298  destroyQureg(vec, QUEST_ENV);
299  destroyQureg(mat, QUEST_ENV);
300 }

References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomDensityMatrix(), getRandomStateVector(), measureWithStats(), NUM_QUBITS, qreal, QUEST_ENV, and toQureg().

◆ TEST_CASE() [53/88]

TEST_CASE ( "mixDamping"  ,
""  [decoherence] 
)
See also
mixDamping
Author
Tyson Jones

Definition at line 23 of file test_decoherence.cpp.

23  {
24 
25  PREPARE_TEST(qureg, ref);
26 
27  SECTION( "correctness" ) {
28 
29  int target = GENERATE( range(0,NUM_QUBITS) );
30  qreal prob = getRandomReal(0, 1);
31  mixDamping(qureg, target, prob);
32 
33  // ref -> kraus0 ref kraus0^dagger + kraus1 ref kraus1^dagger
34  QMatrix kraus0{{1,0},{0,sqrt(1-prob)}};
35  QMatrix rho0 = ref;
36  applyReferenceOp(rho0, target, kraus0);
37  QMatrix kraus1{{0,sqrt(prob)},{0,0}};
38  QMatrix rho1 = ref;
39  applyReferenceOp(rho1, target, kraus1);
40  ref = rho0 + rho1;
41 
42  REQUIRE( areEqual(qureg, ref) );
43  }
44  SECTION( "validation ") {
45 
46  SECTION( "qubit index" ) {
47 
48  int target = GENERATE( -1, NUM_QUBITS );
49  REQUIRE_THROWS_WITH( mixDamping(qureg, target, 0), Contains("Invalid target") );
50 
51  }
52  SECTION( "probability" ) {
53 
54  REQUIRE_THROWS_WITH( mixDamping(qureg, 0, -.1), Contains("Probabilities") );
55  REQUIRE_THROWS_WITH( mixDamping(qureg, 0, 1.1), Contains("Probabilities") );
56  }
57  SECTION( "density-matrix" ) {
58 
60  REQUIRE_THROWS_WITH( mixDamping(vec, 0, 0), Contains("density matrices") );
61  destroyQureg(vec, QUEST_ENV);
62  }
63  }
64  destroyQureg(qureg, QUEST_ENV);
65 }

References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDamping(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

◆ TEST_CASE() [54/88]

TEST_CASE ( "mixDensityMatrix"  ,
""  [decoherence] 
)
See also
mixDensityMatrix
Author
Tyson Jones

Definition at line 73 of file test_decoherence.cpp.

73  {
74 
77  initDebugState(qureg1);
78  initDebugState(qureg2);
79  QMatrix ref1 = toQMatrix(qureg1);
80  QMatrix ref2 = toQMatrix(qureg2);
81 
82  SECTION( "correctness" ) {
83 
84  // test p in {0, 1} and 10 random values in (0,1)
85  qreal prob = GENERATE( 0., 1., take(10, random(0.,1.)) );
86  mixDensityMatrix(qureg1, prob, qureg2);
87 
88  // ensure target qureg modified correctly
89  ref1 = (1-prob)*ref1 + (prob)*ref2;
90  REQUIRE( areEqual(qureg1, ref1) );
91 
92  // enure other qureg was not modified
93  REQUIRE( areEqual(qureg2, ref2) );
94  }
95  SECTION( "input validation" ) {
96 
97  SECTION( "probabilities") {
98 
99  qreal prob = GENERATE( -0.1, 1.1 );
100  REQUIRE_THROWS_WITH( mixDensityMatrix(qureg1, prob, qureg2), Contains("Probabilities") );
101  }
102  SECTION( "density matrices" ) {
103 
104  // one is statevec
106  REQUIRE_THROWS_WITH( mixDensityMatrix(qureg1, 0, state1), Contains("density matrices") );
107  REQUIRE_THROWS_WITH( mixDensityMatrix(state1, 0, qureg1), Contains("density matrices") );
108 
109  // both are statevec
111  REQUIRE_THROWS_WITH( mixDensityMatrix(state1, 0, state2), Contains("density matrices") );
112 
113  destroyQureg(state1, QUEST_ENV);
114  destroyQureg(state2, QUEST_ENV);
115  }
116  SECTION( "matching dimensions" ) {
117 
119  REQUIRE_THROWS_WITH( mixDensityMatrix(qureg1, 0, qureg3), Contains("Dimensions") );
120  REQUIRE_THROWS_WITH( mixDensityMatrix(qureg3, 0, qureg1), Contains("Dimensions") );
121  destroyQureg(qureg3, QUEST_ENV);
122  }
123  }
124  destroyQureg(qureg1, QUEST_ENV);
125  destroyQureg(qureg2, QUEST_ENV);
126 }

References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), initDebugState(), mixDensityMatrix(), NUM_QUBITS, Qureg::numQubitsRepresented, qreal, QUEST_ENV, and toQMatrix().

◆ TEST_CASE() [55/88]

TEST_CASE ( "mixDephasing"  ,
""  [decoherence] 
)
See also
mixDephasing
Author
Tyson Jones

Definition at line 134 of file test_decoherence.cpp.

134  {
135 
136  PREPARE_TEST(qureg, ref);
137 
138  SECTION( "correctness " ) {
139 
140  int target = GENERATE( range(0,NUM_QUBITS) );
141  qreal prob = getRandomReal(0, 1/2.);
142  mixDephasing(qureg, target, prob);
143 
144  // ref -> (1 - prob) ref + prob Z ref Z
145  QMatrix phaseRef = ref;
146  applyReferenceOp(phaseRef, target, QMatrix{{1,0},{0,-1}}); // Z ref Z
147  ref = ((1 - prob) * ref) + (prob * phaseRef);
148 
149  REQUIRE( areEqual(qureg, ref) );
150  }
151  SECTION( "validation ") {
152 
153  SECTION( "qubit index" ) {
154 
155  int target = GENERATE( -1, NUM_QUBITS );
156  REQUIRE_THROWS_WITH( mixDephasing(qureg, target, 0), Contains("Invalid target") );
157 
158  }
159  SECTION( "probability" ) {
160 
161  REQUIRE_THROWS_WITH( mixDephasing(qureg, 0, -.1), Contains("Probabilities") );
162  REQUIRE_THROWS_WITH( mixDephasing(qureg, 0, .6), Contains("probability") && Contains("cannot exceed 1/2") );
163  }
164  SECTION( "density-matrix" ) {
165 
167  REQUIRE_THROWS_WITH( mixDephasing(vec, 0, 0), Contains("density matrices") );
168  destroyQureg(vec, QUEST_ENV);
169  }
170  }
171  destroyQureg(qureg, QUEST_ENV);
172 }

References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDephasing(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

◆ TEST_CASE() [56/88]

TEST_CASE ( "mixDepolarising"  ,
""  [decoherence] 
)
See also
mixDepolarising
Author
Tyson Jones

Definition at line 180 of file test_decoherence.cpp.

180  {
181 
182  PREPARE_TEST(qureg, ref);
183 
184  SECTION( "correctness " ) {
185 
186  int target = GENERATE( range(0,NUM_QUBITS) );
187  qreal prob = getRandomReal(0, 3/4.);
188  mixDepolarising(qureg, target, prob);
189 
190  QMatrix xRef = ref;
191  applyReferenceOp(xRef, target, QMatrix{{0,1},{1,0}}); // X ref X
192  QMatrix yRef = ref;
193  applyReferenceOp(yRef, target, QMatrix{{0,-1i},{1i,0}}); // Y ref Y
194  QMatrix zRef = ref;
195  applyReferenceOp(zRef, target, QMatrix{{1,0},{0,-1}}); // Z ref Z
196  ref = ((1 - prob) * ref) + ((prob/3.) * ( xRef + yRef + zRef));
197 
198  REQUIRE( areEqual(qureg, ref) );
199  }
200  SECTION( "validation ") {
201 
202  SECTION( "qubit index" ) {
203 
204  int target = GENERATE( -1, NUM_QUBITS );
205  REQUIRE_THROWS_WITH( mixDepolarising(qureg, target, 0), Contains("Invalid target") );
206 
207  }
208  SECTION( "probability" ) {
209 
210  REQUIRE_THROWS_WITH( mixDepolarising(qureg, 0, -.1), Contains("Probabilities") );
211  REQUIRE_THROWS_WITH( mixDepolarising(qureg, 0, .76), Contains("probability") && Contains("cannot exceed 3/4") );
212  }
213  SECTION( "density-matrix" ) {
214 
216  REQUIRE_THROWS_WITH( mixDepolarising(vec, 0, 0), Contains("density matrices") );
217  destroyQureg(vec, QUEST_ENV);
218  }
219  }
220  destroyQureg(qureg, QUEST_ENV);
221 }

References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixDepolarising(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

◆ TEST_CASE() [57/88]

TEST_CASE ( "mixKrausMap"  ,
""  [decoherence] 
)
See also
mixKrausMap
Author
Tyson Jones

Definition at line 520 of file test_decoherence.cpp.

520  {
521 
522  PREPARE_TEST(qureg, ref);
523 
524  SECTION( "correctness" ) {
525 
526  int target = GENERATE( range(0,NUM_QUBITS) );
527  int numOps = GENERATE( range(1,5) ); // max 4 inclusive
528  std::vector<QMatrix> matrs = getRandomKrausMap(1, numOps);
529 
530  ComplexMatrix2 ops[numOps];
531  for (int i=0; i<numOps; i++)
532  ops[i] = toComplexMatrix2(matrs[i]);
533  mixKrausMap(qureg, target, ops, numOps);
534 
535  // set ref -> K_i ref K_i^dagger
536  QMatrix matrRefs[numOps];
537  for (int i=0; i<numOps; i++) {
538  matrRefs[i] = ref;
539  applyReferenceOp(matrRefs[i], target, matrs[i]);
540  }
541  ref = getZeroMatrix(ref.size());
542  for (int i=0; i<numOps; i++)
543  ref += matrRefs[i];
544 
545  REQUIRE( areEqual(qureg, ref, 10*REAL_EPS) );
546  }
547  SECTION( "input validation" ) {
548 
549  SECTION( "number of operators" ) {
550 
551  int numOps = GENERATE( 0, 5 );
552  REQUIRE_THROWS_WITH( mixKrausMap(qureg, 0, NULL, numOps), Contains("operators") );
553  }
554  SECTION( "trace preserving" ) {
555 
556  // valid Kraus map
557  int numOps = GENERATE( range(1,5) ); // max 4 inclusive
558  std::vector<QMatrix> matrs = getRandomKrausMap(1, numOps);
559  ComplexMatrix2 ops[numOps];
560  for (int i=0; i<numOps; i++)
561  ops[i] = toComplexMatrix2(matrs[i]);
562 
563  // make invalid
564  ops[GENERATE_REF( range(0,numOps) )].real[0][0] = 0;
565  REQUIRE_THROWS_WITH( mixKrausMap(qureg, 0, ops, numOps), Contains("trace preserving") );
566 
567  }
568  SECTION( "qubit index" ) {
569 
570  int target = GENERATE( -1, NUM_QUBITS );
571  REQUIRE_THROWS_WITH( mixKrausMap(qureg, target, NULL, 1), Contains("Invalid target qubit") );
572  }
573  SECTION( "density-matrix" ) {
574 
576  REQUIRE_THROWS_WITH( mixKrausMap(vec, 0, NULL, 1), Contains("density matrices") );
577  destroyQureg(vec, QUEST_ENV);
578  }
579  SECTION( "operators fit in node" ) {
580 
581  qureg.numAmpsPerChunk = 3; // min 4
582  REQUIRE_THROWS_WITH( mixKrausMap(qureg, 0, NULL, 1), Contains("targets too many qubits") );
583  }
584  }
585  destroyQureg(qureg, QUEST_ENV);
586 }

References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrix2::real, and toComplexMatrix2().

◆ TEST_CASE() [58/88]

TEST_CASE ( "mixMultiQubitKrausMap"  ,
""  [decoherence] 
)
See also
mixMultiQubitKrausMap
Author
Tyson Jones

Definition at line 229 of file test_decoherence.cpp.

229  {
230 
231  PREPARE_TEST(qureg, ref);
232 
233  // figure out max-num (inclusive) targs allowed by hardware backend
234  // (each node must contain as 2^(2*numTargs) amps)
235  int maxNumTargs = calcLog2(qureg.numAmpsPerChunk) / 2;
236 
237  SECTION( "correctness" ) {
238 
239  /* note that this function incurs a stack overhead when numTargs < 4,
240  * and a heap overhead when numTargs >= 4
241  */
242 
243  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) ); // inclusive upper bound
244 
245  // note this is very expensive to try every arrangement (2 min runtime for numTargs=5 alone)
246  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
247 
248  // try the min and max number of operators, and 2 random numbers
249  // (there are way too many to try all!)
250  int maxNumOps = (2*numTargs)*(2*numTargs);
251  int numOps = GENERATE_COPY( 1, maxNumOps, take(2,random(1,maxNumOps)) );
252 
253  // use a new random map
254  std::vector<QMatrix> matrs = getRandomKrausMap(numTargs, numOps);
255 
256  // create map in QuEST datatypes
257  ComplexMatrixN ops[numOps];
258  for (int i=0; i<numOps; i++) {
259  ops[i] = createComplexMatrixN(numTargs);
260  toComplexMatrixN(matrs[i], ops[i]);
261  }
262 
263  mixMultiQubitKrausMap(qureg, targs, numTargs, ops, numOps);
264 
265  // set ref -> K_i ref K_i^dagger
266  QMatrix matrRefs[numOps];
267  for (int i=0; i<numOps; i++) {
268  matrRefs[i] = ref;
269  applyReferenceOp(matrRefs[i], targs, numTargs, matrs[i]);
270  }
271  ref = getZeroMatrix(ref.size());
272  for (int i=0; i<numOps; i++)
273  ref += matrRefs[i];
274 
275  REQUIRE( areEqual(qureg, ref, 1E2*REAL_EPS) );
276 
277  // cleanup QuEST datatypes
278  for (int i=0; i<numOps; i++)
279  destroyComplexMatrixN(ops[i]);
280  }
281  SECTION( "input validation" ) {
282 
283  SECTION( "repetition of target" ) {
284 
285  // make valid targets
286  int targs[NUM_QUBITS];
287  for (int i=0; i<NUM_QUBITS; i++)
288  targs[i] = i;
289 
290  // duplicate one
291  int badInd = GENERATE( range(0,NUM_QUBITS) );
292  int copyInd = GENERATE_COPY( filter([=](int i){ return i!=badInd; }, range(0,NUM_QUBITS)) );
293  targs[badInd] = targs[copyInd];
294 
295  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, NULL, 1), Contains("target qubits") && Contains("unique") );
296  }
297  SECTION( "qubit indices" ) {
298 
299  // make valid targets
300  int targs[NUM_QUBITS];
301  for (int i=0; i<NUM_QUBITS; i++)
302  targs[i] = i;
303 
304  // make one invalid
305  targs[GENERATE( range(0,NUM_QUBITS) )] = GENERATE( -1, NUM_QUBITS );
306 
307  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, NULL, 1), Contains("Invalid target qubit") );
308  }
309  SECTION( "number of operators" ) {
310 
311  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
312  int maxNumOps = (2*numTargs)*(2*numTargs);
313  int numOps = GENERATE_REF( -1, 0, maxNumOps + 1 );
314 
315  // make valid targets to avoid triggering target validation
316  int targs[numTargs];
317  for (int i=0; i<numTargs; i++)
318  targs[i] = i;
319  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, numTargs, NULL, numOps), Contains("operators may be specified") );
320  }
321  SECTION( "initialisation of operators" ) {
322 
323  /* compilers don't auto-initialise to NULL; the below circumstance
324  * only really occurs when 'malloc' returns NULL in createComplexMatrixN,
325  * which actually triggers its own validation. Hence this test is useless
326  * currently.
327  */
328 
329  int numTargs = NUM_QUBITS;
330  int numOps = (2*numTargs)*(2*numTargs);
331 
332  // no need to initialise ops, but set their attribs correct to avoid triggering other validation
333  ComplexMatrixN ops[numOps];
334  for (int i=0; i<numOps; i++)
335  ops[i].numQubits = numTargs;
336 
337  // make one of the max-ops explicitly NULL
338  ops[GENERATE_COPY( range(0,numTargs) )].real = NULL;
339 
340  // make valid targets to avoid triggering target validation
341  int targs[numTargs];
342  for (int i=0; i<numTargs; i++)
343  targs[i] = i;
344 
345  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, numTargs, ops, numOps), Contains("ComplexMatrixN") && Contains("created") );
346  }
347  SECTION( "dimension of operators" ) {
348 
349  // make valid (dimension-wise) max-qubits Kraus map
350  int numTargs = NUM_QUBITS;
351  int numOps = (2*numTargs)*(2*numTargs);
352  ComplexMatrixN ops[numOps];
353  for (int i=0; i<numOps; i++)
354  ops[i] = createComplexMatrixN(numTargs);
355 
356  // make one have wrong-dimensions
357  int badInd = GENERATE_COPY( range(0,numTargs) );
358  destroyComplexMatrixN(ops[badInd]);
359  ops[badInd] = createComplexMatrixN(numTargs - 1);
360 
361  // make valid targets to avoid triggering target validation
362  int targs[numTargs];
363  for (int i=0; i<numTargs; i++)
364  targs[i] = i;
365 
366  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, numTargs, ops, numOps), Contains("same number of qubits") );
367 
368  for (int i=0; i<numOps; i++)
369  destroyComplexMatrixN(ops[i]);
370  }
371  SECTION( "trace preserving" ) {
372 
373  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
374  int maxNumOps = (2*numTargs) * (2*numTargs);
375  int numOps = GENERATE_COPY( 1, 2, maxNumOps );
376 
377  // generate a valid map
378  std::vector<QMatrix> matrs = getRandomKrausMap(numTargs, numOps);
379  ComplexMatrixN ops[numOps];
380  for (int i=0; i<numOps; i++) {
381  ops[i] = createComplexMatrixN(numTargs);
382  toComplexMatrixN(matrs[i], ops[i]);
383  }
384 
385  // make only one invalid
386  ops[GENERATE_REF( range(0,numOps) )].real[0][0] = 0;
387 
388  // make valid targets to avoid triggering target validation
389  int targs[numTargs];
390  for (int i=0; i<numTargs; i++)
391  targs[i] = i;
392 
393  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, numTargs, ops, numOps), Contains("trace preserving") );
394 
395  for (int i=0; i<numOps; i++)
396  destroyComplexMatrixN(ops[i]);
397  }
398  SECTION( "density-matrix" ) {
399 
400  Qureg statevec = createQureg(NUM_QUBITS, QUEST_ENV);
401 
402  // make valid targets to avoid triggering target validation
403  int targs[NUM_QUBITS];
404  for (int i=0; i<NUM_QUBITS; i++)
405  targs[i] = i;
406 
407  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(statevec, targs, NUM_QUBITS, NULL, 1), Contains("valid only for density matrices") );
408  destroyQureg(statevec, QUEST_ENV);
409 
410  }
411  SECTION( "operator fits in node" ) {
412 
413  // each node requires (2 numTargs)^2 amplitudes
414  int minAmps = (2*NUM_QUBITS) * (2*NUM_QUBITS);
415 
416  // make valid targets to avoid triggering target validation
417  int targs[NUM_QUBITS];
418  for (int i=0; i<NUM_QUBITS; i++)
419  targs[i] = i;
420 
421  // make a simple Identity map
423  for (int i=0; i<(1<<NUM_QUBITS); i++)
424  ops[0].real[i][i] = 1;
425 
426  // fake a smaller qureg
427  qureg.numAmpsPerChunk = minAmps - 1;
428  REQUIRE_THROWS_WITH( mixMultiQubitKrausMap(qureg, targs, NUM_QUBITS, ops, 1), Contains("targets too many qubits") && Contains("cannot all fit") );
429 
430  destroyComplexMatrixN(ops[0]);
431  }
432  }
433  destroyQureg(qureg, QUEST_ENV);
434 }

References applyReferenceOp(), areEqual(), calcLog2(), createComplexMatrixN(), createQureg(), destroyComplexMatrixN(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixMultiQubitKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

◆ TEST_CASE() [59/88]

TEST_CASE ( "mixPauli"  ,
""  [decoherence] 
)
See also
mixPauli
Author
Tyson Jones

Definition at line 442 of file test_decoherence.cpp.

442  {
443 
444  PREPARE_TEST(qureg, ref);
445 
446  SECTION( "correctness" ) {
447 
448  int target = GENERATE( range(0,NUM_QUBITS) );
449 
450  // randomly generate valid pauli-error probabilities
451  qreal probs[3];
452  qreal max0 = 1/2.; // satisfies p1 < 1 - py
453  probs[0] = getRandomReal(0, max0);
454  qreal max1 = (max0 - probs[0])/2.; // p2 can use half of p1's "unused space"
455  probs[1] = getRandomReal(0, max1);
456  qreal max2 = (max1 - probs[1])/2.; // p3 can use half of p2's "unused space"
457  probs[2] = getRandomReal(0, max2);
458 
459  // uniformly randomly assign probs (bound to target)
460  int inds[3] = {0,1,2};
461  std::shuffle(inds,inds+3, std::default_random_engine(1E5 * target));
462  qreal probX = probs[inds[0]]; // seed:target shows no variation
463  qreal probY = probs[inds[1]];
464  qreal probZ = probs[inds[2]];
465 
466  mixPauli(qureg, target, probX, probY, probZ);
467 
468  QMatrix xRef = ref;
469  applyReferenceOp(xRef, target, QMatrix{{0,1},{1,0}}); // X ref X
470  QMatrix yRef = ref;
471  applyReferenceOp(yRef, target, QMatrix{{0,-1i},{1i,0}}); // Y ref Y
472  QMatrix zRef = ref;
473  applyReferenceOp(zRef, target, QMatrix{{1,0},{0,-1}}); // Z ref Z
474  ref = ((1 - probX - probY - probZ) * ref) +
475  (probX * xRef) + (probY * yRef) + (probZ * zRef);
476 
477  REQUIRE( areEqual(qureg, ref) );
478  }
479  SECTION( "input validation" ) {
480 
481  SECTION( "qubit index" ) {
482 
483  int target = GENERATE( -1, NUM_QUBITS );
484  REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, 0), Contains("Invalid target") );
485 
486  }
487  SECTION( "probability" ) {
488 
489  int target = 0;
490 
491  // probs clearly must be in [0, 1]
492  REQUIRE_THROWS_WITH( mixPauli(qureg, target, -.1, 0, 0), Contains("Probabilities") );
493  REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, -.1, 0), Contains("Probabilities") );
494  REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, -.1), Contains("Probabilities") );
495 
496  // max single-non-zero-prob is 0.5
497  REQUIRE_THROWS_WITH( mixPauli(qureg, target, .6, 0, 0), Contains("cannot exceed the probability") );
498  REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, .6, 0), Contains("cannot exceed the probability") );
499  REQUIRE_THROWS_WITH( mixPauli(qureg, target, 0, 0, .6), Contains("cannot exceed the probability") );
500 
501  // must satisfy px, py, pz < 1 - px - py - pz
502  REQUIRE_THROWS_WITH( mixPauli(qureg, target, .3, .3, .3), Contains("cannot exceed the probability") );
503  }
504  SECTION( "density-matrix" ) {
505 
507  REQUIRE_THROWS_WITH( mixPauli(vec, 0, 0, 0, 0), Contains("density matrices") );
508  destroyQureg(vec, QUEST_ENV);
509  }
510  }
511  destroyQureg(qureg, QUEST_ENV);
512 }

References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixPauli(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

◆ TEST_CASE() [60/88]

TEST_CASE ( "mixTwoQubitDephasing"  ,
""  [decoherence] 
)
See also
mixTwoQubitDephasing
Author
Tyson Jones

Definition at line 594 of file test_decoherence.cpp.

594  {
595 
596  PREPARE_TEST(qureg, ref);
597 
598  SECTION( "correctness" ) {
599 
600  int targ1 = GENERATE( range(0,NUM_QUBITS) );
601  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
602  qreal prob = getRandomReal(0, 3/4.);
603 
604  mixTwoQubitDephasing(qureg, targ1, targ2, prob);
605 
606  // ref -> (1 - prob) ref + prob/3 (Z1 ref Z1 + Z2 ref Z2 + Z1 Z2 ref Z1 Z2)
607  QMatrix zMatr{{1,0},{0,-1}};
608  QMatrix z1Ref = ref;
609  applyReferenceOp(z1Ref, targ1, zMatr); // Z1 ref Z1
610  QMatrix z2Ref = ref;
611  applyReferenceOp(z2Ref, targ2, zMatr); // Z2 ref Z2
612  QMatrix z1z2Ref = ref;
613  applyReferenceOp(z1z2Ref, targ1, zMatr);
614  applyReferenceOp(z1z2Ref, targ2, zMatr); // Z1 Z2 ref Z1 Z2
615  ref = ((1 - prob) * ref) + (prob/3.) * (z1Ref + z2Ref + z1z2Ref);
616 
617  REQUIRE( areEqual(qureg, ref) );
618  }
619  SECTION( "input validation" ) {
620 
621  SECTION( "qubit indices" ) {
622 
623  int targ = GENERATE( -1, NUM_QUBITS );
624  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(qureg, 0, targ, 0), Contains("Invalid target") );
625  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(qureg, targ, 0, 0), Contains("Invalid target") );
626  }
627  SECTION( "target collision" ) {
628 
629  int targ = GENERATE( range(0,NUM_QUBITS) );
630  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(qureg, targ, targ, 0), Contains("target") && Contains("unique") );
631  }
632  SECTION( "probability" ) {
633 
634  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(qureg, 0, 1, -.1), Contains("Probabilities") );
635  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(qureg, 0, 1, 3/4. + .01), Contains("probability") && Contains("cannot exceed 3/4") );
636  }
637  SECTION( "density-matrix" ) {
638 
640  REQUIRE_THROWS_WITH( mixTwoQubitDephasing(vec, 0, 1, 0), Contains("density matrices") );
641  destroyQureg(vec, QUEST_ENV);
642  }
643  }
644  destroyQureg(qureg, QUEST_ENV);
645 }

References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomReal(), mixTwoQubitDephasing(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

◆ TEST_CASE() [61/88]

TEST_CASE ( "mixTwoQubitDepolarising"  ,
""  [decoherence] 
)
See also
mixTwoQubitDepolarising
Author
Tyson Jones

Definition at line 653 of file test_decoherence.cpp.

653  {
654 
655  PREPARE_TEST(qureg, ref);
656 
657  SECTION( "correctness" ) {
658 
659  int targ1 = GENERATE( range(0,NUM_QUBITS) );
660  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
661  qreal prob = getRandomReal(0, 15/16.);
662 
663  mixTwoQubitDepolarising(qureg, targ1, targ2, prob);
664 
665  QMatrix paulis[4] = {
666  QMatrix{{1,0},{0,1}}, // I
667  QMatrix{{0,1},{1,0}}, // X
668  QMatrix{{0,-1i},{1i,0}}, // Y
669  QMatrix{{1,0},{0,-1}} // Z
670  };
671 
672  int targs[2] = {targ1, targ2};
673  QMatrix refInit = ref;
674  ref = (1 - (16/15.)*prob) * ref;
675  for (int i=0; i<4; i++) {
676  for (int j=0; j<4; j++) {
677  QMatrix term = refInit;
678  applyReferenceOp(term, targs, 2,
679  getKroneckerProduct(paulis[i], paulis[j]));
680  ref += (prob/15.) * term;
681  }
682  }
683 
684  REQUIRE( areEqual(qureg, ref, 1E4*REAL_EPS) );
685  }
686  SECTION( "input validation" ) {
687 
688  SECTION( "qubit indices" ) {
689 
690  int targ = GENERATE( -1, NUM_QUBITS );
691  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(qureg, 0, targ, 0), Contains("Invalid target") );
692  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(qureg, targ, 0, 0), Contains("Invalid target") );
693  }
694  SECTION( "target collision" ) {
695 
696  int targ = GENERATE( range(0,NUM_QUBITS) );
697  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(qureg, targ, targ, 0), Contains("target") && Contains("unique") );
698  }
699  SECTION( "probability" ) {
700 
701  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(qureg, 0, 1, -.1), Contains("Probabilities") );
702  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(qureg, 0, 1, 15/16. + .01), Contains("probability") && Contains("cannot exceed 15/16") );
703  }
704  SECTION( "density-matrix" ) {
705 
707  REQUIRE_THROWS_WITH( mixTwoQubitDepolarising(vec, 0, 1, 0), Contains("density matrices") );
708  destroyQureg(vec, QUEST_ENV);
709  }
710  }
711  destroyQureg(qureg, QUEST_ENV);
712 }

References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getKroneckerProduct(), getRandomReal(), mixTwoQubitDepolarising(), NUM_QUBITS, PREPARE_TEST, qreal, and QUEST_ENV.

◆ TEST_CASE() [62/88]

TEST_CASE ( "mixTwoQubitKrausMap"  ,
""  [decoherence] 
)
See also
mixTwoQubitKrausMap
Author
Tyson Jones

Definition at line 720 of file test_decoherence.cpp.

720  {
721 
722  PREPARE_TEST(qureg, ref);
723 
724  SECTION( "correctness" ) {
725 
726  int targ1 = GENERATE( range(0,NUM_QUBITS) );
727  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
728  int numOps = GENERATE( range(1,17) ); // max 16 inclusive
729  std::vector<QMatrix> matrs = getRandomKrausMap(2, numOps);
730 
731  ComplexMatrix4 ops[numOps];
732  for (int i=0; i<numOps; i++)
733  ops[i] = toComplexMatrix4(matrs[i]);
734  mixTwoQubitKrausMap(qureg, targ1, targ2, ops, numOps);
735 
736  // set ref -> K_i ref K_i^dagger
737  int targs[2] = {targ1, targ2};
738  QMatrix matrRefs[numOps];
739  for (int i=0; i<numOps; i++) {
740  matrRefs[i] = ref;
741  applyReferenceOp(matrRefs[i], targs, 2, matrs[i]);
742  }
743  ref = getZeroMatrix(ref.size());
744  for (int i=0; i<numOps; i++)
745  ref += matrRefs[i];
746 
747  REQUIRE( areEqual(qureg, ref, 10*REAL_EPS) );
748  }
749  SECTION( "input validation" ) {
750 
751  SECTION( "number of operators" ) {
752 
753  int numOps = GENERATE( 0, 17 );
754  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, NULL, numOps), Contains("operators") );
755  }
756  SECTION( "trace preserving" ) {
757 
758  // valid Kraus map
759  int numOps = GENERATE( range(1,16) );
760  std::vector<QMatrix> matrs = getRandomKrausMap(2, numOps);
761  ComplexMatrix4 ops[numOps];
762  for (int i=0; i<numOps; i++)
763  ops[i] = toComplexMatrix4(matrs[i]);
764 
765  // make only one of the ops at a time invalid
766  ops[GENERATE_REF( range(0,numOps) )].real[0][0] = 0;
767  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, ops, numOps), Contains("trace preserving") );
768  }
769  SECTION( "target collision" ) {
770 
771  int target = GENERATE( range(0,NUM_QUBITS) );
772  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, target, target, NULL, 1), Contains("target qubits") && Contains("unique") );
773  }
774  SECTION( "qubit index" ) {
775 
776  int target = GENERATE( -1, NUM_QUBITS );
777  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,target, NULL, 1), Contains("Invalid target qubit") );
778  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, target,0, NULL, 1), Contains("Invalid target qubit") );
779  }
780  SECTION( "density-matrix" ) {
781 
783  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(vec, 0,1, NULL, 1), Contains("density matrices") );
784  destroyQureg(vec, QUEST_ENV);
785  }
786  SECTION( "operators fit in node" ) {
787 
788  qureg.numAmpsPerChunk = 15; // min 16
789  REQUIRE_THROWS_WITH( mixTwoQubitKrausMap(qureg, 0,1, NULL, 1), Contains("targets too many qubits") );
790  }
791  }
792  destroyQureg(qureg, QUEST_ENV);
793 }

References applyReferenceOp(), areEqual(), createQureg(), destroyQureg(), getRandomKrausMap(), getZeroMatrix(), mixTwoQubitKrausMap(), NUM_QUBITS, PREPARE_TEST, QUEST_ENV, ComplexMatrix4::real, and toComplexMatrix4().

◆ TEST_CASE() [63/88]

TEST_CASE ( "multiControlledMultiQubitUnitary"  ,
""  [unitaries] 
)
See also
multiControlledMultiQubitUnitary
Author
Tyson Jones

Definition at line 852 of file test_unitaries.cpp.

852  {
853 
854  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
855 
856  // figure out max-num targs (inclusive) allowed by hardware backend
857  int maxNumTargs = calcLog2(quregVec.numAmpsPerChunk);
858  if (maxNumTargs >= NUM_QUBITS)
859  maxNumTargs = NUM_QUBITS - 1; // leave room for min-number of control qubits
860 
861  SECTION( "correctness" ) {
862 
863  // try all possible numbers of targets and controls
864  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
865  int maxNumCtrls = NUM_QUBITS - numTargs;
866  int numCtrls = GENERATE_COPY( range(1,maxNumCtrls+1) );
867 
868  // generate all possible valid qubit arrangements
869  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
870  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls, targs, numTargs) );
871 
872  // for each qubit arrangement, use a new random unitary
873  QMatrix op = getRandomUnitary(numTargs);
874  ComplexMatrixN matr = createComplexMatrixN(numTargs);
875  toComplexMatrixN(op, matr);
876 
877  SECTION( "state-vector" ) {
878 
879  multiControlledMultiQubitUnitary(quregVec, ctrls, numCtrls, targs, numTargs, matr);
880  applyReferenceOp(refVec, ctrls, numCtrls, targs, numTargs, op);
881  REQUIRE( areEqual(quregVec, refVec) );
882  }
883  SECTION( "density-matrix" ) {
884 
885  multiControlledMultiQubitUnitary(quregMatr, ctrls, numCtrls, targs, numTargs, matr);
886  applyReferenceOp(refMatr, ctrls, numCtrls, targs, numTargs, op);
887  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
888  }
889  destroyComplexMatrixN(matr);
890  }
891  SECTION( "input validation" ) {
892 
893  SECTION( "number of targets" ) {
894 
895  // there cannot be more targets than qubits in register
896  // (numTargs=NUM_QUBITS is caught elsewhere, because that implies ctrls are invalid)
897  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
898  int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
899  int ctrls[] = {0};
900  ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
901  toComplexMatrixN(getRandomUnitary(NUM_QUBITS+1), matr); // ensure unitary
902 
903  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, numTargs, matr), Contains("Invalid number of target"));
904  destroyComplexMatrixN(matr);
905  }
906  SECTION( "repetition in targets" ) {
907 
908  int ctrls[] = {0};
909  int numTargs = 3;
910  int targs[] = {1,2,2};
911  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
912  toComplexMatrixN(getRandomUnitary(numTargs), matr); // ensure unitary
913 
914  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, numTargs, matr), Contains("target") && Contains("unique"));
915  destroyComplexMatrixN(matr);
916  }
917  SECTION( "number of controls" ) {
918 
919  int numCtrls = GENERATE( -1, 0, NUM_QUBITS, NUM_QUBITS+1 );
920  int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
921  int targs[1] = {0};
923  toComplexMatrixN(getRandomUnitary(1), matr); // ensure unitary
924 
925  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, numCtrls, targs, 1, matr), Contains("Invalid number of control"));
926  destroyComplexMatrixN(matr);
927  }
928  SECTION( "repetition in controls" ) {
929 
930  int ctrls[] = {0,1,1};
931  int targs[] = {3};
933  toComplexMatrixN(getRandomUnitary(1), matr); // ensure unitary
934 
935  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 3, targs, 1, matr), Contains("control") && Contains("unique"));
936  destroyComplexMatrixN(matr);
937  }
938  SECTION( "control and target collision" ) {
939 
940  int ctrls[] = {0,1,2};
941  int targs[] = {3,1,4};
943  toComplexMatrixN(getRandomUnitary(3), matr); // ensure unitary
944 
945  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 3, targs, 3, matr), Contains("Control") && Contains("target") && Contains("disjoint"));
946  destroyComplexMatrixN(matr);
947  }
948  SECTION( "qubit indices" ) {
949 
950  // valid inds
951  int numQb = 2;
952  int qb1[2] = {0,1};
953  int qb2[2] = {2,3};
954  ComplexMatrixN matr = createComplexMatrixN(numQb);
955  toComplexMatrixN(getRandomUnitary(numQb), matr); // ensure unitary
956 
957  // make qb1 invalid
958  int inv = GENERATE( -1, NUM_QUBITS );
959  qb1[GENERATE_COPY(range(0,numQb))] = inv;
960 
961  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, qb1, numQb, qb2, numQb, matr), Contains("Invalid control") );
962  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, qb2, numQb, qb1, numQb, matr), Contains("Invalid target") );
963  destroyComplexMatrixN(matr);
964  }
965  SECTION( "unitarity" ) {
966 
967  int ctrls[1] = {0};
968  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
969  int targs[numTargs];
970  for (int i=0; i<numTargs; i++)
971  targs[i] = i+1;
972 
973  ComplexMatrixN matr = createComplexMatrixN(numTargs); // initially zero, hence not-unitary
974  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, numTargs, matr), Contains("unitary") );
975  destroyComplexMatrixN(matr);
976  }
977  SECTION( "unitary creation" ) {
978 
979  int ctrls[1] = {0};
980  int targs[3] = {1,2,3};
981 
982  /* compilers don't auto-initialise to NULL; the below circumstance
983  * only really occurs when 'malloc' returns NULL in createComplexMatrixN,
984  * which actually triggers its own validation. Hence this test is useless
985  * currently.
986  */
987  ComplexMatrixN matr;
988  matr.real = NULL;
989  matr.imag = NULL;
990  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, 3, matr), Contains("created") );
991  }
992  SECTION( "unitary dimensions" ) {
993 
994  int ctrls[1] = {0};
995  int targs[2] = {1,2};
996  ComplexMatrixN matr = createComplexMatrixN(3); // intentionally wrong size
997  toComplexMatrixN(getRandomUnitary(3), matr); // ensure unitary
998 
999  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, 2, matr), Contains("matrix size"));
1000  destroyComplexMatrixN(matr);
1001  }
1002  SECTION( "unitary fits in node" ) {
1003 
1004  // pretend we have a very limited distributed memory (judged by matr size)
1005  quregVec.numAmpsPerChunk = 1;
1006  int ctrls[1] = {0};
1007  int targs[2] = {1,2};
1009  toComplexMatrixN(getRandomUnitary(2), matr); // ensure unitary
1010 
1011  REQUIRE_THROWS_WITH( multiControlledMultiQubitUnitary(quregVec, ctrls, 1, targs, 2, matr), Contains("targets too many qubits"));
1012  destroyComplexMatrixN(matr);
1013  }
1014  }
1015  CLEANUP_TEST( quregVec, quregMatr );
1016 }

References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, multiControlledMultiQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

◆ TEST_CASE() [64/88]

TEST_CASE ( "multiControlledPhaseFlip"  ,
""  [unitaries] 
)
See also
multiControlledPhaseFlip
Author
Tyson Jones

Definition at line 1024 of file test_unitaries.cpp.

1024  {
1025 
1026  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1027 
1028  // acts on the final control qubit
1029  QMatrix op{{1,0},{0,-1}};
1030 
1031  SECTION( "correctness" ) {
1032 
1033  // generate ALL valid qubit arrangements
1034  int numCtrls = GENERATE( range(1,NUM_QUBITS) ); // numCtrls=NUM_QUBITS stopped by overzealous validation
1035  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls) );
1036 
1037  SECTION( "state-vector" ) {
1038 
1039  multiControlledPhaseFlip(quregVec, ctrls, numCtrls);
1040  applyReferenceOp(refVec, ctrls, numCtrls-1, ctrls[numCtrls-1], op);
1041  REQUIRE( areEqual(quregVec, refVec) );
1042  }
1043  SECTION( "density-matrix" ) {
1044 
1045  multiControlledPhaseFlip(quregMatr, ctrls, numCtrls);
1046  applyReferenceOp(refMatr, ctrls, numCtrls-1, ctrls[numCtrls-1], op);
1047  REQUIRE( areEqual(quregMatr, refMatr) );
1048  }
1049  }
1050  SECTION( "input validation" ) {
1051 
1052  SECTION( "number of controls" ) {
1053 
1054  int numCtrls = GENERATE( -1, 0, NUM_QUBITS+1 );
1055  int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
1056  REQUIRE_THROWS_WITH( multiControlledPhaseFlip(quregVec, ctrls, numCtrls), Contains("Invalid number of qubits"));
1057  }
1058  SECTION( "repetition of controls" ) {
1059 
1060  int numCtrls = 3;
1061  int ctrls[] = {0,1,1};
1062  REQUIRE_THROWS_WITH( multiControlledPhaseFlip(quregVec, ctrls, numCtrls), Contains("qubits must be unique"));
1063  }
1064  SECTION( "qubit indices" ) {
1065 
1066  int numCtrls = 3;
1067  int ctrls[] = { 1, 2, GENERATE( -1, NUM_QUBITS ) };
1068  REQUIRE_THROWS_WITH( multiControlledPhaseFlip(quregVec, ctrls, numCtrls), Contains("Invalid qubit") );
1069  }
1070  }
1071  CLEANUP_TEST( quregVec, quregMatr );
1072 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, multiControlledPhaseFlip(), NUM_QUBITS, PREPARE_TEST, and sublists().

◆ TEST_CASE() [65/88]

TEST_CASE ( "multiControlledPhaseShift"  ,
""  [unitaries] 
)
See also
multiControlledPhaseShift
Author
Tyson Jones

Definition at line 1080 of file test_unitaries.cpp.

1080  {
1081 
1082  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1083  qreal param = getRandomReal(-2*M_PI, 2*M_PI);
1084  QMatrix op{{1,0},{0,expI(param)}};
1085 
1086  SECTION( "correctness" ) {
1087 
1088  // generate ALL valid qubit arrangements
1089  int numCtrls = GENERATE( range(1,NUM_QUBITS) ); // numCtrls=NUM_QUBITS stopped by overzealous validation
1090  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls) );
1091 
1092  SECTION( "state-vector" ) {
1093 
1094  multiControlledPhaseShift(quregVec, ctrls, numCtrls, param);
1095  applyReferenceOp(refVec, ctrls, numCtrls-1, ctrls[numCtrls-1], op);
1096  REQUIRE( areEqual(quregVec, refVec) );
1097  }
1098  SECTION( "density-matrix" ) {
1099 
1100  multiControlledPhaseShift(quregMatr, ctrls, numCtrls, param);
1101  applyReferenceOp(refMatr, ctrls, numCtrls-1, ctrls[numCtrls-1], op);
1102  REQUIRE( areEqual(quregMatr, refMatr) );
1103  }
1104  }
1105  SECTION( "input validation" ) {
1106 
1107  SECTION( "number of controls" ) {
1108 
1109  int numCtrls = GENERATE( -1, 0, NUM_QUBITS+1 );
1110  int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
1111  REQUIRE_THROWS_WITH( multiControlledPhaseShift(quregVec, ctrls, numCtrls, param), Contains("Invalid number of qubits"));
1112  }
1113  SECTION( "repetition of controls" ) {
1114 
1115  int numCtrls = 3;
1116  int ctrls[] = {0,1,1};
1117  REQUIRE_THROWS_WITH( multiControlledPhaseShift(quregVec, ctrls, numCtrls, param), Contains("qubits must be unique"));
1118  }
1119  SECTION( "qubit indices" ) {
1120 
1121  int numCtrls = 3;
1122  int ctrls[] = { 1, 2, GENERATE( -1, NUM_QUBITS ) };
1123  REQUIRE_THROWS_WITH( multiControlledPhaseShift(quregVec, ctrls, numCtrls, param), Contains("Invalid qubit") );
1124  }
1125  }
1126  CLEANUP_TEST( quregVec, quregMatr );
1127 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), multiControlledPhaseShift(), NUM_QUBITS, PREPARE_TEST, qreal, and sublists().

◆ TEST_CASE() [66/88]

TEST_CASE ( "multiControlledTwoQubitUnitary"  ,
""  [unitaries] 
)
See also
multiControlledTwoQubitUnitary
Author
Tyson Jones

Definition at line 1135 of file test_unitaries.cpp.

1135  {
1136 
1137  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1138 
1139  // in distributed mode, each node must be able to fit all amps modified by unitary
1140  REQUIRE( quregVec.numAmpsPerChunk >= 4 );
1141 
1142  // every test will use a unique random matrix
1143  QMatrix op = getRandomUnitary(2);
1144  ComplexMatrix4 matr = toComplexMatrix4(op);
1145 
1146  SECTION( "correctness" ) {
1147 
1148  // generate ALL valid qubit arrangements
1149  int targ1 = GENERATE( range(0,NUM_QUBITS) );
1150  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
1151  int targs[] = {targ1, targ2};
1152  int numCtrls = GENERATE( range(1,NUM_QUBITS-1) ); // leave room for 2 targets (upper bound is exclusive)
1153  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls, targs, 2) );
1154 
1155  SECTION( "state-vector" ) {
1156 
1157  multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, targ2, matr);
1158  applyReferenceOp(refVec, ctrls, numCtrls, targ1, targ2, op);
1159  REQUIRE( areEqual(quregVec, refVec) );
1160  }
1161  SECTION( "density-matrix" ) {
1162 
1163  multiControlledTwoQubitUnitary(quregMatr, ctrls, numCtrls, targ1, targ2, matr);
1164  applyReferenceOp(refMatr, ctrls, numCtrls, targ1, targ2, op);
1165  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
1166  }
1167  }
1168  SECTION( "input validation" ) {
1169 
1170  SECTION( "number of controls" ) {
1171 
1172  // numCtrls=(NUM_QUBITS-1) is ok since requires ctrl qubit inds are invalid
1173  int numCtrls = GENERATE( -1, 0, NUM_QUBITS, NUM_QUBITS+1 );
1174  int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
1175  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, 0, 1, matr), Contains("Invalid number of control"));
1176  }
1177  SECTION( "repetition of controls" ) {
1178 
1179  int numCtrls = 3;
1180  int ctrls[] = {0,1,1};
1181  int targ1 = 2;
1182  int targ2 = 3;
1183  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, targ2, matr), Contains("control") && Contains("unique"));;
1184  }
1185  SECTION( "repetition of targets" ) {
1186 
1187  int numCtrls = 3;
1188  int ctrls[] = {0,1,2};
1189  int targ1 = 3;
1190  int targ2 = targ1;
1191  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, targ2, matr), Contains("target") && Contains("unique"));
1192  }
1193  SECTION( "control and target collision" ) {
1194 
1195  int numCtrls = 3;
1196  int ctrls[] = {0,1,2};
1197  int targ1 = 3;
1198  int targ2 = ctrls[GENERATE_COPY( range(0,numCtrls) )];
1199  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, targ2, matr), Contains("Control") && Contains("target") );
1200  }
1201  SECTION( "qubit indices" ) {
1202 
1203  // valid indices
1204  int targ1 = 0;
1205  int targ2 = 1;
1206  int numCtrls = 3;
1207  int ctrls[] = { 2, 3, 4 };
1208 
1209  int inv = GENERATE( -1, NUM_QUBITS );
1210  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, inv, targ2, matr), Contains("Invalid target") );
1211  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, inv, matr), Contains("Invalid target") );
1212 
1213  ctrls[numCtrls-1] = inv; // make ctrls invalid
1214  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, numCtrls, targ1, targ2, matr), Contains("Invalid control") );
1215  }
1216  SECTION( "unitarity " ) {
1217 
1218  int ctrls[1] = {0};
1219  matr.real[0][0] = 0; // break unitarity
1220  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, 1, 1, 2, matr), Contains("unitary") );
1221  }
1222  SECTION( "unitary fits in node" ) {
1223 
1224  // pretend we have a very limited distributed memory
1225  quregVec.numAmpsPerChunk = 1;
1226  int ctrls[1] = {0};
1227  REQUIRE_THROWS_WITH( multiControlledTwoQubitUnitary(quregVec, ctrls, 1, 1, 2, matr), Contains("targets too many qubits"));
1228  }
1229  }
1230  CLEANUP_TEST( quregVec, quregMatr );
1231 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), multiControlledTwoQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, sublists(), and toComplexMatrix4().

◆ TEST_CASE() [67/88]

TEST_CASE ( "multiControlledUnitary"  ,
""  [unitaries] 
)
See also
multiControlledUnitary
Author
Tyson Jones

Definition at line 1239 of file test_unitaries.cpp.

1239  {
1240 
1241  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1242 
1243  // every test will use a unique random matrix
1244  QMatrix op = getRandomUnitary(1);
1245  ComplexMatrix2 matr = toComplexMatrix2(op);
1246 
1247  SECTION( "correctness" ) {
1248 
1249  int target = GENERATE( range(0,NUM_QUBITS) );
1250  int numCtrls = GENERATE( range(1,NUM_QUBITS) ); // leave space for one target (exclusive upper bound)
1251  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls, target) );
1252 
1253  SECTION( "state-vector" ) {
1254 
1255  multiControlledUnitary(quregVec, ctrls, numCtrls, target, matr);
1256  applyReferenceOp(refVec, ctrls, numCtrls, target, op);
1257  REQUIRE( areEqual(quregVec, refVec) );
1258  }
1259  SECTION( "density-matrix" ) {
1260 
1261  multiControlledUnitary(quregMatr, ctrls, numCtrls, target, matr);
1262  applyReferenceOp(refMatr, ctrls, numCtrls, target, op);
1263  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
1264  }
1265  }
1266  SECTION( "input validation" ) {
1267 
1268  SECTION( "number of controls" ) {
1269 
1270  int numCtrls = GENERATE( -1, 0, NUM_QUBITS, NUM_QUBITS+1 );
1271  int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
1272  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, numCtrls, 0, matr), Contains("Invalid number of control"));
1273  }
1274  SECTION( "repetition of controls" ) {
1275 
1276  int ctrls[] = {0,1,1};
1277  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, 3, 2, matr), Contains("control") && Contains("unique"));
1278  }
1279  SECTION( "control and target collision" ) {
1280 
1281  int ctrls[] = {0,1,2};
1282  int targ = ctrls[GENERATE( range(0,3) )];
1283  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, 3, targ, matr), Contains("Control") && Contains("target") );
1284  }
1285  SECTION( "qubit indices" ) {
1286 
1287  int ctrls[] = { 1, 2, GENERATE( -1, NUM_QUBITS ) };
1288  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, 3, 0, matr), Contains("Invalid control") );
1289 
1290  ctrls[2] = 3; // make ctrls valid
1291  int targ = GENERATE( -1, NUM_QUBITS );
1292  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, 3, targ, matr), Contains("Invalid target") );
1293  }
1294  SECTION( "unitarity" ) {
1295 
1296  matr.real[0][0] = 0; // break matr unitarity
1297  int ctrls[] = {0};
1298  REQUIRE_THROWS_WITH( multiControlledUnitary(quregVec, ctrls, 1, 1, matr), Contains("unitary") );
1299  }
1300  }
1301  CLEANUP_TEST( quregVec, quregMatr );
1302 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), multiControlledUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, sublists(), and toComplexMatrix2().

◆ TEST_CASE() [68/88]

TEST_CASE ( "multiQubitUnitary"  ,
""  [unitaries] 
)
See also
multiQubitUnitary
Author
Tyson Jones

Definition at line 1310 of file test_unitaries.cpp.

1310  {
1311 
1312  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1313 
1314  // figure out max-num (inclusive) targs allowed by hardware backend
1315  int maxNumTargs = calcLog2(quregVec.numAmpsPerChunk);
1316 
1317  SECTION( "correctness" ) {
1318 
1319  // generate all possible qubit arrangements
1320  int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) ); // inclusive upper bound
1321  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
1322 
1323  // for each qubit arrangement, use a new random unitary
1324  QMatrix op = getRandomUnitary(numTargs);
1325  ComplexMatrixN matr = createComplexMatrixN(numTargs);
1326  toComplexMatrixN(op, matr);
1327 
1328  SECTION( "state-vector" ) {
1329 
1330  multiQubitUnitary(quregVec, targs, numTargs, matr);
1331  applyReferenceOp(refVec, targs, numTargs, op);
1332  REQUIRE( areEqual(quregVec, refVec) );
1333  }
1334  SECTION( "density-matrix" ) {
1335 
1336  multiQubitUnitary(quregMatr, targs, numTargs, matr);
1337  applyReferenceOp(refMatr, targs, numTargs, op);
1338  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
1339  }
1340  destroyComplexMatrixN(matr);
1341  }
1342  SECTION( "input validation" ) {
1343 
1344  SECTION( "number of targets" ) {
1345 
1346  // there cannot be more targets than qubits in register
1347  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
1348  int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
1349  ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
1350 
1351  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, numTargs, matr), Contains("Invalid number of target"));
1352  destroyComplexMatrixN(matr);
1353  }
1354  SECTION( "repetition in targets" ) {
1355 
1356  int numTargs = 3;
1357  int targs[] = {1,2,2};
1358  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
1359 
1360  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, numTargs, matr), Contains("target") && Contains("unique"));
1361  destroyComplexMatrixN(matr);
1362  }
1363  SECTION( "qubit indices" ) {
1364 
1365  int numTargs = 3;
1366  int targs[] = {1,2,3};
1367  ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
1368 
1369  int inv = GENERATE( -1, NUM_QUBITS );
1370  targs[GENERATE_COPY( range(0,numTargs) )] = inv; // make invalid target
1371  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, numTargs, matr), Contains("Invalid target") );
1372 
1373  destroyComplexMatrixN(matr);
1374  }
1375  SECTION( "unitarity" ) {
1376 
1377  int numTargs = GENERATE_COPY( range(1,maxNumTargs) );
1378  int targs[numTargs];
1379  for (int i=0; i<numTargs; i++)
1380  targs[i] = i+1;
1381 
1382  ComplexMatrixN matr = createComplexMatrixN(numTargs); // initially zero, hence not-unitary
1383 
1384  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, numTargs, matr), Contains("unitary") );
1385  destroyComplexMatrixN(matr);
1386  }
1387  SECTION( "unitary creation" ) {
1388 
1389  int numTargs = 3;
1390  int targs[] = {1,2,3};
1391 
1392  /* compilers don't auto-initialise to NULL; the below circumstance
1393  * only really occurs when 'malloc' returns NULL in createComplexMatrixN,
1394  * which actually triggers its own validation. Hence this test is useless
1395  * currently.
1396  */
1397  ComplexMatrixN matr;
1398  matr.real = NULL;
1399  matr.imag = NULL;
1400  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, numTargs, matr), Contains("created") );
1401  }
1402  SECTION( "unitary dimensions" ) {
1403 
1404  int targs[2] = {1,2};
1405  ComplexMatrixN matr = createComplexMatrixN(3); // intentionally wrong size
1406 
1407  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, targs, 2, matr), Contains("matrix size"));
1408  destroyComplexMatrixN(matr);
1409  }
1410  SECTION( "unitary fits in node" ) {
1411 
1412  // pretend we have a very limited distributed memory (judged by matr size)
1413  quregVec.numAmpsPerChunk = 1;
1414  int qb[] = {1,2};
1415  ComplexMatrixN matr = createComplexMatrixN(2); // prevents seg-fault if validation doesn't trigger
1416  REQUIRE_THROWS_WITH( multiQubitUnitary(quregVec, qb, 2, matr), Contains("targets too many qubits"));
1417  destroyComplexMatrixN(matr);
1418  }
1419  }
1420  CLEANUP_TEST( quregVec, quregMatr );
1421 }

References applyReferenceOp(), areEqual(), calcLog2(), CLEANUP_TEST, createComplexMatrixN(), destroyComplexMatrixN(), getRandomUnitary(), ComplexMatrixN::imag, multiQubitUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrixN::real, sublists(), and toComplexMatrixN().

◆ TEST_CASE() [69/88]

TEST_CASE ( "multiRotatePauli"  ,
""  [unitaries] 
)
See also
multiRotatePauli
Author
Tyson Jones

Definition at line 1429 of file test_unitaries.cpp.

1429  {
1430 
1431  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1432  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
1433 
1434  SECTION( "correctness" ) {
1435 
1436  int numTargs = GENERATE( range(1,NUM_QUBITS+1) );
1437  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
1438 
1439  /* it's too expensive to try ALL Pauli sequences, via
1440  * pauliOpType* paulis = GENERATE_COPY( pauliseqs(numTargs) );.
1441  * Furthermore, take(10, pauliseqs(numTargs)) will try the same pauli codes.
1442  * Hence, we instead opt to repeatedlyrandomly generate pauliseqs
1443  */
1444  GENERATE( range(0,10) ); // gen 10 random pauli-codes for every targs
1445  pauliOpType paulis[numTargs];
1446  for (int i=0; i<numTargs; i++)
1447  paulis[i] = (pauliOpType) getRandomInt(0,4);
1448 
1449  // exclude identities from reference matrix exp (they apply unwanted global phase)
1450  int refTargs[numTargs];
1451  int numRefTargs = 0;
1452 
1453  QMatrix xMatr{{0,1},{1,0}};
1454  QMatrix yMatr{{0,-1i},{1i,0}};
1455  QMatrix zMatr{{1,0},{0,-1}};
1456 
1457  // build correct reference matrix by pauli-matrix exponentiation...
1458  QMatrix pauliProd{{1}};
1459  for (int i=0; i<numTargs; i++) {
1460  QMatrix fac;
1461  if (paulis[i] == PAULI_I) continue; // exclude I-targets from ref list
1462  if (paulis[i] == PAULI_X) fac = xMatr;
1463  if (paulis[i] == PAULI_Y) fac = yMatr;
1464  if (paulis[i] == PAULI_Z) fac = zMatr;
1465  pauliProd = getKroneckerProduct(fac, pauliProd);
1466 
1467  // include this target in ref list
1468  refTargs[numRefTargs++] = targs[i];
1469  }
1470 
1471  // produces exp(-i param/2 pauliProd), unless pauliProd = I
1472  QMatrix op;
1473  if (numRefTargs > 0)
1474  op = getExponentialOfPauliMatrix(param, pauliProd);
1475 
1476  SECTION( "state-vector" ) {
1477 
1478  multiRotatePauli(quregVec, targs, paulis, numTargs, param);
1479  if (numRefTargs > 0)
1480  applyReferenceOp(refVec, refTargs, numRefTargs, op);
1481  REQUIRE( areEqual(quregVec, refVec) );
1482  }
1483  SECTION( "density-matrix" ) {
1484 
1485  multiRotatePauli(quregMatr, targs, paulis, numTargs, param);
1486  if (numRefTargs > 0)
1487  applyReferenceOp(refMatr, refTargs, numRefTargs, op);
1488  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
1489  }
1490  }
1491  SECTION( "input validation" ) {
1492 
1493  SECTION( "number of targets" ) {
1494 
1495  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
1496  int targs[NUM_QUBITS+1]; // prevent seg-fault if validation isn't triggered
1497  pauliOpType paulis[NUM_QUBITS+1] = {PAULI_I};
1498  REQUIRE_THROWS_WITH( multiRotatePauli(quregVec, targs, paulis, numTargs, param), Contains("Invalid number of target"));
1499 
1500  }
1501  SECTION( "repetition of targets" ) {
1502 
1503  int numTargs = 3;
1504  int targs[3] = {0, 1, 1};
1505  pauliOpType paulis[3] = {PAULI_I};
1506  REQUIRE_THROWS_WITH( multiRotatePauli(quregVec, targs, paulis, numTargs, param), Contains("target") && Contains("unique"));
1507  }
1508  SECTION( "qubit indices" ) {
1509 
1510  int numTargs = 3;
1511  int targs[3] = {0, 1, 2};
1512  targs[GENERATE_COPY(range(0,numTargs))] = GENERATE( -1, NUM_QUBITS );
1513  pauliOpType paulis[3] = {PAULI_I};
1514  REQUIRE_THROWS_WITH( multiRotatePauli(quregVec, targs, paulis, numTargs, param), Contains("Invalid target"));
1515  }
1516  SECTION( "pauli codes" ) {
1517  int numTargs = 3;
1518  int targs[3] = {0, 1, 2};
1519  pauliOpType paulis[3] = {PAULI_I, PAULI_I, PAULI_I};
1520  paulis[GENERATE_COPY(range(0,numTargs))] = (pauliOpType) GENERATE( -1, 4 );
1521  REQUIRE_THROWS_WITH( multiRotatePauli(quregVec, targs, paulis, numTargs, param), Contains("Invalid Pauli code"));
1522  }
1523  }
1524  CLEANUP_TEST( quregVec, quregMatr );
1525 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfPauliMatrix(), getKroneckerProduct(), getRandomInt(), getRandomReal(), multiRotatePauli(), NUM_QUBITS, PAULI_I, PAULI_X, PAULI_Y, PAULI_Z, PREPARE_TEST, qreal, and sublists().

◆ TEST_CASE() [70/88]

TEST_CASE ( "multiRotateZ"  ,
""  [unitaries] 
)
See also
multiRotateZ
Author
Tyson Jones

Definition at line 1533 of file test_unitaries.cpp.

1533  {
1534 
1535  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1536  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
1537 
1538  SECTION( "correctness" ) {
1539 
1540  int numTargs = GENERATE( range(1,NUM_QUBITS+1) );
1541  int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
1542 
1543  // build correct reference matrix by diagonal-matrix exponentiation...
1544  QMatrix zMatr{{1,0},{0,-1}};
1545  QMatrix zProd = zMatr;
1546  for (int t=0; t<numTargs-1; t++)
1547  zProd = getKroneckerProduct(zMatr, zProd); // Z . Z ... Z
1548 
1549  // (-i param/2) Z . I . Z ...
1550  QMatrix expArg = (-1i * param / 2.) *
1551  getFullOperatorMatrix(NULL, 0, targs, numTargs, zProd, NUM_QUBITS);
1552 
1553  // exp( -i param/2 Z . I . Z ...)
1555 
1556  // all qubits to specify full operator matrix on reference structures
1557  int allQubits[NUM_QUBITS];
1558  for (int i=0; i<NUM_QUBITS; i++)
1559  allQubits[i] = i;
1560 
1561  SECTION( "state-vector" ) {
1562 
1563  multiRotateZ(quregVec, targs, numTargs, param);
1564  applyReferenceOp(refVec, allQubits, NUM_QUBITS, op);
1565  REQUIRE( areEqual(quregVec, refVec) );
1566 
1567  }
1568  SECTION( "density-matrix" ) {
1569 
1570  multiRotateZ(quregMatr, targs, numTargs, param);
1571  applyReferenceOp(refMatr, allQubits, NUM_QUBITS, op);
1572  REQUIRE( areEqual(quregMatr, refMatr, 2*REAL_EPS) );
1573  }
1574  }
1575  SECTION( "input validation" ) {
1576 
1577  SECTION( "number of targets" ) {
1578 
1579  int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
1580  int targs[NUM_QUBITS+1]; // prevent seg-fault if validation isn't triggered
1581  REQUIRE_THROWS_WITH( multiRotateZ(quregVec, targs, numTargs, param), Contains("Invalid number of target"));
1582 
1583  }
1584  SECTION( "repetition of targets" ) {
1585 
1586  int numTargs = 3;
1587  int targs[3] = {0, 1, 1};
1588  REQUIRE_THROWS_WITH( multiRotateZ(quregVec, targs, numTargs, param), Contains("target") && Contains("unique"));
1589  }
1590  SECTION( "qubit indices" ) {
1591 
1592  int numTargs = 3;
1593  int targs[3] = {0, 1, 2};
1594  targs[GENERATE_COPY(range(0,numTargs))] = GENERATE( -1, NUM_QUBITS );
1595  REQUIRE_THROWS_WITH( multiRotateZ(quregVec, targs, numTargs, param), Contains("Invalid target"));
1596  }
1597  }
1598  CLEANUP_TEST( quregVec, quregMatr );
1599 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, getExponentialOfDiagonalMatrix(), getFullOperatorMatrix(), getKroneckerProduct(), getRandomReal(), multiRotateZ(), NUM_QUBITS, PREPARE_TEST, qreal, and sublists().

◆ TEST_CASE() [71/88]

TEST_CASE ( "multiStateControlledUnitary"  ,
""  [unitaries] 
)
See also
multiStateControlledUnitary
Author
Tyson Jones

Definition at line 1607 of file test_unitaries.cpp.

1607  {
1608 
1609  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1610 
1611  // every test will use a unique random matrix
1612  QMatrix op = getRandomUnitary(1);
1613  ComplexMatrix2 matr = toComplexMatrix2(op);
1614 
1615  // the zero-conditioned control qubits can be effected by notting before/after ctrls
1616  QMatrix notOp{{0,1},{1,0}};
1617 
1618  SECTION( "correctness" ) {
1619 
1620  int target = GENERATE( range(0,NUM_QUBITS) );
1621  int numCtrls = GENERATE( range(1,NUM_QUBITS) ); // leave space for one target (exclusive upper bound)
1622  int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls, target) );
1623  int* ctrlState = GENERATE_COPY( bitsets(numCtrls) );
1624 
1625  SECTION( "state-vector" ) {
1626 
1627  multiStateControlledUnitary(quregVec, ctrls, ctrlState, numCtrls, target, matr);
1628 
1629  // simulate controlled-state by notting before & after controls
1630  for (int i=0; i<numCtrls; i++)
1631  if (ctrlState[i] == 0)
1632  applyReferenceOp(refVec, ctrls[i], notOp);
1633  applyReferenceOp(refVec, ctrls, numCtrls, target, op);
1634  for (int i=0; i<numCtrls; i++)
1635  if (ctrlState[i] == 0)
1636  applyReferenceOp(refVec, ctrls[i], notOp);
1637 
1638  REQUIRE( areEqual(quregVec, refVec) );
1639  }
1640  SECTION( "density-matrix" ) {
1641 
1642  multiStateControlledUnitary(quregMatr, ctrls, ctrlState, numCtrls, target, matr);
1643 
1644  // simulate controlled-state by notting before & after controls
1645  for (int i=0; i<numCtrls; i++)
1646  if (ctrlState[i] == 0)
1647  applyReferenceOp(refMatr, ctrls[i], notOp);
1648  applyReferenceOp(refMatr, ctrls, numCtrls, target, op);
1649  for (int i=0; i<numCtrls; i++)
1650  if (ctrlState[i] == 0)
1651  applyReferenceOp(refMatr, ctrls[i], notOp);
1652 
1653  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
1654  }
1655  }
1656  SECTION( "input validation" ) {
1657 
1658  SECTION( "number of controls" ) {
1659 
1660  int numCtrls = GENERATE( -1, 0, NUM_QUBITS, NUM_QUBITS+1 );
1661  int ctrls[NUM_QUBITS+1];
1662  int ctrlState[NUM_QUBITS+1] = {0};
1663  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, numCtrls, 0, matr), Contains("Invalid number of control"));
1664  }
1665  SECTION( "repetition of controls" ) {
1666 
1667  int ctrls[] = {0,1,1};
1668  int ctrlState[] = {0, 1, 0};
1669  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 3, 2, matr), Contains("control") && Contains("unique"));
1670  }
1671  SECTION( "control and target collision" ) {
1672 
1673  int ctrls[] = {0,1,2};
1674  int ctrlState[] = {0, 1, 0};
1675  int targ = ctrls[GENERATE( range(0,3) )];
1676  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 3, targ, matr), Contains("Control") && Contains("target") );
1677  }
1678  SECTION( "qubit indices" ) {
1679 
1680  int ctrls[] = { 1, 2, GENERATE( -1, NUM_QUBITS ) };
1681  int ctrlState[] = {0, 1, 0};
1682  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 3, 0, matr), Contains("Invalid control") );
1683 
1684  ctrls[2] = 3; // make ctrls valid
1685  int targ = GENERATE( -1, NUM_QUBITS );
1686  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 3, targ, matr), Contains("Invalid target") );
1687  }
1688  SECTION( "unitarity" ) {
1689 
1690  matr.real[0][0] = 0; // break matr unitarity
1691  int ctrls[] = {0};
1692  int ctrlState[1] = {0};
1693  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 1, 1, matr), Contains("unitary") );
1694  }
1695  SECTION( "control state bits" ) {
1696 
1697  // valid qubits
1698  int ctrls[] = {0, 1, 2};
1699  int ctrlState[] = {0, 0, 0};
1700  int targ = 3;
1701 
1702  // make invalid
1703  ctrlState[2] = GENERATE(-1, 2);
1704  REQUIRE_THROWS_WITH( multiStateControlledUnitary(quregVec, ctrls, ctrlState, 3, targ, matr), Contains("state") );
1705  }
1706  }
1707  CLEANUP_TEST( quregVec, quregMatr );
1708 }

References applyReferenceOp(), areEqual(), bitsets(), CLEANUP_TEST, getRandomUnitary(), multiStateControlledUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, sublists(), and toComplexMatrix2().

◆ TEST_CASE() [72/88]

TEST_CASE ( "pauliX"  ,
""  [unitaries] 
)
See also
pauliX
Author
Tyson Jones

Definition at line 1716 of file test_unitaries.cpp.

1716  {
1717 
1718  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1719  QMatrix op{{0,1},{1,0}};
1720 
1721  SECTION( "correctness" ) {
1722 
1723  int target = GENERATE( range(0,NUM_QUBITS) );
1724 
1725  SECTION( "state-vector" ) {
1726 
1727  pauliX(quregVec, target);
1728  applyReferenceOp(refVec, target, op);
1729  REQUIRE( areEqual(quregVec, refVec) );
1730  }
1731  SECTION( "density-matrix correctness" ) {
1732 
1733  pauliX(quregMatr, target);
1734  applyReferenceOp(refMatr, target, op);
1735  REQUIRE( areEqual(quregMatr, refMatr) );
1736  }
1737  }
1738  SECTION( "input validation" ) {
1739 
1740  SECTION( "qubit indices" ) {
1741 
1742  int target = GENERATE( -1, NUM_QUBITS );
1743  REQUIRE_THROWS_WITH( pauliX(quregVec, target), Contains("Invalid target") );
1744  }
1745  }
1746  CLEANUP_TEST( quregVec, quregMatr );
1747 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliX(), and PREPARE_TEST.

◆ TEST_CASE() [73/88]

TEST_CASE ( "pauliY"  ,
""  [unitaries] 
)
See also
pauliY
Author
Tyson Jones

Definition at line 1755 of file test_unitaries.cpp.

1755  {
1756 
1757  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1758  QMatrix op{{0,-1i},{1i,0}};
1759 
1760  SECTION( "correctness" ) {
1761 
1762  int target = GENERATE( range(0,NUM_QUBITS) );
1763 
1764  SECTION( "state-vector" ) {
1765 
1766  pauliY(quregVec, target);
1767  applyReferenceOp(refVec, target, op);
1768  REQUIRE( areEqual(quregVec, refVec) );
1769  }
1770  SECTION( "density-matrix correctness" ) {
1771 
1772  pauliY(quregMatr, target);
1773  applyReferenceOp(refMatr, target, op);
1774  REQUIRE( areEqual(quregMatr, refMatr) );
1775  }
1776  }
1777  SECTION( "input validation" ) {
1778 
1779  SECTION( "qubit indices" ) {
1780 
1781  int target = GENERATE( -1, NUM_QUBITS );
1782  REQUIRE_THROWS_WITH( pauliY(quregVec, target), Contains("Invalid target") );
1783  }
1784  }
1785  CLEANUP_TEST( quregVec, quregMatr );
1786 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliY(), and PREPARE_TEST.

◆ TEST_CASE() [74/88]

TEST_CASE ( "pauliZ"  ,
""  [unitaries] 
)
See also
pauliZ
Author
Tyson Jones

Definition at line 1794 of file test_unitaries.cpp.

1794  {
1795 
1796  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1797  QMatrix op{{1,0},{0,-1}};
1798 
1799  SECTION( "correctness" ) {
1800 
1801  int target = GENERATE( range(0,NUM_QUBITS) );
1802 
1803  SECTION( "state-vector" ) {
1804 
1805  pauliZ(quregVec, target);
1806  applyReferenceOp(refVec, target, op);
1807  REQUIRE( areEqual(quregVec, refVec) );
1808  }
1809  SECTION( "density-matrix correctness" ) {
1810 
1811  pauliZ(quregMatr, target);
1812  applyReferenceOp(refMatr, target, op);
1813  REQUIRE( areEqual(quregMatr, refMatr) );
1814  }
1815  }
1816  SECTION( "input validation" ) {
1817 
1818  SECTION( "qubit indices" ) {
1819 
1820  int target = GENERATE( -1, NUM_QUBITS );
1821  REQUIRE_THROWS_WITH( pauliZ(quregVec, target), Contains("Invalid target") );
1822  }
1823  }
1824  CLEANUP_TEST( quregVec, quregMatr );
1825 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, pauliZ(), and PREPARE_TEST.

◆ TEST_CASE() [75/88]

TEST_CASE ( "phaseShift"  ,
""  [unitaries] 
)
See also
phaseShift
Author
Tyson Jones

Definition at line 1833 of file test_unitaries.cpp.

1833  {
1834 
1835  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1836  qreal param = getRandomReal(-2*M_PI, 2*M_PI);
1837  QMatrix op{{1,0},{0,expI(param)}};
1838 
1839  SECTION( "correctness" ) {
1840 
1841  int target = GENERATE( range(0,NUM_QUBITS) );
1842 
1843  SECTION( "state-vector ") {
1844 
1845  phaseShift(quregVec, target, param);
1846  applyReferenceOp(refVec, target, op);
1847  REQUIRE( areEqual(quregVec, refVec) );
1848  }
1849  SECTION( "density-matrix" ) {
1850 
1851  phaseShift(quregMatr, target, param);
1852  applyReferenceOp(refMatr, target, op);
1853  REQUIRE( areEqual(quregMatr, refMatr) );
1854  }
1855  }
1856  SECTION( "input validation" ) {
1857 
1858  SECTION( "qubit indices" ) {
1859 
1860  int target = GENERATE( -1, NUM_QUBITS );
1861  REQUIRE_THROWS_WITH( phaseShift(quregVec, target, param), Contains("Invalid target") );
1862  }
1863  }
1864  CLEANUP_TEST( quregVec, quregMatr );
1865 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), NUM_QUBITS, phaseShift(), PREPARE_TEST, and qreal.

◆ TEST_CASE() [76/88]

TEST_CASE ( "rotateAroundAxis"  ,
""  [unitaries] 
)
See also
rotateAroundAxis
Author
Tyson Jones

Definition at line 1873 of file test_unitaries.cpp.

1873  {
1874 
1875  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1876 
1877  // each test will use a random parameter and axis vector
1878  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
1879  Vector vec = {.x=getRandomReal(-1,1), .y=getRandomReal(-1,1), .z=getRandomReal(-1,1)};
1880 
1881  // Rn(a) = cos(a/2)I - i sin(a/2) n . paulivector
1882  // (pg 24 of vcpc.univie.ac.at/~ian/hotlist/qc/talks/bloch-sphere-rotations.pdf)
1883  qreal c = cos(param/2);
1884  qreal s = sin(param/2);
1885  qreal m = sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z);
1886  QMatrix op{{c - 1i*vec.z*s/m, -(vec.y + 1i*vec.x)*s/m},
1887  {(vec.y - 1i*vec.x)*s/m, c + 1i*vec.z*s/m}};
1888 
1889  SECTION( "correctness" ) {
1890 
1891  int target = GENERATE( range(0,NUM_QUBITS) );
1892 
1893  SECTION( "state-vector ") {
1894 
1895  rotateAroundAxis(quregVec, target, param, vec);
1896  applyReferenceOp(refVec, target, op);
1897  REQUIRE( areEqual(quregVec, refVec) );
1898  }
1899  SECTION( "density-matrix" ) {
1900 
1901  rotateAroundAxis(quregMatr, target, param, vec);
1902  applyReferenceOp(refMatr, target, op);
1903  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
1904  }
1905  }
1906  SECTION( "input validation" ) {
1907 
1908  SECTION( "qubit indices" ) {
1909 
1910  int target = GENERATE( -1, NUM_QUBITS );
1911  REQUIRE_THROWS_WITH( rotateAroundAxis(quregVec, target, param, vec), Contains("Invalid target") );
1912  }
1913  SECTION( "zero rotation axis" ) {
1914 
1915  int target = 0;
1916  vec = {.x=0, .y=0, .z=0};
1917  REQUIRE_THROWS_WITH( rotateAroundAxis(quregVec, target, param, vec), Contains("Invalid axis") && Contains("zero") );
1918  }
1919  }
1920  CLEANUP_TEST( quregVec, quregMatr );
1921 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), NUM_QUBITS, PREPARE_TEST, qreal, rotateAroundAxis(), Vector::x, Vector::y, and Vector::z.

◆ TEST_CASE() [77/88]

TEST_CASE ( "rotateX"  ,
""  [unitaries] 
)
See also
rotateX
Author
Tyson Jones

Definition at line 1929 of file test_unitaries.cpp.

1929  {
1930 
1931  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1932  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
1933  QMatrix op{{cos(param/2), -1i*sin(param/2)}, {-1i*sin(param/2), cos(param/2)}};
1934 
1935  SECTION( "correctness" ) {
1936 
1937  int target = GENERATE( range(0,NUM_QUBITS) );
1938 
1939  SECTION( "state-vector ") {
1940 
1941  rotateX(quregVec, target, param);
1942  applyReferenceOp(refVec, target, op);
1943  REQUIRE( areEqual(quregVec, refVec) );
1944  }
1945  SECTION( "density-matrix" ) {
1946 
1947  rotateX(quregMatr, target, param);
1948  applyReferenceOp(refMatr, target, op);
1949  REQUIRE( areEqual(quregMatr, refMatr) );
1950  }
1951  }
1952  SECTION( "input validation" ) {
1953 
1954  SECTION( "qubit indices" ) {
1955 
1956  int target = GENERATE( -1, NUM_QUBITS );
1957  REQUIRE_THROWS_WITH( rotateX(quregVec, target, param), Contains("Invalid target") );
1958  }
1959  }
1960  CLEANUP_TEST( quregVec, quregMatr );
1961 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), NUM_QUBITS, PREPARE_TEST, qreal, and rotateX().

◆ TEST_CASE() [78/88]

TEST_CASE ( "rotateY"  ,
""  [unitaries] 
)
See also
rotateY
Author
Tyson Jones

Definition at line 1969 of file test_unitaries.cpp.

1969  {
1970 
1971  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1972  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
1973  QMatrix op{{cos(param/2), -sin(param/2)},{sin(param/2), cos(param/2)}};
1974 
1975  SECTION( "correctness" ) {
1976 
1977  int target = GENERATE( range(0,NUM_QUBITS) );
1978 
1979  SECTION( "state-vector ") {
1980 
1981  rotateY(quregVec, target, param);
1982  applyReferenceOp(refVec, target, op);
1983  REQUIRE( areEqual(quregVec, refVec) );
1984  }
1985  SECTION( "density-matrix" ) {
1986 
1987  rotateY(quregMatr, target, param);
1988  applyReferenceOp(refMatr, target, op);
1989  REQUIRE( areEqual(quregMatr, refMatr, 2*REAL_EPS) );
1990  }
1991  }
1992  SECTION( "input validation" ) {
1993 
1994  SECTION( "qubit indices" ) {
1995 
1996  int target = GENERATE( -1, NUM_QUBITS );
1997  REQUIRE_THROWS_WITH( rotateY(quregVec, target, param), Contains("Invalid target") );
1998  }
1999  }
2000  CLEANUP_TEST( quregVec, quregMatr );
2001 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomReal(), NUM_QUBITS, PREPARE_TEST, qreal, and rotateY().

◆ TEST_CASE() [79/88]

TEST_CASE ( "rotateZ"  ,
""  [unitaries] 
)
See also
rotateZ
Author
Tyson Jones

Definition at line 2009 of file test_unitaries.cpp.

2009  {
2010 
2011  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
2012  qreal param = getRandomReal(-4*M_PI, 4*M_PI);
2013  QMatrix op{{expI(-param/2.),0},{0,expI(param/2.)}};
2014 
2015  SECTION( "correctness" ) {
2016 
2017  int target = GENERATE( range(0,NUM_QUBITS) );
2018 
2019  SECTION( "state-vector ") {
2020 
2021  rotateZ(quregVec, target, param);
2022  applyReferenceOp(refVec, target, op);
2023  REQUIRE( areEqual(quregVec, refVec) );
2024  }
2025  SECTION( "density-matrix" ) {
2026 
2027  rotateZ(quregMatr, target, param);
2028  applyReferenceOp(refMatr, target, op);
2029  REQUIRE( areEqual(quregMatr, refMatr) );
2030  }
2031  }
2032  SECTION( "input validation" ) {
2033 
2034  SECTION( "qubit indices" ) {
2035 
2036  int target = GENERATE( -1, NUM_QUBITS );
2037  REQUIRE_THROWS_WITH( rotateZ(quregVec, target, param), Contains("Invalid target") );
2038  }
2039  }
2040  CLEANUP_TEST( quregVec, quregMatr );
2041 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), getRandomReal(), NUM_QUBITS, PREPARE_TEST, qreal, and rotateZ().

◆ TEST_CASE() [80/88]

TEST_CASE ( "setAmps"  ,
""  [state_initialisations] 
)
See also
setAmps
Author
Tyson Jones

Definition at line 368 of file test_state_initialisations.cpp.

368  {
369 
371 
372  int maxInd = vec.numAmpsTotal;
373  qreal reals[maxInd];
374  qreal imags[maxInd];
375 
376  SECTION( "correctness" ) {
377 
378  SECTION( "state-vector" ) {
379 
380  // all valid number of amplitudes and offsets
381  int startInd = GENERATE_COPY( range(0,maxInd) );
382  int numAmps = GENERATE_COPY( range(0,1+maxInd-startInd) ); // upper-bound allows all amps specified
383 
384  // generate random amplitudes
385  for (int i=0; i<numAmps; i++) {
386  reals[i] = getRandomReal(-5,5);
387  imags[i] = getRandomReal(-5,5);
388  }
389 
390  // check both specified and un-specified amplitudes are correctly handled
391  initDebugState(vec);
392  QVector vecRef = toQVector(vec);
393 
394  setAmps(vec, startInd, reals, imags, numAmps);
395  for (int i=0; i<numAmps; i++)
396  vecRef[startInd+i] = reals[i] + 1i*(imags[i]);
397 
398  REQUIRE( areEqual(vec, vecRef) );
399  }
400  }
401  SECTION( "input validation" ) {
402 
403  SECTION( "start index" ) {
404 
405  int startInd = GENERATE_COPY( -1, maxInd );
406  int numAmps = 0;
407  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid amplitude index") );
408  }
409 
410  SECTION( "number of amplitudes" ) {
411 
412  // independent
413  int startInd = 0;
414  int numAmps = GENERATE_COPY( -1, maxInd+1 );
415  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("Invalid number of amplitudes") );
416 
417  // invalid considering start-index
418  startInd = maxInd - 1;
419  numAmps = 2;
420  REQUIRE_THROWS_WITH( setAmps(vec, startInd, reals, imags, numAmps), Contains("More amplitudes given than exist") );
421  }
422  SECTION( "density-matrix" ) {
423 
425  REQUIRE_THROWS_WITH( setAmps(mat, 0, reals, imags, 0), Contains("valid only for state-vectors") );
426  destroyQureg(mat, QUEST_ENV);
427  }
428  }
429  destroyQureg(vec, QUEST_ENV);
430 }

References areEqual(), createDensityQureg(), createQureg(), destroyQureg(), getRandomReal(), initDebugState(), NUM_QUBITS, Qureg::numAmpsTotal, qreal, QUEST_ENV, setAmps(), and toQVector().

◆ TEST_CASE() [81/88]

TEST_CASE ( "setWeightedQureg"  ,
""  [state_initialisations] 
)
See also
setWeightedQureg
Author
Tyson Jones

Definition at line 438 of file test_state_initialisations.cpp.

438  {
439 
440  SECTION( "correctness" ) {
441 
442  // repeat each test below 10 times
443  GENERATE( range(0,10) );
444 
445  /* note tolerance in areEqual increases with tests, since
446  * small differences propogate in vecC which is not re-initialised
447  */
448 
449  SECTION( "state-vector" ) {
450 
451  // make three random vectors
455  for (int j=0; j<vecA.numAmpsPerChunk; j++) {
456  vecA.stateVec.real[j] = getRandomReal(-5,5); vecA.stateVec.imag[j] = getRandomReal(-5,5);
457  vecB.stateVec.real[j] = getRandomReal(-5,5); vecB.stateVec.imag[j] = getRandomReal(-5,5);
458  vecC.stateVec.real[j] = getRandomReal(-5,5); vecC.stateVec.imag[j] = getRandomReal(-5,5);
459  }
460  copyStateToGPU(vecA); copyStateToGPU(vecB); copyStateToGPU(vecC);
461  QVector refA = toQVector(vecA);
462  QVector refB = toQVector(vecB);
463  QVector refC = toQVector(vecC);
464  QVector refOut;
465 
466  // get three random factors
467  qcomp numA = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
468  qcomp numB = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
469  qcomp numC = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
470  Complex facA = toComplex(numA);
471  Complex facB = toComplex(numB);
472  Complex facC = toComplex(numC);
473 
474  // check out-qureg is correct, when all quregs are unique...
475  setWeightedQureg(facA, vecA, facB, vecB, facC, vecC);
476  refOut = numA*refA + numB*refB + numC*refC;
477  REQUIRE( areEqual(vecC, refOut) );
478 
479  // ... and that other qureg's aren't modified
480  REQUIRE( areEqual(vecA, refA) );
481  REQUIRE( areEqual(vecB, refB) );
482 
483  // check quregOut correct, when it's also qureg2
484  refC = toQVector(vecC);
485  setWeightedQureg(facB, vecB, facC, vecC, facA, vecC);
486  refOut = numB*refB + numC*refC + numA*refC;
487  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
488 
489  // ... and that the remaining qureg is not modified
490  REQUIRE( areEqual(vecB, refB) );
491 
492  // check quregOut correct, when it's also qureg1
493  refC = toQVector(vecC);
494  setWeightedQureg(facC, vecC, facB, vecB, facA, vecC);
495  refOut = numC*refC + numB*refB + numA*refC;
496  REQUIRE( areEqual(vecC, refOut, 10*REAL_EPS) );
497 
498  // ... and that the remaining qureg is not modified
499  REQUIRE( areEqual(vecB, refB) );
500 
501  // check quregOut is correct when it's both input quregs
502  refC = toQVector(vecC);
503  setWeightedQureg(facA, vecC, facB, vecC, facC, vecC);
504  refOut = numA*refC + numB*refC + numC*refC;
505  REQUIRE( areEqual(vecC, refOut, 1E2*REAL_EPS) );
506 
507  // cleanup
508  destroyQureg(vecA, QUEST_ENV);
509  destroyQureg(vecB, QUEST_ENV);
510  destroyQureg(vecC, QUEST_ENV);
511  }
512  SECTION( "density-matrix" ) {
513 
514  // make three random matrices
518  for (int j=0; j<matA.numAmpsPerChunk; j++) {
519  matA.stateVec.real[j] = getRandomReal(-5,5); matA.stateVec.imag[j] = getRandomReal(-5,5);
520  matB.stateVec.real[j] = getRandomReal(-5,5); matB.stateVec.imag[j] = getRandomReal(-5,5);
521  matC.stateVec.real[j] = getRandomReal(-5,5); matC.stateVec.imag[j] = getRandomReal(-5,5);
522  }
523  copyStateToGPU(matA); copyStateToGPU(matB); copyStateToGPU(matC);
524  QMatrix refA = toQMatrix(matA);
525  QMatrix refB = toQMatrix(matB);
526  QMatrix refC = toQMatrix(matC);
527  QMatrix refOut;
528 
529  // get three random factors
530  qcomp numA = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
531  qcomp numB = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
532  qcomp numC = getRandomReal(-5,5) + 1i*getRandomReal(-5,5);
533  Complex facA = toComplex(numA);
534  Complex facB = toComplex(numB);
535  Complex facC = toComplex(numC);
536 
537  // check out-qureg is correct, when all quregs are unique...
538  setWeightedQureg(facA, matA, facB, matB, facC, matC);
539  refOut = numA*refA + numB*refB + numC*refC;
540  REQUIRE( areEqual(matC, refOut) );
541 
542  // ... and that other qureg's aren't modified
543  REQUIRE( areEqual(matA, refA) );
544  REQUIRE( areEqual(matB, refB) );
545 
546  // check quregOut correct, when it's also qureg2
547  refC = toQMatrix(matC);
548  setWeightedQureg(facB, matB, facC, matC, facA, matC);
549  refOut = numB*refB + numC*refC + numA*refC;
550  REQUIRE( areEqual(matC, refOut, 10*REAL_EPS) );
551 
552  // ... and that the remaining qureg is not modified
553  REQUIRE( areEqual(matB, refB) );
554 
555  // check quregOut correct, when it's also qureg1
556  refC = toQMatrix(matC);
557  setWeightedQureg(facC, matC, facB, matB, facA, matC);
558  refOut = numC*refC + numB*refB + numA*refC;
559  REQUIRE( areEqual(matC, refOut, 1E2*REAL_EPS) );
560 
561  // ... and that the remaining qureg is not modified
562  REQUIRE( areEqual(matB, refB) );
563 
564  // check quregOut is correct when it's both input quregs
565  refC = toQMatrix(matC);
566  setWeightedQureg(facA, matC, facB, matC, facC, matC);
567  refOut = numA*refC + numB*refC + numC*refC;
568  REQUIRE( areEqual(matC, refOut, 1E3*REAL_EPS) );
569 
570  // cleanup
571  destroyQureg(matA, QUEST_ENV);
572  destroyQureg(matB, QUEST_ENV);
573  destroyQureg(matC, QUEST_ENV);
574  }
575  }
576  SECTION( "input validation" ) {
577 
578  SECTION( "qureg types" ) {
579 
582  Complex f = {.real=0, .imag=0};
583 
584  // two state-vecs, one density-matrix
585  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, vec), Contains("state-vectors or") && Contains("density matrices") );
586  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
587  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
588 
589  // one state-vec, two density-matrices
590  REQUIRE_THROWS_WITH( setWeightedQureg(f, vec, f, mat, f, mat), Contains("state-vectors or") && Contains("density matrices") );
591  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, vec, f, mat), Contains("state-vectors or") && Contains("density matrices") );
592  REQUIRE_THROWS_WITH( setWeightedQureg(f, mat, f, mat, f, vec), Contains("state-vectors or") && Contains("density matrices") );
593 
594  destroyQureg(vec, QUEST_ENV);
595  destroyQureg(mat, QUEST_ENV);
596  }
597  SECTION( "qureg dimensions" ) {
598 
600  Qureg vecB = createQureg(NUM_QUBITS + 1, QUEST_ENV);
603  Complex f = {.real=0, .imag=0};
604 
605  // state-vecs
606  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecA, f, vecB, f, vecB), Contains("Dimensions") );
607  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecA, f, vecB), Contains("Dimensions") );
608  REQUIRE_THROWS_WITH( setWeightedQureg(f, vecB, f, vecB, f, vecA), Contains("Dimensions") );
609 
610  // density-matrices
611  REQUIRE_THROWS_WITH( setWeightedQureg(f, matA, f, matB, f, matB), Contains("Dimensions") );
612  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matA, f, matB), Contains("Dimensions") );
613  REQUIRE_THROWS_WITH( setWeightedQureg(f, matB, f, matB, f, matA), Contains("Dimensions") );
614 
615  destroyQureg(vecA, QUEST_ENV);
616  destroyQureg(vecB, QUEST_ENV);
617  destroyQureg(matA, QUEST_ENV);
618  destroyQureg(matB, QUEST_ENV);
619  }
620  }
621 }

References areEqual(), copyStateToGPU(), createDensityQureg(), createQureg(), destroyQureg(), getRandomReal(), NUM_QUBITS, Qureg::numAmpsPerChunk, qcomp, QUEST_ENV, Complex::real, setWeightedQureg(), Qureg::stateVec, toComplex, toQMatrix(), and toQVector().

◆ TEST_CASE() [82/88]

TEST_CASE ( "sGate"  ,
""  [unitaries] 
)
See also
sGate
Author
Tyson Jones

Definition at line 2049 of file test_unitaries.cpp.

2049  {
2050 
2051  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
2052  QMatrix op{{1,0},{0,1i}};
2053 
2054  SECTION( "correctness" ) {
2055 
2056  int target = GENERATE( range(0,NUM_QUBITS) );
2057 
2058  SECTION( "state-vector ") {
2059 
2060  sGate(quregVec, target);
2061  applyReferenceOp(refVec, target, op);
2062  REQUIRE( areEqual(quregVec, refVec) );
2063  }
2064  SECTION( "density-matrix" ) {
2065 
2066  sGate(quregMatr, target);
2067  applyReferenceOp(refMatr, target, op);
2068  REQUIRE( areEqual(quregMatr, refMatr) );
2069  }
2070  }
2071  SECTION( "input validation" ) {
2072 
2073  SECTION( "qubit indices" ) {
2074 
2075  int target = GENERATE( -1, NUM_QUBITS );
2076  REQUIRE_THROWS_WITH( sGate(quregVec, target), Contains("Invalid target") );
2077  }
2078  }
2079  CLEANUP_TEST( quregVec, quregMatr );
2080 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, and sGate().

◆ TEST_CASE() [83/88]

TEST_CASE ( "sqrtSwapGate"  ,
""  [unitaries] 
)
See also
sqrtSwapGate
Author
Tyson Jones

Definition at line 2088 of file test_unitaries.cpp.

2088  {
2089 
2090  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
2091  qcomp a = (1. + 1i)/2.;
2092  qcomp b = (1. - 1i)/2.;
2093  QMatrix op{{1,0,0,0},{0,a,b,0},{0,b,a,0},{0,0,0,1}};
2094 
2095  SECTION( "correctness" ) {
2096 
2097  int targ1 = GENERATE( range(0,NUM_QUBITS) );
2098  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
2099  int targs[] = {targ1, targ2};
2100 
2101  SECTION( "state-vector" ) {
2102 
2103  sqrtSwapGate(quregVec, targ1, targ2);
2104  applyReferenceOp(refVec, targs, 2, op);
2105  REQUIRE( areEqual(quregVec, refVec) );
2106  }
2107  SECTION( "density-matrix" ) {
2108 
2109  sqrtSwapGate(quregMatr, targ1, targ2);
2110  applyReferenceOp(refMatr, targs, 2, op);
2111  REQUIRE( areEqual(quregMatr, refMatr) );
2112  }
2113  }
2114  SECTION( "input validation" ) {
2115 
2116  SECTION( "qubit indices" ) {
2117 
2118  int targ1 = GENERATE( -1, NUM_QUBITS );
2119  int targ2 = 0;
2120  REQUIRE_THROWS_WITH( sqrtSwapGate(quregVec, targ1, targ2), Contains("Invalid target") );
2121  REQUIRE_THROWS_WITH( sqrtSwapGate(quregVec, targ2, targ1), Contains("Invalid target") );
2122  }
2123  SECTION( "repetition of targets" ) {
2124 
2125  int qb = 0;
2126  REQUIRE_THROWS_WITH( sqrtSwapGate(quregVec, qb, qb), Contains("target") && Contains("unique") );
2127  }
2128  }
2129  CLEANUP_TEST( quregVec, quregMatr );
2130 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, qcomp, and sqrtSwapGate().

◆ TEST_CASE() [84/88]

TEST_CASE ( "swapGate"  ,
""  [unitaries] 
)
See also
swapGate
Author
Tyson Jones

Definition at line 2138 of file test_unitaries.cpp.

2138  {
2139 
2140  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
2141  QMatrix op{{1,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,1}};
2142 
2143  SECTION( "correctness" ) {
2144 
2145  int targ1 = GENERATE( range(0,NUM_QUBITS) );
2146  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
2147  int targs[] = {targ1, targ2};
2148 
2149  SECTION( "state-vector" ) {
2150 
2151  swapGate(quregVec, targ1, targ2);
2152  applyReferenceOp(refVec, targs, 2, op);
2153  REQUIRE( areEqual(quregVec, refVec) );
2154  }
2155  SECTION( "density-matrix" ) {
2156 
2157  swapGate(quregMatr, targ1, targ2);
2158  applyReferenceOp(refMatr, targs, 2, op);
2159  REQUIRE( areEqual(quregMatr, refMatr) );
2160  }
2161  }
2162  SECTION( "input validation" ) {
2163 
2164  SECTION( "qubit indices" ) {
2165 
2166  int targ1 = GENERATE( -1, NUM_QUBITS );
2167  int targ2 = 0;
2168  REQUIRE_THROWS_WITH( swapGate(quregVec, targ1, targ2), Contains("Invalid target") );
2169  REQUIRE_THROWS_WITH( swapGate(quregVec, targ2, targ1), Contains("Invalid target") );
2170  }
2171  SECTION( "repetition of targets" ) {
2172 
2173  int qb = 0;
2174  REQUIRE_THROWS_WITH( swapGate(quregVec, qb, qb), Contains("target") && Contains("unique") );
2175  }
2176  }
2177  CLEANUP_TEST( quregVec, quregMatr );
2178 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, NUM_QUBITS, PREPARE_TEST, and swapGate().

◆ TEST_CASE() [85/88]

TEST_CASE ( "tGate"  ,
""  [unitaries] 
)
See also
tGate
Author
Tyson Jones

Definition at line 2186 of file test_unitaries.cpp.

2186  {
2187 
2188  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
2189  QMatrix op{{1,0},{0,expI(M_PI/4.)}};
2190 
2191  SECTION( "correctness" ) {
2192 
2193  int target = GENERATE( range(0,NUM_QUBITS) );
2194 
2195  SECTION( "state-vector ") {
2196 
2197  tGate(quregVec, target);
2198  applyReferenceOp(refVec, target, op);
2199  REQUIRE( areEqual(quregVec, refVec) );
2200  }
2201  SECTION( "density-matrix" ) {
2202 
2203  tGate(quregMatr, target);
2204  applyReferenceOp(refMatr, target, op);
2205  REQUIRE( areEqual(quregMatr, refMatr) );
2206  }
2207  }
2208  SECTION( "input validation" ) {
2209 
2210  SECTION( "qubit indices" ) {
2211 
2212  int target = GENERATE( -1, NUM_QUBITS );
2213  REQUIRE_THROWS_WITH( tGate(quregVec, target), Contains("Invalid target") );
2214  }
2215  }
2216  CLEANUP_TEST( quregVec, quregMatr );
2217 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, expI(), NUM_QUBITS, PREPARE_TEST, and tGate().

◆ TEST_CASE() [86/88]

TEST_CASE ( "toComplex"  ,
""  [data_structures] 
)
See also
toComplex
Author
Tyson Jones

Definition at line 42 of file test_data_structures.cpp.

42  {
43 
44  qcomp a = .5 - .2i;
45  Complex b = toComplex(a);
46 
47  REQUIRE( real(a) == b.real );
48  REQUIRE( imag(a) == b.imag );
49 }

References Complex::imag, qcomp, Complex::real, and toComplex.

◆ TEST_CASE() [87/88]

TEST_CASE ( "twoQubitUnitary"  ,
""  [unitaries] 
)
See also
twoQubitUnitary
Author
Tyson Jones

Definition at line 2225 of file test_unitaries.cpp.

2225  {
2226 
2227  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
2228 
2229  // in distributed mode, each node must be able to fit all amps modified by unitary
2230  REQUIRE( quregVec.numAmpsPerChunk >= 4 );
2231 
2232  // every test will use a unique random matrix
2233  QMatrix op = getRandomUnitary(2);
2234  ComplexMatrix4 matr = toComplexMatrix4(op);
2235 
2236  SECTION( "correctness" ) {
2237 
2238  int targ1 = GENERATE( range(0,NUM_QUBITS) );
2239  int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
2240  int targs[] = {targ1, targ2};
2241 
2242  SECTION( "state-vector" ) {
2243 
2244  twoQubitUnitary(quregVec, targ1, targ2, matr);
2245  applyReferenceOp(refVec, targs, 2, op);
2246  REQUIRE( areEqual(quregVec, refVec) );
2247  }
2248  SECTION( "density-matrix" ) {
2249 
2250  twoQubitUnitary(quregMatr, targ1, targ2, matr);
2251  applyReferenceOp(refMatr, targs, 2, op);
2252  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
2253  }
2254  }
2255  SECTION( "input validation" ) {
2256 
2257  SECTION( "qubit indices" ) {
2258 
2259  int targ1 = GENERATE( -1, NUM_QUBITS );
2260  int targ2 = 0;
2261  REQUIRE_THROWS_WITH( twoQubitUnitary(quregVec, targ1, targ2, matr), Contains("Invalid target") );
2262  REQUIRE_THROWS_WITH( twoQubitUnitary(quregVec, targ2, targ1, matr), Contains("Invalid target") );
2263  }
2264  SECTION( "repetition of targets" ) {
2265 
2266  int qb = 0;
2267  REQUIRE_THROWS_WITH( twoQubitUnitary(quregVec, qb, qb, matr), Contains("target") && Contains("unique") );
2268  }
2269  SECTION( "unitarity" ) {
2270 
2271  matr.real[0][0] = 0; // break matr unitarity
2272  REQUIRE_THROWS_WITH( twoQubitUnitary(quregVec, 0, 1, matr), Contains("unitary") );
2273  }
2274  SECTION( "unitary fits in node" ) {
2275 
2276  // pretend we have a very limited distributed memory
2277  quregVec.numAmpsPerChunk = 1;
2278  REQUIRE_THROWS_WITH( twoQubitUnitary(quregVec, 0, 1, matr), Contains("targets too many qubits"));
2279  }
2280  }
2281  CLEANUP_TEST( quregVec, quregMatr );
2282 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix4::real, toComplexMatrix4(), and twoQubitUnitary().

◆ TEST_CASE() [88/88]

TEST_CASE ( "unitary"  ,
""  [unitaries] 
)
See also
unitary
Author
Tyson Jones

Definition at line 2290 of file test_unitaries.cpp.

2290  {
2291 
2292  PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
2293 
2294  // every test will use a unique random matrix
2295  QMatrix op = getRandomUnitary(1);
2296  ComplexMatrix2 matr = toComplexMatrix2(op);
2297 
2298  SECTION( "correctness" ) {
2299 
2300  int target = GENERATE( range(0,NUM_QUBITS) );
2301 
2302  SECTION( "state-vector" ) {
2303 
2304  unitary(quregVec, target, matr);
2305  applyReferenceOp(refVec, target, op);
2306  REQUIRE( areEqual(quregVec, refVec) );
2307  }
2308  SECTION( "density-matrix" ) {
2309 
2310  unitary(quregMatr, target, matr);
2311  applyReferenceOp(refMatr, target, op);
2312  REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
2313  }
2314  }
2315  SECTION( "input validation" ) {
2316 
2317  SECTION( "qubit indices" ) {
2318 
2319  int target = GENERATE( -1, NUM_QUBITS );
2320  REQUIRE_THROWS_WITH( unitary(quregVec, target, matr), Contains("Invalid target") );
2321  }
2322  SECTION( "unitarity" ) {
2323 
2324  matr.real[0][0] = 0; // break matr unitarity
2325  REQUIRE_THROWS_WITH( unitary(quregVec, 0, matr), Contains("unitary") );
2326  }
2327  }
2328  CLEANUP_TEST( quregVec, quregMatr );
2329 }

References applyReferenceOp(), areEqual(), CLEANUP_TEST, getRandomUnitary(), NUM_QUBITS, PREPARE_TEST, ComplexMatrix2::real, toComplexMatrix2(), and unitary().

qreal getProbAmp(Qureg qureg, long long int index)
Get the probability of a state-vector at an index in the full state vector.
Definition: QuEST.c:690
void initBlankState(Qureg qureg)
Initialises a qureg to have all-zero-amplitudes.
Definition: QuEST.c:117
Represents a 3-vector of real numbers.
Definition: QuEST.h:148
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
void controlledPauliY(Qureg qureg, const int controlQubit, const int targetQubit)
Apply the controlled pauliY (single control, single target) gate, also known as the c-Y and c-sigma-Y...
Definition: QuEST.c:535
QMatrix getFullOperatorMatrix(int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op, int numQubits)
Takes a 2^numTargs-by-2^numTargs matrix op and a returns a 2^numQubits-by-2^numQubits matrix where op...
Definition: utilities.cpp:293
QuESTEnv QUEST_ENV
The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
Definition: main.cpp:20
qreal real[4][4]
Definition: QuEST.h:127
#define fromComplex(comp)
void initPureState(Qureg qureg, Qureg pure)
Initialise a set of qubits, which can be a state vector or density matrix, to a given pure state.
Definition: QuEST.c:143
#define CLEANUP_TEST(quregVec, quregMatr)
Destroys the data structures made by PREPARE_TEST.
@ PAULI_Z
Definition: QuEST.h:96
void tGate(Qureg qureg, const int targetQubit)
Apply the single-qubit T gate.
Definition: QuEST.c:475
qreal calcTotalProb(Qureg qureg)
A debugging function which calculates the probability of the qubits in qureg being in any state,...
Definition: QuEST.c:822
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1021
void rotateZ(Qureg qureg, const int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the Z-axis of the Bloch-sphere (also known as a phase s...
Definition: QuEST.c:208
@ PAULI_I
Definition: QuEST.h:96
Complex getDensityAmp(Qureg qureg, long long int row, long long int col)
Get an amplitude from a density matrix at a given row and column.
Definition: QuEST.c:707
int getRandomInt(int min, int max)
Returns a random integer between min (inclusive) and max (exclusive), from the uniform distribution.
Definition: utilities.cpp:481
std::vector< QMatrix > getRandomKrausMap(int numQb, int numOps)
Returns a random Kraus map of #numOps 2^numQb-by-2^numQb operators, from an undisclosed distribution.
Definition: utilities.cpp:533
ComplexMatrixN createComplexMatrixN(int numQubits)
Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary f...
Definition: QuEST.c:1000
qreal getImagAmp(Qureg qureg, long long int index)
Get the imaginary component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:683
void mixKrausMap(Qureg qureg, int target, ComplexMatrix2 *ops, int numOps)
Apply a general single-qubit Kraus map to a density matrix, as specified by at most four Kraus operat...
Definition: QuEST.c:966
qreal z
Definition: QuEST.h:150
#define NUM_QUBITS
The default number of qubits in the registers created for unit testing (both statevectors and density...
Definition: utilities.hpp:36
void mixDephasing(Qureg qureg, const int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit dephasing noise.
Definition: QuEST.c:902
qreal calcPurity(Qureg qureg)
Calculates the purity of a density matrix, by the trace of the density matrix squared.
Definition: QuEST.c:855
int measure(Qureg qureg, int measureQubit)
Measures a single qubit, collapsing it randomly to 0 or 1.
Definition: QuEST.c:756
QMatrix getRandomUnitary(int numQb)
Returns a uniformly random (under Haar) 2^numQb-by-2^numQb unitary matrix.
Definition: utilities.cpp:485
qreal calcFidelity(Qureg qureg, Qureg pureState)
Calculates the fidelity of qureg (a statevector or density matrix) against a reference pure state (ne...
Definition: QuEST.c:861
qreal getRandomReal(qreal min, qreal max)
Returns a random real between min (inclusive) and max (exclusive), from the uniform distribution.
Definition: utilities.cpp:410
QMatrix getKetBra(QVector ket, QVector bra)
Returns the matrix |ket><bra|, with ith-jth element ket(i) conj(bra(j)), since |ket><bra| = sum_i a_i...
Definition: utilities.cpp:159
void mixTwoQubitDepolarising(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit homogeneous depolarising noise.
Definition: QuEST.c:943
void rotateX(Qureg qureg, const int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:186
void cloneQureg(Qureg targetQureg, Qureg copyQureg)
Set targetQureg to be a clone of copyQureg.
Definition: QuEST.c:163
void multiControlledTwoQubitUnitary(Qureg qureg, int *controlQubits, const int numControlQubits, const int targetQubit1, const int targetQubit2, ComplexMatrix4 u)
Apply a general multi-controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:281
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:125
Information about the environment the program is running in.
Definition: QuEST.h:199
void pauliZ(Qureg qureg, const int targetQubit)
Apply the single-qubit Pauli-Z (also known as the Z, sigma-Z or phase-flip) gate.
Definition: QuEST.c:453
void multiControlledPhaseShift(Qureg qureg, int *controlQubits, int numControlQubits, qreal angle)
Introduce a phase factor on state of the passed qubits.
Definition: QuEST.c:509
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
void controlledPhaseFlip(Qureg qureg, const int idQubit1, const int idQubit2)
Apply the (two-qubit) controlled phase flip gate, also known as the controlled pauliZ gate.
Definition: QuEST.c:547
#define qreal
void multiRotatePauli(Qureg qureg, int *targetQubits, enum pauliOpType *targetPaulis, int numTargets, qreal angle)
Apply a multi-qubit multi-Pauli rotation on a selected number of qubits.
Definition: QuEST.c:640
QMatrix toQMatrix(ComplexMatrix2 src)
Returns a copy of the given 2-by-2 matrix.
Definition: utilities.cpp:835
void toQureg(Qureg qureg, QVector vec)
Initialises the state-vector qureg to have the same amplitudes as vec.
Definition: utilities.cpp:946
void setAmps(Qureg qureg, long long int startInd, qreal *reals, qreal *imags, long long int numAmps)
Overwrites a subset of the amplitudes in qureg, with those passed in reals and imags.
Definition: QuEST.c:779
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
void multiControlledUnitary(Qureg qureg, int *controlQubits, const int numControlQubits, const int targetQubit, ComplexMatrix2 u)
Apply a general multiple-control single-target unitary, which can include a global phase factor.
Definition: QuEST.c:372
void multiControlledPhaseFlip(Qureg qureg, int *controlQubits, int numControlQubits)
Apply the multiple-qubit controlled phase flip gate, also known as the multiple-qubit controlled paul...
Definition: QuEST.c:559
#define PREPARE_TEST(quregVec, quregMatr, refVec, refMatr)
Prepares the needed data structures for unit testing unitaries.
@ PAULI_X
Definition: QuEST.h:96
Complex getAmp(Qureg qureg, long long int index)
Get the complex amplitude at a given index in the state vector.
Definition: QuEST.c:697
QMatrix getExponentialOfPauliMatrix(qreal angle, QMatrix a)
Returns the matrix exponential of a kronecker product of pauli matrices (or of any involutory matrice...
Definition: utilities.cpp:205
int measureWithStats(Qureg qureg, int measureQubit, qreal *outcomeProb)
Measures a single qubit, collapsing it randomly to 0 or 1, and additionally gives the probability of ...
Definition: QuEST.c:743
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:167
void controlledMultiQubitUnitary(Qureg qureg, int ctrl, int *targs, const int numTargs, ComplexMatrixN u)
Apply a general controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:312
void multiStateControlledUnitary(Qureg qureg, int *controlQubits, int *controlState, const int numControlQubits, const int targetQubit, ComplexMatrix2 u)
Apply a general multiple-control, conditioned on a specific bit sequence, single-target unitary,...
Definition: QuEST.c:387
void toComplexMatrixN(QMatrix qm, ComplexMatrixN cm)
Initialises cm with the values of qm.
Definition: utilities.cpp:824
void setWeightedQureg(Complex fac1, Qureg qureg1, Complex fac2, Qureg qureg2, Complex facOut, Qureg out)
Modifies qureg out to the result of (facOut out + fac1 qureg1 + fac2 qureg2), imposing no constraints...
Definition: QuEST.c:795
void multiControlledMultiQubitUnitary(Qureg qureg, int *ctrls, const int numCtrls, int *targs, const int numTargs, ComplexMatrixN u)
Apply a general multi-controlled multi-qubit unitary (including a global phase factor).
Definition: QuEST.c:329
void phaseShift(Qureg qureg, const int targetQubit, qreal angle)
Shift the phase between and of a single qubit by a given angle.
Definition: QuEST.c:486
qreal calcHilbertSchmidtDistance(Qureg a, Qureg b)
Computes the Hilbert Schmidt distance between two density matrices a and b, defined as the Frobenius ...
Definition: QuEST.c:889
qreal y
Definition: QuEST.h:150
qcomp expI(qreal phase)
Returns the unit-norm complex number exp(i*phase).
Definition: utilities.cpp:406
std::vector< qcomp > QVector
A complex vector, which can be zero-initialised with QVector(numAmps).
Definition: utilities.hpp:60
void multiQubitUnitary(Qureg qureg, int *targs, const int numTargs, ComplexMatrixN u)
Apply a general multi-qubit unitary (including a global phase factor) with any number of target qubit...
Definition: QuEST.c:295
qreal x
Definition: QuEST.h:150
void compactUnitary(Qureg qureg, const int targetQubit, Complex alpha, Complex beta)
Apply a single-qubit unitary parameterised by two given complex scalars.
Definition: QuEST.c:403
QVector toQVector(Qureg qureg)
Returns an equal-size copy of the given state-vector qureg.
Definition: utilities.cpp:904
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:170
void hadamard(Qureg qureg, const int targetQubit)
Apply the single-qubit Hadamard gate.
Definition: QuEST.c:175
void rotateY(Qureg qureg, const int targetQubit, qreal angle)
Rotate a single qubit by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:197
void swapGate(Qureg qureg, int qb1, int qb2)
Performs a SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:599
void controlledUnitary(Qureg qureg, const int controlQubit, const int targetQubit, ComplexMatrix2 u)
Apply a general controlled unitary (single control, single target), which can include a global phase ...
Definition: QuEST.c:359
void controlledRotateY(Qureg qureg, const int controlQubit, const int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Y-axis of the Bloch-sphere.
Definition: QuEST.c:231
#define qcomp
void initStateFromAmps(Qureg qureg, qreal *reals, qreal *imags)
Initialise qureg by specifying the complete statevector.
Definition: QuEST.c:155
void controlledNot(Qureg qureg, const int controlQubit, const int targetQubit)
Apply the controlled not (single control, single target) gate, also known as the c-X,...
Definition: QuEST.c:523
ComplexMatrix4 toComplexMatrix4(QMatrix qm)
Returns a ComplexMatrix4 copy of QMatix qm.
Definition: utilities.cpp:818
void copyStateToGPU(Qureg qureg)
In GPU mode, this copies the state-vector (or density matrix) from RAM (qureg.stateVec) to VRAM / GPU...
Definition: QuEST_cpu.c:36
#define toComplex(scalar)
int numRanks
Definition: QuEST.h:202
void controlledRotateAroundAxis(Qureg qureg, const int controlQubit, const int targetQubit, qreal angle, Vector axis)
Applies a controlled rotation by a given angle around a given vector on the Bloch-sphere.
Definition: QuEST.c:586
qreal getRealAmp(Qureg qureg, long long int index)
Get the real component of the complex probability amplitude at an index in the state vector.
Definition: QuEST.c:676
void controlledTwoQubitUnitary(Qureg qureg, const int controlQubit, const int targetQubit1, const int targetQubit2, ComplexMatrix4 u)
Apply a general controlled two-qubit unitary (including a global phase factor).
Definition: QuEST.c:268
@ PAULI_Y
Definition: QuEST.h:96
int getNumQubits(Qureg qureg)
Get the number of qubits in a qureg object.
Definition: QuEST.c:666
Complex calcInnerProduct(Qureg bra, Qureg ket)
Computes the inner product of two equal-size state vectors, given by.
Definition: QuEST.c:829
void controlledPhaseShift(Qureg qureg, const int idQubit1, const int idQubit2, qreal angle)
Introduce a phase factor on state of qubits idQubit1 and idQubit2.
Definition: QuEST.c:497
void destroyQureg(Qureg qureg, QuESTEnv env)
Deallocate a Qureg object representing a set of qubits.
Definition: QuEST.c:75
QVector getRandomStateVector(int numQb)
Returns a random numQb-length L2-normalised state-vector from an undisclosed distribution.
Definition: utilities.cpp:453
void mixTwoQubitKrausMap(Qureg qureg, int target1, int target2, ComplexMatrix4 *ops, int numOps)
Apply a general two-qubit Kraus map to a density matrix, as specified by at most sixteen Kraus operat...
Definition: QuEST.c:976
qreal ** real
Definition: QuEST.h:139
void initDebugState(Qureg qureg)
Initialises qureg to be in the un-normalised, non-physical state with with n-th complex amplitude (2n...
Definition: QuEST.c:1057
void applyPauliSum(Qureg inQureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg outQureg)
Modifies outQureg to be the result of applying the weighted sum of Pauli products (a Hermitian but no...
Definition: QuEST.c:806
void mixDamping(Qureg qureg, const int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit amplitude damping (decay to 0 state).
Definition: QuEST.c:935
QMatrix getRandomQMatrix(int dim)
Returns a dim-by-dim complex matrix, where the real and imaginary value of each element are independe...
Definition: utilities.cpp:368
void initClassicalState(Qureg qureg, long long int stateInd)
Initialise a set of qubits to the classical state (also known as a "computational basis state") with...
Definition: QuEST.c:132
void unitary(Qureg qureg, const int targetQubit, ComplexMatrix2 u)
Apply a general single-qubit unitary (including a global phase factor).
Definition: QuEST.c:347
Represents a system of qubits.
Definition: QuEST.h:160
void controlledRotateZ(Qureg qureg, const int controlQubit, const int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the Z-axis of the Bloch-sphere.
Definition: QuEST.c:243
void mixTwoQubitDephasing(Qureg qureg, int qubit1, int qubit2, qreal prob)
Mixes a density matrix qureg to induce two-qubit dephasing noise.
Definition: QuEST.c:912
qreal ** imag
Definition: QuEST.h:140
ComplexArray stateVec
Computational state amplitudes - a subset thereof in the MPI version.
Definition: QuEST.h:179
qreal real[2][2]
Definition: QuEST.h:116
long long int getNumAmps(Qureg qureg)
Get the number of probability amplitudes in a qureg object, given by 2^numQubits.
Definition: QuEST.c:670
void controlledCompactUnitary(Qureg qureg, const int controlQubit, const int targetQubit, Complex alpha, Complex beta)
Apply a controlled unitary (single control, single target) parameterised by two given complex scalars...
Definition: QuEST.c:416
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:163
Qureg createCloneQureg(Qureg qureg, QuESTEnv env)
Create a new Qureg which is an exact clone of the passed qureg, which can be either a statevector or ...
Definition: QuEST.c:62
qreal collapseToOutcome(Qureg qureg, const int measureQubit, int outcome)
Updates qureg to be consistent with measuring measureQubit in the given outcome (0 or 1),...
Definition: QuEST.c:724
void controlledRotateX(Qureg qureg, const int controlQubit, const int targetQubit, qreal angle)
Applies a controlled rotation by a given angle around the X-axis of the Bloch-sphere.
Definition: QuEST.c:219
#define PREPARE_TEST(qureg, ref)
Prepares a density matrix in the debug state, and the reference QMatrix.
std::vector< std::vector< qcomp > > QMatrix
A complex square matrix.
Definition: utilities.hpp:49
qreal calcExpecPauliSum(Qureg qureg, enum pauliOpType *allPauliCodes, qreal *termCoeffs, int numSumTerms, Qureg workspace)
Computes the expected value of a sum of products of Pauli operators.
Definition: QuEST.c:880
ComplexMatrix2 toComplexMatrix2(QMatrix qm)
Returns a ComplexMatrix2 copy of QMatix qm.
Definition: utilities.cpp:812
Catch::Generators::GeneratorWrapper< int * > sublists(int *list, int len, int sublen)
Returns a Catch2 generator of every length-sublen sublist of length-len list, in increasing lexograph...
Definition: utilities.cpp:1074
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:165
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:172
qreal real
Definition: QuEST.h:105
void mixDensityMatrix(Qureg combineQureg, qreal otherProb, Qureg otherQureg)
Modifies combineQureg to become (1-prob)combineProb + prob otherQureg.
Definition: QuEST.c:770
Qureg createQureg(int numQubits, QuESTEnv env)
Create a Qureg object representing a set of qubits which will remain in a pure state.
Definition: QuEST.c:34
qreal calcProbOfOutcome(Qureg qureg, const int measureQubit, int outcome)
Gives the probability of a specified qubit being measured in the given outcome (0 or 1).
Definition: QuEST.c:845
void multiRotateZ(Qureg qureg, int *qubits, int numQubits, qreal angle)
Apply a multi-qubit Z rotation on a selected number of qubits.
Definition: QuEST.c:624
qreal imag
Definition: QuEST.h:106
void pauliY(Qureg qureg, const int targetQubit)
Apply the single-qubit Pauli-Y (also known as the Y or sigma-Y) gate.
Definition: QuEST.c:442
QMatrix getKroneckerProduct(QMatrix a, QMatrix b)
Returns the kronecker product of a and b, where a and b are square but possibly differently-sized com...
Definition: utilities.cpp:169
QMatrix getRandomDensityMatrix(int numQb)
Returns a random numQb-by-numQb density matrix, from an undisclosed distribution, in a very mixed sta...
Definition: utilities.cpp:457
QMatrix getExponentialOfDiagonalMatrix(QMatrix a)
Returns the matrix exponential of a diagonal, square, complex matrix.
Definition: utilities.cpp:187
void mixPauli(Qureg qureg, int qubit, qreal probX, qreal probY, qreal probZ)
Mixes a density matrix qureg to induce general single-qubit Pauli noise.
Definition: QuEST.c:955
QMatrix getZeroMatrix(size_t dim)
Returns a dim-by-dim square complex matrix, initialised to all zeroes.
Definition: utilities.cpp:143
Represents one complex number.
Definition: QuEST.h:103
void twoQubitUnitary(Qureg qureg, const int targetQubit1, const int targetQubit2, ComplexMatrix4 u)
Apply a general two-qubit unitary (including a global phase factor).
Definition: QuEST.c:255
QVector getRandomQVector(int dim)
Returns a dim-length vector with random complex amplitudes in the square joining {-1-i,...
Definition: utilities.cpp:420
void sGate(Qureg qureg, const int targetQubit)
Apply the single-qubit S gate.
Definition: QuEST.c:464
void rotateAroundAxis(Qureg qureg, const int rotQubit, qreal angle, Vector axis)
Rotate a single qubit by a given angle around a given Vector on the Bloch-sphere.
Definition: QuEST.c:573
void initZeroState(Qureg qureg)
Initialise a set of qubits to the classical zero state .
Definition: QuEST.c:111
qreal calcDensityInnerProduct(Qureg rho1, Qureg rho2)
Computes the Hilbert-Schmidt scalar product (which is equivalent to the Frobenius inner product of ma...
Definition: QuEST.c:837
bool areEqual(QVector a, QVector b)
Returns true if the absolute value of the difference between every amplitude in vectors a and b is le...
Definition: utilities.cpp:387
Qureg createDensityQureg(int numQubits, QuESTEnv env)
Create a Qureg for qubits which are represented by a density matrix, and can be in mixed states.
Definition: QuEST.c:48
void applyReferenceOp(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
Modifies the state-vector state to be the result of applying the multi-target operator matrix op,...
Definition: utilities.cpp:573
Catch::Generators::GeneratorWrapper< int * > bitsets(int numBits)
Returns a Catch2 generator of every numBits-length bit-set, in increasing lexographic order,...
Definition: utilities.cpp:1143
void initPlusState(Qureg qureg)
Initialise a set of qubits to the plus state (and similarly for density matrices).
Definition: QuEST.c:123
qreal calcExpecPauliProd(Qureg qureg, int *targetQubits, enum pauliOpType *pauliCodes, int numTargets, Qureg workspace)
Computes the expected value of a product of Pauli operators.
Definition: QuEST.c:871
void pauliX(Qureg qureg, const int targetQubit)
Apply the single-qubit Pauli-X (also known as the X, sigma-X, NOT or bit-flip) gate.
Definition: QuEST.c:431
void sqrtSwapGate(Qureg qureg, int qb1, int qb2)
Performs a sqrt SWAP gate between qubit1 and qubit2.
Definition: QuEST.c:611
void mixMultiQubitKrausMap(Qureg qureg, int *targets, int numTargets, ComplexMatrixN *ops, int numOps)
Apply a general N-qubit Kraus map to a density matrix, as specified by at most (2N)^2 Kraus operators...
Definition: QuEST.c:986
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:114
void mixDepolarising(Qureg qureg, const int targetQubit, qreal prob)
Mixes a density matrix qureg to induce single-qubit homogeneous depolarising noise.
Definition: QuEST.c:924