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