The Quantum Exact Simulation Toolkit v4.2.0
Loading...
Searching...
No Matches
channels.cpp
1/** @file
2 * Unit tests of the channels module.
3 *
4 * @author Tyson Jones
5 *
6 * @defgroup unitchannels Channels
7 * @ingroup unittests
8 */
9
10#include "quest.h"
11
12#include <catch2/catch_test_macros.hpp>
13#include <catch2/matchers/catch_matchers_string.hpp>
14#include <catch2/generators/catch_generators_range.hpp>
15
16#include "tests/utils/macros.hpp"
17#include "tests/utils/linalg.hpp"
18#include "tests/utils/convert.hpp"
19#include "tests/utils/compare.hpp"
20#include "tests/utils/random.hpp"
21
22#include <vector>
23
24using Catch::Matchers::ContainsSubstring;
25using std::vector;
26
27
28
29/*
30 * UTILITIES
31 */
32
33#define TEST_CATEGORY \
34 LABEL_UNIT_TAG "[channels]"
35
36
37
38/**
39 * TESTS
40 *
41 * @ingroup unitchannels
42 * @{
43 */
44
45
46TEST_CASE( "createKrausMap", TEST_CATEGORY ) {
47
48 SECTION( LABEL_CORRECTNESS ) {
49
50 int numQubits = GENERATE( range(1,4) ); // 4qb superop = 8qb matrix = 16 statevec
51 int numMatrices = GENERATE( 1, 2, 10 );
52 CAPTURE( numQubits, numMatrices );
53
54 KrausMap map = createKrausMap(numQubits, numMatrices);
55
56 // verify dimensions
57 REQUIRE( map.numQubits == numQubits );
58 REQUIRE( map.numMatrices == numMatrices );
59 REQUIRE( map.numRows == getPow2(numQubits) );
60
61 // verify superoperator dimensions
62 REQUIRE( map.superop.numQubits == numQubits );
63 REQUIRE( map.superop.numRows == getPow2(2 * numQubits) );
64
65 // verify default fields
66 REQUIRE( *(map.isApproxCPTP) == -1 );
67 REQUIRE( *(map.superop.wasGpuSynced) == 0 );
68
69 // verify pointers
70 REQUIRE( map.matrices != nullptr );
71 REQUIRE( map.superop.cpuElems != nullptr );
72 REQUIRE( map.superop.cpuElemsFlat != nullptr );
73 if (getQuESTEnv().isGpuAccelerated)
74 REQUIRE( map.superop.gpuElemsFlat != nullptr );
75 else
76 REQUIRE( map.superop.gpuElemsFlat == nullptr );
77
78 // verify that all matrices default to zero
79 bool isZero = true;
80 for (qindex i=0; i<map.numMatrices && isZero; i++)
81 for (qindex r=0; r<map.numRows && isZero; r++)
82 for (qindex c=0; c<map.numRows && isZero; c++)
83 isZero = (map.matrices[i][r][c] == qcomp(0,0));
84 REQUIRE( isZero );
85
86 // verify superoperator defaults to zero
87 isZero = true;
88 for (qindex r=0; r<map.superop.numRows && isZero; r++)
89 for (qindex c=0; c<map.superop.numRows && isZero; c++)
90 isZero = (map.superop.cpuElems[r][c] == qcomp(0,0));
91 REQUIRE( isZero );
92
93 destroyKrausMap(map);
94 }
95
96 SECTION( LABEL_VALIDATION ) {
97
98 SECTION( "env is init" ) {
99
100 // no way to test this
101 SUCCEED( );
102 }
103
104 SECTION( "too few qubits" ) {
105
106 int numQubits = GENERATE( -1, 0 );
107
108 REQUIRE_THROWS_WITH( createKrausMap(numQubits,1), ContainsSubstring("one or more qubits") );
109 }
110
111 SECTION( "too few operators" ) {
112
113 int numOpers = GENERATE( -1, 0 );
114
115 REQUIRE_THROWS_WITH( createKrausMap(1,numOpers), ContainsSubstring("strictly positive number of matrices") );
116 }
117
118 SECTION( "too many qubits" ) {
119
120 REQUIRE_THROWS_WITH( createKrausMap(100,1), ContainsSubstring("can be addressed by the qindex type") );
121
122 REQUIRE_THROWS_WITH( createKrausMap(15,1), ContainsSubstring("necessary memory") && ContainsSubstring("would overflow") );
123
124 // no overflows, but definitely exceeds local RAM and fails to allocate; frightens address sanitizer!
125 // note the specific error message depends on the what backend the auto-deployer tried to use (e.g.
126 // GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
127 // advance or whether it proceeded to malloc() which subsequently failed
128 #ifndef SANITIZER_IS_ACTIVE
129 REQUIRE_THROWS_WITH( createKrausMap(12,1),
130 ContainsSubstring("failed") ||
131 ContainsSubstring("insufficient available memory") ||
132 ContainsSubstring("exceeds the available memory") ||
133 ContainsSubstring("available GPU memory") );
134 #endif
135 }
136
137 SECTION( "too many operators" ) {
138
139 /// @todo
140 /// there is currently no validation for that the operator
141 /// list was too big and would ergo overflow memory (since
142 /// it's just a ridiculous, annoying scenario)
143
144 SUCCEED( );
145 }
146 }
147}
148
149
150TEST_CASE( "destroyKrausMap", TEST_CATEGORY ) {
151
152 SECTION( LABEL_CORRECTNESS ) {
153
154 KrausMap map = createKrausMap(3, 3);
155 REQUIRE_NOTHROW( destroyKrausMap(map) );
156 }
157
158 SECTION( LABEL_VALIDATION ) {
159
160 // sanitizer interferes with un-initialised struct values
161 #ifndef SANITIZER_IS_ACTIVE
162 SECTION( "not created" ) {
163
164 KrausMap m;
165 REQUIRE_THROWS_WITH( destroyKrausMap(m), ContainsSubstring("Invalid KrausMap") && ContainsSubstring("not created") );
166 }
167 #endif
168 }
169}
170
171
172TEST_CASE( "syncKrausMap", TEST_CATEGORY ) {
173
174 SECTION( LABEL_CORRECTNESS ) {
175
176 int numTargs = GENERATE( range(1,4) ); // 4qb superop = 8qb matrix = 16qb statevec
177 int numMatrs = GENERATE( 1, 2, 10 );
178 CAPTURE( numTargs, numMatrs );
179
180 KrausMap map = createKrausMap(numTargs, numMatrs);
181 REQUIRE( *(map.superop.wasGpuSynced) == 0 );
182
183 *(map.isApproxCPTP) = 0;
184
185 // validate the fields are updated
186 syncKrausMap(map);
187 REQUIRE( *(map.superop.wasGpuSynced) == 1 );
188 REQUIRE( *(map.isApproxCPTP) == -1 );
189
190 // validate the superop gets inferred correctly from the kraus map
191 auto matrices = getRandomKrausMap(numTargs, numMatrs);
192 setKrausMap(map, matrices); // calls sync anyway
193 syncKrausMap(map);
194 REQUIRE_AGREE( map.superop, getSuperOperator(matrices) );
195
196 // to test that the GPU memory was actually overwritten,
197 // we would need a custom accessor of GPU memory, requiring
198 // the tests are CUDA-compiled - no thank you mam! It is
199 // certain this function works from the other GPU tests.
200
201 destroyKrausMap(map);
202 }
203
204 SECTION( LABEL_VALIDATION ) {
205
206 /// @todo fails in MSVC for unknown reason
207 #ifndef _MSC_VER
208 // sanitizer messes with default initialisation
209 #ifndef SANITIZER_IS_ACTIVE
210 SECTION( "not created" ) {
211
212 KrausMap m;
213 REQUIRE_THROWS_WITH( syncKrausMap(m), ContainsSubstring("Invalid KrausMap") && ContainsSubstring("not created") );
214 }
215 #endif
216 #endif
217 }
218}
219
220
221TEST_CASE( "setKrausMap", TEST_CATEGORY ) {
222
223 SECTION( LABEL_CORRECTNESS ) {
224
225 int numQubits = GENERATE( range(1,4) ); // 4qb superop = 8qb matrix = 16qb statevec
226 int numOps = GENERATE( 1, 2, 10 );
227 CAPTURE( numQubits, numOps );
228
229 KrausMap map = createKrausMap(numQubits, numOps);
230 auto matrices = getRandomKrausMap(numQubits, numOps);
231
232 SECTION( LABEL_C_INTERFACE ) {
233
234 qcomp*** ptrs = (qcomp***) malloc(numOps * sizeof *ptrs);
235 for (int n=0; n<numOps; n++) {
236 ptrs[n] = (qcomp**) malloc(map.numRows * sizeof **ptrs);
237 for (int r=0; r<map.numRows; r++)
238 ptrs[n][r] = matrices[n][r].data();
239 }
240
241 setKrausMap(map, ptrs);
242 REQUIRE( *(map.superop.wasGpuSynced) == 1 );
243 REQUIRE_AGREE( map.superop, getSuperOperator(matrices) );
244
245 for (int n=0; n<numOps; n++)
246 free(ptrs[n]);
247 free(ptrs);
248 }
249
250 SECTION( LABEL_CPP_INTERFACE ) {
251
252 *(map.superop.wasGpuSynced) = 0;
253
254 setKrausMap(map, matrices);
255 REQUIRE( *(map.superop.wasGpuSynced) == 1 );
256 REQUIRE_AGREE( map.superop, getSuperOperator(matrices) );
257 }
258
259 // to test that the GPU memory was actually overwritten,
260 // we would need a custom accessor of GPU memory, requiring
261 // the tests are CUDA-compiled - no thank you mam! It is
262 // certain this function works from the other GPU tests.
263
264 destroyKrausMap(map);
265 }
266
267 SECTION( LABEL_VALIDATION ) {
268
269 // only C++ interface is validated
270
271 int numQubits = 3;
272 int numOps = 3;
273 KrausMap map = createKrausMap(numQubits, numOps);
274
275 int err = GENERATE( -1, +1 );
276
277 /// @todo fails in MSVC for unknown reason
278 #ifndef _MSC_VER
279 // sanitizer messes with default initialisation
280 #ifndef SANITIZER_IS_ACTIVE
281 SECTION( "not created" ) {
282
283 KrausMap bad;
284 REQUIRE_THROWS_WITH( setKrausMap(bad, getRandomKrausMap(numQubits, numOps)), ContainsSubstring("invalid") );
285 }
286 #endif
287 #endif
288
289 SECTION( "inconsistent dimensions" ) {
290
291 REQUIRE_THROWS_WITH( setKrausMap(map, getRandomKrausMap(numQubits+err, numOps)), ContainsSubstring("dimension") );
292 }
293
294 SECTION( "inconsistent number of matrices" ) {
295
296 REQUIRE_THROWS_WITH( setKrausMap(map, getRandomKrausMap(numQubits, numOps-err)), ContainsSubstring("number of matrices") );
297 }
298
299 destroyKrausMap(map);
300 }
301}
302
303
304TEST_CASE( "setInlineKrausMap", TEST_CATEGORY ) {
305
306 SECTION( LABEL_CORRECTNESS ) {
307
308 int numQubits = GENERATE( range(1,4) ); // 4qb superop = 8qb matrix = 16qb statevec
309 int numOps = GENERATE( 1, 2, 10 );
310 CAPTURE( numQubits, numOps );
311
312 KrausMap map = createKrausMap(numQubits, numOps);
313 auto matrices = getRandomKrausMap(numQubits, numOps);
314
315 // only the C++ interface can be tested
316
317 SECTION( LABEL_CPP_INTERFACE ) {
318
319 *(map.superop.wasGpuSynced) = 0;
320
321 setInlineKrausMap(map, numQubits, numOps, matrices);
322 REQUIRE( *(map.superop.wasGpuSynced) == 1 );
323 REQUIRE_AGREE( map.superop, getSuperOperator(matrices) );
324
325 /// @todo test GPU memory is overwritten
326 }
327
328 destroyKrausMap(map);
329 }
330
331 SECTION( LABEL_VALIDATION ) {
332
333 // only C++ interface can be validated
334
335 int numQubits = 3;
336 int numOps = 3;
337 KrausMap map = createKrausMap(numQubits, numOps);
338
339 int err = GENERATE( -1, +1 );
340
341 /// @todo fails in MSVC for unknown reason
342 #ifndef _MSC_VER
343 // sanitizer messes with default initialisation
344 #ifndef SANITIZER_IS_ACTIVE
345 SECTION( "not created" ) {
346
347 KrausMap bad;
348 REQUIRE_THROWS_WITH( setInlineKrausMap(bad, numQubits, numOps, getRandomKrausMap(numQubits, numOps)), ContainsSubstring("invalid") );
349 }
350 #endif
351 #endif
352
353 SECTION( "macro parameters" ) {
354
355 // check macro parameters are consistent
356 REQUIRE_THROWS_WITH( setInlineKrausMap(map, numQubits+err, numOps, getRandomKrausMap(numQubits, numOps)), ContainsSubstring("number of Kraus operators") && ContainsSubstring("qubits") );
357 REQUIRE_THROWS_WITH( setInlineKrausMap(map, numQubits, numOps+err, getRandomKrausMap(numQubits, numOps)), ContainsSubstring("number of Kraus operators") && ContainsSubstring("qubits") );
358 }
359
360 SECTION( "dimensions" ) {
361
362 // check lists are correctly sized
363 REQUIRE_THROWS_WITH( setInlineKrausMap(map, numQubits, numOps, getRandomKrausMap(numQubits+err, numOps )), ContainsSubstring("dimension") );
364 REQUIRE_THROWS_WITH( setInlineKrausMap(map, numQubits, numOps, getRandomKrausMap(numQubits, numOps+err)), ContainsSubstring("number of matrices") );
365 }
366
367 destroyKrausMap(map);
368 }
369}
370
371
372TEST_CASE( "createInlineKrausMap", TEST_CATEGORY ) {
373
374 SECTION( LABEL_CORRECTNESS ) {
375
376 int numQubits = GENERATE( range(1,4) ); // 4qb superop = 8qb matrix = 16qb statevec
377 int numOps = GENERATE( 1, 2, 10 );
378 CAPTURE( numQubits, numOps );
379
380 auto matrices = getRandomKrausMap(numQubits, numOps);
381
382 // only the C++ interface can be tested
383
384 SECTION( LABEL_CPP_INTERFACE ) {
385
386 KrausMap map = createInlineKrausMap(numQubits, numOps, matrices);
387
388 REQUIRE( *(map.superop.wasGpuSynced) == 1 );
389 REQUIRE_AGREE( map.superop, getSuperOperator(matrices) );
390
391 /// @todo test GPU memory is overwritten
392
393 destroyKrausMap(map);
394 }
395 }
396
397 SECTION( LABEL_VALIDATION ) {
398
399 // only C++ interface can be validated
400
401 SECTION( "env not created" ) {
402
403 // no way to test
404 SUCCEED( );
405 }
406
407 SECTION( "incomaptible number of matrices" ) {
408
409 int err = GENERATE( -1, +1 );
410
411 REQUIRE_THROWS_WITH( createInlineKrausMap(3, 3, getRandomKrausMap(3, 3+err)), ContainsSubstring("matrices") );
412 }
413
414 SECTION( "incompatible dimensions" ) {
415
416 int err = GENERATE( -1, +1 );
417
418 REQUIRE_THROWS_WITH( createInlineKrausMap(3, 3, getRandomKrausMap(3+err, 3)), ContainsSubstring("rows") );
419 }
420
421 SECTION( "too few qubits" ) {
422
423 int numQubits = GENERATE( -1, 0 );
424
425 REQUIRE_THROWS_WITH( createInlineKrausMap(numQubits,1,{{{}}}), ContainsSubstring("one or more qubits") );
426 }
427
428 SECTION( "too few operators" ) {
429
430 int numOpers = GENERATE( -1, 0 );
431
432 REQUIRE_THROWS_WITH( createInlineKrausMap(1,numOpers,{{{}}}), ContainsSubstring("strictly positive number of matrices") );
433 }
434
435 SECTION( "too many qubits" ) {
436
437 REQUIRE_THROWS_WITH( createInlineKrausMap(100,1,{{{}}}), ContainsSubstring("can be addressed by the qindex type") );
438
439 REQUIRE_THROWS_WITH( createInlineKrausMap(15,1,{{{}}}), ContainsSubstring("necessary memory") && ContainsSubstring("would overflow") );
440
441 // cannot check when massive alloc run-time fails since the passed
442 // vectors must be of the correct size - and ergo impossibly big!
443 }
444
445 SECTION( "too many operators" ) {
446
447 /// @todo
448 /// there is currently no validation for that the operator
449 /// list was too big and would ergo overflow memory (since
450 /// it's just a ridiculous, annoying scenario)
451
452 SUCCEED( );
453 }
454 }
455}
456
457
458
459TEST_CASE( "createSuperOp", TEST_CATEGORY ) {
460
461 SECTION( LABEL_CORRECTNESS ) {
462
463 int numQubits = GENERATE( range(1,4) ); // 4qb superop = 8qb matrix = 16 statevec
464 CAPTURE( numQubits );
465
466 SuperOp op = createSuperOp(numQubits);
467
468 // verify dimensions
469 REQUIRE( op.numQubits == numQubits );
470 REQUIRE( op.numRows == getPow2(2*numQubits) );
471
472 // verify default fields
473 REQUIRE( *(op.wasGpuSynced) == 0 );
474
475 // verify pointers
476 REQUIRE( op.cpuElems != nullptr );
477 REQUIRE( op.cpuElemsFlat != nullptr );
478 if (getQuESTEnv().isGpuAccelerated)
479 REQUIRE( op.gpuElemsFlat != nullptr );
480 else
481 REQUIRE( op.gpuElemsFlat == nullptr );
482
483 // verify superoperator defaults to zero
484 bool isZero = true;
485 for (qindex r=0; r<op.numRows && isZero; r++)
486 for (qindex c=0; c<op.numRows && isZero; c++)
487 isZero = (op.cpuElems[r][c] == qcomp(0,0));
488 REQUIRE( isZero );
489
490 destroySuperOp(op);
491 }
492
493 SECTION( LABEL_VALIDATION ) {
494
495 SECTION( "env is init" ) {
496
497 // no way to test this
498 SUCCEED( );
499 }
500
501 SECTION( "too few qubits" ) {
502
503 int numQubits = GENERATE( -1, 0 );
504
505 REQUIRE_THROWS_WITH( createSuperOp(numQubits), ContainsSubstring("one or more qubits") );
506 }
507
508 SECTION( "too many qubits" ) {
509
510 REQUIRE_THROWS_WITH( createSuperOp(100), ContainsSubstring("qindex") );
511
512 REQUIRE_THROWS_WITH( createSuperOp(15), ContainsSubstring("size_t") );
513
514 // no overflows, but definitely exceeds local RAM and fails to allocate; frightens address sanitizer!
515 // note the specific error message depends on the what backend the auto-deployer tried to use (e.g.
516 // GPU-accel or distributed) and whether memory-probers realised there was insufficient memory in
517 // advance or whether it proceeded to malloc() which subsequently failed
518 #ifndef SANITIZER_IS_ACTIVE
519 REQUIRE_THROWS_WITH( createSuperOp(12),
520 ContainsSubstring("failed") ||
521 ContainsSubstring("insufficient available memory") ||
522 ContainsSubstring("available GPU memory") ||
523 ContainsSubstring("exceeds that available") );
524 #endif
525 }
526 }
527}
528
529
530TEST_CASE( "syncSuperOp", TEST_CATEGORY ) {
531
532 SECTION( LABEL_CORRECTNESS ) {
533
534 SuperOp op = createSuperOp(1);
535 REQUIRE( *(op.wasGpuSynced) == 0 );
536
537 syncSuperOp(op);
538 REQUIRE( *(op.wasGpuSynced) == 1 );
539
540 // to test that the GPU memory was actually overwritten,
541 // we would need a custom accessor of GPU memory, requiring
542 // the tests are CUDA-compiled - no thank you mam! It is
543 // certain this function works from the other GPU tests.
544
545 destroySuperOp(op);
546 }
547
548 SECTION( LABEL_VALIDATION ) {
549
550 /// @todo fails in MSVC for unknown reason
551 #ifndef _MSC_VER
552 // sanitizer messes with default initialisation
553 #ifndef SANITIZER_IS_ACTIVE
554 SECTION( "not created" ) {
555
556 SuperOp m;
557 REQUIRE_THROWS_WITH( syncSuperOp(m), ContainsSubstring("invalid fields") );
558 }
559 #endif
560 #endif
561 }
562}
563
564
565TEST_CASE( "destroySuperOp", TEST_CATEGORY ) {
566
567 SECTION( LABEL_CORRECTNESS ) {
568
569 SuperOp m = createSuperOp(5);
570 REQUIRE_NOTHROW( destroySuperOp(m) );
571 }
572
573 SECTION( LABEL_VALIDATION ) {
574
575 // sanitizer interferes with un-initialised struct values
576 #ifndef SANITIZER_IS_ACTIVE
577 SECTION( "not created" ) {
578
579 SuperOp m;
580 REQUIRE_THROWS_WITH( destroySuperOp(m), ContainsSubstring("invalid fields") );
581 }
582 #endif
583 }
584}
585
586
587TEST_CASE( "setSuperOp", TEST_CATEGORY ) {
588
589 SECTION( LABEL_CORRECTNESS ) {
590
591 int numQubits = GENERATE( range(1,4) ); // 3qb superop = 6qb matrix = 12qb statevec
592 CAPTURE( numQubits );
593
594 SuperOp op = createSuperOp(numQubits);
595 REQUIRE( *(op.wasGpuSynced) == 0 );
596
597 int dim = getPow2(2 * numQubits);
598 qmatrix ref = getRandomMatrix(dim);
599
600 SECTION( LABEL_C_INTERFACE ) {
601
602 // nested pointers
603 qcomp** ptrs = (qcomp**) malloc(dim * sizeof *ptrs);
604 for (int i=0; i<dim; i++) {
605 ptrs[i] = (qcomp*) malloc(dim * sizeof **ptrs);
606 for (int j=0; j<dim; j++)
607 ptrs[i][j] = ref[i][j];
608 }
609 setSuperOp(op, ptrs);
610 REQUIRE_AGREE( op, ref );
611 REQUIRE( *(op.wasGpuSynced) == 1 );
612
613 // cannot test 2D VLAs in this C++ file
614
615 // cleanup
616 for (int i=0; i<dim; i++)
617 free(ptrs[i]);
618 free(ptrs);
619 }
620
621 SECTION( LABEL_CPP_INTERFACE ) {
622
623 // nested vectors
624 setSuperOp( op, getZeroMatrix(dim) ); // clear
625 setSuperOp( op, ref );
626 REQUIRE_AGREE( op, ref );
627 REQUIRE( *(op.wasGpuSynced) == 1 );
628 }
629
630 destroySuperOp(op);
631 }
632
633 SECTION( LABEL_VALIDATION ) {
634
635 SuperOp op = createSuperOp(1);
636
637 /// @todo fails in MSVC for unknown reason
638 #ifndef _MSC_VER
639 // sanitizer messes with default initialisation
640 #ifndef SANITIZER_IS_ACTIVE
641 SECTION( "not created" ) {
642
643 SuperOp bad;
644 qcomp** dummy;
645 REQUIRE_THROWS_WITH( setSuperOp(bad, dummy), ContainsSubstring("invalid fields") );
646 }
647 #endif
648 #endif
649
650 SECTION( "null pointer" ) {
651
652 qcomp** ptr = nullptr;
653 REQUIRE_THROWS_WITH( setSuperOp(op, ptr), ContainsSubstring("was a null pointer") );
654
655 qcomp* arr[1] = {nullptr};
656 REQUIRE_THROWS_WITH( setSuperOp(op, arr), ContainsSubstring("contained a null pointer") );
657 }
658
659 SECTION( "invalid dimensions" ) {
660
661 // detectable only by the C++ interface
662
663 REQUIRE_NOTHROW( setSuperOp(op, qmatrix(4, qvector(4))) );
664
665 REQUIRE_THROWS_WITH( setSuperOp(op, qmatrix(3, qvector(4))), ContainsSubstring("Incompatible number of rows") );
666 REQUIRE_THROWS_WITH( setSuperOp(op, qmatrix(5, qvector(4))), ContainsSubstring("Incompatible number of rows") );
667
668 REQUIRE_THROWS_WITH( setSuperOp(op, qmatrix(4, qvector(3))), ContainsSubstring("Incompatible number of columns") );
669 REQUIRE_THROWS_WITH( setSuperOp(op, qmatrix(4, qvector(5))), ContainsSubstring("Incompatible number of columns") );
670 }
671
672 destroySuperOp(op);
673 }
674}
675
676
677TEST_CASE( "setInlineSuperOp", TEST_CATEGORY ) {
678
679 SECTION( LABEL_CORRECTNESS ) {
680
681 SuperOp op = createSuperOp(1);
682 REQUIRE( *(op.wasGpuSynced) == 0 );
683
684 // can only check C++ interface
685
686 setInlineSuperOp( op, 1, {{1,2,3,4},{5,6,7,8},{-9,-8,-7,-6},{5_i,4_i,3_i,2_i}} );
687 REQUIRE_AGREE( op, {{1,2,3,4},{5,6,7,8},{-9,-8,-7,-6},{5_i,4_i,3_i,2_i}} );
688 REQUIRE( *(op.wasGpuSynced) == 1 );
689
690 destroySuperOp(op);
691 }
692
693 SECTION( LABEL_VALIDATION ) {
694
695 SuperOp op = createSuperOp(1);
696
697 /// @todo fails in MSVC for unknown reason
698 #ifndef _MSC_VER
699 // sanitizer messes with default initialisation
700 #ifndef SANITIZER_IS_ACTIVE
701 SECTION( "not created" ) {
702
703 SuperOp bad;
704 REQUIRE_THROWS_WITH( setInlineSuperOp(bad, 1, {{}}), ContainsSubstring("invalid fields") );
705 }
706 #endif
707 #endif
708
709 SECTION( "mismatching dimension" ) {
710
711 REQUIRE_THROWS_WITH( setInlineSuperOp(op, 2, {{}}), ContainsSubstring("specified number of qubits") && ContainsSubstring("differs") );
712 }
713
714 SECTION( "invalid dimensions" ) {
715
716 // detectable only by the C++ interface
717
718 REQUIRE_NOTHROW( setInlineSuperOp(op, 1, qmatrix(4, qvector(4))) );
719
720 REQUIRE_THROWS_WITH( setInlineSuperOp(op, 1, qmatrix(3, qvector(4))), ContainsSubstring("Incompatible number of rows") );
721 REQUIRE_THROWS_WITH( setInlineSuperOp(op, 1, qmatrix(5, qvector(4))), ContainsSubstring("Incompatible number of rows") );
722
723 REQUIRE_THROWS_WITH( setInlineSuperOp(op, 1, qmatrix(4, qvector(3))), ContainsSubstring("Incompatible number of columns") );
724 REQUIRE_THROWS_WITH( setInlineSuperOp(op, 1, qmatrix(4, qvector(5))), ContainsSubstring("Incompatible number of columns") );
725 }
726
727 destroySuperOp(op);
728 }
729}
730
731
732TEST_CASE( "createInlineSuperOp", TEST_CATEGORY ) {
733
734 SECTION( LABEL_CORRECTNESS ) {
735
736 SuperOp op = createInlineSuperOp(1, {{1,2,3,4}, {5,6,7,8}, {-9,-8,-7,-6}, {-5_i,-4_i,-3_i,-2_i}});
737 REQUIRE_AGREE( op, {{1,2,3,4}, {5,6,7,8}, {-9,-8,-7,-6}, {-5_i,-4_i,-3_i,-2_i}});
738 REQUIRE( *(op.wasGpuSynced) == 1 );
739
740 destroySuperOp(op);
741 }
742
743 SECTION( LABEL_VALIDATION ) {
744
745 SECTION( "env not initialised" ) {
746
747 // impossible to test
748 SUCCEED( );
749 }
750
751 SECTION( "too few qubits" ) {
752
753 int numQubits = GENERATE( -1, 0 );
754
755 REQUIRE_THROWS_WITH( createInlineSuperOp(numQubits, {{}}), ContainsSubstring("must act upon one or more qubits") );
756 }
757
758 SECTION( "mismatching dimension" ) {
759
760 REQUIRE_THROWS_WITH( createInlineSuperOp(1, {{1,2},{3,4}}), ContainsSubstring("inconsistent with the number of rows") );
761 }
762 }
763}
764
765
766/** @} (end defgroup) */
767
768
769
770/**
771 * @todo
772 * UNTESTED FUNCTIONS
773 */
774
775void reportKrausMap(KrausMap map);
776
777void reportSuperOp(SuperOp op);
KrausMap createInlineKrausMap(int numQubits, int numOperators, std::vector< std::vector< std::vector< qcomp > > > matrices)
SuperOp createInlineSuperOp(int numQubits, std::vector< std::vector< qcomp > > matrix)
KrausMap createKrausMap(int numQubits, int numOperators)
Definition channels.cpp:176
SuperOp createSuperOp(int numQubits)
Definition channels.cpp:162
void destroySuperOp(SuperOp op)
Definition channels.cpp:203
void destroyKrausMap(KrausMap map)
Definition channels.cpp:210
void reportKrausMap(KrausMap map)
Definition channels.cpp:467
void reportSuperOp(SuperOp op)
Definition channels.cpp:447
void setInlineSuperOp(SuperOp op, int numQb, std::vector< std::vector< qcomp > > matrix)
void setInlineKrausMap(KrausMap map, int numQb, int numOps, std::vector< std::vector< std::vector< qcomp > > > matrices)
void setSuperOp(SuperOp op, qcomp **matrix)
Definition channels.cpp:271
void setKrausMap(KrausMap map, qcomp ***matrices)
Definition channels.cpp:309
void syncSuperOp(SuperOp op)
Definition channels.cpp:223
void syncKrausMap(KrausMap map)
Definition channels.cpp:236
QuESTEnv getQuESTEnv()
qmatrix getZeroMatrix(size_t dim)
Definition qmatrix.cpp:18
vector< qmatrix > getRandomKrausMap(int numQb, int numOps)
Definition random.cpp:405
TEST_CASE("createKrausMap", TEST_CATEGORY)
Definition channels.cpp:46