The Quantum Exact Simulation Toolkit v4.2.0
Loading...
Searching...
No Matches
test_operators.cpp
1/** @file
2 * Ported tests of the deprecated QuEST v3 interface,
3 * unit testing the "operators" module.
4 *
5 * This file should be excluded from doxygen parsing so
6 * as not to conflict with the doc of the v4 unit tests.
7 *
8 * @author Tyson Jones
9 * @author Oliver Thomson Brown (ported to Catch2 v3)
10 * @author Ali Rezaei (tested porting to QuEST v4)
11 */
12
13#include <catch2/catch_test_macros.hpp>
14#include <catch2/generators/catch_generators_adapters.hpp>
15#include <catch2/generators/catch_generators_range.hpp>
16#include <catch2/matchers/catch_matchers_string.hpp>
17
18#include "quest.h"
19#include "test_utilities.hpp"
20
21/** Prepares the needed data structures for unit testing some operators.
22 * This creates a statevector and density matrix of the size NUM_QUBITS,
23 * and corresponding QVector and QMatrix instances for analytic comparison.
24 */
25#define PREPARE_TEST(quregVec, quregMatr, refVec, refMatr) \
26 Qureg quregVec = createForcedQureg(NUM_QUBITS); \
27 Qureg quregMatr = createForcedDensityQureg(NUM_QUBITS); \
28 initDebugState(quregVec); \
29 initDebugState(quregMatr); \
30 QVector refVec = toQVector(quregVec); \
31 QMatrix refMatr = toQMatrix(quregMatr); \
32 assertQuregAndRefInDebugState(quregVec, refVec); \
33 assertQuregAndRefInDebugState(quregMatr, refMatr);
34
35/** Destroys the data structures made by PREPARE_TEST */
36#define CLEANUP_TEST(quregVec, quregMatr) \
37 destroyQureg(quregVec); \
38 destroyQureg(quregMatr);
39
40/* allows concise use of ContainsSubstring in catch's REQUIRE_THROWS_WITH */
41using Catch::Matchers::ContainsSubstring;
42
43
44
45/** @sa applyDiagonalOp
46 * @ingroup deprecatedtests
47 * @author Tyson Jones
48 */
49TEST_CASE( "applyDiagonalOp", "[operators]" ) {
50
51 PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
52
53 SECTION( "correctness" ) {
54
55 // try 10 random operators
56 GENERATE( range(0,10) );
57
58 // make a totally random (non-Hermitian) diagonal oeprator
59 DiagonalOp op = createDiagonalOp(NUM_QUBITS, getQuESTEnv());
60 for (long long int i=0; i<op.numElemsPerNode; i++)
61 op.cpuElems[i] = getRandomComplex();
62 syncDiagonalOp(op);
63
64 SECTION( "state-vector" ) {
65
66 QVector ref = toQMatrix(op) * refVec;
67 applyDiagonalOp(quregVec, op);
68 REQUIRE( areEqual(quregVec, ref) );
69 }
70 SECTION( "density-matrix" ) {
71
72 QMatrix ref = toQMatrix(op) * refMatr;
73 applyDiagonalOp(quregMatr, op);
74 REQUIRE( areEqual(quregMatr, ref, 100*REAL_EPS) );
75 }
76
77 destroyDiagonalOp(op, getQuESTEnv());
78 }
79 SECTION( "input validation" ) {
80
81 SECTION( "mismatching size" ) {
82
83 DiagonalOp op = createDiagonalOp(NUM_QUBITS + 1, getQuESTEnv());
84
85 REQUIRE_THROWS_WITH( applyDiagonalOp(quregVec, op), ContainsSubstring("different number of qubits"));
86 REQUIRE_THROWS_WITH( applyDiagonalOp(quregMatr, op), ContainsSubstring("different number of qubits"));
87
88 destroyDiagonalOp(op, getQuESTEnv());
89 }
90 }
91 CLEANUP_TEST( quregVec, quregMatr );
92}
93
94/** @sa applyFullQFT
95 * @ingroup deprecatedtests
96 * @author Tyson Jones
97 */
98TEST_CASE( "applyFullQFT", "[operators]" ) {
99
100 PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
101
102 SECTION( "correctness" ) {
103
104 // try 10 times for each kind of input
105 GENERATE( range(0,10) );
106
107 SECTION( "state-vector" ) {
108
109 SECTION( "normalised" ) {
110
111 refVec = getRandomStateVector(NUM_QUBITS);
112 toQureg(quregVec, refVec);
113 refVec = getDFT(refVec);
114
115 applyFullQFT(quregVec);
116 REQUIRE( areEqual(quregVec, refVec) );
117 }
118 SECTION( "unnormalised" ) {
119
120 refVec = getRandomQVector(1 << NUM_QUBITS);
121 toQureg(quregVec, refVec);
122 refVec = getDFT(refVec);
123
124 applyFullQFT(quregVec);
125 REQUIRE( areEqual(quregVec, refVec) );
126 }
127 }
128 SECTION( "density-matrix" ) {
129
130 SECTION( "pure" ) {
131
132 /* a pure density matrix should be mapped to a pure state
133 * corresponding to the state-vector DFT
134 */
135
136 refVec = getRandomStateVector(NUM_QUBITS);
137 refMatr = getPureDensityMatrix(refVec);
138
139 toQureg(quregMatr, refMatr);
140 applyFullQFT(quregMatr);
141
142 refVec = getDFT(refVec);
143 refMatr = getPureDensityMatrix(refVec);
144
145 REQUIRE( areEqual(quregMatr, refMatr) );
146 }
147 SECTION( "mixed" ) {
148
149 /* a mixed density matrix, conceptualised as a mixture of orthogonal
150 * state-vectors, should be mapped to an equally weighted mixture
151 * of DFTs of each state-vector (because QFT is unitary and hence
152 * maintains state orthogonality)
153 */
154
155 int numStates = (1 << NUM_QUBITS)/4; // quarter as many states as possible
156 std::vector<QVector> states = getRandomOrthonormalVectors(NUM_QUBITS, numStates);
157 std::vector<qreal> probs = getRandomProbabilities(numStates);
158
159 // set qureg to random mixture
160 refMatr = getMixedDensityMatrix(probs, states);
161 toQureg(quregMatr, refMatr);
162
163 // apply QFT to mixture
164 applyFullQFT(quregMatr);
165
166 // compute dft of mixture, via dft of each state
167 refMatr = getZeroMatrix(1 << NUM_QUBITS);
168 for (int i=0; i<numStates; i++)
169 refMatr += probs[i] * getPureDensityMatrix(getDFT(states[i]));
170
171 REQUIRE( areEqual(quregMatr, refMatr) );
172 }
173 SECTION( "unnormalised" ) {
174
175 /* repeat method above, except that we use unnormalised vectors,
176 * and mix them with arbitrary complex numbers instead of probabilities,
177 * yielding an unnormalised density matrix
178 */
179
180 int numVecs = (1 << NUM_QUBITS)/4; // quarter as many states as possible
181 std::vector<QVector> vecs;
182 std::vector<qcomp> coeffs;
183 for (int i=0; i<numVecs; i++) {
184 vecs.push_back(getRandomQVector(1 << NUM_QUBITS));
185 coeffs.push_back(getRandomComplex());
186 }
187
188 // produce unnormalised matrix
189 refMatr = getZeroMatrix(1 << NUM_QUBITS);
190 for (int i=0; i<numVecs; i++)
191 refMatr += coeffs[i] * getPureDensityMatrix(vecs[i]);
192
193 toQureg(quregMatr, refMatr);
194 applyFullQFT(quregMatr);
195
196 // compute target matrix via dft of each unnormalised vector
197 refMatr = getZeroMatrix(1 << NUM_QUBITS);
198 for (int i=0; i<numVecs; i++)
199 refMatr += coeffs[i] * getPureDensityMatrix(getDFT(vecs[i]));
200
201 REQUIRE( areEqual(quregMatr, refMatr) );
202 }
203 }
204 }
205 SECTION( "input validation" ) {
206
207 SUCCEED( );
208 }
209 CLEANUP_TEST( quregVec, quregMatr );
210}
211
212
213
214/** @sa applyGateMatrixN
215 * @ingroup deprecatedtests
216 * @author Tyson Jones
217 */
218TEST_CASE( "applyGateMatrixN", "[operators]" ) {
219
220 PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
221
222 // figure out max-num (inclusive) targs allowed by hardware backend
223 int maxNumTargs = calcLog2(quregVec.numAmpsPerNode);
224
225 SECTION( "correctness" ) {
226
227 // generate all possible qubit arrangements
228 int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) ); // inclusive upper bound
229 int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
230
231 // for each qubit arrangement, use a new random unitary
232 QMatrix op = getRandomQMatrix(1 << numTargs);
233 ComplexMatrixN matr = createComplexMatrixN(numTargs);
234 toComplexMatrixN(op, matr);
235
236 SECTION( "state-vector" ) {
237
238 applyGateMatrixN(quregVec, targs, numTargs, matr);
239 applyReferenceOp(refVec, targs, numTargs, op);
240 REQUIRE( areEqual(quregVec, refVec) );
241 }
242 SECTION( "density-matrix" ) {
243
244 applyGateMatrixN(quregMatr, targs, numTargs, matr);
245 applyReferenceOp(refMatr, targs, numTargs, op);
246 REQUIRE( areEqual(quregMatr, refMatr, 1E4*REAL_EPS) );
247 }
248 destroyComplexMatrixN(matr);
249 }
250 SECTION( "input validation" ) {
251
252 SECTION( "number of targets" ) {
253
254 // there cannot be more targets than qubits in register
255 int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
256 int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
257 ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
258 syncCompMatr(matr);
259
260 REQUIRE_THROWS_WITH( applyGateMatrixN(quregVec, targs, numTargs, matr), ContainsSubstring("number of target qubits") );
261 destroyComplexMatrixN(matr);
262 }
263 SECTION( "repetition in targets" ) {
264
265 int numTargs = 3;
266 int targs[] = {1,2,2};
267 ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
268 syncCompMatr(matr);
269
270 REQUIRE_THROWS_WITH( applyGateMatrixN(quregVec, targs, numTargs, matr), ContainsSubstring("target") && ContainsSubstring("unique") );
271 destroyComplexMatrixN(matr);
272 }
273 SECTION( "qubit indices" ) {
274
275 int numTargs = 3;
276 int targs[] = {1,2,3};
277 ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
278 syncCompMatr(matr);
279
280 int inv = GENERATE( -1, NUM_QUBITS );
281 targs[GENERATE_COPY( range(0,numTargs) )] = inv; // make invalid target
282 REQUIRE_THROWS_WITH( applyGateMatrixN(quregVec, targs, numTargs, matr), ContainsSubstring("Invalid target") );
283
284 destroyComplexMatrixN(matr);
285 }
286 SECTION( "matrix creation" ) {
287
288 int numTargs = 3;
289 int targs[] = {1,2,3};
290
291 ComplexMatrixN matr;
292 matr.cpuElems = NULL;
293 REQUIRE_THROWS_WITH( applyGateMatrixN(quregVec, targs, numTargs, matr), ContainsSubstring("created") );
294 }
295 SECTION( "matrix dimensions" ) {
296
297 int targs[2] = {1,2};
298 ComplexMatrixN matr = createComplexMatrixN(3); // intentionally wrong size
299 syncCompMatr(matr);
300
301 REQUIRE_THROWS_WITH( applyGateMatrixN(quregVec, targs, 2, matr), ContainsSubstring("matrix has an inconsistent size"));
302 destroyComplexMatrixN(matr);
303 }
304 SECTION( "matrix fits in node" ) {
305
306 // pretend we have a very limited distributed memory (judged by matr size)
307 quregVec.isDistributed = 1;
308 quregVec.numAmpsPerNode = 1;
309 quregVec.logNumAmpsPerNode = 0;
310
311 int qb[] = {1,2};
312 ComplexMatrixN matr = createComplexMatrixN(2); // prevents seg-fault if validation doesn't trigger
313 syncCompMatr(matr);
314
315 REQUIRE_THROWS_WITH( applyGateMatrixN(quregVec, qb, 2, matr), ContainsSubstring("communication buffer") && ContainsSubstring("cannot simultaneously store") );
316
317 destroyComplexMatrixN(matr);
318 }
319 }
320 CLEANUP_TEST( quregVec, quregMatr );
321}
322
323
324
325/** @sa applyGateSubDiagonalOp
326 * @ingroup deprecatedtests
327 * @author Tyson Jones
328 */
329TEST_CASE( "applyGateSubDiagonalOp", "[operators]" ) {
330
331 PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
332
333 SECTION( "correctness" ) {
334
335 // generate all possible targets
336 int numTargs = GENERATE( range(1,NUM_QUBITS+1) );
337 int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
338
339 // initialise a random non-unitary diagonal op
340 SubDiagonalOp op = createSubDiagonalOp(numTargs);
341 for (long long int i=0; i<op.numElems; i++)
342 op.cpuElems[i] = getRandomComplex();
343 syncDiagMatr(op);
344 QMatrix opMatr = toQMatrix(op);
345
346 SECTION( "state-vector" ) {
347
348 applyGateSubDiagonalOp(quregVec, targs, numTargs, op);
349 applyReferenceOp(refVec, targs, numTargs, opMatr);
350 REQUIRE( areEqual(quregVec, refVec) );
351 }
352 SECTION( "density-matrix" ) {
353
354 applyGateSubDiagonalOp(quregMatr, targs, numTargs, op);
355 applyReferenceOp(refMatr, targs, numTargs, opMatr);
356 REQUIRE( areEqual(quregMatr, refMatr, 1E4*REAL_EPS) );
357 }
358
359 destroySubDiagonalOp(op);
360 }
361 SECTION( "input validation" ) {
362
363 SECTION( "diagonal dimension" ) {
364
365 int numTargs = 3;
366 SubDiagonalOp op = createSubDiagonalOp(numTargs);
367 syncDiagMatr(op);
368
369 int badNumTargs = GENERATE_COPY( numTargs-1, numTargs+1 );
370 int badTargs[NUM_QUBITS+1];
371 for (int i=0; i<NUM_QUBITS+1; i++)
372 badTargs[i] = i;
373
374 REQUIRE_THROWS_WITH( applyGateSubDiagonalOp(quregVec, badTargs, badNumTargs, op), ContainsSubstring("inconsistent size") );
375 destroySubDiagonalOp(op);
376 }
377 SECTION( "number of targets" ) {
378
379 // make too many targets (which are otherwise valid)
380 SubDiagonalOp badOp = createSubDiagonalOp(NUM_QUBITS + 1);
381 int targs[NUM_QUBITS + 1];
382 for (int t=0; t<badOp.numQubits; t++)
383 targs[t] = t;
384 for (int i=0; i<badOp.numElems; i++)
385 badOp.cpuElems[i] = qcomp(1, 0);
386 syncDiagMatr(badOp);
387
388 REQUIRE_THROWS_WITH( applyGateSubDiagonalOp(quregVec, targs, badOp.numQubits, badOp), ContainsSubstring("number of target qubits") && ContainsSubstring("exceeds") );
389 destroySubDiagonalOp(badOp);
390 }
391 SECTION( "repetition in targets" ) {
392
393 // make a valid unitary diagonal op
394 SubDiagonalOp op = createSubDiagonalOp(3);
395 for (int i=0; i<op.numElems; i++)
396 op.cpuElems[i] = qcomp(1, 0);
397 syncDiagMatr(op);
398
399 // make a repetition in the target list
400 int targs[] = {2,1,2};
401
402 REQUIRE_THROWS_WITH( applyGateSubDiagonalOp(quregVec, targs, op.numQubits, op), ContainsSubstring("target qubits contained duplicates") );
403 destroySubDiagonalOp(op);
404 }
405 SECTION( "qubit indices" ) {
406
407 // make a valid unitary diagonal op
408 SubDiagonalOp op = createSubDiagonalOp(3);
409 for (int i=0; i<op.numElems; i++)
410 op.cpuElems[i] = qcomp(1,0);
411 syncDiagMatr(op);
412
413 int targs[] = {0,1,2};
414
415 // make each target in-turn invalid
416 int badIndex = GENERATE( range(0,3) );
417 int badValue = GENERATE( -1, NUM_QUBITS );
418 targs[badIndex] = badValue;
419
420 REQUIRE_THROWS_WITH( applyGateSubDiagonalOp(quregVec, targs, op.numQubits, op), ContainsSubstring("Invalid target qubit") );
421 destroySubDiagonalOp(op);
422 }
423 }
424 CLEANUP_TEST( quregVec, quregMatr );
425}
426
427
428
429/** @sa applyMatrix2
430 * @ingroup deprecatedtests
431 * @author Tyson Jones
432 */
433TEST_CASE( "applyMatrix2", "[operators]" ) {
434
435 PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
436
437 // every test will use a unique random matrix
438 QMatrix op = getRandomQMatrix(2); // 2-by-2
440
441 SECTION( "correctness" ) {
442
443 int target = GENERATE( range(0,NUM_QUBITS) );
444
445 // reference boilerplate
446 int* ctrls = NULL;
447 int numCtrls = 0;
448 int targs[] = {target};
449 int numTargs = 1;
450
451 SECTION( "state-vector" ) {
452
453 applyMatrix2(quregVec, target, matr);
454 applyReferenceMatrix(refVec, ctrls, numCtrls, targs, numTargs, op);
455
456 REQUIRE( areEqual(quregVec, refVec) );
457 }
458 SECTION( "density-matrix" ) {
459
460 applyMatrix2(quregMatr, target, matr);
461 applyReferenceMatrix(refMatr, ctrls, numCtrls, targs, numTargs, op);
462
463 REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
464 }
465 }
466 SECTION( "input validation" ) {
467
468 SECTION( "qubit indices" ) {
469
470 int target = GENERATE( -1, NUM_QUBITS );
471 REQUIRE_THROWS_WITH( applyMatrix2(quregVec, target, matr), ContainsSubstring("Invalid target") );
472 }
473 }
474 CLEANUP_TEST( quregVec, quregMatr );
475}
476
477
478
479/** @sa applyMatrix4
480 * @ingroup deprecatedtests
481 * @author Tyson Jones
482 */
483TEST_CASE( "applyMatrix4", "[operators]" ) {
484
485 PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
486
487 // in distributed mode, each node must be able to fit all amps modified by matrix
488 REQUIRE( quregVec.numAmpsPerNode >= 4 );
489
490 // every test will use a unique random matrix
491 QMatrix op = getRandomQMatrix(4); // 4-by-4
493
494 SECTION( "correctness" ) {
495
496 int targ1 = GENERATE( range(0,NUM_QUBITS) );
497 int targ2 = GENERATE_COPY( filter([=](int t){ return t!=targ1; }, range(0,NUM_QUBITS)) );
498
499 // reference boilerplate
500 int* ctrls = NULL;
501 int numCtrls = 0;
502 int targs[] = {targ1, targ2};
503 int numTargs = 2;
504
505 SECTION( "state-vector" ) {
506
507 applyMatrix4(quregVec, targ1, targ2, matr);
508 applyReferenceMatrix(refVec, ctrls, numCtrls, targs, numTargs, op);
509 REQUIRE( areEqual(quregVec, refVec) );
510 }
511 SECTION( "density-matrix" ) {
512
513 applyMatrix4(quregMatr, targ1, targ2, matr);
514 applyReferenceMatrix(refMatr, ctrls, numCtrls, targs, numTargs, op);
515 REQUIRE( areEqual(quregMatr, refMatr, 10*REAL_EPS) );
516 }
517 }
518 SECTION( "input validation" ) {
519
520 SECTION( "qubit indices" ) {
521
522 int targ1 = GENERATE( -1, NUM_QUBITS );
523 int targ2 = 0;
524 REQUIRE_THROWS_WITH( applyMatrix4(quregVec, targ1, targ2, matr), ContainsSubstring("Invalid target") );
525 REQUIRE_THROWS_WITH( applyMatrix4(quregVec, targ2, targ1, matr), ContainsSubstring("Invalid target") );
526 }
527 SECTION( "repetition of targets" ) {
528
529 int qb = 0;
530 REQUIRE_THROWS_WITH( applyMatrix4(quregVec, qb, qb, matr), ContainsSubstring("target") && ContainsSubstring("unique") );
531 }
532 SECTION( "matrix fits in node" ) {
533
534 // pretend we have a very limited distributed memory
535 quregVec.isDistributed = 1;
536 quregVec.numAmpsPerNode = 1;
537 quregVec.logNumAmpsPerNode = 0;
538 REQUIRE_THROWS_WITH( applyMatrix4(quregVec, 0, 1, matr), ContainsSubstring("communication buffer") && ContainsSubstring("cannot simultaneously store") );
539 }
540 }
541 CLEANUP_TEST( quregVec, quregMatr );
542}
543
544
545
546/** @sa applyMatrixN
547 * @ingroup deprecatedtests
548 * @author Tyson Jones
549 */
550TEST_CASE( "applyMatrixN", "[operators]" ) {
551
552 PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
553
554 // figure out max-num (inclusive) targs allowed by hardware backend
555 int maxNumTargs = calcLog2(quregVec.numAmpsPerNode);
556
557 SECTION( "correctness" ) {
558
559 // generate all possible qubit arrangements
560 int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) ); // inclusive upper bound
561 int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
562
563 // for each qubit arrangement, use a new random matrix
564 QMatrix op = getRandomQMatrix(1 << numTargs);
565 ComplexMatrixN matr = createComplexMatrixN(numTargs);
566 toComplexMatrixN(op, matr);
567
568 // reference boilerplate
569 int* ctrls = NULL;
570 int numCtrls = 0;
571
572 SECTION( "state-vector" ) {
573
574 applyMatrixN(quregVec, targs, numTargs, matr);
575 applyReferenceMatrix(refVec, ctrls, numCtrls, targs, numTargs, op);
576 REQUIRE( areEqual(quregVec, refVec) );
577 }
578 SECTION( "density-matrix" ) {
579
580 applyMatrixN(quregMatr, targs, numTargs, matr);
581 applyReferenceMatrix(refMatr, ctrls, numCtrls, targs, numTargs, op);
582 REQUIRE( areEqual(quregMatr, refMatr, 100*REAL_EPS) );
583 }
584 destroyComplexMatrixN(matr);
585 }
586 SECTION( "input validation" ) {
587
588 SECTION( "number of targets" ) {
589
590 // there cannot be more targets than qubits in register
591 int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
592 int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
593 ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
594 syncCompMatr(matr);
595
596 REQUIRE_THROWS_WITH( applyMatrixN(quregVec, targs, numTargs, matr), ContainsSubstring("number of target qubits") );
597 destroyComplexMatrixN(matr);
598 }
599 SECTION( "repetition in targets" ) {
600
601 int numTargs = 3;
602 int targs[] = {1,2,2};
603 ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
604 syncCompMatr(matr);
605
606 REQUIRE_THROWS_WITH( applyMatrixN(quregVec, targs, numTargs, matr), ContainsSubstring("target") && ContainsSubstring("unique") );
607 destroyComplexMatrixN(matr);
608 }
609 SECTION( "qubit indices" ) {
610
611 int numTargs = 3;
612 int targs[] = {1,2,3};
613 ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
614 syncCompMatr(matr);
615
616 int inv = GENERATE( -1, NUM_QUBITS );
617 targs[GENERATE_COPY( range(0,numTargs) )] = inv; // make invalid target
618 REQUIRE_THROWS_WITH( applyMatrixN(quregVec, targs, numTargs, matr), ContainsSubstring("Invalid target") );
619
620 destroyComplexMatrixN(matr);
621 }
622 SECTION( "matrix creation" ) {
623
624 int numTargs = 3;
625 int targs[] = {1,2,3};
626
627 ComplexMatrixN matr;
628 matr.cpuElems = NULL;
629 REQUIRE_THROWS_WITH( applyMatrixN(quregVec, targs, numTargs, matr), ContainsSubstring("created") );
630 }
631 SECTION( "matrix dimensions" ) {
632
633 int targs[2] = {1,2};
634 ComplexMatrixN matr = createComplexMatrixN(3); // intentionally wrong size
635 syncCompMatr(matr);
636
637 REQUIRE_THROWS_WITH( applyMatrixN(quregVec, targs, 2, matr), ContainsSubstring("matrix has an inconsistent size") );
638 destroyComplexMatrixN(matr);
639 }
640 SECTION( "matrix fits in node" ) {
641
642 // pretend we have a very limited distributed memory (judged by matr size)
643 quregVec.isDistributed = 1;
644 quregVec.numAmpsPerNode = 1;
645 quregVec.logNumAmpsPerNode = 0;
646 int qb[] = {1,2};
647 ComplexMatrixN matr = createComplexMatrixN(2); // prevents seg-fault if validation doesn't trigger
648 syncCompMatr(matr);
649
650 REQUIRE_THROWS_WITH( applyMatrixN(quregVec, qb, 2, matr), ContainsSubstring("communication buffer") && ContainsSubstring("cannot simultaneously store") );
651
652 destroyComplexMatrixN(matr);
653 }
654 }
655 CLEANUP_TEST( quregVec, quregMatr );
656}
657
658
659
660/** @sa applyMultiControlledGateMatrixN
661 * @ingroup deprecatedtests
662 * @author Tyson Jones
663 */
664TEST_CASE( "applyMultiControlledGateMatrixN", "[operators]" ) {
665
666 PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
667
668 // figure out max-num targs (inclusive) allowed by hardware backend
669 int maxNumTargs = calcLog2(quregVec.numAmpsPerNode);
670 if (maxNumTargs >= NUM_QUBITS)
671 maxNumTargs = NUM_QUBITS - 1; // leave room for min-number of control qubits
672
673 SECTION( "correctness" ) {
674
675 // try all possible numbers of targets and controls
676 int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
677 int maxNumCtrls = NUM_QUBITS - numTargs;
678 int numCtrls = GENERATE_COPY( range(1,maxNumCtrls+1) );
679
680 // generate all possible valid qubit arrangements
681 int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
682 int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls, targs, numTargs) );
683
684 // for each qubit arrangement, use a new random unitary
685 QMatrix op = getRandomQMatrix(1 << numTargs);
686 ComplexMatrixN matr = createComplexMatrixN(numTargs);
687 toComplexMatrixN(op, matr);
688
689 SECTION( "state-vector" ) {
690
691 applyMultiControlledGateMatrixN(quregVec, ctrls, numCtrls, targs, numTargs, matr);
692 applyReferenceOp(refVec, ctrls, numCtrls, targs, numTargs, op);
693 REQUIRE( areEqual(quregVec, refVec) );
694 }
695 SECTION( "density-matrix" ) {
696
697 applyMultiControlledGateMatrixN(quregMatr, ctrls, numCtrls, targs, numTargs, matr);
698 applyReferenceOp(refMatr, ctrls, numCtrls, targs, numTargs, op);
699 REQUIRE( areEqual(quregMatr, refMatr, 1E4*REAL_EPS) );
700 }
701 destroyComplexMatrixN(matr);
702 }
703 SECTION( "input validation" ) {
704
705 SECTION( "number of targets" ) {
706
707 // there cannot be more targets than qubits in register
708 // (numTargs=NUM_QUBITS is caught elsewhere, because that implies ctrls are invalid)
709 int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
710 int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
711 int ctrls[] = {0};
712 ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
713 toComplexMatrixN(getRandomUnitary(NUM_QUBITS+1), matr); // ensure unitary
714
715 REQUIRE_THROWS_WITH( applyMultiControlledGateMatrixN(quregVec, ctrls, 1, targs, numTargs, matr), ContainsSubstring("number of target qubits") );
716 destroyComplexMatrixN(matr);
717 }
718 SECTION( "repetition in targets" ) {
719
720 int ctrls[] = {0};
721 int numTargs = 3;
722 int targs[] = {1,2,2};
723 ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
724 toComplexMatrixN(getRandomUnitary(numTargs), matr); // ensure unitary
725
726 REQUIRE_THROWS_WITH( applyMultiControlledGateMatrixN(quregVec, ctrls, 1, targs, numTargs, matr), ContainsSubstring("target") && ContainsSubstring("unique"));
727 destroyComplexMatrixN(matr);
728 }
729 SECTION( "number of controls" ) {
730
731 int numCtrls = GENERATE( -1, NUM_QUBITS+1 );
732 int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
733 int targs[1] = {0};
734 ComplexMatrixN matr = createComplexMatrixN(1);
735 toComplexMatrixN(getRandomUnitary(1), matr); // ensure unitary
736
737 REQUIRE_THROWS_WITH( applyMultiControlledGateMatrixN(quregVec, ctrls, numCtrls, targs, 1, matr), ContainsSubstring("number of control qubits") );
738 destroyComplexMatrixN(matr);
739 }
740 SECTION( "repetition in controls" ) {
741
742 int ctrls[] = {0,1,1};
743 int targs[] = {3};
744 ComplexMatrixN matr = createComplexMatrixN(1);
745 toComplexMatrixN(getRandomUnitary(1), matr); // ensure unitary
746
747 REQUIRE_THROWS_WITH( applyMultiControlledGateMatrixN(quregVec, ctrls, 3, targs, 1, matr), ContainsSubstring("control") && ContainsSubstring("unique") );
748 destroyComplexMatrixN(matr);
749 }
750 SECTION( "control and target collision" ) {
751
752 int ctrls[] = {1};
753 int targs[] = {3,1,0};
754 ComplexMatrixN matr = createComplexMatrixN(3);
755 toComplexMatrixN(getRandomUnitary(3), matr); // ensure unitary
756
757 REQUIRE_THROWS_WITH( applyMultiControlledGateMatrixN(quregVec, ctrls, 1, targs, 3, matr), ContainsSubstring("control and target qubits") );
758 destroyComplexMatrixN(matr);
759 }
760 SECTION( "qubit indices" ) {
761
762 // valid inds
763 int numQb = 2;
764 int qb1[2] = {0,1};
765 int qb2[2] = {2,3};
766 ComplexMatrixN matr = createComplexMatrixN(numQb);
767 toComplexMatrixN(getRandomUnitary(numQb), matr); // ensure unitary
768
769 // make qb1 invalid
770 int inv = GENERATE( -1, NUM_QUBITS );
771 qb1[GENERATE_COPY(range(0,numQb))] = inv;
772
773 REQUIRE_THROWS_WITH( applyMultiControlledGateMatrixN(quregVec, qb1, numQb, qb2, numQb, matr), ContainsSubstring("Invalid control") );
774 REQUIRE_THROWS_WITH( applyMultiControlledGateMatrixN(quregVec, qb2, numQb, qb1, numQb, matr), ContainsSubstring("Invalid target") );
775 destroyComplexMatrixN(matr);
776 }
777 SECTION( "matrix creation" ) {
778
779 int ctrls[1] = {0};
780 int targs[3] = {1,2,3};
781
782 ComplexMatrixN matr;
783 matr.cpuElems = NULL;
784 REQUIRE_THROWS_WITH( applyMultiControlledGateMatrixN(quregVec, ctrls, 1, targs, 3, matr), ContainsSubstring("created") );
785 }
786 SECTION( "matrix dimensions" ) {
787
788 int ctrls[1] = {0};
789 int targs[2] = {1,2};
790 ComplexMatrixN matr = createComplexMatrixN(3); // intentionally wrong size
791 toComplexMatrixN(getRandomUnitary(3), matr); // ensure unitary
792
793 REQUIRE_THROWS_WITH( applyMultiControlledGateMatrixN(quregVec, ctrls, 1, targs, 2, matr), ContainsSubstring("matrix has an inconsistent size"));
794 destroyComplexMatrixN(matr);
795 }
796 SECTION( "matrix fits in node" ) {
797
798 // pretend we have a very limited distributed memory (judged by matr size)
799 quregVec.isDistributed = 1;
800 quregVec.numAmpsPerNode = 1;
801 quregVec.logNumAmpsPerNode = 0;
802 int ctrls[1] = {0};
803 int targs[2] = {1,2};
804 ComplexMatrixN matr = createComplexMatrixN(2);
805 toComplexMatrixN(getRandomUnitary(2), matr); // ensure unitary
806
807 REQUIRE_THROWS_WITH( applyMultiControlledGateMatrixN(quregVec, ctrls, 1, targs, 2, matr), ContainsSubstring("communication buffer") && ContainsSubstring("cannot simultaneously store") );
808 destroyComplexMatrixN(matr);
809 }
810 }
811 CLEANUP_TEST( quregVec, quregMatr );
812}
813
814
815
816// applyMultiControlledMatrixN removed because replacement function
817// multiplyCompMatr() does not accept control-qubits (because WHO
818// would ever want to left-apply a controlled matrix onto a density
819// matrix??)
820
821 // /** @sa applyMultiControlledMatrixN
822 // * @ingroup deprecatedtests
823 // * @author Tyson Jones
824 // */
825 // TEST_CASE( "applyMultiControlledMatrixN", "[operators]" ) {
826
827 // PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
828
829 // // figure out max-num targs (inclusive) allowed by hardware backend
830 // int maxNumTargs = calcLog2(quregVec.numAmpsPerNode);
831 // if (maxNumTargs >= NUM_QUBITS)
832 // maxNumTargs = NUM_QUBITS - 1; // leave room for min-number of control qubits
833
834 // SECTION( "correctness" ) {
835
836 // // try all possible numbers of targets and controls
837 // int numTargs = GENERATE_COPY( range(1,maxNumTargs+1) );
838 // int maxNumCtrls = NUM_QUBITS - numTargs;
839 // int numCtrls = GENERATE_COPY( range(1,maxNumCtrls+1) );
840
841 // // generate all possible valid qubit arrangements
842 // int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
843 // int* ctrls = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numCtrls, targs, numTargs) );
844
845 // // for each qubit arrangement, use a new random unitary
846 // QMatrix op = getRandomQMatrix(1 << numTargs);
847 // ComplexMatrixN matr = createComplexMatrixN(numTargs);
848 // toComplexMatrixN(op, matr);
849
850 // SECTION( "state-vector" ) {
851
852 // applyMultiControlledMatrixN(quregVec, ctrls, numCtrls, targs, numTargs, matr);
853 // applyReferenceMatrix(refVec, ctrls, numCtrls, targs, numTargs, op);
854 // REQUIRE( areEqual(quregVec, refVec) );
855 // }
856 // SECTION( "density-matrix" ) {
857
858 // applyMultiControlledMatrixN(quregMatr, ctrls, numCtrls, targs, numTargs, matr);
859 // applyReferenceMatrix(refMatr, ctrls, numCtrls, targs, numTargs, op);
860 // REQUIRE( areEqual(quregMatr, refMatr, 100*REAL_EPS) );
861 // }
862 // destroyComplexMatrixN(matr);
863 // }
864 // SECTION( "input validation" ) {
865
866 // SECTION( "number of targets" ) {
867
868 // // there cannot be more targets than qubits in register
869 // // (numTargs=NUM_QUBITS is caught elsewhere, because that implies ctrls are invalid)
870 // int numTargs = GENERATE( -1, 0, NUM_QUBITS+1 );
871 // int targs[NUM_QUBITS+1]; // prevents seg-fault if validation doesn't trigger
872 // int ctrls[] = {0};
873 // ComplexMatrixN matr = createComplexMatrixN(NUM_QUBITS+1); // prevent seg-fault
874 // toComplexMatrixN(getRandomQMatrix( 1 << (NUM_QUBITS+1)), matr);
875
876 // REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 1, targs, numTargs, matr), ContainsSubstring("Invalid number of target"));
877 // destroyComplexMatrixN(matr);
878 // }
879 // SECTION( "repetition in targets" ) {
880
881 // int ctrls[] = {0};
882 // int numTargs = 3;
883 // int targs[] = {1,2,2};
884 // ComplexMatrixN matr = createComplexMatrixN(numTargs); // prevents seg-fault if validation doesn't trigger
885 // toComplexMatrixN(getRandomQMatrix(1 << numTargs), matr);
886
887 // REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 1, targs, numTargs, matr), ContainsSubstring("target") && ContainsSubstring("unique"));
888 // destroyComplexMatrixN(matr);
889 // }
890 // SECTION( "number of controls" ) {
891
892 // int numCtrls = GENERATE( -1, 0, NUM_QUBITS, NUM_QUBITS+1 );
893 // int ctrls[NUM_QUBITS+1]; // avoids seg-fault if validation not triggered
894 // int targs[1] = {0};
895 // ComplexMatrixN matr = createComplexMatrixN(1);
896 // toComplexMatrixN(getRandomQMatrix(1 << 1), matr);
897
898 // REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, numCtrls, targs, 1, matr), ContainsSubstring("Invalid number of control"));
899 // destroyComplexMatrixN(matr);
900 // }
901 // SECTION( "repetition in controls" ) {
902
903 // int ctrls[] = {0,1,1};
904 // int targs[] = {3};
905 // ComplexMatrixN matr = createComplexMatrixN(1);
906 // toComplexMatrixN(getRandomQMatrix(1 << 1), matr);
907
908 // REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 3, targs, 1, matr), ContainsSubstring("control") && ContainsSubstring("unique"));
909 // destroyComplexMatrixN(matr);
910 // }
911 // SECTION( "control and target collision" ) {
912
913 // int ctrls[] = {0,1,2};
914 // int targs[] = {3,1,4};
915 // ComplexMatrixN matr = createComplexMatrixN(3);
916 // toComplexMatrixN(getRandomQMatrix(1 << 3), matr);
917
918 // REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 3, targs, 3, matr), ContainsSubstring("Control") && ContainsSubstring("target") && ContainsSubstring("disjoint"));
919 // destroyComplexMatrixN(matr);
920 // }
921 // SECTION( "qubit indices" ) {
922
923 // // valid inds
924 // int numQb = 2;
925 // int qb1[2] = {0,1};
926 // int qb2[2] = {2,3};
927 // ComplexMatrixN matr = createComplexMatrixN(numQb);
928 // toComplexMatrixN(getRandomQMatrix(1 << numQb), matr);
929
930 // // make qb1 invalid
931 // int inv = GENERATE( -1, NUM_QUBITS );
932 // qb1[GENERATE_COPY(range(0,numQb))] = inv;
933
934 // REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, qb1, numQb, qb2, numQb, matr), ContainsSubstring("Invalid control") );
935 // REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, qb2, numQb, qb1, numQb, matr), ContainsSubstring("Invalid target") );
936 // destroyComplexMatrixN(matr);
937 // }
938 // SECTION( "matrix creation" ) {
939
940 // int ctrls[1] = {0};
941 // int targs[3] = {1,2,3};
942
943 // /* compilers don't auto-initialise to NULL; the below circumstance
944 // * only really occurs when 'malloc' returns NULL in createComplexMatrixN,
945 // * which actually triggers its own validation. Hence this test is useless
946 // * currently.
947 // */
948 // ComplexMatrixN matr;
949 // matr.cpuElems = NULL;
950 // REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 1, targs, 3, matr), ContainsSubstring("created") );
951 // }
952 // SECTION( "matrix dimensions" ) {
953
954 // int ctrls[1] = {0};
955 // int targs[2] = {1,2};
956 // ComplexMatrixN matr = createComplexMatrixN(3); // intentionally wrong size
957 // toComplexMatrixN(getRandomQMatrix(1 << 3), matr);
958
959 // REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 1, targs, 2, matr), ContainsSubstring("matrix size"));
960 // destroyComplexMatrixN(matr);
961 // }
962 // SECTION( "matrix fits in node" ) {
963
964 // // pretend we have a very limited distributed memory (judged by matr size)
965 // quregVec.numAmpsPerNode = 1;
966 // int ctrls[1] = {0};
967 // int targs[2] = {1,2};
968 // ComplexMatrixN matr = createComplexMatrixN(2);
969 // toComplexMatrixN(getRandomQMatrix(1 << 2), matr);
970
971 // REQUIRE_THROWS_WITH( applyMultiControlledMatrixN(quregVec, ctrls, 1, targs, 2, matr), ContainsSubstring("targets too many qubits"));
972 // destroyComplexMatrixN(matr);
973 // }
974 // }
975 // CLEANUP_TEST( quregVec, quregMatr );
976 // }
977
978
979
980// applyMultiVarPhaseFunc removed because phase functions are
981// completely deprecated, in favour of functions like
982// setDiagMatrFromMultiVarFunc and setFullStateDiagMatrFromMultiDimLists
983
984 // /** @sa applyMultiVarPhaseFunc
985 // * @ingroup deprecatedtests
986 // * @author Tyson Jones
987 // */
988 // TEST_CASE( "applyMultiVarPhaseFunc", "[operators]" ) {
989
990 // PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
991
992 // SECTION( "correctness" ) {
993
994 // // try every kind of binary encodings
995 // enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
996
997 // // try every possible number of registers
998 // // (between #qubits containing 1, and 1 containing #qubits)
999 // int numRegs;
1000 // int maxNumRegs = 0;
1001 // if (encoding == UNSIGNED)
1002 // maxNumRegs = NUM_QUBITS;
1003 // if (encoding == TWOS_COMPLEMENT)
1004 // maxNumRegs = NUM_QUBITS/2; // floors
1005 // numRegs = GENERATE_COPY( range(1, maxNumRegs+1) );
1006
1007 // // try every possible total number of involed qubits
1008 // int totalNumQubits;
1009 // int minTotalQubits = 0;
1010 // if (encoding == UNSIGNED)
1011 // // each register must contain at least 1 qubit
1012 // minTotalQubits = numRegs;
1013 // if (encoding == TWOS_COMPLEMENT)
1014 // // each register must contain at least 2 qubits
1015 // minTotalQubits = 2*numRegs;
1016 // totalNumQubits = GENERATE_COPY( range(minTotalQubits,NUM_QUBITS+1) );
1017
1018 // // try every qubits subset and ordering
1019 // int* regs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), totalNumQubits) );
1020
1021 // // assign each sub-reg its minimum length
1022 // int unallocQubits = totalNumQubits;
1023 // VLA(int, numQubitsPerReg, numRegs);
1024 // for (int i=0; i<numRegs; i++)
1025 // if (encoding == UNSIGNED) {
1026 // numQubitsPerReg[i] = 1;
1027 // unallocQubits -= 1;
1028 // }
1029 // else if (encoding == TWOS_COMPLEMENT) {
1030 // numQubitsPerReg[i] = 2;
1031 // unallocQubits -= 2;
1032 // }
1033 // // and randomly allocate the remaining qubits between the registers
1034 // while (unallocQubits > 0) {
1035 // numQubitsPerReg[getRandomInt(0,numRegs)] += 1;
1036 // unallocQubits--;
1037 // }
1038
1039
1040 // // each register gets a random number of terms in the full phase function
1041 // VLA(int, numTermsPerReg, numRegs);
1042 // int numTermsTotal = 0;
1043 // for (int r=0; r<numRegs; r++) {
1044 // int numTerms = getRandomInt(1,5);
1045 // numTermsPerReg[r] = numTerms;
1046 // numTermsTotal += numTerms;
1047 // }
1048
1049 // // populate the multi-var phase function with random but POSITIVE-power terms,
1050 // // which must further be integers in two's complement
1051 // int flatInd = 0;
1052 // VLA(qreal, coeffs, numTermsTotal);
1053 // VLA(qreal, expons, numTermsTotal);
1054 // for (int r=0; r<numRegs; r++) {
1055 // for (int t=0; t<numTermsPerReg[r]; t++) {
1056 // coeffs[flatInd] = getRandomReal(-10,10);
1057 // if (encoding == TWOS_COMPLEMENT)
1058 // expons[flatInd] = getRandomInt(0, 3+1);
1059 // else if (encoding == UNSIGNED)
1060 // expons[flatInd] = getRandomReal(0, 3);
1061
1062 // flatInd++;
1063 // }
1064 // }
1065
1066 // /* To perform this calculation more distinctly from the QuEST
1067 // * core method, we can exploit that
1068 // * exp(i (f1[x1] + f2[x2]))|x2>|x1> = exp(i f2[x2])|x2> (x) exp(i f1[x1])|x1>
1069 // * and so compute a separate diagonal matrix for each sub-register with
1070 // * phases determined only by its own variable, and Kronecker multiply
1071 // * them together. The target qubits of the Kronecker product is then
1072 // * just the full register, stored in *regs.
1073 // */
1074 // QMatrix allRegMatr{{1}};
1075 // int startInd = 0;
1076
1077 // for (int r=0; r<numRegs; r++) {
1078
1079 // QMatrix singleRegMatr = getZeroMatrix( 1 << numQubitsPerReg[r] );
1080
1081 // for (size_t i=0; i<singleRegMatr.size(); i++) {
1082
1083 // long long int ind = 0;
1084 // if (encoding == UNSIGNED)
1085 // ind = i;
1086 // if (encoding == TWOS_COMPLEMENT)
1087 // ind = getTwosComplement(i, numQubitsPerReg[r]);
1088
1089 // qreal phase = 0;
1090 // for (int t=0; t<numTermsPerReg[r]; t++)
1091 // phase += coeffs[t+startInd] * pow(ind, expons[t+startInd]);
1092
1093 // singleRegMatr[i][i] = expI(phase);
1094 // }
1095 // allRegMatr = getKroneckerProduct(singleRegMatr, allRegMatr);
1096 // startInd += numTermsPerReg[r];
1097 // }
1098
1099 // SECTION( "state-vector" ) {
1100
1101 // applyMultiVarPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, coeffs, expons, numTermsPerReg);
1102 // applyReferenceOp(refVec, regs, totalNumQubits, allRegMatr);
1103 // REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
1104 // }
1105 // SECTION( "density-matrix" ) {
1106
1107 // applyMultiVarPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, coeffs, expons, numTermsPerReg);
1108 // applyReferenceOp(refMatr, regs, totalNumQubits, allRegMatr);
1109 // REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
1110 // }
1111 // }
1112 // SECTION( "input validation" ) {
1113
1114 // int numRegs = 2;
1115 // int numQubitsPerReg[] = {2,3};
1116 // int qubits[] = {0,1,2,3,4};
1117
1118 // SECTION( "number of registers" ) {
1119
1120 // numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
1121 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFunc(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, NULL, NULL, NULL), ContainsSubstring("Invalid number of qubit subregisters") );
1122 // }
1123 // SECTION( "number of qubits" ) {
1124
1125 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
1126 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFunc(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, NULL, NULL, NULL), ContainsSubstring("Invalid number of qubits") );
1127 // }
1128 // SECTION( "repetition of qubits" ) {
1129
1130 // qubits[GENERATE(2,3,4)] = qubits[1];
1131 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFunc(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, NULL, NULL, NULL), ContainsSubstring("The qubits must be unique") );
1132 // }
1133 // SECTION( "qubit indices" ) {
1134
1135 // qubits[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
1136 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFunc(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, NULL, NULL, NULL), ContainsSubstring("Invalid qubit index") );
1137 // }
1138 // SECTION( "number of terms" ) {
1139
1140 // int numTermsPerReg[] = {3, 3};
1141
1142 // numTermsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0 );
1143 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFunc(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, NULL, NULL, numTermsPerReg), ContainsSubstring("Invalid number of terms in the phase function") );
1144 // }
1145 // SECTION( "bit encoding name" ) {
1146
1147 // enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
1148 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFunc(quregVec, qubits, numQubitsPerReg, numRegs, enc, NULL, NULL, NULL), ContainsSubstring("Invalid bit encoding") );
1149 // }
1150 // SECTION( "two's complement register" ) {
1151
1152 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
1153 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFunc(quregVec, qubits, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NULL, NULL, NULL), ContainsSubstring("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
1154 // }
1155 // SECTION( "fractional exponent" ) {
1156
1157 // int numTermsPerReg[] = {3, 3};
1158 // qreal coeffs[] = {0,0,0, 0,0,0};
1159 // qreal expos[] = {1,2,3, 1,2,3};
1160
1161 // expos[GENERATE(range(0,6))] = GENERATE( 0.5, 1.999, 5.0001 );
1162 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFunc(quregVec, qubits, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, coeffs, expos, numTermsPerReg), ContainsSubstring("The phase function contained a fractional exponent, which is illegal in TWOS_COMPLEMENT") );
1163
1164 // // ensure fractional exponents are valid in unsigned mode however
1165 // REQUIRE_NOTHROW( applyMultiVarPhaseFunc(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, coeffs, expos, numTermsPerReg) );
1166
1167 // }
1168 // SECTION( "negative exponent" ) {
1169
1170 // int numTermsPerReg[] = {3, 3};
1171 // qreal coeffs[] = {0,0,0, 0,0,0};
1172 // qreal expos[] = {1,2,3, 1,2,3};
1173
1174 // expos[GENERATE(range(0,6))] = GENERATE( -1, -2, -2.5 );
1175 // enum bitEncoding enc = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
1176
1177 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFunc(quregVec, qubits, numQubitsPerReg, numRegs, enc, coeffs, expos, numTermsPerReg), ContainsSubstring("The phase function contained an illegal negative exponent") );
1178 // }
1179 // }
1180 // CLEANUP_TEST( quregVec, quregMatr );
1181 // }
1182
1183
1184
1185// applyMultiVarPhaseFuncOverrides removed because phase functions are
1186// completely deprecated, in favour of functions like
1187// setDiagMatrFromMultiVarFunc and setFullStateDiagMatrFromMultiDimLists
1188
1189 // /** @sa applyMultiVarPhaseFuncOverrides
1190 // * @ingroup deprecatedtests
1191 // * @author Tyson Jones
1192 // */
1193 // TEST_CASE( "applyMultiVarPhaseFuncOverrides", "[operators]" ) {
1194
1195 // PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1196
1197 // SECTION( "correctness" ) {
1198
1199 // // try every kind of binary encodings
1200 // enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
1201
1202 // // try every possible number of registers
1203 // // (between #qubits containing 1, and 1 containing #qubits)
1204 // int numRegs;
1205 // int maxNumRegs = 0;
1206 // if (encoding == UNSIGNED)
1207 // maxNumRegs = NUM_QUBITS;
1208 // if (encoding == TWOS_COMPLEMENT)
1209 // maxNumRegs = NUM_QUBITS/2; // floors
1210 // numRegs = GENERATE_COPY( range(1, maxNumRegs+1) );
1211
1212 // // try every possible total number of involed qubits
1213 // int totalNumQubits;
1214 // int minTotalQubits = 0;
1215 // if (encoding == UNSIGNED)
1216 // // each register must contain at least 1 qubit
1217 // minTotalQubits = numRegs;
1218 // if (encoding == TWOS_COMPLEMENT)
1219 // // each register must contain at least 2 qubits
1220 // minTotalQubits = 2*numRegs;
1221 // totalNumQubits = GENERATE_COPY( range(minTotalQubits,NUM_QUBITS+1) );
1222
1223 // // try every qubits subset and ordering
1224 // int* regs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), totalNumQubits) );
1225
1226 // // assign each sub-reg its minimum length
1227 // int unallocQubits = totalNumQubits;
1228 // VLA(int, numQubitsPerReg, numRegs);
1229 // for (int i=0; i<numRegs; i++)
1230 // if (encoding == UNSIGNED) {
1231 // numQubitsPerReg[i] = 1;
1232 // unallocQubits -= 1;
1233 // }
1234 // else if (encoding == TWOS_COMPLEMENT) {
1235 // numQubitsPerReg[i] = 2;
1236 // unallocQubits -= 2;
1237 // }
1238 // // and randomly allocate the remaining qubits between the registers
1239 // while (unallocQubits > 0) {
1240 // numQubitsPerReg[getRandomInt(0,numRegs)] += 1;
1241 // unallocQubits--;
1242 // }
1243
1244
1245 // // each register gets a random number of terms in the full phase function
1246 // VLA(int, numTermsPerReg, numRegs);
1247 // int numTermsTotal = 0;
1248 // for (int r=0; r<numRegs; r++) {
1249 // int numTerms = getRandomInt(1,5);
1250 // numTermsPerReg[r] = numTerms;
1251 // numTermsTotal += numTerms;
1252 // }
1253
1254 // // populate the multi-var phase function with random but POSITIVE-power terms,
1255 // // which must further be integers in two's complement
1256 // int flatInd = 0;
1257 // VLA(qreal, coeffs, numTermsTotal);
1258 // VLA(qreal, expons, numTermsTotal);
1259 // for (int r=0; r<numRegs; r++) {
1260 // for (int t=0; t<numTermsPerReg[r]; t++) {
1261 // coeffs[flatInd] = getRandomReal(-10,10);
1262 // if (encoding == TWOS_COMPLEMENT)
1263 // expons[flatInd] = getRandomInt(0, 3+1);
1264 // else if (encoding == UNSIGNED)
1265 // expons[flatInd] = getRandomReal(0, 3);
1266
1267 // flatInd++;
1268 // }
1269 // }
1270
1271
1272 // // choose a random number of overrides (even overriding every amplitude)
1273 // int numOverrides = getRandomInt(0, (1<<totalNumQubits) + 1);
1274
1275 // // randomise each override index (uniqueness isn't checked)
1276 // VLA(long long int, overrideInds, numOverrides*numRegs);
1277 // flatInd = 0;
1278 // for (int v=0; v<numOverrides; v++) {
1279 // for (int r=0; r<numRegs; r++) {
1280 // if (encoding == UNSIGNED)
1281 // overrideInds[flatInd] = getRandomInt(0, 1<<numQubitsPerReg[r]);
1282 // else if (encoding == TWOS_COMPLEMENT)
1283 // overrideInds[flatInd] = getRandomInt(-(1<<(numQubitsPerReg[r]-1)), (1<<(numQubitsPerReg[r]-1))-1);
1284 // flatInd++;
1285 // }
1286 // }
1287
1288 // // override to a random phase
1289 // VLA(qreal, overridePhases, numOverrides);
1290 // for (int v=0; v<numOverrides; v++)
1291 // overridePhases[v] = getRandomReal(-4, 4); // periodic in [-pi, pi]
1292
1293 // /* To perform this calculation more distinctly from the QuEST
1294 // * core method, we can exploit that
1295 // * exp(i (f1[x1] + f2[x2]))|x2>|x1> = exp(i f2[x2])|x2> (x) exp(i f1[x1])|x1>
1296 // * and so compute a separate diagonal matrix for each sub-register with
1297 // * phases determined only by its own variable, and Kronecker multiply
1298 // * them together. The target qubits of the Kronecker product is then
1299 // * just the full register, stored in *regs. We do this, then iterate
1300 // * the list of overrides directly to overwrite the ultimate diagonal
1301 // * entries
1302 // */
1303 // QMatrix allRegMatr{{1}};
1304 // int startInd = 0;
1305 // for (int r=0; r<numRegs; r++) {
1306
1307 // QMatrix singleRegMatr = getZeroMatrix( 1 << numQubitsPerReg[r] );
1308
1309 // for (size_t i=0; i<singleRegMatr.size(); i++) {
1310
1311 // long long int ind = 0;
1312 // if (encoding == UNSIGNED)
1313 // ind = i;
1314 // if (encoding == TWOS_COMPLEMENT)
1315 // ind = getTwosComplement(i, numQubitsPerReg[r]);
1316
1317 // qreal phase = 0;
1318 // for (int t=0; t<numTermsPerReg[r]; t++)
1319 // phase += coeffs[t+startInd] * pow(ind, expons[t+startInd]);
1320
1321 // singleRegMatr[i][i] = expI(phase);
1322 // }
1323 // allRegMatr = getKroneckerProduct(singleRegMatr, allRegMatr);
1324 // startInd += numTermsPerReg[r];
1325 // }
1326 // setDiagMatrixOverrides(allRegMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
1327
1328 // SECTION( "state-vector" ) {
1329
1330 // applyMultiVarPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, coeffs, expons, numTermsPerReg, overrideInds, overridePhases, numOverrides);
1331 // applyReferenceOp(refVec, regs, totalNumQubits, allRegMatr);
1332 // REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
1333 // }
1334 // SECTION( "density-matrix" ) {
1335
1336 // applyMultiVarPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, coeffs, expons, numTermsPerReg, overrideInds, overridePhases, numOverrides);
1337 // applyReferenceOp(refMatr, regs, totalNumQubits, allRegMatr);
1338 // REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
1339 // }
1340 // }
1341 // SECTION( "input validation" ) {
1342
1343 // int numRegs = 2;
1344 // int numQubitsPerReg[] = {2,3};
1345 // int qubits[] = {0,1,2,3,4};
1346
1347 // SECTION( "number of registers" ) {
1348
1349 // numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
1350 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, NULL, NULL, NULL, NULL, NULL, 0), ContainsSubstring("Invalid number of qubit subregisters") );
1351 // }
1352 // SECTION( "number of qubits" ) {
1353
1354 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
1355 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, NULL, NULL, NULL, NULL, NULL, 0), ContainsSubstring("Invalid number of qubits") );
1356 // }
1357 // SECTION( "repetition of qubits" ) {
1358
1359 // qubits[GENERATE(2,3,4)] = qubits[1];
1360 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, NULL, NULL, NULL, NULL, NULL, 0), ContainsSubstring("The qubits must be unique") );
1361 // }
1362 // SECTION( "qubit indices" ) {
1363
1364 // qubits[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
1365 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, NULL, NULL, NULL, NULL, NULL, 0), ContainsSubstring("Invalid qubit index") );
1366 // }
1367 // SECTION( "number of terms" ) {
1368
1369 // int numTermsPerReg[] = {3, 3};
1370
1371 // numTermsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0 );
1372 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, NULL, NULL, numTermsPerReg, NULL, NULL, 0), ContainsSubstring("Invalid number of terms in the phase function") );
1373 // }
1374 // SECTION( "bit encoding name" ) {
1375
1376 // enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
1377 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, enc, NULL, NULL, NULL, NULL, NULL, 0), ContainsSubstring("Invalid bit encoding") );
1378 // }
1379 // SECTION( "two's complement register" ) {
1380
1381 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
1382 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NULL, NULL, NULL, NULL, NULL, 0), ContainsSubstring("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
1383 // }
1384 // SECTION( "fractional exponent" ) {
1385
1386 // int numTermsPerReg[] = {3, 3};
1387 // qreal coeffs[] = {0,0,0, 0,0,0};
1388 // qreal expos[] = {1,2,3, 1,2,3};
1389
1390 // expos[GENERATE(range(0,6))] = GENERATE( 0.5, 1.999, 5.0001 );
1391 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, coeffs, expos, numTermsPerReg, NULL, NULL, 0), ContainsSubstring("The phase function contained a fractional exponent, which is illegal in TWOS_COMPLEMENT") );
1392
1393 // // ensure fractional exponents are valid in unsigned mode however
1394 // REQUIRE_NOTHROW( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, coeffs, expos, numTermsPerReg, NULL, NULL, 0) );
1395 // }
1396 // SECTION( "negative exponent" ) {
1397
1398 // int numTermsPerReg[] = {3, 3};
1399 // qreal coeffs[] = {0,0,0, 0,0,0};
1400 // qreal expos[] = {1,2,3, 1,2,3};
1401
1402 // expos[GENERATE(range(0,6))] = GENERATE( -1, -2, -2.5 );
1403 // enum bitEncoding enc = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
1404
1405 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, enc, coeffs, expos, numTermsPerReg, NULL, NULL, 0), ContainsSubstring("The phase function contained an illegal negative exponent") );
1406 // }
1407 // SECTION( "number of overrides" ) {
1408
1409 // int numTermsPerReg[] = {3, 3};
1410 // qreal coeffs[] = {0,0,0, 0,0,0};
1411 // qreal expos[] = {1,2,3, 1,2,3};
1412
1413 // int numOverrides = -1;
1414 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, UNSIGNED, coeffs, expos, numTermsPerReg, NULL, NULL, numOverrides), ContainsSubstring("Invalid number of phase function overrides specified") );
1415 // }
1416 // SECTION( "override indices" ) {
1417
1418 // int numTermsPerReg[] = {3, 3};
1419 // qreal coeffs[] = {0,0,0, 0,0,0};
1420 // qreal expos[] = {1,2,3, 1,2,3};
1421
1422 // // numQubitsPerReg = {2, 3}
1423 // int numOverrides = 3;
1424 // long long int overrideInds[] = {0,0, 0,0, 0,0}; // repetition not checked
1425 // qreal overridePhases[] = {.1, .1, .1};
1426
1427 // // first element of overrideInds coordinate is a 2 qubit register
1428 // enum bitEncoding enc = UNSIGNED;
1429 // int badInd = GENERATE(0, 2, 4);
1430 // overrideInds[badInd] = GENERATE( -1, (1<<2) );
1431 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, enc, coeffs, expos, numTermsPerReg, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the UNSIGNED encoding") );
1432 // overrideInds[badInd] = 0;
1433
1434 // // second element of overrideInds coordinate is a 3 qubit register
1435 // badInd += 1;
1436 // overrideInds[badInd] = GENERATE( -1, (1<<3) );
1437 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, enc, coeffs, expos, numTermsPerReg, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the UNSIGNED encoding") );
1438 // overrideInds[badInd] = 0;
1439 // badInd -= 1;
1440
1441 // enc = TWOS_COMPLEMENT;
1442 // int minInd = -(1<<(numQubitsPerReg[0]-1));
1443 // int maxInd = (1<<(numQubitsPerReg[0]-1)) - 1;
1444 // overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
1445 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, enc, coeffs, expos, numTermsPerReg, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
1446 // overrideInds[badInd] = 0;
1447
1448 // badInd++;
1449 // minInd = -(1<<(numQubitsPerReg[1]-1));
1450 // maxInd = (1<<(numQubitsPerReg[1]-1)) -1;
1451 // overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
1452 // REQUIRE_THROWS_WITH( applyMultiVarPhaseFuncOverrides(quregVec, qubits, numQubitsPerReg, numRegs, enc, coeffs, expos, numTermsPerReg, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
1453 // }
1454 // }
1455 // CLEANUP_TEST( quregVec, quregMatr );
1456 // }
1457
1458
1459
1460// applyNamedPhaseFunc removed because phase functions are
1461// completely deprecated, in favour of functions like
1462// setDiagMatrFromMultiVarFunc and setFullStateDiagMatrFromMultiDimLists
1463
1464 // /** @sa applyNamedPhaseFunc
1465 // * @ingroup deprecatedtests
1466 // * @author Tyson Jones
1467 // */
1468 // TEST_CASE( "applyNamedPhaseFunc", "[operators]" ) {
1469
1470 // PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1471
1472 // SECTION( "correctness" ) {
1473
1474 // // try every kind of binary encoding
1475 // enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
1476
1477 // // try every possible number of registers
1478 // // (between #qubits containing 1, and 1 containing #qubits)
1479 // int numRegs;
1480 // int maxNumRegs = 0;
1481 // if (encoding == UNSIGNED)
1482 // maxNumRegs = NUM_QUBITS;
1483 // if (encoding == TWOS_COMPLEMENT)
1484 // maxNumRegs = NUM_QUBITS/2; // floors
1485 // numRegs = GENERATE_COPY( range(1, maxNumRegs+1) );
1486
1487 // // try every possible total number of involved qubits
1488 // int totalNumQubits;
1489 // int minTotalQubits = 0;
1490 // if (encoding == UNSIGNED)
1491 // // each register must contain at least 1 qubit
1492 // minTotalQubits = numRegs;
1493 // if (encoding == TWOS_COMPLEMENT)
1494 // // each register must contain at least 2 qubits
1495 // minTotalQubits = 2*numRegs;
1496 // totalNumQubits = GENERATE_COPY( range(minTotalQubits,NUM_QUBITS+1) );
1497
1498 // // try every qubits subset and ordering
1499 // int* regs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), totalNumQubits) );
1500
1501 // // assign each sub-reg its minimum length
1502 // int unallocQubits = totalNumQubits;
1503 // VLA(int, numQubitsPerReg, numRegs);
1504 // for (int i=0; i<numRegs; i++)
1505 // if (encoding == UNSIGNED) {
1506 // numQubitsPerReg[i] = 1;
1507 // unallocQubits -= 1;
1508 // }
1509 // else if (encoding == TWOS_COMPLEMENT) {
1510 // numQubitsPerReg[i] = 2;
1511 // unallocQubits -= 2;
1512 // }
1513 // // and randomly allocate the remaining qubits between the registers
1514 // while (unallocQubits > 0) {
1515 // numQubitsPerReg[getRandomInt(0,numRegs)] += 1;
1516 // unallocQubits--;
1517 // }
1518
1519 // // for reference, determine the values corresponding to each register for all basis states
1520 // std::vector<std::vector<qreal>> regVals(1<<totalNumQubits, std::vector<qreal>(numRegs));
1521 // for (long long int i=0; i<(1<<totalNumQubits); i++) {
1522
1523 // long long int bits = i;
1524 // for (int r=0; r<numRegs; r++) {
1525 // regVals[i][r] = bits % (1 << numQubitsPerReg[r]);
1526 // bits = bits >> numQubitsPerReg[r];
1527
1528 // if (encoding == TWOS_COMPLEMENT)
1529 // regVals[i][r] = getTwosComplement(regVals[i][r], numQubitsPerReg[r]);
1530 // }
1531 // }
1532
1533 // /* the reference diagonal matrix which assumes the qubits are
1534 // * contiguous and strictly increasing between the registers, and hence
1535 // * only depends on the number of qubits in each register.
1536 // */
1537 // QMatrix diagMatr = getZeroMatrix(1 << totalNumQubits);
1538
1539 // SECTION( "NORM" ) {
1540
1541 // for (size_t i=0; i<diagMatr.size(); i++) {
1542 // qreal phase = 0;
1543 // for (int r=0; r<numRegs; r++)
1544 // phase += pow(regVals[i][r], 2);
1545 // phase = sqrt(phase);
1546 // diagMatr[i][i] = expI(phase);
1547 // }
1548
1549 // SECTION( "state-vector" ) {
1550
1551 // applyNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, NORM);
1552 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
1553 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
1554 // }
1555 // SECTION( "density-matrix" ) {
1556
1557 // applyNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, NORM);
1558 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
1559 // REQUIRE( areEqual(quregMatr, refMatr, 142*REAL_EPS) );
1560 // }
1561 // }
1562 // SECTION( "PRODUCT" ) {
1563
1564 // for (size_t i=0; i<diagMatr.size(); i++) {
1565 // qreal phase = 1;
1566 // for (int r=0; r<numRegs; r++)
1567 // phase *= regVals[i][r];
1568 // diagMatr[i][i] = expI(phase);
1569 // }
1570
1571 // SECTION( "state-vector" ) {
1572
1573 // applyNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, PRODUCT);
1574 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
1575 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
1576 // }
1577 // SECTION( "density-matrix" ) {
1578
1579 // applyNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, PRODUCT);
1580 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
1581 // REQUIRE( areEqual(quregMatr, refMatr, 142*REAL_EPS) );
1582 // }
1583 // }
1584 // SECTION( "DISTANCE" ) {
1585
1586 // // test only if there are an even number of registers
1587 // if (numRegs%2 == 0) {
1588
1589 // for (size_t i=0; i<diagMatr.size(); i++) {
1590 // qreal phase = 0;
1591 // for (int r=0; r<numRegs; r+=2)
1592 // phase += pow(regVals[i][r+1]-regVals[i][r], 2);
1593 // phase = sqrt(phase);
1594 // diagMatr[i][i] = expI(phase);
1595 // }
1596 // }
1597
1598 // SECTION( "state-vector" ) {
1599
1600 // if (numRegs%2 == 0) {
1601 // applyNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, DISTANCE);
1602 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
1603 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
1604 // }
1605 // }
1606 // SECTION( "density-matrix" ) {
1607
1608 // if (numRegs%2 == 0) {
1609 // applyNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, DISTANCE);
1610 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
1611 // REQUIRE( areEqual(quregMatr, refMatr, 142*REAL_EPS) );
1612 // }
1613 // }
1614 // }
1615 // }
1616 // SECTION( "input validation" ) {
1617
1618 // int numRegs = 2;
1619 // int numQubitsPerReg[] = {2,3};
1620 // int regs[] = {0,1,2,3,4};
1621
1622 // SECTION( "number of registers" ) {
1623
1624 // numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
1625 // REQUIRE_THROWS_WITH( applyNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM), ContainsSubstring("Invalid number of qubit subregisters") );
1626 // }
1627 // SECTION( "number of qubits" ) {
1628
1629 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
1630 // REQUIRE_THROWS_WITH( applyNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM), ContainsSubstring("Invalid number of qubits") );
1631 // }
1632 // SECTION( "repetition of qubits" ) {
1633
1634 // regs[GENERATE(2,3,4)] = regs[1];
1635 // REQUIRE_THROWS_WITH( applyNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM), ContainsSubstring("The qubits must be unique") );
1636 // }
1637 // SECTION( "qubit indices" ) {
1638
1639 // regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
1640 // REQUIRE_THROWS_WITH( applyNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM), ContainsSubstring("Invalid qubit index") );
1641 // }
1642 // SECTION( "bit encoding name" ) {
1643
1644 // enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
1645 // REQUIRE_THROWS_WITH( applyNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM), ContainsSubstring("Invalid bit encoding") );
1646 // }
1647 // SECTION( "two's complement register" ) {
1648
1649 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
1650 // REQUIRE_THROWS_WITH( applyNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM), ContainsSubstring("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
1651 // }
1652 // SECTION( "phase function name" ) {
1653
1654 // enum phaseFunc func = (enum phaseFunc) GENERATE( -1, MAX_INDEX_PHASE_FUNC + 1 );
1655 // REQUIRE_THROWS_WITH( applyNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func), ContainsSubstring("Invalid named phase function") );
1656 // }
1657 // SECTION( "phase function parameters" ) {
1658
1659 // enum phaseFunc func = GENERATE( SCALED_NORM, INVERSE_NORM, SCALED_INVERSE_NORM, SCALED_INVERSE_SHIFTED_NORM, SCALED_PRODUCT, INVERSE_PRODUCT, SCALED_INVERSE_PRODUCT, SCALED_DISTANCE, INVERSE_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_SHIFTED_DISTANCE );
1660 // REQUIRE_THROWS_WITH( applyNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func), ContainsSubstring("Invalid number of parameters") );
1661 // }
1662 // SECTION( "distance pair registers" ) {
1663
1664 // int numQb[] = {1,1,1,1,1};
1665 // int qb[] = {0,1,2,3,4};
1666
1667 // numRegs = GENERATE( 1, 3, 5 );
1668 // REQUIRE_THROWS_WITH( applyNamedPhaseFunc(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE), ContainsSubstring("Phase functions DISTANCE") && ContainsSubstring("even number of sub-registers") );
1669 // }
1670 // }
1671 // CLEANUP_TEST( quregVec, quregMatr );
1672 // }
1673
1674
1675
1676// applyNamedPhaseFuncOverrides removed because phase functions are
1677// completely deprecated, in favour of functions like
1678// setDiagMatrFromMultiVarFunc and setFullStateDiagMatrFromMultiDimLists
1679
1680 // /** @sa applyNamedPhaseFuncOverrides
1681 // * @ingroup deprecatedtests
1682 // * @author Tyson Jones
1683 // */
1684 // TEST_CASE( "applyNamedPhaseFuncOverrides", "[operators]" ) {
1685
1686 // PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1687
1688 // SECTION( "correctness" ) {
1689
1690 // // try every kind of binary encoding
1691 // enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
1692
1693 // // try every possible number of registers
1694 // // (between #qubits containing 1, and 1 containing #qubits)
1695 // int numRegs;
1696 // int maxNumRegs = 0;
1697 // if (encoding == UNSIGNED)
1698 // maxNumRegs = NUM_QUBITS;
1699 // if (encoding == TWOS_COMPLEMENT)
1700 // maxNumRegs = NUM_QUBITS/2; // floors
1701 // numRegs = GENERATE_COPY( range(1, maxNumRegs+1) );
1702
1703 // // try every possible total number of involved qubits
1704 // int totalNumQubits;
1705 // int minTotalQubits = 0;
1706 // if (encoding == UNSIGNED)
1707 // // each register must contain at least 1 qubit
1708 // minTotalQubits = numRegs;
1709 // if (encoding == TWOS_COMPLEMENT)
1710 // // each register must contain at least 2 qubits
1711 // minTotalQubits = 2*numRegs;
1712 // totalNumQubits = GENERATE_COPY( range(minTotalQubits,NUM_QUBITS+1) );
1713
1714 // // try every qubits subset and ordering
1715 // int* regs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), totalNumQubits) );
1716
1717 // // assign each sub-reg its minimum length
1718 // int unallocQubits = totalNumQubits;
1719 // VLA(int, numQubitsPerReg, numRegs);
1720 // for (int i=0; i<numRegs; i++)
1721 // if (encoding == UNSIGNED) {
1722 // numQubitsPerReg[i] = 1;
1723 // unallocQubits -= 1;
1724 // }
1725 // else if (encoding == TWOS_COMPLEMENT) {
1726 // numQubitsPerReg[i] = 2;
1727 // unallocQubits -= 2;
1728 // }
1729 // // and randomly allocate the remaining qubits between the registers
1730 // while (unallocQubits > 0) {
1731 // numQubitsPerReg[getRandomInt(0,numRegs)] += 1;
1732 // unallocQubits--;
1733 // }
1734
1735
1736 // // choose a random number of overrides (even overriding every amplitude)
1737 // int numOverrides = getRandomInt(0, (1<<totalNumQubits) + 1);
1738
1739 // // randomise each override index (uniqueness isn't checked)
1740 // VLA(long long int, overrideInds, numOverrides*numRegs);
1741 // int flatInd = 0;
1742 // for (int v=0; v<numOverrides; v++) {
1743 // for (int r=0; r<numRegs; r++) {
1744 // if (encoding == UNSIGNED)
1745 // overrideInds[flatInd] = getRandomInt(0, 1<<numQubitsPerReg[r]);
1746 // else if (encoding == TWOS_COMPLEMENT)
1747 // overrideInds[flatInd] = getRandomInt(-(1<<(numQubitsPerReg[r]-1)), (1<<(numQubitsPerReg[r]-1))-1);
1748 // flatInd++;
1749 // }
1750 // }
1751
1752 // // override to a random phase
1753 // VLA(qreal, overridePhases, numOverrides);
1754 // for (int v=0; v<numOverrides; v++)
1755 // overridePhases[v] = getRandomReal(-4, 4); // periodic in [-pi, pi]
1756
1757
1758 // // determine the values corresponding to each register for all basis states
1759 // std::vector<std::vector<qreal>> regVals(1<<totalNumQubits, std::vector<qreal>(numRegs));
1760 // for (long long int i=0; i<(1<<totalNumQubits); i++) {
1761
1762 // long long int bits = i;
1763 // for (int r=0; r<numRegs; r++) {
1764 // regVals[i][r] = bits % (1 << numQubitsPerReg[r]);
1765 // bits = bits >> numQubitsPerReg[r];
1766
1767 // if (encoding == TWOS_COMPLEMENT)
1768 // regVals[i][r] = getTwosComplement(regVals[i][r], numQubitsPerReg[r]);
1769 // }
1770 // }
1771
1772 // /* a reference diagonal matrix which assumes the qubits are
1773 // * contiguous and strictly increasing between the registers, and hence
1774 // * only depends on the number of qubits in each register.
1775 // */
1776 // QMatrix diagMatr = getZeroMatrix(1 << totalNumQubits);
1777
1778 // SECTION( "NORM" ) {
1779
1780 // for (size_t i=0; i<diagMatr.size(); i++) {
1781 // qreal phase = 0;
1782 // for (int r=0; r<numRegs; r++)
1783 // phase += pow(regVals[i][r], 2);
1784 // phase = sqrt(phase);
1785 // diagMatr[i][i] = expI(phase);
1786 // }
1787 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
1788
1789 // SECTION( "state-vector" ) {
1790
1791 // applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, NORM, overrideInds, overridePhases, numOverrides);
1792 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
1793 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
1794 // }
1795 // SECTION( "density-matrix" ) {
1796
1797 // applyNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, NORM, overrideInds, overridePhases, numOverrides);
1798 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
1799 // REQUIRE( areEqual(quregMatr, refMatr, 1E4*REAL_EPS) );
1800 // }
1801 // }
1802 // SECTION( "PRODUCT" ) {
1803
1804 // for (size_t i=0; i<diagMatr.size(); i++) {
1805 // qreal phase = 1;
1806 // for (int r=0; r<numRegs; r++)
1807 // phase *= regVals[i][r];
1808 // diagMatr[i][i] = expI(phase);
1809 // }
1810
1811 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
1812
1813 // SECTION( "state-vector" ) {
1814
1815 // applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, PRODUCT, overrideInds, overridePhases, numOverrides);
1816 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
1817 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
1818 // }
1819 // SECTION( "density-matrix" ) {
1820
1821 // applyNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, PRODUCT, overrideInds, overridePhases, numOverrides);
1822 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
1823 // REQUIRE( areEqual(quregMatr, refMatr, 1E4*REAL_EPS) );
1824 // }
1825 // }
1826 // SECTION( "DISTANCE" ) {
1827
1828 // // test only if there are an even number of registers
1829 // if (numRegs%2 == 0) {
1830
1831 // for (size_t i=0; i<diagMatr.size(); i++) {
1832 // qreal phase = 0;
1833 // for (int r=0; r<numRegs; r+=2)
1834 // phase += pow(regVals[i][r+1]-regVals[i][r], 2);
1835 // phase = sqrt(phase);
1836 // diagMatr[i][i] = expI(phase);
1837 // }
1838
1839 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
1840 // }
1841
1842 // SECTION( "state-vector" ) {
1843
1844 // if (numRegs%2 == 0) {
1845 // applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, DISTANCE, overrideInds, overridePhases, numOverrides);
1846 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
1847 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
1848 // }
1849 // }
1850 // SECTION( "density-matrix" ) {
1851
1852 // if (numRegs%2 == 0) {
1853 // applyNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, DISTANCE, overrideInds, overridePhases, numOverrides);
1854 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
1855 // REQUIRE( areEqual(quregMatr, refMatr, 1E4*REAL_EPS) );
1856 // }
1857 // }
1858 // }
1859 // }
1860 // SECTION( "input validation" ) {
1861
1862 // int numRegs = 2;
1863 // int numQubitsPerReg[] = {2,3};
1864 // int regs[] = {0,1,2,3,4};
1865
1866 // SECTION( "number of registers" ) {
1867
1868 // numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
1869 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, NULL, 0), ContainsSubstring("Invalid number of qubit subregisters") );
1870 // }
1871 // SECTION( "number of qubits" ) {
1872
1873 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
1874 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, NULL, 0), ContainsSubstring("Invalid number of qubits") );
1875 // }
1876 // SECTION( "repetition of qubits" ) {
1877
1878 // regs[GENERATE(2,3,4)] = regs[1];
1879 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, NULL, 0), ContainsSubstring("The qubits must be unique") );
1880 // }
1881 // SECTION( "qubit indices" ) {
1882
1883 // regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
1884 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, NULL, 0), ContainsSubstring("Invalid qubit index") );
1885 // }
1886 // SECTION( "bit encoding name" ) {
1887
1888 // enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
1889 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, NULL, 0), ContainsSubstring("Invalid bit encoding") );
1890 // }
1891 // SECTION( "two's complement register" ) {
1892
1893 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
1894 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM, NULL, NULL, 0), ContainsSubstring("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
1895 // }
1896 // SECTION( "phase function name" ) {
1897
1898 // enum phaseFunc func = (enum phaseFunc) GENERATE( -1, MAX_INDEX_PHASE_FUNC + 1 );
1899 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, NULL, 0), ContainsSubstring("Invalid named phase function") );
1900 // }
1901 // SECTION( "phase function parameters" ) {
1902
1903 // enum phaseFunc func = GENERATE( SCALED_NORM, INVERSE_NORM, SCALED_INVERSE_NORM, SCALED_INVERSE_SHIFTED_NORM, SCALED_PRODUCT, INVERSE_PRODUCT, SCALED_INVERSE_PRODUCT, SCALED_DISTANCE, INVERSE_DISTANCE, SCALED_INVERSE_DISTANCE, SCALED_INVERSE_SHIFTED_DISTANCE );
1904 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, NULL, 0), ContainsSubstring("Invalid number of parameters") );
1905 // }
1906 // SECTION( "distance pair registers" ) {
1907
1908 // int numQb[] = {1,1,1,1,1};
1909 // int qb[] = {0,1,2,3,4};
1910
1911 // numRegs = GENERATE( 1, 3, 5 );
1912 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE, NULL, NULL, 0), ContainsSubstring("Phase functions DISTANCE") && ContainsSubstring("even number of sub-registers") );
1913 // }
1914 // SECTION( "number of overrides" ) {
1915
1916 // int numOverrides = -1;
1917 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, NULL, numOverrides), ContainsSubstring("Invalid number of phase function overrides specified") );
1918 // }
1919 // SECTION( "override indices" ) {
1920
1921 // // numQubitsPerReg = {2, 3}
1922 // int numOverrides = 3;
1923 // long long int overrideInds[] = {0,0, 0,0, 0,0}; // repetition not checked
1924 // qreal overridePhases[] = {.1, .1, .1};
1925
1926 // // first element of overrideInds coordinate is a 2 qubit register
1927 // enum bitEncoding enc = UNSIGNED;
1928 // int badInd = GENERATE(0, 2, 4);
1929 // overrideInds[badInd] = GENERATE( -1, (1<<2) );
1930 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the UNSIGNED encoding") );
1931 // overrideInds[badInd] = 0;
1932
1933 // // second element of overrideInds coordinate is a 3 qubit register
1934 // badInd += 1;
1935 // overrideInds[badInd] = GENERATE( -1, (1<<3) );
1936 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the UNSIGNED encoding") );
1937 // overrideInds[badInd] = 0;
1938 // badInd -= 1;
1939
1940 // enc = TWOS_COMPLEMENT;
1941 // int minInd = -(1<<(numQubitsPerReg[0]-1));
1942 // int maxInd = (1<<(numQubitsPerReg[0]-1)) - 1;
1943 // overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
1944 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
1945 // overrideInds[badInd] = 0;
1946
1947 // badInd++;
1948 // minInd = -(1<<(numQubitsPerReg[1]-1));
1949 // maxInd = (1<<(numQubitsPerReg[1]-1)) -1;
1950 // overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
1951 // REQUIRE_THROWS_WITH( applyNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
1952 // }
1953 // }
1954 // CLEANUP_TEST( quregVec, quregMatr );
1955 // }
1956
1957
1958
1959// applyParamNamedPhaseFunc removed because phase functions are
1960// completely deprecated, in favour of functions like
1961// setDiagMatrFromMultiVarFunc and setFullStateDiagMatrFromMultiDimLists
1962
1963 // /** @sa applyParamNamedPhaseFunc
1964 // * @ingroup deprecatedtests
1965 // * @author Tyson Jones
1966 // */
1967 // TEST_CASE( "applyParamNamedPhaseFunc", "[operators]" ) {
1968
1969 // PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
1970
1971 // SECTION( "correctness" ) {
1972
1973 // // try every kind of binary encoding
1974 // enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
1975
1976 // // try every possible number of registers
1977 // // (between #qubits containing 1, and 1 containing #qubits)
1978 // int numRegs;
1979 // int maxNumRegs = 0;
1980 // if (encoding == UNSIGNED)
1981 // maxNumRegs = NUM_QUBITS;
1982 // if (encoding == TWOS_COMPLEMENT)
1983 // maxNumRegs = NUM_QUBITS/2; // floors
1984 // numRegs = GENERATE_COPY( range(1, maxNumRegs+1) );
1985
1986 // // try every possible total number of involved qubits
1987 // int totalNumQubits;
1988 // int minTotalQubits = 0;
1989 // if (encoding == UNSIGNED)
1990 // // each register must contain at least 1 qubit
1991 // minTotalQubits = numRegs;
1992 // if (encoding == TWOS_COMPLEMENT)
1993 // // each register must contain at least 2 qubits
1994 // minTotalQubits = 2*numRegs;
1995 // totalNumQubits = GENERATE_COPY( range(minTotalQubits,NUM_QUBITS+1) );
1996
1997 // // Previously, we would try every qubits subset and ordering, via:
1998 // // int* regs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), totalNumQubits) );
1999 // // Alas, this is too many tests and times out Ubuntu unit testing. So instead, we
2000 // // randomly choose some qubits, 10 times.
2001 // GENERATE( range(0, 10) );
2002 // VLA(int, regs, totalNumQubits);
2003 // setRandomTargets(regs, totalNumQubits, NUM_QUBITS);
2004
2005 // // assign each sub-reg its minimum length
2006 // int unallocQubits = totalNumQubits;
2007 // VLA(int, numQubitsPerReg, numRegs);
2008 // for (int i=0; i<numRegs; i++)
2009 // if (encoding == UNSIGNED) {
2010 // numQubitsPerReg[i] = 1;
2011 // unallocQubits -= 1;
2012 // }
2013 // else if (encoding == TWOS_COMPLEMENT) {
2014 // numQubitsPerReg[i] = 2;
2015 // unallocQubits -= 2;
2016 // }
2017 // // and randomly allocate the remaining qubits between the registers
2018 // while (unallocQubits > 0) {
2019 // numQubitsPerReg[getRandomInt(0,numRegs)] += 1;
2020 // unallocQubits--;
2021 // }
2022
2023 // /* produce a reference diagonal matrix which assumes the qubits are
2024 // * contiguous and strictly increasing between the registers, and hence
2025 // * only depends on the number of qubits in each register.
2026 // */
2027 // QMatrix diagMatr = getZeroMatrix(1 << totalNumQubits);
2028
2029 // // determine the values corresponding to each register for all basis states
2030 // std::vector<std::vector<qreal>> regVals(1<<totalNumQubits, std::vector<qreal>(numRegs));
2031 // for (long long int i=0; i<(1<<totalNumQubits); i++) {
2032
2033 // long long int bits = i;
2034 // for (int r=0; r<numRegs; r++) {
2035 // regVals[i][r] = bits % (1 << numQubitsPerReg[r]);
2036 // bits = bits >> numQubitsPerReg[r];
2037
2038 // if (encoding == TWOS_COMPLEMENT)
2039 // regVals[i][r] = getTwosComplement(regVals[i][r], numQubitsPerReg[r]);
2040 // }
2041 // }
2042
2043 // SECTION( "INVERSE_NORM" ) {
2044
2045 // enum phaseFunc func = INVERSE_NORM;
2046 // qreal divPhase = getRandomReal(-4, 4);
2047
2048 // for (size_t i=0; i<diagMatr.size(); i++) {
2049 // qreal phase = 0;
2050 // for (int r=0; r<numRegs; r++)
2051 // phase += pow(regVals[i][r], 2);
2052 // phase = (phase == 0.)? divPhase : 1/sqrt(phase);
2053 // diagMatr[i][i] = expI(phase);
2054 // }
2055
2056 // qreal params[] = {divPhase};
2057 // int numParams = 1;
2058
2059 // SECTION( "state-vector" ) {
2060
2061 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2062 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2063 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2064 // }
2065 // SECTION( "density-matrix" ) {
2066
2067 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2068 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2069 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2070 // }
2071
2072 // }
2073 // SECTION( "SCALED_NORM" ) {
2074
2075 // enum phaseFunc func = SCALED_NORM;
2076 // qreal coeff = getRandomReal(-10, 10);
2077
2078 // for (size_t i=0; i<diagMatr.size(); i++) {
2079 // qreal phase = 0;
2080 // for (int r=0; r<numRegs; r++)
2081 // phase += pow(regVals[i][r], 2);
2082 // phase = coeff * sqrt(phase);
2083 // diagMatr[i][i] = expI(phase);
2084 // }
2085
2086 // qreal params[] = {coeff};
2087 // int numParams = 1;
2088
2089 // SECTION( "state-vector" ) {
2090
2091 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2092 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2093 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2094 // }
2095 // SECTION( "density-matrix" ) {
2096
2097 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2098 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2099 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2100 // }
2101 // }
2102 // SECTION( "SCALED_INVERSE_NORM" ) {
2103
2104 // enum phaseFunc func = SCALED_INVERSE_NORM;
2105 // qreal coeff = getRandomReal(-10, 10);
2106 // qreal divPhase = getRandomReal(-4, 4);
2107
2108 // for (size_t i=0; i<diagMatr.size(); i++) {
2109 // qreal phase = 0;
2110 // for (int r=0; r<numRegs; r++)
2111 // phase += pow(regVals[i][r], 2);
2112 // phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
2113 // diagMatr[i][i] = expI(phase);
2114 // }
2115
2116 // qreal params[] = {coeff, divPhase};
2117 // int numParams = 2;
2118
2119 // SECTION( "state-vector" ) {
2120
2121 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2122 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2123 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2124 // }
2125 // SECTION( "density-matrix" ) {
2126
2127 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2128 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2129 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2130 // }
2131 // }
2132 // SECTION( "SCALED_INVERSE_SHIFTED_NORM" ) {
2133
2134 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_NORM;
2135 // int numParams = 2 + numRegs;
2136 // VLA(qreal, params, numParams);
2137 // params[0] = getRandomReal(-10, 10); // scaling
2138 // params[1] = getRandomReal(-4, 4); // divergence override
2139 // for (int r=0; r<numRegs; r++)
2140 // params[2+r] = getRandomReal(-8, 8); // shifts
2141
2142 // for (size_t i=0; i<diagMatr.size(); i++) {
2143 // qreal phase = 0;
2144 // for (int r=0; r<numRegs; r++)
2145 // phase += pow(regVals[i][r] - params[2+r], 2);
2146 // phase = sqrt(phase);
2147 // phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
2148 // diagMatr[i][i] = expI(phase);
2149 // }
2150
2151 // SECTION( "state-vector" ) {
2152
2153 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2154 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2155 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2156 // }
2157 // SECTION( "density-matrix" ) {
2158
2159 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2160 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2161 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2162 // }
2163 // }
2164 // SECTION( "INVERSE_PRODUCT" ) {
2165
2166 // enum phaseFunc func = INVERSE_PRODUCT;
2167 // qreal divPhase = getRandomReal(-4, 4);
2168
2169 // for (size_t i=0; i<diagMatr.size(); i++) {
2170 // qreal phase = 1;
2171 // for (int r=0; r<numRegs; r++)
2172 // phase *= regVals[i][r];
2173 // phase = (phase == 0.)? divPhase : 1. / phase;
2174 // diagMatr[i][i] = expI(phase);
2175 // }
2176
2177 // qreal params[] = {divPhase};
2178 // int numParams = 1;
2179
2180 // SECTION( "state-vector" ) {
2181
2182 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2183 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2184 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2185 // }
2186 // SECTION( "density-matrix" ) {
2187
2188 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2189 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2190 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2191 // }
2192 // }
2193 // SECTION( "SCALED_PRODUCT" ) {
2194
2195 // enum phaseFunc func = SCALED_PRODUCT;
2196 // qreal coeff = getRandomReal(-10, 10);
2197
2198 // for (size_t i=0; i<diagMatr.size(); i++) {
2199 // qreal phase = 1;
2200 // for (int r=0; r<numRegs; r++)
2201 // phase *= regVals[i][r];
2202 // diagMatr[i][i] = expI(coeff * phase);
2203 // }
2204
2205 // qreal params[] = {coeff};
2206 // int numParams = 1;
2207
2208 // SECTION( "state-vector" ) {
2209
2210 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2211 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2212 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2213 // }
2214 // SECTION( "density-matrix" ) {
2215
2216 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2217 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2218 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2219 // }
2220 // }
2221 // SECTION( "SCALED_INVERSE_PRODUCT" ) {
2222
2223 // enum phaseFunc func = SCALED_INVERSE_PRODUCT;
2224 // qreal coeff = getRandomReal(-10, 10);
2225 // qreal divPhase = getRandomReal(-4, 4);
2226 // qreal params[] = {coeff, divPhase};
2227 // int numParams = 2;
2228
2229 // for (size_t i=0; i<diagMatr.size(); i++) {
2230 // qreal phase = 1;
2231 // for (int r=0; r<numRegs; r++)
2232 // phase *= regVals[i][r];
2233 // phase = (phase == 0)? divPhase : coeff / phase;
2234 // diagMatr[i][i] = expI(phase);
2235 // }
2236
2237 // SECTION( "state-vector" ) {
2238
2239 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2240 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2241 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2242 // }
2243 // SECTION( "density-matrix" ) {
2244
2245 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2246 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2247 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2248 // }
2249 // }
2250 // SECTION( "INVERSE_DISTANCE" ) {
2251
2252 // enum phaseFunc func = INVERSE_DISTANCE;
2253 // qreal divPhase = getRandomReal( -4, 4 );
2254 // qreal params[] = {divPhase};
2255 // int numParams = 1;
2256
2257 // // test only if there are an even number of registers
2258 // if (numRegs%2 == 0) {
2259
2260 // for (size_t i=0; i<diagMatr.size(); i++) {
2261 // qreal phase = 0;
2262 // for (int r=0; r<numRegs; r+=2)
2263 // phase += pow(regVals[i][r+1]-regVals[i][r], 2);
2264 // phase = (phase == 0.)? divPhase : 1./sqrt(phase);
2265 // diagMatr[i][i] = expI(phase);
2266 // }
2267 // }
2268
2269 // SECTION( "state-vector" ) {
2270
2271 // if (numRegs%2 == 0) {
2272 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2273 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2274 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2275 // }
2276 // }
2277 // SECTION( "density-matrix" ) {
2278
2279 // if (numRegs%2 == 0) {
2280 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2281 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2282 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2283 // }
2284 // }
2285 // }
2286 // SECTION( "SCALED_DISTANCE" ) {
2287
2288 // enum phaseFunc func = SCALED_DISTANCE;
2289 // qreal coeff = getRandomReal( -10, 10 );
2290 // qreal params[] = {coeff};
2291 // int numParams = 1;
2292
2293 // // test only if there are an even number of registers
2294 // if (numRegs%2 == 0) {
2295
2296 // for (size_t i=0; i<diagMatr.size(); i++) {
2297 // qreal phase = 0;
2298 // for (int r=0; r<numRegs; r+=2)
2299 // phase += pow(regVals[i][r+1]-regVals[i][r], 2);
2300 // phase = coeff * sqrt(phase);
2301 // diagMatr[i][i] = expI(phase);
2302 // }
2303 // }
2304
2305 // SECTION( "state-vector" ) {
2306
2307 // if (numRegs%2 == 0) {
2308 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2309 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2310 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2311 // }
2312 // }
2313 // SECTION( "density-matrix" ) {
2314
2315 // if (numRegs%2 == 0) {
2316 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2317 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2318 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2319 // }
2320 // }
2321 // }
2322 // SECTION( "SCALED_INVERSE_DISTANCE" ) {
2323
2324 // enum phaseFunc func = SCALED_INVERSE_DISTANCE;
2325 // qreal coeff = getRandomReal( -10, 10 );
2326 // qreal divPhase = getRandomReal( -4, 4 );
2327 // qreal params[] = {coeff, divPhase};
2328 // int numParams = 2;
2329
2330 // // test only if there are an even number of registers
2331 // if (numRegs%2 == 0) {
2332
2333 // for (size_t i=0; i<diagMatr.size(); i++) {
2334 // qreal phase = 0;
2335 // for (int r=0; r<numRegs; r+=2)
2336 // phase += pow(regVals[i][r+1]-regVals[i][r], 2);
2337 // phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
2338 // diagMatr[i][i] = expI(phase);
2339 // }
2340 // }
2341
2342 // SECTION( "state-vector" ) {
2343
2344 // if (numRegs%2 == 0) {
2345 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2346 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2347 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2348 // }
2349 // }
2350 // SECTION( "density-matrix" ) {
2351
2352 // if (numRegs%2 == 0) {
2353 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2354 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2355 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2356 // }
2357 // }
2358 // }
2359 // SECTION( "SCALED_INVERSE_SHIFTED_DISTANCE" ) {
2360
2361 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_DISTANCE;
2362 // int numParams = 2 + numRegs/2;
2363 // VLA(qreal, params, numParams);
2364
2365 // // test only if there are an even number of registers
2366 // if (numRegs%2 == 0) {
2367
2368 // params[0] = getRandomReal( -10, 10 ); // scaling
2369 // params[1] = getRandomReal( -4, 4 ); // divergence override
2370 // for (int r=0; r<numRegs/2; r++)
2371 // params[2+r] = getRandomReal( -8, 8 ); // shifts
2372
2373 // for (size_t i=0; i<diagMatr.size(); i++) {
2374 // qreal phase = 0;
2375 // for (int r=0; r<numRegs; r+=2)
2376 // phase += pow(regVals[i][r]-regVals[i][r+1]-params[2+r/2], 2);
2377 // phase = sqrt(phase);
2378 // phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
2379 // diagMatr[i][i] = expI(phase);
2380 // }
2381 // }
2382
2383 // SECTION( "state-vector" ) {
2384
2385 // if (numRegs%2 == 0) {
2386 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2387 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2388 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2389 // }
2390 // }
2391 // SECTION( "density-matrix" ) {
2392
2393 // if (numRegs%2 == 0) {
2394 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2395 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2396 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2397 // }
2398 // }
2399 // }
2400 // SECTION( "SCALED_INVERSE_SHIFTED_WEIGHTED_DISTANCE" ) {
2401
2402 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_WEIGHTED_DISTANCE;
2403 // int numParams = 2 + numRegs;
2404 // VLA(qreal, params, numParams);
2405
2406 // // test only if there are an even number of registers
2407 // if (numRegs%2 == 0) {
2408
2409 // params[0] = getRandomReal( -10, 10 ); // scaling
2410 // params[1] = getRandomReal( -4, 4 ); // divergence override
2411 // for (int r=0; r<numRegs; r+=2) {
2412 // params[2+r] = getRandomReal( -10, 10 ); // factor
2413 // params[2+r+1] = getRandomReal( -8, 8 ); // shift
2414 // }
2415
2416 // for (size_t i=0; i<diagMatr.size(); i++) {
2417 // qreal phase = 0;
2418 // for (int r=0; r<numRegs; r+=2)
2419 // phase += params[2+r] * pow(regVals[i][r]-regVals[i][r+1]-params[2+r+1], 2);
2420 // if (phase < 0)
2421 // phase = 0;
2422 // phase = sqrt(phase);
2423 // phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
2424 // diagMatr[i][i] = expI(phase);
2425 // }
2426 // }
2427
2428 // SECTION( "state-vector" ) {
2429
2430 // if (numRegs%2 == 0) {
2431 // applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2432 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2433 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2434 // }
2435 // }
2436 // SECTION( "density-matrix" ) {
2437
2438 // if (numRegs%2 == 0) {
2439 // applyParamNamedPhaseFunc(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams);
2440 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2441 // REQUIRE( areEqual(quregMatr, refMatr, 1E4*REAL_EPS) );
2442 // }
2443 // }
2444 // }
2445 // }
2446 // SECTION( "input validation" ) {
2447
2448 // int numRegs = 2;
2449 // int numQubitsPerReg[] = {2,3};
2450 // int regs[] = {0,1,2,3,4};
2451
2452 // SECTION( "number of registers" ) {
2453
2454 // numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
2455 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), ContainsSubstring("Invalid number of qubit subregisters") );
2456 // }
2457 // SECTION( "number of qubits" ) {
2458
2459 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
2460 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), ContainsSubstring("Invalid number of qubits") );
2461 // }
2462 // SECTION( "repetition of qubits" ) {
2463
2464 // regs[GENERATE(2,3,4)] = regs[1];
2465 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), ContainsSubstring("The qubits must be unique") );
2466 // }
2467 // SECTION( "qubit indices" ) {
2468
2469 // regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
2470 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0), ContainsSubstring("Invalid qubit index") );
2471 // }
2472 // SECTION( "bit encoding name" ) {
2473
2474 // enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
2475 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0), ContainsSubstring("Invalid bit encoding") );
2476 // }
2477 // SECTION( "two's complement register" ) {
2478
2479 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
2480 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM, NULL, 0), ContainsSubstring("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
2481 // }
2482 // SECTION( "phase function name" ) {
2483
2484 // enum phaseFunc func = (enum phaseFunc) GENERATE( -1, MAX_INDEX_PHASE_FUNC + 1 );
2485 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, 0), ContainsSubstring("Invalid named phase function") );
2486 // }
2487 // SECTION( "phase function parameters" ) {
2488
2489 // VLA(qreal, params, numRegs + 3);
2490 // for (int r=0; r<numRegs + 3; r++)
2491 // params[r] = 0;
2492
2493 // SECTION( "no parameter functions" ) {
2494
2495 // enum phaseFunc func = GENERATE( NORM, PRODUCT, DISTANCE );
2496 // int numParams = GENERATE( -1, 1, 2 );
2497 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), ContainsSubstring("Invalid number of parameters") );
2498 // }
2499 // SECTION( "single parameter functions" ) {
2500
2501 // enum phaseFunc func = GENERATE( SCALED_NORM, INVERSE_NORM, SCALED_PRODUCT, INVERSE_PRODUCT, SCALED_DISTANCE, INVERSE_DISTANCE );
2502 // int numParams = GENERATE( -1, 0, 2 );
2503 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), ContainsSubstring("Invalid number of parameters") );
2504 // }
2505 // SECTION( "two parameter functions" ) {
2506
2507 // enum phaseFunc func = GENERATE( SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_DISTANCE );
2508 // int numParams = GENERATE( 0, 1, 3 );
2509 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), ContainsSubstring("Invalid number of parameters") );
2510 // }
2511 // SECTION( "shifted distance" ) {
2512
2513 // if (numRegs%2 == 0) {
2514 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_DISTANCE;
2515 // int numParams = GENERATE_COPY( 0, 1, numRegs/2 - 1, numRegs/2, numRegs/2 + 1, numRegs/2 + 3 );
2516 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), ContainsSubstring("Invalid number of parameters") );
2517 // }
2518 // }
2519 // SECTION( "shifted norm" ) {
2520
2521 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_NORM;
2522 // int numParams = GENERATE_COPY( 0, 1, numRegs-1, numRegs, numRegs+1, numRegs+3 );
2523 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), ContainsSubstring("Invalid number of parameters") );
2524 // }
2525 // SECTION( "shifted weighted distance" ) {
2526
2527 // if (numRegs%2 == 0) {
2528 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_WEIGHTED_DISTANCE;
2529 // int numParams = GENERATE_COPY( 0, 1, 2 + numRegs - 1, 2 + numRegs + 1 );
2530 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams), ContainsSubstring("Invalid number of parameters") );
2531 // }
2532 // }
2533 // }
2534 // SECTION( "distance pair registers" ) {
2535
2536 // int numQb[] = {1,1,1,1,1};
2537 // int qb[] = {0,1,2,3,4};
2538
2539 // numRegs = GENERATE( 1, 3, 5 );
2540 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFunc(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE, NULL, 0), ContainsSubstring("Phase functions DISTANCE") && ContainsSubstring("even number of sub-registers") );
2541 // }
2542 // }
2543 // CLEANUP_TEST( quregVec, quregMatr );
2544 // }
2545
2546
2547
2548 // applyParamNamedPhaseFuncOverrides removed because phase functions are
2549 // completely deprecated, in favour of functions like
2550 // setDiagMatrFromMultiVarFunc and setFullStateDiagMatrFromMultiDimLists
2551
2552 // /** @sa applyParamNamedPhaseFuncOverrides
2553 // * @ingroup deprecatedtests
2554 // * @author Tyson Jones
2555 // */
2556 // TEST_CASE( "applyParamNamedPhaseFuncOverrides", "[operators]" ) {
2557
2558 // PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
2559
2560 // SECTION( "correctness" ) {
2561
2562 // // try every kind of binary encoding
2563 // enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
2564
2565 // // try every possible number of registers
2566 // // (between #qubits containing 1, and 1 containing #qubits)
2567 // int numRegs;
2568 // int maxNumRegs = 0;
2569 // if (encoding == UNSIGNED)
2570 // maxNumRegs = NUM_QUBITS;
2571 // if (encoding == TWOS_COMPLEMENT)
2572 // maxNumRegs = NUM_QUBITS/2; // floors
2573 // numRegs = GENERATE_COPY( range(1, maxNumRegs+1) );
2574
2575 // // try every possible total number of involved qubits
2576 // int totalNumQubits;
2577 // int minTotalQubits = 0;
2578 // if (encoding == UNSIGNED)
2579 // // each register must contain at least 1 qubit
2580 // minTotalQubits = numRegs;
2581 // if (encoding == TWOS_COMPLEMENT)
2582 // // each register must contain at least 2 qubits
2583 // minTotalQubits = 2*numRegs;
2584 // totalNumQubits = GENERATE_COPY( range(minTotalQubits,NUM_QUBITS+1) );
2585
2586 // // Previously, we would try every qubits subset and ordering, via:
2587 // // int* regs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), totalNumQubits) );
2588 // // Alas, this is too many tests and times out Ubuntu unit testing. So instead, we
2589 // // randomly choose some qubits, 10 times.
2590 // GENERATE( range(0, 10) );
2591 // VLA(int, regs, totalNumQubits);
2592 // setRandomTargets(regs, totalNumQubits, NUM_QUBITS);
2593
2594 // // assign each sub-reg its minimum length
2595 // int unallocQubits = totalNumQubits;
2596 // VLA(int, numQubitsPerReg, numRegs);
2597 // for (int i=0; i<numRegs; i++)
2598 // if (encoding == UNSIGNED) {
2599 // numQubitsPerReg[i] = 1;
2600 // unallocQubits -= 1;
2601 // }
2602 // else if (encoding == TWOS_COMPLEMENT) {
2603 // numQubitsPerReg[i] = 2;
2604 // unallocQubits -= 2;
2605 // }
2606 // // and randomly allocate the remaining qubits between the registers
2607 // while (unallocQubits > 0) {
2608 // numQubitsPerReg[getRandomInt(0,numRegs)] += 1;
2609 // unallocQubits--;
2610 // }
2611
2612 // // choose a random number of overrides (even overriding every amplitude)
2613 // int numOverrides = getRandomInt(0, (1<<totalNumQubits) + 1);
2614
2615 // // randomise each override index (uniqueness isn't checked)
2616 // VLA(long long int, overrideInds, numOverrides*numRegs);
2617 // int flatInd = 0;
2618 // for (int v=0; v<numOverrides; v++) {
2619 // for (int r=0; r<numRegs; r++) {
2620 // if (encoding == UNSIGNED)
2621 // overrideInds[flatInd] = getRandomInt(0, 1<<numQubitsPerReg[r]);
2622 // else if (encoding == TWOS_COMPLEMENT)
2623 // overrideInds[flatInd] = getRandomInt(-(1<<(numQubitsPerReg[r]-1)), (1<<(numQubitsPerReg[r]-1))-1);
2624 // flatInd++;
2625 // }
2626 // }
2627
2628 // // override to a random phase
2629 // VLA(qreal, overridePhases, numOverrides);
2630 // for (int v=0; v<numOverrides; v++)
2631 // overridePhases[v] = getRandomReal(-4, 4); // periodic in [-pi, pi]
2632
2633 // // determine the values corresponding to each register for all basis states
2634 // std::vector<std::vector<qreal>> regVals(1<<totalNumQubits, std::vector<qreal>(numRegs));
2635 // for (long long int i=0; i<(1<<totalNumQubits); i++) {
2636
2637 // long long int bits = i;
2638 // for (int r=0; r<numRegs; r++) {
2639 // regVals[i][r] = bits % (1 << numQubitsPerReg[r]);
2640 // bits = bits >> numQubitsPerReg[r];
2641
2642 // if (encoding == TWOS_COMPLEMENT)
2643 // regVals[i][r] = getTwosComplement(regVals[i][r], numQubitsPerReg[r]);
2644 // }
2645 // }
2646
2647 // /* produce a reference diagonal matrix which assumes the qubits are
2648 // * contiguous and strictly increasing between the registers, and hence
2649 // * only depends on the number of qubits in each register.
2650 // */
2651 // QMatrix diagMatr = getZeroMatrix(1 << totalNumQubits);
2652
2653
2654 // SECTION( "INVERSE_NORM" ) {
2655
2656 // enum phaseFunc func = INVERSE_NORM;
2657 // qreal divPhase = getRandomReal(-4, 4);
2658 // qreal params[] = {divPhase};
2659 // int numParams = 1;
2660
2661 // for (size_t i=0; i<diagMatr.size(); i++) {
2662 // qreal phase = 0;
2663 // for (int r=0; r<numRegs; r++)
2664 // phase += pow(regVals[i][r], 2);
2665 // phase = (phase == 0.)? divPhase : 1/sqrt(phase);
2666 // diagMatr[i][i] = expI(phase);
2667 // }
2668 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
2669
2670 // SECTION( "state-vector" ) {
2671
2672 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2673 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2674 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2675 // }
2676 // SECTION( "density-matrix" ) {
2677
2678 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2679 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2680 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2681 // }
2682 // }
2683 // SECTION( "SCALED_NORM" ) {
2684
2685 // enum phaseFunc func = SCALED_NORM;
2686 // qreal coeff = getRandomReal(-10, 10);
2687 // qreal params[] = {coeff};
2688 // int numParams = 1;
2689
2690 // for (size_t i=0; i<diagMatr.size(); i++) {
2691 // qreal phase = 0;
2692 // for (int r=0; r<numRegs; r++)
2693 // phase += pow(regVals[i][r], 2);
2694 // phase = coeff * sqrt(phase);
2695 // diagMatr[i][i] = expI(phase);
2696 // }
2697 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
2698
2699 // SECTION( "state-vector" ) {
2700
2701 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2702 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2703 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2704 // }
2705 // SECTION( "density-matrix" ) {
2706
2707 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2708 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2709 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2710 // }
2711 // }
2712 // SECTION( "SCALED_INVERSE_NORM" ) {
2713
2714 // enum phaseFunc func = SCALED_INVERSE_NORM;
2715 // qreal coeff = getRandomReal(-10, 10);
2716 // qreal divPhase = getRandomReal(-4, 4);
2717 // qreal params[] = {coeff, divPhase};
2718 // int numParams = 2;
2719
2720 // for (size_t i=0; i<diagMatr.size(); i++) {
2721 // qreal phase = 0;
2722 // for (int r=0; r<numRegs; r++)
2723 // phase += pow(regVals[i][r], 2);
2724 // phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
2725 // diagMatr[i][i] = expI(phase);
2726 // }
2727 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
2728
2729 // SECTION( "state-vector" ) {
2730
2731 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2732 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2733 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2734 // }
2735 // SECTION( "density-matrix" ) {
2736
2737 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2738 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2739 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2740 // }
2741 // }
2742 // SECTION( "SCALED_INVERSE_SHIFTED_NORM" ) {
2743
2744 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_NORM;
2745 // int numParams = 2 + numRegs;
2746 // VLA(qreal, params, numParams);
2747 // params[0] = getRandomReal(-10, 10); // scaling
2748 // params[1] = getRandomReal(-4, 4); // divergence override
2749 // for (int r=0; r<numRegs; r++)
2750 // params[2+r] = getRandomReal(-8, 8); // shifts
2751
2752 // for (size_t i=0; i<diagMatr.size(); i++) {
2753 // qreal phase = 0;
2754 // for (int r=0; r<numRegs; r++)
2755 // phase += pow(regVals[i][r] - params[2+r], 2);
2756 // phase = sqrt(phase);
2757 // phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
2758 // diagMatr[i][i] = expI(phase);
2759 // }
2760 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
2761
2762 // SECTION( "state-vector" ) {
2763
2764 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2765 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2766 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2767 // }
2768 // SECTION( "density-matrix" ) {
2769
2770 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2771 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2772 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2773 // }
2774 // }
2775 // SECTION( "INVERSE_PRODUCT" ) {
2776
2777 // enum phaseFunc func = INVERSE_PRODUCT;
2778 // qreal divPhase = getRandomReal(-4, 4);
2779 // qreal params[] = {divPhase};
2780 // int numParams = 1;
2781
2782 // for (size_t i=0; i<diagMatr.size(); i++) {
2783 // qreal phase = 1;
2784 // for (int r=0; r<numRegs; r++)
2785 // phase *= regVals[i][r];
2786 // phase = (phase == 0.)? divPhase : 1. / phase;
2787 // diagMatr[i][i] = expI(phase);
2788 // }
2789 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
2790
2791 // SECTION( "state-vector" ) {
2792
2793 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2794 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2795 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2796 // }
2797 // SECTION( "density-matrix" ) {
2798
2799 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2800 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2801 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2802 // }
2803 // }
2804 // SECTION( "SCALED_PRODUCT" ) {
2805
2806 // enum phaseFunc func = SCALED_PRODUCT;
2807 // qreal coeff = getRandomReal(-10, 10);
2808 // qreal params[] = {coeff};
2809 // int numParams = 1;
2810
2811 // for (size_t i=0; i<diagMatr.size(); i++) {
2812 // qreal phase = 1;
2813 // for (int r=0; r<numRegs; r++)
2814 // phase *= regVals[i][r];
2815 // diagMatr[i][i] = expI(coeff * phase);
2816 // }
2817 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
2818
2819 // SECTION( "state-vector" ) {
2820
2821 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2822 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2823 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2824 // }
2825 // SECTION( "density-matrix" ) {
2826
2827 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2828 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2829 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2830 // }
2831 // }
2832 // SECTION( "SCALED_INVERSE_PRODUCT" ) {
2833
2834 // enum phaseFunc func = SCALED_INVERSE_PRODUCT;
2835 // qreal coeff = getRandomReal(-10, 10);
2836 // qreal divPhase = getRandomReal(-4, 4);
2837 // qreal params[] = {coeff, divPhase};
2838 // int numParams = 2;
2839
2840 // for (size_t i=0; i<diagMatr.size(); i++) {
2841 // qreal phase = 1;
2842 // for (int r=0; r<numRegs; r++)
2843 // phase *= regVals[i][r];
2844 // phase = (phase == 0)? divPhase : coeff / phase;
2845 // diagMatr[i][i] = expI(phase);
2846 // }
2847 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
2848
2849 // SECTION( "state-vector" ) {
2850
2851 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2852 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2853 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2854 // }
2855 // SECTION( "density-matrix" ) {
2856
2857 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2858 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2859 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2860 // }
2861 // }
2862 // SECTION( "INVERSE_DISTANCE" ) {
2863
2864 // enum phaseFunc func = INVERSE_DISTANCE;
2865 // qreal divPhase = getRandomReal( -4, 4 );
2866 // qreal params[] = {divPhase};
2867 // int numParams = 1;
2868
2869 // // test only if there are an even number of registers
2870 // if (numRegs%2 == 0) {
2871
2872 // for (size_t i=0; i<diagMatr.size(); i++) {
2873 // qreal phase = 0;
2874 // for (int r=0; r<numRegs; r+=2)
2875 // phase += pow(regVals[i][r+1]-regVals[i][r], 2);
2876 // phase = (phase == 0.)? divPhase : 1./sqrt(phase);
2877 // diagMatr[i][i] = expI(phase);
2878 // }
2879 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
2880 // }
2881
2882 // SECTION( "state-vector" ) {
2883
2884 // if (numRegs%2 == 0) {
2885 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2886 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2887 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2888 // }
2889 // }
2890 // SECTION( "density-matrix" ) {
2891
2892 // if (numRegs%2 == 0) {
2893 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2894 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2895 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2896 // }
2897 // }
2898 // }
2899 // SECTION( "SCALED_DISTANCE" ) {
2900
2901 // enum phaseFunc func = SCALED_DISTANCE;
2902 // qreal coeff = getRandomReal( -10, 10 );
2903 // qreal params[] = {coeff};
2904 // int numParams = 1;
2905
2906 // // test only if there are an even number of registers
2907 // if (numRegs%2 == 0) {
2908
2909 // for (size_t i=0; i<diagMatr.size(); i++) {
2910 // qreal phase = 0;
2911 // for (int r=0; r<numRegs; r+=2)
2912 // phase += pow(regVals[i][r+1]-regVals[i][r], 2);
2913 // phase = coeff * sqrt(phase);
2914 // diagMatr[i][i] = expI(phase);
2915 // }
2916 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
2917 // }
2918
2919 // SECTION( "state-vector" ) {
2920
2921 // if (numRegs%2 == 0) {
2922 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2923 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2924 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2925 // }
2926 // }
2927 // SECTION( "density-matrix" ) {
2928
2929 // if (numRegs%2 == 0) {
2930 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2931 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2932 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2933 // }
2934 // }
2935 // }
2936 // SECTION( "SCALED_INVERSE_DISTANCE" ) {
2937
2938 // enum phaseFunc func = SCALED_INVERSE_DISTANCE;
2939 // qreal coeff = getRandomReal( -10, 10 );
2940 // qreal divPhase = getRandomReal( -4, 4 );
2941 // qreal params[] = {coeff, divPhase};
2942 // int numParams = 2;
2943
2944 // // test only if there are an even number of registers
2945 // if (numRegs%2 == 0) {
2946
2947 // for (size_t i=0; i<diagMatr.size(); i++) {
2948 // qreal phase = 0;
2949 // for (int r=0; r<numRegs; r+=2)
2950 // phase += pow(regVals[i][r+1]-regVals[i][r], 2);
2951 // phase = (phase == 0.)? divPhase : coeff/sqrt(phase);
2952 // diagMatr[i][i] = expI(phase);
2953 // }
2954 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
2955 // }
2956
2957 // SECTION( "state-vector" ) {
2958
2959 // if (numRegs%2 == 0) {
2960 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2961 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
2962 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
2963 // }
2964 // }
2965 // SECTION( "density-matrix" ) {
2966
2967 // if (numRegs%2 == 0) {
2968 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
2969 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
2970 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
2971 // }
2972 // }
2973 // }
2974 // SECTION( "SCALED_INVERSE_SHIFTED_DISTANCE" ) {
2975
2976 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_DISTANCE;
2977 // int numParams = 2 + numRegs/2;
2978 // VLA(qreal, params, numParams);
2979
2980 // // test only if there are an even number of registers
2981 // if (numRegs%2 == 0) {
2982
2983 // params[0] = getRandomReal( -10, 10 ); // scaling
2984 // params[1] = getRandomReal( -4, 4 ); // divergence override
2985 // for (int r=0; r<numRegs/2; r++)
2986 // params[2+r] = getRandomReal( -8, 8 ); // shifts
2987
2988 // for (size_t i=0; i<diagMatr.size(); i++) {
2989 // qreal phase = 0;
2990 // for (int r=0; r<numRegs; r+=2)
2991 // phase += pow(regVals[i][r]-regVals[i][r+1]-params[2+r/2], 2);
2992 // phase = sqrt(phase);
2993 // phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
2994 // diagMatr[i][i] = expI(phase);
2995 // }
2996
2997 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
2998 // }
2999
3000 // SECTION( "state-vector" ) {
3001
3002 // if (numRegs%2 == 0) {
3003 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
3004 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
3005 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
3006 // }
3007 // }
3008 // SECTION( "density-matrix" ) {
3009
3010 // if (numRegs%2 == 0) {
3011 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
3012 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
3013 // REQUIRE( areEqual(quregMatr, refMatr, 1E2*REAL_EPS) );
3014 // }
3015 // }
3016 // }
3017 // SECTION( "SCALED_INVERSE_SHIFTED_WEIGHTED_DISTANCE" ) {
3018
3019 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_WEIGHTED_DISTANCE;
3020 // int numParams = 2 + numRegs;
3021 // VLA(qreal, params, numParams);
3022
3023 // // test only if there are an even number of registers
3024 // if (numRegs%2 == 0) {
3025
3026 // params[0] = getRandomReal( -10, 10 ); // scaling
3027 // params[1] = getRandomReal( -4, 4 ); // divergence override
3028 // for (int r=0; r<numRegs; r+=2) {
3029 // params[2+r] = getRandomReal( -10, 10 ); // factor
3030 // params[2+r+1] = getRandomReal( -8, 8 ); // shift
3031 // }
3032
3033 // for (size_t i=0; i<diagMatr.size(); i++) {
3034 // qreal phase = 0;
3035 // for (int r=0; r<numRegs; r+=2)
3036 // phase += params[2+r] * pow(regVals[i][r]-regVals[i][r+1]-params[2+r+1], 2);
3037 // if (phase < 0)
3038 // phase = 0;
3039 // phase = sqrt(phase);
3040 // phase = (phase <= REAL_EPS)? params[1] : params[0]/phase;
3041 // diagMatr[i][i] = expI(phase);
3042 // }
3043
3044 // setDiagMatrixOverrides(diagMatr, numQubitsPerReg, numRegs, encoding, overrideInds, overridePhases, numOverrides);
3045 // }
3046
3047 // SECTION( "state-vector" ) {
3048
3049 // if (numRegs%2 == 0) {
3050 // applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
3051 // applyReferenceOp(refVec, regs, totalNumQubits, diagMatr);
3052 // REQUIRE( areEqual(quregVec, refVec, 1E2*REAL_EPS) );
3053 // }
3054 // }
3055 // SECTION( "density-matrix" ) {
3056
3057 // if (numRegs%2 == 0) {
3058 // applyParamNamedPhaseFuncOverrides(quregMatr, regs, numQubitsPerReg, numRegs, encoding, func, params, numParams, overrideInds, overridePhases, numOverrides);
3059 // applyReferenceOp(refMatr, regs, totalNumQubits, diagMatr);
3060 // REQUIRE( areEqual(quregMatr, refMatr, 1E4*REAL_EPS) );
3061 // }
3062 // }
3063 // }
3064 // }
3065 // SECTION( "input validation" ) {
3066
3067 // int numRegs = 2;
3068 // int numQubitsPerReg[] = {2,3};
3069 // int regs[] = {0,1,2,3,4};
3070
3071 // SECTION( "number of registers" ) {
3072
3073 // numRegs = GENERATE_COPY( -1, 0, 1+MAX_NUM_REGS_APPLY_ARBITRARY_PHASE );
3074 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), ContainsSubstring("Invalid number of qubit subregisters") );
3075 // }
3076 // SECTION( "number of qubits" ) {
3077
3078 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = GENERATE( -1, 0, 1+NUM_QUBITS );
3079 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), ContainsSubstring("Invalid number of qubits") );
3080 // }
3081 // SECTION( "repetition of qubits" ) {
3082
3083 // regs[GENERATE(2,3,4)] = regs[1];
3084 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), ContainsSubstring("The qubits must be unique") );
3085 // }
3086 // SECTION( "qubit indices" ) {
3087
3088 // regs[GENERATE(range(0,NUM_QUBITS))] = GENERATE( -1, NUM_QUBITS );
3089 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, 0), ContainsSubstring("Invalid qubit index") );
3090 // }
3091 // SECTION( "bit encoding name" ) {
3092
3093 // enum bitEncoding enc = (enum bitEncoding) GENERATE( -1, 2 );
3094 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, NULL, NULL, 0), ContainsSubstring("Invalid bit encoding") );
3095 // }
3096 // SECTION( "two's complement register" ) {
3097
3098 // numQubitsPerReg[GENERATE_COPY(range(0,numRegs))] = 1;
3099 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, TWOS_COMPLEMENT, NORM, NULL, 0, NULL, NULL, 0), ContainsSubstring("A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding") );
3100 // }
3101 // SECTION( "phase function name" ) {
3102
3103 // enum phaseFunc func = (enum phaseFunc) GENERATE( -1, MAX_INDEX_PHASE_FUNC + 1 );
3104 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, NULL, 0, NULL, NULL, 0), ContainsSubstring("Invalid named phase function") );
3105 // }
3106 // SECTION( "phase function parameters" ) {
3107
3108 // VLA(qreal, params, numRegs + 3);
3109 // for (int r=0; r<numRegs + 3; r++)
3110 // params[r] = 0;
3111
3112 // SECTION( "no parameter functions" ) {
3113
3114 // enum phaseFunc func = GENERATE( NORM, PRODUCT, DISTANCE );
3115 // int numParams = GENERATE( -1, 1, 2 );
3116 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), ContainsSubstring("Invalid number of parameters") );
3117 // }
3118 // SECTION( "single parameter functions" ) {
3119
3120 // enum phaseFunc func = GENERATE( SCALED_NORM, INVERSE_NORM, SCALED_PRODUCT, INVERSE_PRODUCT, SCALED_DISTANCE, INVERSE_DISTANCE );
3121 // int numParams = GENERATE( -1, 0, 2 );
3122 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), ContainsSubstring("Invalid number of parameters") );
3123 // }
3124 // SECTION( "two parameter functions" ) {
3125
3126 // enum phaseFunc func = GENERATE( SCALED_INVERSE_NORM, SCALED_INVERSE_PRODUCT, SCALED_INVERSE_DISTANCE );
3127 // int numParams = GENERATE( 0, 1, 3 );
3128 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), ContainsSubstring("Invalid number of parameters") );
3129 // }
3130 // SECTION( "shifted distance" ) {
3131
3132 // if (numRegs%2 == 0) {
3133 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_DISTANCE;
3134 // int numParams = GENERATE_COPY( 0, 1, numRegs/2 - 1, numRegs/2, numRegs/2 + 1, numRegs/2 + 3 );
3135 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), ContainsSubstring("Invalid number of parameters") );
3136 // }
3137 // }
3138 // SECTION( "shifted weighted distance" ) {
3139
3140 // if (numRegs%2 == 0) {
3141 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_WEIGHTED_DISTANCE;
3142 // int numParams = GENERATE_COPY( 0, 1, 2 + numRegs - 1, 2 + numRegs + 1 );
3143 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), ContainsSubstring("Invalid number of parameters") );
3144 // }
3145 // }
3146 // SECTION( "shifted norm" ) {
3147
3148 // enum phaseFunc func = SCALED_INVERSE_SHIFTED_NORM;
3149 // int numParams = GENERATE_COPY( 0, 1, numRegs-1, numRegs, numRegs+1, numRegs+3 );
3150 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, func, params, numParams, NULL, NULL, 0), ContainsSubstring("Invalid number of parameters") );
3151 // }
3152 // }
3153 // SECTION( "distance pair registers" ) {
3154
3155 // int numQb[] = {1,1,1,1,1};
3156 // int qb[] = {0,1,2,3,4};
3157
3158 // numRegs = GENERATE( 1, 3, 5 );
3159 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, qb, numQb, numRegs, UNSIGNED, DISTANCE, NULL, 0, NULL, NULL, 0), ContainsSubstring("Phase functions DISTANCE") && ContainsSubstring("even number of sub-registers") );
3160 // }
3161 // SECTION( "number of overrides" ) {
3162
3163 // int numOverrides = -1;
3164 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, UNSIGNED, NORM, NULL, 0, NULL, NULL, numOverrides), ContainsSubstring("Invalid number of phase function overrides specified") );
3165 // }
3166 // SECTION( "override indices" ) {
3167
3168 // // numQubitsPerReg = {2, 3}
3169 // int numOverrides = 3;
3170 // long long int overrideInds[] = {0,0, 0,0, 0,0}; // repetition not checked
3171 // qreal overridePhases[] = {.1, .1, .1};
3172
3173 // // first element of overrideInds coordinate is a 2 qubit register
3174 // enum bitEncoding enc = UNSIGNED;
3175 // int badInd = GENERATE(0, 2, 4);
3176 // overrideInds[badInd] = GENERATE( -1, (1<<2) );
3177 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the UNSIGNED encoding") );
3178 // overrideInds[badInd] = 0;
3179
3180 // // second element of overrideInds coordinate is a 3 qubit register
3181 // badInd += 1;
3182 // overrideInds[badInd] = GENERATE( -1, (1<<3) );
3183 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the UNSIGNED encoding") );
3184 // overrideInds[badInd] = 0;
3185 // badInd -= 1;
3186
3187 // enc = TWOS_COMPLEMENT;
3188 // int minInd = -(1<<(numQubitsPerReg[0]-1));
3189 // int maxInd = (1<<(numQubitsPerReg[0]-1)) - 1;
3190 // overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
3191 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
3192 // overrideInds[badInd] = 0;
3193
3194 // badInd++;
3195 // minInd = -(1<<(numQubitsPerReg[1]-1));
3196 // maxInd = (1<<(numQubitsPerReg[1]-1)) -1;
3197 // overrideInds[badInd] = GENERATE_COPY( minInd-1, maxInd+1 );
3198 // REQUIRE_THROWS_WITH( applyParamNamedPhaseFuncOverrides(quregVec, regs, numQubitsPerReg, numRegs, enc, NORM, NULL, 0, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
3199 // }
3200 // }
3201 // CLEANUP_TEST( quregVec, quregMatr );
3202 // }
3203
3204
3205
3206// applyPauliHamil removed because PauliHamil deprecated in favour
3207// of PauliStrSum (with analogous function applyPauliStrSum) which
3208// presently has an incompatible initialiser
3209
3210 // /** @sa applyPauliHamil
3211 // * @ingroup deprecatedtests
3212 // * @author Tyson Jones
3213 // */
3214 // TEST_CASE( "applyPauliHamil", "[operators]" ) {
3215
3216 // Qureg vecIn = createForcedQureg(NUM_QUBITS);
3217 // Qureg vecOut = createForcedQureg(NUM_QUBITS);
3218 // Qureg matIn = createForcedDensityQureg(NUM_QUBITS);
3219 // Qureg matOut = createForcedDensityQureg(NUM_QUBITS);
3220
3221 // initDebugState(vecIn);
3222 // initDebugState(matIn);
3223
3224 // SECTION( "correctness" ) {
3225
3226 // /* it's too expensive to try every possible Pauli configuration, so
3227 // * we'll try 10 random codes, and for each, random coefficients
3228 // */
3229 // GENERATE( range(0,10) );
3230
3231 // int numTerms = GENERATE( 1, 2, 10, 15 );
3232 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
3233 // setRandomPauliSum(hamil);
3234 // QMatrix refHamil = toQMatrix(hamil);
3235
3236 // SECTION( "state-vector" ) {
3237
3238 // QVector vecRef = toQVector(vecIn);
3239 // applyPauliHamil(vecIn, hamil, vecOut);
3240
3241 // // ensure vecIn barely changes under precision
3242 // REQUIRE( areEqual(vecIn, vecRef) );
3243
3244 // // ensure vecOut changed correctly
3245 // REQUIRE( areEqual(vecOut, refHamil * vecRef) );
3246 // }
3247 // SECTION( "density-matrix" ) {
3248
3249 // QMatrix matRef = toQMatrix(matIn);
3250 // applyPauliHamil(matIn, hamil, matOut);
3251
3252 // // ensure matIn barely changes under precision
3253 // REQUIRE( areEqual(matIn, matRef) );
3254
3255 // // ensure matOut changed correctly
3256 // REQUIRE( areEqual(matOut, refHamil * matRef, 1E2*REAL_EPS) );
3257 // }
3258
3259 // destroyPauliHamil(hamil);
3260 // }
3261 // SECTION( "input validation" ) {
3262
3263 // SECTION( "pauli codes" ) {
3264
3265 // int numTerms = 3;
3266 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
3267
3268 // // make one pauli code wrong
3269 // hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
3270 // REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), ContainsSubstring("Invalid Pauli code") );
3271
3272 // destroyPauliHamil(hamil);
3273 // }
3274 // SECTION( "qureg dimensions" ) {
3275
3276 // Qureg badVec = createForcedQureg(NUM_QUBITS+1);
3277 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, 1);
3278
3279 // REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, badVec), ContainsSubstring("Dimensions of the qubit registers don't match") );
3280
3281 // destroyQureg(badVec);
3282 // destroyPauliHamil(hamil);
3283 // }
3284 // SECTION( "qureg types" ) {
3285
3286 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, 1);
3287
3288 // REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, matOut), ContainsSubstring("Registers must both be state-vectors or both be density matrices") );
3289
3290 // destroyPauliHamil(hamil);
3291 // }
3292 // SECTION( "matching hamiltonian qubits" ) {
3293
3294 // PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
3295
3296 // REQUIRE_THROWS_WITH( applyPauliHamil(vecIn, hamil, vecOut), ContainsSubstring("same number of qubits") );
3297 // REQUIRE_THROWS_WITH( applyPauliHamil(matIn, hamil, matOut), ContainsSubstring("same number of qubits") );
3298
3299 // destroyPauliHamil(hamil);
3300 // }
3301 // }
3302 // destroyQureg(vecIn);
3303 // destroyQureg(vecOut);
3304 // destroyQureg(matIn);
3305 // destroyQureg(matOut);
3306 // }
3307
3308
3309
3310// applyPauliSum removed because analogous function
3311// applyPauliStrSum involves new type PauliStrSum
3312// with an incompatible initialiser
3313
3314 // /** @sa applyPauliSum
3315 // * @ingroup deprecatedtests
3316 // * @author Tyson Jones
3317 // */
3318 // TEST_CASE( "applyPauliSum", "[operators]" ) {
3319
3320 // Qureg vecIn = createForcedQureg(NUM_QUBITS);
3321 // Qureg vecOut = createForcedQureg(NUM_QUBITS);
3322 // Qureg matIn = createForcedDensityQureg(NUM_QUBITS);
3323 // Qureg matOut = createForcedDensityQureg(NUM_QUBITS);
3324
3325 // initDebugState(vecIn);
3326 // initDebugState(matIn);
3327
3328 // SECTION( "correctness" ) {
3329
3330 // /* it's too expensive to try ALL Pauli sequences, via
3331 // * pauliOpType* paulis = GENERATE_COPY( pauliseqs(numPaulis) );.
3332 // * Furthermore, take(10, pauliseqs(numTargs)) will try the same pauli codes.
3333 // * Hence, we instead opt to repeatedly randomly generate pauliseqs
3334 // */
3335 // GENERATE( range(0,10) ); // gen 10 random pauli-codes
3336
3337 // int numTerms = GENERATE( 1, 2, 10, 15);
3338 // int numPaulis = numTerms * NUM_QUBITS;
3339
3340 // // each test will use random coefficients
3341 // VLA(qreal, coeffs, numTerms);
3342 // VLA(pauliOpType, paulis, numPaulis);
3343 // setRandomPauliSum(coeffs, paulis, NUM_QUBITS, numTerms);
3344 // QMatrix pauliSum = toQMatrix(coeffs, paulis, NUM_QUBITS, numTerms);
3345
3346 // SECTION( "state-vector" ) {
3347
3348 // QVector vecRef = toQVector(vecIn);
3349 // applyPauliSum(vecIn, paulis, coeffs, numTerms, vecOut);
3350
3351 // // ensure vecIn barely changes under precision
3352 // REQUIRE( areEqual(vecIn, vecRef) );
3353
3354 // // ensure vecOut changed correctly
3355 // REQUIRE( areEqual(vecOut, pauliSum * vecRef) );
3356 // }
3357 // SECTION( "density-matrix" ) {
3358
3359 // QMatrix matRef = toQMatrix(matIn);
3360 // applyPauliSum(matIn, paulis, coeffs, numTerms, matOut);
3361
3362 // // ensure matIn barely changes under precision
3363 // REQUIRE( areEqual(matIn, matRef) );
3364
3365 // // ensure matOut changed correctly
3366 // REQUIRE( areEqual(matOut, pauliSum * matRef, 1E2*REAL_EPS) );
3367 // }
3368 // }
3369 // SECTION( "input validation" ) {
3370
3371 // SECTION( "number of terms" ) {
3372
3373 // int numTerms = GENERATE( -1, 0 );
3374 // REQUIRE_THROWS_WITH( applyPauliSum(vecIn, NULL, NULL, numTerms, vecOut), ContainsSubstring("Invalid number of terms") );
3375 // }
3376 // SECTION( "pauli codes" ) {
3377
3378 // // valid codes
3379 // int numTerms = 3;
3380 // int numPaulis = numTerms*NUM_QUBITS;
3381 // VLA(pauliOpType, paulis, numPaulis);
3382 // for (int i=0; i<numPaulis; i++)
3383 // paulis[i] = PAULI_I;
3384
3385 // // make one invalid
3386 // paulis[GENERATE_COPY( range(0,numPaulis) )] = (pauliOpType) GENERATE( -1, 4 );
3387 // REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, numTerms, vecOut), ContainsSubstring("Invalid Pauli code") );
3388 // }
3389 // SECTION( "qureg dimensions" ) {
3390
3391 // Qureg badVec = createForcedQureg(NUM_QUBITS+1);
3392 // pauliOpType paulis[NUM_QUBITS];
3393 // REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, badVec), ContainsSubstring("Dimensions of the qubit registers don't match") );
3394 // destroyQureg(badVec);
3395 // }
3396 // SECTION( "qureg types" ) {
3397
3398 // pauliOpType paulis[NUM_QUBITS];
3399 // REQUIRE_THROWS_WITH( applyPauliSum(vecIn, paulis, NULL, 1, matOut), ContainsSubstring("Registers must both be state-vectors or both be density matrices") );
3400 // }
3401 // }
3402 // destroyQureg(vecIn);
3403 // destroyQureg(vecOut);
3404 // destroyQureg(matIn);
3405 // destroyQureg(matOut);
3406 // }
3407
3408
3409
3410// applyPhaseFunc removed because phase functions are
3411// completely deprecated, in favour of functions like
3412// setDiagMatrFromMultiVarFunc and setFullStateDiagMatrFromMultiDimLists
3413
3414 // /** @sa applyPhaseFunc
3415 // * @ingroup deprecatedtests
3416 // * @author Tyson Jones
3417 // */
3418 // TEST_CASE( "applyPhaseFunc", "[operators]" ) {
3419
3420 // PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
3421
3422 // SECTION( "correctness" ) {
3423
3424 // // try every kind of binary encodings
3425 // enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
3426
3427 // // try every sub-register size
3428 // int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
3429
3430 // // force at least 2 qubits in two's compement though
3431 // if (encoding == TWOS_COMPLEMENT && numQubits == 1)
3432 // numQubits++;
3433
3434 // // try every possible sub-register
3435 // int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
3436
3437 // // choose a random number of terms in the phase function
3438 // int numTerms = getRandomInt(1, 5);
3439
3440 // // populate the phase function with random but POSITIVE-power terms,
3441 // // and in two's complement mode, strictly integer powers
3442 // VLA(qreal, coeffs, numTerms);
3443 // VLA(qreal, expons, numTerms);
3444 // for (int t=0; t<numTerms; t++) {
3445 // coeffs[t] = getRandomReal(-10,10);
3446 // if (encoding == TWOS_COMPLEMENT)
3447 // expons[t] = getRandomInt(0, 3+1); // repetition of power is ok
3448 // else
3449 // expons[t] = getRandomReal(0, 3);
3450 // }
3451
3452 // // build a reference diagonal matrix, on the reduced Hilbert space
3453 // QMatrix matr = getZeroMatrix( 1 << numQubits );
3454 // for (size_t i=0; i<matr.size(); i++) {
3455
3456 // long long int ind = 0;
3457 // if (encoding == UNSIGNED)
3458 // ind = i;
3459 // if (encoding == TWOS_COMPLEMENT)
3460 // ind = getTwosComplement(i, numQubits);
3461
3462 // qreal phase = 0;
3463 // for (int t=0; t<numTerms; t++)
3464 // phase += coeffs[t] * pow(ind, expons[t]);
3465
3466 // matr[i][i] = expI(phase);
3467 // }
3468
3469 // SECTION( "state-vector" ) {
3470
3471 // applyPhaseFunc(quregVec, qubits, numQubits, encoding, coeffs, expons, numTerms);
3472 // applyReferenceOp(refVec, qubits, numQubits, matr);
3473 // REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
3474 // }
3475 // SECTION( "density-matrix" ) {
3476
3477 // applyPhaseFunc(quregMatr, qubits, numQubits, encoding, coeffs, expons, numTerms);
3478 // applyReferenceOp(refMatr, qubits, numQubits, matr);
3479 // REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
3480 // }
3481 // }
3482 // SECTION( "input validation" ) {
3483
3484 // int numQubits = 3;
3485 // int qubits[] = {0,1,2};
3486
3487 // SECTION( "number of qubits" ) {
3488
3489 // numQubits = GENERATE_COPY( -1, 0, NUM_QUBITS+1 );
3490 // REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, NULL, numQubits, UNSIGNED, NULL, NULL, 1), ContainsSubstring("Invalid number of qubits") );
3491 // }
3492 // SECTION( "repetition of qubits" ) {
3493
3494 // qubits[GENERATE(1,2)] = qubits[0];
3495 // REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1), ContainsSubstring("The qubits must be unique") );
3496 // }
3497 // SECTION( "qubit indices" ) {
3498
3499 // int inv = GENERATE( -1, NUM_QUBITS );
3500 // qubits[ GENERATE_COPY( range(0,numQubits) )] = inv;
3501 // REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1), ContainsSubstring("Invalid qubit index") );
3502 // }
3503 // SECTION( "number of terms" ) {
3504
3505 // int numTerms = GENERATE( -1, 0 );
3506 // REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, numTerms), ContainsSubstring("Invalid number of terms in the phase function") );
3507 // }
3508 // SECTION( "bit encoding name" ) {
3509
3510 // enum bitEncoding enc = (enum bitEncoding) GENERATE( -1,2 );
3511 // REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, enc, NULL, NULL, 1), ContainsSubstring("Invalid bit encoding") );
3512 // }
3513 // SECTION( "two's complement register" ) {
3514
3515 // numQubits = 1;
3516 // REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, TWOS_COMPLEMENT, NULL, NULL, 1), ContainsSubstring("too few qubits to employ TWOS_COMPLEMENT") );
3517 // }
3518 // SECTION( "fractional exponent" ) {
3519
3520 // int numTerms = 3;
3521 // qreal coeffs[] = {0,0,0};
3522 // qreal expos[] = {1,2,3};
3523 // expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( 0.5, 1.999, 5.0001 );
3524
3525 // REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms), ContainsSubstring("fractional exponent") && ContainsSubstring("TWOS_COMPLEMENT") && ContainsSubstring("negative indices were not overriden") );
3526 // }
3527 // SECTION( "negative exponent" ) {
3528
3529 // int numTerms = 3;
3530 // qreal coeffs[] = {0,0,0};
3531 // qreal expos[] = {1,2,3};
3532 // expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( -1, -2, -1.5 );
3533
3534 // enum bitEncoding encoding = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
3535
3536 // REQUIRE_THROWS_WITH( applyPhaseFunc(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms), ContainsSubstring("The phase function contained a negative exponent which would diverge at zero, but the zero index was not overriden") );
3537 // }
3538 // }
3539 // CLEANUP_TEST( quregVec, quregMatr );
3540 // }
3541
3542
3543
3544// applyPhaseFuncOverrides removed because phase functions are
3545// completely deprecated, in favour of functions like
3546// setDiagMatrFromMultiVarFunc and setFullStateDiagMatrFromMultiDimLists
3547
3548 // /** @sa applyPhaseFuncOverrides
3549 // * @ingroup deprecatedtests
3550 // * @author Tyson Jones
3551 // */
3552 // TEST_CASE( "applyPhaseFuncOverrides", "[operators]" ) {
3553
3554 // PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
3555
3556 // SECTION( "correctness" ) {
3557
3558 // // try every kind of binary encodings
3559 // enum bitEncoding encoding = GENERATE( UNSIGNED,TWOS_COMPLEMENT );
3560
3561 // // try every sub-register size
3562 // int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
3563
3564 // // force at least 2 qubits in two's compement though
3565 // if (encoding == TWOS_COMPLEMENT && numQubits == 1)
3566 // numQubits++;
3567
3568 // // try every possible sub-register
3569 // int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
3570
3571 // // choose a random number of terms in the phase function
3572 // int numTerms = getRandomInt(1, 21);
3573
3574 // // populate the phase function with random powers.
3575 // // this includes negative powers, so we must always override 0.
3576 // // in two's complement, we must use only integer powers
3577 // VLA(qreal, coeffs, numTerms);
3578 // VLA(qreal, expons, numTerms);
3579 // for (int t=0; t<numTerms; t++) {
3580 // coeffs[t] = getRandomReal(-10,10);
3581 // if (encoding == TWOS_COMPLEMENT)
3582 // expons[t] = getRandomInt(-3, 3+1); // note we COULD do getRandomReal(), and override all negatives
3583 // else
3584 // expons[t] = getRandomReal(-3, 3);
3585 // }
3586
3587 // // choose a random number of overrides (even overriding every amplitude)
3588 // int numOverrides = getRandomInt(1, (1<<numQubits) + 1);
3589
3590 // // randomise each override index (uniqueness isn't checked)
3591 // VLA(long long int, overrideInds, numOverrides);
3592 // overrideInds[0] = 0LL;
3593 // for (int i=1; i<numOverrides; i++)
3594 // if (encoding == UNSIGNED)
3595 // overrideInds[i] = getRandomInt(0, 1<<numQubits);
3596 // else if (encoding == TWOS_COMPLEMENT)
3597 // overrideInds[i] = getRandomInt(-(1<<(numQubits-1)), (1<<(numQubits-1))-1);
3598
3599 // // override to a random phase
3600 // VLA(qreal, overridePhases, numOverrides);
3601 // for (int i=0; i<numOverrides; i++)
3602 // overridePhases[i] = getRandomReal(-4, 4); // periodic in [-pi, pi]
3603
3604 // // build a reference diagonal matrix, on the reduced Hilbert space
3605 // QMatrix matr = getZeroMatrix( 1 << numQubits );
3606 // for (size_t i=0; i<matr.size(); i++) {
3607
3608 // long long int ind = 0;
3609 // if (encoding == UNSIGNED)
3610 // ind = i;
3611 // if (encoding == TWOS_COMPLEMENT)
3612 // ind = getTwosComplement(i, numQubits);
3613
3614 // // reference diagonal matrix incorporates overriden phases
3615 // qreal phase;
3616 // bool overriden = false;
3617 // for (int v=0; v<numOverrides; v++) {
3618 // if (ind == overrideInds[v]) {
3619 // phase = overridePhases[v];
3620 // overriden = true;
3621 // break;
3622 // }
3623 // }
3624
3625 // if (!overriden) {
3626 // phase = 0;
3627 // for (int t=0; t<numTerms; t++)
3628 // phase += coeffs[t] * pow(ind, expons[t]);
3629 // }
3630
3631 // matr[i][i] = expI(phase);
3632 // }
3633
3634 // SECTION( "state-vector" ) {
3635
3636 // applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expons, numTerms, overrideInds, overridePhases, numOverrides);
3637 // applyReferenceOp(refVec, qubits, numQubits, matr);
3638 // REQUIRE( areEqual(quregVec, refVec, 1E4*REAL_EPS) );
3639 // }
3640 // SECTION( "density-matrix" ) {
3641
3642 // applyPhaseFuncOverrides(quregMatr, qubits, numQubits, encoding, coeffs, expons, numTerms, overrideInds, overridePhases, numOverrides);
3643 // applyReferenceOp(refMatr, qubits, numQubits, matr);
3644 // REQUIRE( areEqual(quregMatr, refMatr, 1E6*REAL_EPS) );
3645 // }
3646 // }
3647 // SECTION( "input validation" ) {
3648
3649 // int numQubits = 3;
3650 // int qubits[] = {0,1,2};
3651
3652 // SECTION( "number of qubits" ) {
3653
3654 // int numQubits = GENERATE_COPY( -1, 0, NUM_QUBITS+1 );
3655 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, NULL, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), ContainsSubstring("Invalid number of qubits") );
3656 // }
3657 // SECTION( "repetition qubits" ) {
3658
3659 // qubits[GENERATE(1,2)] = qubits[0];
3660 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), ContainsSubstring("The qubits must be unique") );
3661 // }
3662 // SECTION( "qubit indices" ) {
3663
3664 // int inv = GENERATE( -1, NUM_QUBITS );
3665 // qubits[ GENERATE_COPY( range(0,numQubits) )] = inv;
3666 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, 1, NULL, NULL, 0), ContainsSubstring("Invalid qubit index") );
3667 // }
3668 // SECTION( "number of terms" ) {
3669
3670 // int numTerms = GENERATE( -1, 0 );
3671 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, NULL, NULL, numTerms, NULL, NULL, 0), ContainsSubstring("Invalid number of terms in the phase function") );
3672 // }
3673 // SECTION( "bit encoding name" ) {
3674
3675 // enum bitEncoding enc = (enum bitEncoding) GENERATE( -1,2 );
3676 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, enc, NULL, NULL, 1, NULL, NULL, 0), ContainsSubstring("Invalid bit encoding") );
3677 // }
3678 // SECTION( "two's complement register" ) {
3679
3680 // numQubits = 1;
3681 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, NULL, NULL, 1, NULL, NULL, 0), ContainsSubstring("too few qubits to employ TWOS_COMPLEMENT") );
3682 // }
3683 // SECTION( "number of overrides" ) {
3684
3685 // qreal dummyTerms[] = {0};
3686
3687 // int numOverrides = GENERATE_COPY( -1, 1 + (1<<numQubits) );
3688 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, UNSIGNED, dummyTerms, dummyTerms, 1, NULL, NULL, numOverrides), ContainsSubstring("Invalid number of phase function overrides") );
3689 // }
3690 // SECTION( "override indices" ) {
3691
3692 // int numOverrides = 3;
3693 // long long int overrideInds[] = {0,1,2};
3694 // qreal overridePhases[] = {.1,.1,.1};
3695 // qreal dummyTerms[] = {0};
3696
3697 // enum bitEncoding encoding = UNSIGNED;
3698 // overrideInds[GENERATE(0,1,2)] = GENERATE_COPY( -1, (1<<numQubits) );
3699 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, dummyTerms, dummyTerms, 1, overrideInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the UNSIGNED encoding") );
3700
3701 // encoding = TWOS_COMPLEMENT;
3702 // long long int newInds[] = {0,1,2};
3703 // int minInd = -(1<<(numQubits-1));
3704 // int maxInd = (1<<(numQubits-1)) -1;
3705 // newInds[GENERATE(0,1,2)] = GENERATE_COPY( minInd-1, maxInd+1 );
3706 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, dummyTerms, dummyTerms, 1, newInds, overridePhases, numOverrides), ContainsSubstring("Invalid phase function override index, in the TWOS_COMPLEMENT encoding") );
3707 // }
3708 // SECTION( "fractional exponent" ) {
3709
3710 // int numTerms = 3;
3711 // qreal coeffs[] = {0,0,0};
3712 // qreal expos[] = {1,2,3};
3713
3714 // // make one exponent fractional, thereby requiring negative overrides
3715 // expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( 0.5, 1.999, 5.0001 );
3716
3717 // // catch when no negative indices are overridden
3718 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, NULL, NULL, 0), ContainsSubstring("fractional exponent") && ContainsSubstring("TWOS_COMPLEMENT") && ContainsSubstring("negative indices were not overriden") );
3719
3720 // int numNegs = 1 << (numQubits-1);
3721 // VLA(long long int, overrideInds, numNegs);
3722 // VLA(qreal, overridePhases, numNegs);
3723 // for (int i=0; i<numNegs; i++) {
3724 // overrideInds[i] = -(i+1);
3725 // overridePhases[i] = 0;
3726 // }
3727
3728 // // ensure no throw when all are overriden
3729 // REQUIRE_NOTHROW( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, overrideInds, overridePhases, numNegs) );
3730
3731 // // catch when at least one isn't overriden
3732 // overrideInds[GENERATE_COPY( range(0,numNegs) )] = 0; // override a non-negative
3733 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, TWOS_COMPLEMENT, coeffs, expos, numTerms, overrideInds, overridePhases, numNegs), ContainsSubstring("fractional exponent") && ContainsSubstring("TWOS_COMPLEMENT") && ContainsSubstring("negative indices were not overriden") );
3734 // }
3735 // SECTION( "negative exponent" ) {
3736
3737 // int numTerms = 3;
3738 // qreal coeffs[] = {0,0,0};
3739 // qreal expos[] = {1,2,3};
3740 // expos[GENERATE_COPY( range(0,numTerms) )] = GENERATE( -1, -2 );
3741
3742 // enum bitEncoding encoding = GENERATE( UNSIGNED, TWOS_COMPLEMENT );
3743
3744 // // test both when giving no overrides, and giving all non-zero overrides
3745 // int numOverrides = GENERATE( 0, 3 );
3746 // long long int overrideInds[] = {1,2,3};
3747 // qreal overridePhases[] = {0,0,0};
3748 // REQUIRE_THROWS_WITH( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms, overrideInds, overridePhases, numOverrides), ContainsSubstring("The phase function contained a negative exponent which would diverge at zero, but the zero index was not overriden") );
3749
3750 // // but ensure that when the zero IS overriden (anywhere), there's no error
3751 // numOverrides = 3;
3752 // overrideInds[GENERATE_COPY(range(0,numOverrides))] = 0;
3753 // REQUIRE_NOTHROW( applyPhaseFuncOverrides(quregVec, qubits, numQubits, encoding, coeffs, expos, numTerms, overrideInds, overridePhases, numOverrides) );
3754 // }
3755 // }
3756 // CLEANUP_TEST( quregVec, quregMatr );
3757 // }
3758
3759
3760
3761/** @sa applyProjector
3762 * @ingroup deprecatedtests
3763 * @author Tyson Jones
3764 */
3765TEST_CASE( "applyProjector", "[operators]" ) {
3766
3767 Qureg vec = createForcedQureg(NUM_QUBITS);
3768 Qureg mat = createForcedDensityQureg(NUM_QUBITS);
3769
3770 SECTION( "correctness" ) {
3771
3772 int qubit = GENERATE( range(0,NUM_QUBITS) );
3773 int outcome = GENERATE( 0, 1 );
3774
3775 // repeat these random tests 10 times on every qubit, and for both outcomes
3776 GENERATE( range(0,10) );
3777
3778 SECTION( "state-vector" ) {
3779
3780 SECTION( "normalised" ) {
3781
3782 // use a random L2 state for every qubit & outcome
3783 QVector vecRef = getRandomStateVector(NUM_QUBITS);
3784 toQureg(vec, vecRef);
3785
3786 // zero non-outcome reference amps
3787 for (size_t ind=0; ind<vecRef.size(); ind++) {
3788 int bit = (ind >> qubit) & 1; // target-th bit
3789 if (bit != outcome)
3790 vecRef[ind] = 0;
3791 }
3792
3793 applyProjector(vec, qubit, outcome);
3794 REQUIRE( areEqual(vec, vecRef) );
3795 }
3796 SECTION( "unnormalised" ) {
3797
3798 // use a random non-physical state for every qubit & outcome
3799 QVector vecRef = getRandomQVector(1 << NUM_QUBITS);
3800 toQureg(vec, vecRef);
3801
3802 // zero non-outcome reference amps
3803 for (size_t ind=0; ind<vecRef.size(); ind++) {
3804 int bit = (ind >> qubit) & 1; // target-th bit
3805 if (bit != outcome)
3806 vecRef[ind] = 0;
3807 }
3808
3809 applyProjector(vec, qubit, outcome);
3810 REQUIRE( areEqual(vec, vecRef) );
3811 }
3812 }
3813 SECTION( "density-matrix" ) {
3814
3815 SECTION( "pure" ) {
3816
3817 QVector vecRef = getRandomStateVector(NUM_QUBITS);
3818 QMatrix matRef = getPureDensityMatrix(vecRef);
3819
3820 toQureg(mat, matRef);
3821 applyProjector(mat, qubit, outcome);
3822
3823 // zero any amplitudes that aren't |outcome><outcome|
3824 for (size_t r=0; r<matRef.size(); r++) {
3825 for (size_t c=0; c<matRef.size(); c++) {
3826 int ketBit = (c >> qubit) & 1;
3827 int braBit = (r >> qubit) & 1;
3828 if (!(ketBit == outcome && braBit == outcome))
3829 matRef[r][c] = 0;
3830 }
3831 }
3832
3833 REQUIRE( areEqual(mat, matRef) );
3834 }
3835 SECTION( "mixed" ) {
3836
3837 QMatrix matRef = getRandomDensityMatrix(NUM_QUBITS);
3838
3839 toQureg(mat, matRef);
3840 applyProjector(mat, qubit, outcome);
3841
3842 // zero any amplitudes that aren't |outcome><outcome|
3843 for (size_t r=0; r<matRef.size(); r++) {
3844 for (size_t c=0; c<matRef.size(); c++) {
3845 int ketBit = (c >> qubit) & 1;
3846 int braBit = (r >> qubit) & 1;
3847 if (!(ketBit == outcome && braBit == outcome))
3848 matRef[r][c] = 0;
3849 }
3850 }
3851
3852 REQUIRE( areEqual(mat, matRef) );
3853 }
3854 SECTION( "unnormalised" ) {
3855
3856 QMatrix matRef = getRandomQMatrix(1 << NUM_QUBITS);
3857
3858 toQureg(mat, matRef);
3859 applyProjector(mat, qubit, outcome);
3860
3861 // zero any amplitudes that aren't |outcome><outcome|
3862 for (size_t r=0; r<matRef.size(); r++) {
3863 for (size_t c=0; c<matRef.size(); c++) {
3864 int ketBit = (c >> qubit) & 1;
3865 int braBit = (r >> qubit) & 1;
3866 if (!(ketBit == outcome && braBit == outcome))
3867 matRef[r][c] = 0;
3868 }
3869 }
3870
3871 REQUIRE( areEqual(mat, matRef) );
3872 }
3873 }
3874 }
3875 SECTION( "input validation" ) {
3876
3877 SECTION( "qubit index" ) {
3878
3879 int qubit = GENERATE( -1, NUM_QUBITS );
3880 int outcome = 0;
3881 REQUIRE_THROWS_WITH( applyProjector(mat, qubit, outcome), ContainsSubstring("Invalid target qubit") );
3882 }
3883 SECTION( "outcome value" ) {
3884
3885 int qubit = 0;
3886 int outcome = GENERATE( -1, 2 );
3887 REQUIRE_THROWS_WITH( applyProjector(mat, qubit, outcome), ContainsSubstring("measurement outcome") && ContainsSubstring("is invalid") );
3888 }
3889 }
3890 destroyQureg(vec);
3891 destroyQureg(mat);
3892}
3893
3894
3895
3896/** @sa applyQFT
3897 * @ingroup deprecatedtests
3898 * @author Tyson Jones
3899 */
3900TEST_CASE( "applyQFT", "[operators]" ) {
3901
3902 PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
3903
3904 SECTION( "correctness" ) {
3905
3906 // try every sub-register size
3907 int numQubits = GENERATE_COPY( range(1,NUM_QUBITS+1) );
3908
3909 // try every possible sub-register
3910 int* qubits = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numQubits) );
3911
3912 SECTION( "state-vector" ) {
3913
3914 SECTION( "normalised" ) {
3915
3916 QVector refVec = getRandomStateVector(NUM_QUBITS);
3917 toQureg(quregVec, refVec);
3918
3919 applyQFT(quregVec, qubits, numQubits);
3920 refVec = getDFT(refVec, qubits, numQubits);
3921
3922 REQUIRE( areEqual(quregVec, refVec) );
3923 }
3924 SECTION( "unnormalised" ) {
3925
3926 QVector refVec = getRandomQVector(1 << NUM_QUBITS);
3927 toQureg(quregVec, refVec);
3928
3929 applyQFT(quregVec, qubits, numQubits);
3930 refVec = getDFT(refVec, qubits, numQubits);
3931
3932 REQUIRE( areEqual(quregVec, refVec) );
3933 }
3934 }
3935 SECTION( "density-matrix" ) {
3936
3937 SECTION( "pure" ) {
3938
3939 /* a pure density matrix should be mapped to a pure state
3940 * corresponding to the state-vector DFT
3941 */
3942
3943 refVec = getRandomStateVector(NUM_QUBITS);
3944 refMatr = getPureDensityMatrix(refVec);
3945 toQureg(quregMatr, refMatr);
3946
3947 applyQFT(quregMatr, qubits, numQubits);
3948 refVec = getDFT(refVec, qubits, numQubits);
3949 refMatr = getPureDensityMatrix(refVec);
3950
3951 REQUIRE( areEqual(quregMatr, refMatr) );
3952 }
3953 SECTION( "mixed" ) {
3954
3955 /* a mixed density matrix, conceptualised as a mixture of orthogonal
3956 * state-vectors, should be mapped to an equally weighted mixture
3957 * of DFTs of each state-vector (because QFT is unitary and hence
3958 * maintains state orthogonality)
3959 */
3960
3961 int numStates = (1 << NUM_QUBITS)/4; // a quarter of as many states as are possible
3962 std::vector<QVector> states = getRandomOrthonormalVectors(NUM_QUBITS, numStates);
3963 std::vector<qreal> probs = getRandomProbabilities(numStates);
3964
3965 // set qureg to random mixture of state-vectors
3966 refMatr = getMixedDensityMatrix(probs, states);
3967 toQureg(quregMatr, refMatr);
3968
3969 // apply QFT to mixture
3970 applyQFT(quregMatr, qubits, numQubits);
3971
3972 // compute dft of mixture, via dft of each state
3973 refMatr = getZeroMatrix(1 << NUM_QUBITS);
3974 for (int i=0; i<numStates; i++) {
3975 QVector dft = getDFT(states[i], qubits, numQubits);
3976 refMatr += probs[i] * getPureDensityMatrix(dft);
3977 }
3978
3979 REQUIRE( areEqual(quregMatr, refMatr) );
3980 }
3981 SECTION( "unnormalised" ) {
3982
3983 /* repeat method above, except that we use unnormalised vectors,
3984 * and mix them with arbitrary complex numbers instead of probabilities,
3985 * yielding an unnormalised density matrix
3986 */
3987
3988 int numVecs = (1 << NUM_QUBITS)/4; // a quarter of as many states as are possible
3989 std::vector<QVector> vecs;
3990 std::vector<qcomp> coeffs;
3991 for (int i=0; i<numVecs; i++) {
3992 vecs.push_back(getRandomQVector(1 << NUM_QUBITS));
3993 coeffs.push_back(getRandomComplex());
3994 }
3995
3996 // produce unnormalised matrix via random complex sum of random unnormalised vectors
3997 refMatr = getZeroMatrix(1 << NUM_QUBITS);
3998 for (int i=0; i<numVecs; i++)
3999 refMatr += coeffs[i] * getPureDensityMatrix(vecs[i]);
4000
4001 toQureg(quregMatr, refMatr);
4002 applyQFT(quregMatr, qubits, numQubits);
4003
4004 // compute target matrix via dft of each unnormalised vector
4005 refMatr = getZeroMatrix(1 << NUM_QUBITS);
4006 for (int i=0; i<numVecs; i++) {
4007 QVector dft = getDFT(vecs[i], qubits, numQubits);
4008 refMatr += coeffs[i] * getPureDensityMatrix(dft);
4009 }
4010
4011 REQUIRE( areEqual(quregMatr, refMatr) );
4012 }
4013 }
4014 }
4015 SECTION( "input validation" ) {
4016
4017 SECTION( "number of targets" ) {
4018
4019 // there cannot be more targets than qubits in register
4020 int numQubits = GENERATE( -1, 0);
4021 int qubits[NUM_QUBITS+1];
4022
4023 REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), ContainsSubstring("number of target qubits") && ContainsSubstring("invalid") );
4024 REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, NUM_QUBITS+1), ContainsSubstring("number of target qubits") && ContainsSubstring("exceeds") && ContainsSubstring("Qureg") );
4025
4026 }
4027 SECTION( "repetition in targets" ) {
4028
4029 int numQubits = 3;
4030 int qubits[] = {1,2,2};
4031
4032 REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), ContainsSubstring("target") && ContainsSubstring("unique") );
4033 }
4034 SECTION( "qubit indices" ) {
4035
4036 int numQubits = 3;
4037 int qubits[] = {1,2,3};
4038
4039 int inv = GENERATE( -1, NUM_QUBITS );
4040 qubits[GENERATE_COPY( range(0,numQubits) )] = inv; // make invalid target
4041 REQUIRE_THROWS_WITH( applyQFT(quregVec, qubits, numQubits), ContainsSubstring("Invalid target") );
4042 }
4043 }
4044 CLEANUP_TEST( quregVec, quregMatr );
4045}
4046
4047
4048
4049/** @sa applySubDiagonalOp
4050 * @ingroup deprecatedtests
4051 * @author Tyson Jones
4052 */
4053TEST_CASE( "applySubDiagonalOp", "[operators]" ) {
4054
4055 PREPARE_TEST( quregVec, quregMatr, refVec, refMatr );
4056
4057 SECTION( "correctness" ) {
4058
4059 // generate all possible targets
4060 int numTargs = GENERATE( range(1,NUM_QUBITS+1) );
4061 int* targs = GENERATE_COPY( sublists(range(0,NUM_QUBITS), numTargs) );
4062
4063 // initialise a random non-unitary diagonal op
4064 SubDiagonalOp op = createSubDiagonalOp(numTargs);
4065 for (long long int i=0; i<op.numElems; i++)
4066 op.cpuElems[i] = getRandomComplex();
4067 syncDiagMatr(op);
4068
4069 QMatrix opMatr = toQMatrix(op);
4070
4071 SECTION( "state-vector" ) {
4072
4073 applySubDiagonalOp(quregVec, targs, numTargs, op);
4074 applyReferenceMatrix(refVec, targs, numTargs, opMatr);
4075 REQUIRE( areEqual(quregVec, refVec) );
4076 }
4077 SECTION( "density-matrix" ) {
4078
4079 applySubDiagonalOp(quregMatr, targs, numTargs, op);
4080 applyReferenceMatrix(refMatr, targs, numTargs, opMatr);
4081 REQUIRE( areEqual(quregMatr, refMatr, 100*REAL_EPS) );
4082 }
4083
4084 destroySubDiagonalOp(op);
4085 }
4086 SECTION( "input validation" ) {
4087
4088 SECTION( "diagonal dimension" ) {
4089
4090 int numTargs = 3;
4091 SubDiagonalOp op = createSubDiagonalOp(numTargs);
4092 syncDiagMatr(op);
4093
4094 int badNumTargs = GENERATE_COPY( numTargs-1, numTargs+1 );
4095 int badTargs[NUM_QUBITS+1];
4096 for (int i=0; i<NUM_QUBITS+1; i++)
4097 badTargs[i] = i;
4098
4099 REQUIRE_THROWS_WITH( applySubDiagonalOp(quregVec, badTargs, badNumTargs, op), ContainsSubstring("inconsistent size") );
4100 destroySubDiagonalOp(op);
4101 }
4102 SECTION( "number of targets" ) {
4103
4104 // make too many targets (which are otherwise valid)
4105 SubDiagonalOp badOp = createSubDiagonalOp(NUM_QUBITS + 1);
4106 int targs[NUM_QUBITS + 1];
4107 for (int t=0; t<badOp.numQubits; t++)
4108 targs[t] = t;
4109 for (int i=0; i<badOp.numElems; i++)
4110 badOp.cpuElems[i] = qcomp(1,0);
4111 syncDiagMatr(badOp);
4112
4113 REQUIRE_THROWS_WITH( applySubDiagonalOp(quregVec, targs, badOp.numQubits, badOp), ContainsSubstring("number of target qubits") && ContainsSubstring("exceeds") );
4114 destroySubDiagonalOp(badOp);
4115 }
4116 SECTION( "repetition in targets" ) {
4117
4118 // make a valid unitary diagonal op
4119 SubDiagonalOp op = createSubDiagonalOp(3);
4120 for (int i=0; i<op.numElems; i++)
4121 op.cpuElems[i] = qcomp(1,0);
4122 syncDiagMatr(op);
4123
4124 // make a repetition in the target list
4125 int targs[] = {2,1,2};
4126
4127 REQUIRE_THROWS_WITH( applySubDiagonalOp(quregVec, targs, op.numQubits, op), ContainsSubstring("target qubits contained duplicates") );
4128 destroySubDiagonalOp(op);
4129 }
4130 SECTION( "qubit indices" ) {
4131
4132 // make a valid unitary diagonal op
4133 SubDiagonalOp op = createSubDiagonalOp(3);
4134 for (int i=0; i<op.numElems; i++)
4135 op.cpuElems[i] = qcomp(1,0);
4136 syncDiagMatr(op);
4137
4138 int targs[] = {0,1,2};
4139
4140 // make each target in-turn invalid
4141 int badIndex = GENERATE( range(0,3) );
4142 int badValue = GENERATE( -1, NUM_QUBITS );
4143 targs[badIndex] = badValue;
4144
4145 REQUIRE_THROWS_WITH( applySubDiagonalOp(quregVec, targs, op.numQubits, op), ContainsSubstring("Invalid target qubit") );
4146 destroySubDiagonalOp(op);
4147 }
4148 }
4149 CLEANUP_TEST( quregVec, quregMatr );
4150}
4151
4152
4153
4154// applyTrotterCircuit removed because replacement
4155// function applyTrotterizedTimeEvol accepts new
4156// type PauliStrSum which has an initialiser which is
4157// incompatible with the deprecated PauliHamil
4158
4159 // /** @sa applyTrotterCircuit
4160 // * @ingroup deprecatedtests
4161 // * @author Tyson Jones
4162 // */
4163 // TEST_CASE( "applyTrotterCircuit", "[operators]" ) {
4164
4165 // Qureg vec = createForcedQureg(NUM_QUBITS);
4166 // Qureg mat = createForcedDensityQureg(NUM_QUBITS);
4167 // initDebugState(vec);
4168 // initDebugState(mat);
4169
4170 // Qureg vecRef = createCloneQureg(vec);
4171 // Qureg matRef = createCloneQureg(mat);
4172
4173 // SECTION( "correctness" ) {
4174
4175 // SECTION( "one term" ) {
4176
4177 // // a Hamiltonian with one term has an exact (trivial) Trotterisation
4178 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, 1);
4179
4180 // // H = coeff X Y Z (on qubits 0,1,2)
4181 // qreal coeff = getRandomReal(-5, 5);
4182 // int numTargs = 3;
4183 // int targs[] = {0, 1, 2};
4184 // pauliOpType codes[] = {PAULI_X, PAULI_Y, PAULI_Z};
4185 // hamil.termCoeffs[0] = coeff;
4186 // for (int i=0; i<numTargs; i++)
4187 // hamil.pauliCodes[targs[i]] = codes[i];
4188
4189 // // time can be negative
4190 // qreal time = getRandomReal(-2,2);
4191
4192 // // by commutation, all reps & orders yield the same total unitary
4193 // int reps = GENERATE( range(1,5) );
4194
4195 // // applyTrotter(t, 1, 1) = exp(-i t coeff paulis)
4196 // // multiRotatePauli(a) = exp(- i a / 2 paulis)
4197
4198 // SECTION( "state-vector" ) {
4199
4200 // int order = GENERATE( 1, 2, 4 );
4201
4202 // applyTrotterCircuit(vec, hamil, time, order, reps);
4203 // multiRotatePauli(vecRef, targs, codes, numTargs, 2*time*coeff);
4204 // REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
4205 // }
4206 // SECTION( "density-matrix" ) {
4207
4208 // int order = GENERATE( 1, 2 ); // precision bites density-matrices quickly
4209
4210 // applyTrotterCircuit(mat, hamil, time, order, reps);
4211 // multiRotatePauli(matRef, targs, codes, numTargs, 2*time*coeff);
4212 // REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
4213 // }
4214
4215 // destroyPauliHamil(hamil);
4216 // }
4217 // SECTION( "commuting terms" ) {
4218
4219 // // a Hamiltonian of commuting terms, Trotterises exactly
4220 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, 2);
4221
4222 // // H = c0 X Y I + c1 X I Z (on qubits 0,1,2)
4223 // int targs[] = {0, 1, 2};
4224 // hamil.pauliCodes[0] = PAULI_X;
4225 // hamil.pauliCodes[0 + NUM_QUBITS] = PAULI_X;
4226 // hamil.pauliCodes[1] = PAULI_Y;
4227 // hamil.pauliCodes[1 + NUM_QUBITS] = PAULI_I;
4228 // hamil.pauliCodes[2] = PAULI_I;
4229 // hamil.pauliCodes[2 + NUM_QUBITS] = PAULI_Z;
4230 // for (int i=0; i<hamil.numSumTerms; i++)
4231 // hamil.termCoeffs[i] = getRandomReal(-5,5);
4232
4233 // // time can be negative
4234 // qreal time = getRandomReal(-2,2);
4235
4236 // // applyTrotter(t, 1, 1) = exp(-i t c0 paulis0) exp(-i t c1 paulis1)
4237 // // multiRotatePauli(a) = exp(- i a / 2 paulis)
4238
4239 // SECTION( "state-vector" ) {
4240
4241 // int reps = GENERATE( range(1,5) );
4242 // int order = GENERATE( 1, 2, 4 );
4243
4244 // applyTrotterCircuit(vec, hamil, time, order, reps);
4245 // multiRotatePauli(vecRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
4246 // multiRotatePauli(vecRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
4247 // REQUIRE( areEqual(vec, vecRef, 10*REAL_EPS) );
4248 // }
4249 // SECTION( "density-matrix" ) {
4250
4251 // int reps = GENERATE( range(1,5) );
4252 // int order = GENERATE( 1, 2 ); // precision hurts density matrices quickly
4253
4254 // applyTrotterCircuit(mat, hamil, time, order, reps);
4255 // multiRotatePauli(matRef, targs, hamil.pauliCodes, 3, 2*time*hamil.termCoeffs[0]);
4256 // multiRotatePauli(matRef, targs, &(hamil.pauliCodes[NUM_QUBITS]), 3, 2*time*hamil.termCoeffs[1]);
4257 // REQUIRE( areEqual(mat, matRef, 1E2*REAL_EPS) );
4258 // }
4259
4260 // destroyPauliHamil(hamil);
4261 // }
4262 // SECTION( "general" ) {
4263
4264 // /* We'll consider an analytic time-evolved state, so that we can avoid
4265 // * comparing applyTrotterCircuit to other numerical approximations.
4266 // * We can construct such a state, by using a Hamiltonian with known
4267 // * analytic eigenvalues, and hence a known period. Time evolution of the
4268 // * period will just yield the input state.
4269 // *
4270 // * E.g. H = pi sqrt(2) X Y Z X Y + pi Y Z X Y Z + pi Z X Y Z X
4271 // * has (degenerate) eigenvalues +- 2 pi, so the period
4272 // * of the Hamiltonian is t=1.
4273 // */
4274
4275 // // hardcoded 5 qubits here in the Pauli codes
4276 // REQUIRE( NUM_QUBITS == 5 );
4277
4278 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, 3);
4279 // qreal coeffs[] = {(qreal) (M_PI * sqrt(2.0)), M_PI, M_PI};
4280 // enum pauliOpType codes[] = {
4281 // PAULI_X, PAULI_Y, PAULI_Z, PAULI_X, PAULI_Y,
4282 // PAULI_Y, PAULI_Z, PAULI_X, PAULI_Y, PAULI_Z,
4283 // PAULI_Z, PAULI_X, PAULI_Y, PAULI_Z, PAULI_X};
4284 // initPauliHamil(hamil, coeffs, codes);
4285
4286 // // evolving to t=1 should leave the input state unchanged
4287 // qreal time = 1;
4288
4289 // // since unnormalised (initDebugState), max fid is 728359.8336
4290 // qreal fidNorm = 728359.8336;
4291
4292 // SECTION( "absolute" ) {
4293
4294 // // such a high order and reps should yield precise solution
4295 // int order = 4;
4296 // int reps = 20;
4297 // applyTrotterCircuit(vec, hamil, time, 4, 20);
4298 // qreal fid = calcFidelity(vec, vecRef) / fidNorm;
4299
4300 // REQUIRE( fid == Approx(1).epsilon(1E-8) );
4301 // }
4302 // SECTION( "repetitions scaling" ) {
4303
4304 // // exclude order 1; too few reps for monotonic increase of accuracy
4305 // int order = GENERATE( 2, 4, 6 );
4306
4307 // // accuracy should increase with increasing repetitions
4308 // int reps[] = {1, 5, 10};
4309
4310 // qreal prevFid = 0;
4311 // for (int i=0; i<3; i++) {
4312 // initDebugState(vec);
4313 // applyTrotterCircuit(vec, hamil, time, order, reps[i]);
4314 // qreal fid = calcFidelity(vec, vecRef) / fidNorm;
4315
4316 // REQUIRE( fid >= prevFid );
4317 // prevFid = fid;
4318 // }
4319 // }
4320 // SECTION( "order scaling" ) {
4321
4322 // // exclude order 1; too few reps for monotonic increase of accuracy
4323 // int reps = GENERATE( 5, 10 );
4324
4325 // // accuracy should increase with increasing repetitions
4326 // int orders[] = {1, 2, 4, 6};
4327
4328 // qreal prevFid = 0;
4329 // for (int i=0; i<4; i++) {
4330 // initDebugState(vec);
4331 // applyTrotterCircuit(vec, hamil, time, orders[i], reps);
4332 // qreal fid = calcFidelity(vec, vecRef) / fidNorm;
4333
4334 // REQUIRE( fid >= prevFid );
4335 // prevFid = fid;
4336 // }
4337 // }
4338
4339 // destroyPauliHamil(hamil);
4340 // }
4341 // }
4342 // SECTION( "input validation" ) {
4343
4344 // SECTION( "repetitions" ) {
4345
4346 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, 1);
4347 // int reps = GENERATE( -1, 0 );
4348
4349 // REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, reps), ContainsSubstring("repetitions must be >=1") );
4350
4351 // destroyPauliHamil(hamil);
4352 // }
4353 // SECTION( "order" ) {
4354
4355 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, 1);
4356 // int order = GENERATE( -1, 0, 3, 5, 7 );
4357
4358 // REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, order, 1), ContainsSubstring("order must be 1, or an even number") );
4359
4360 // destroyPauliHamil(hamil);
4361 // }
4362 // SECTION( "pauli codes" ) {
4363
4364 // int numTerms = 3;
4365 // PauliHamil hamil = createPauliHamil(NUM_QUBITS, numTerms);
4366
4367 // // make one pauli code wrong
4368 // hamil.pauliCodes[GENERATE_COPY( range(0,numTerms*NUM_QUBITS) )] = (pauliOpType) GENERATE( -1, 4 );
4369 // REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), ContainsSubstring("Invalid Pauli code") );
4370
4371 // destroyPauliHamil(hamil);
4372 // }
4373 // SECTION( "matching hamiltonian qubits" ) {
4374
4375 // PauliHamil hamil = createPauliHamil(NUM_QUBITS + 1, 1);
4376
4377 // REQUIRE_THROWS_WITH( applyTrotterCircuit(vec, hamil, 1, 1, 1), ContainsSubstring("same number of qubits") );
4378 // REQUIRE_THROWS_WITH( applyTrotterCircuit(mat, hamil, 1, 1, 1), ContainsSubstring("same number of qubits") );
4379
4380 // destroyPauliHamil(hamil);
4381 // }
4382 // }
4383
4384 // destroyQureg(vec);
4385 // destroyQureg(mat);
4386 // destroyQureg(vecRef);
4387 // destroyQureg(matRef);
4388 // }
4389
TEST_CASE("applyDiagonalOp", "[operators]")
void applyReferenceMatrix(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
ComplexMatrix4 toComplexMatrix4(QMatrix qm)
unsigned int calcLog2(long unsigned int res)
QVector getRandomQVector(int dim)
QMatrix getMixedDensityMatrix(vector< qreal > probs, vector< QVector > states)
bool areEqual(QVector a, QVector b)
vector< vector< qcomp > > QMatrix
ComplexMatrix2 toComplexMatrix2(QMatrix qm)
void applyReferenceOp(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
QVector getDFT(QVector in)
void toComplexMatrixN(QMatrix qm, ComplexMatrixN cm)
QMatrix getRandomQMatrix(int dim)
QMatrix toQMatrix(CompMatr1 src)
vector< qcomp > QVector
QMatrix getPureDensityMatrix(QVector state)
void toQureg(Qureg qureg, QVector vec)
QuESTEnv getQuESTEnv()
void syncDiagMatr(DiagMatr matr)
Definition matrices.cpp:374
void syncCompMatr(CompMatr matr)
Definition matrices.cpp:373
Qureg createForcedQureg(int numQubits)
Definition qureg.cpp:299
Qureg createForcedDensityQureg(int numQubits)
Definition qureg.cpp:309
void destroyQureg(Qureg qureg)
Definition qureg.cpp:334
qmatrix getZeroMatrix(size_t dim)
Definition qmatrix.cpp:18
qvector getRandomStateVector(int numQb)
Definition random.cpp:296
qcomp getRandomComplex()
Definition random.cpp:107
qmatrix getRandomUnitary(int numQb)
Definition random.cpp:348
qmatrix getRandomDensityMatrix(int numQb)
Definition random.cpp:308
vector< qreal > getRandomProbabilities(int numProbs)
Definition random.cpp:160
Definition qureg.h:49