The Quantum Exact Simulation Toolkit v4.3.0
Loading...
Searching...
No Matches
 TEST_CASE ("getPauliStr", TEST_CATEGORY)
 
 TEST_CASE ("getInlinePauliStr", TEST_CATEGORY)
 
 TEST_CASE ("createPauliStrSum", TEST_CATEGORY)
 
 TEST_CASE ("createInlinePauliStrSum", TEST_CATEGORY)
 
 TEST_CASE ("createPauliStrSumFromFile", TEST_CATEGORY)
 
 TEST_CASE ("createPauliStrSumFromReversedFile", TEST_CATEGORY)
 
 TEST_CASE ("destroyPauliStrSum", TEST_CATEGORY)
 
 TEST_CASE ("sortPauliStrSumLexicographic", TEST_CATEGORY)
 
 TEST_CASE ("sortPauliStrSumMagnitude", TEST_CATEGORY)
 

Detailed Description

Function Documentation

◆ TEST_CASE() [1/9]

TEST_CASE ( "createInlinePauliStrSum" ,
TEST_CATEGORY  )

Definition at line 351 of file paulis.cpp.

351 {
352
353 SECTION( LABEL_CORRECTNESS ) {
354
355 // C++ interface does not mandate literal
356
357 SECTION( "pauli parsing" ) {
358
359 // ZYXI
360 unsigned ref = 0 + 1*4 + 2*4*4 + 3*4*4*4;
361 auto str = GENERATE(
362 ".1i ZYXI", ".1I Z Y X I", ".1j ZY X I ",
363 ".1i zyxi", ".1I z y x i", ".1j zy x i ",
364 ".1i 3210", ".1I 3 2 1 0", ".1J 32 1 0 ",
365 ".1i Zy1i", ".1I 3 Y X 0", ".1J Zy 1 I "
366 );
367
369 REQUIRE( sum.strings[0].lowPaulis == ref );
371 }
372
373 SECTION( "coefficient parsing" ) {
374
375 // beware that when QUEST_FLOAT_PRECISION=1, qcomp cannot store smaller than 1E-37 (triggering a validation error)
376 vector<std::string> strs = {"1 X", "0 X", "0.1 X", "5E2-1i X", "-1E-25i X", "1 - 6E-5i X", "-1.5E-15 - 5.123E-30i 0"};
377 vector<qcomp> coeffs = { 1, 0, 0.1, 5E2-1_i, -(1E-25)*1_i, 1 -(6E-5)*1_i, qcomp(-1.5E-15, -5.123E-30) };
378
379 size_t i = GENERATE_REF( range(0, (int) strs.size()) );
380 CAPTURE( strs[i], coeffs[i] );
381
383 REQUIRE_AGREE( sum.coeffs[0], coeffs[i] ); // should be strict
385 }
386
387 SECTION( "newlines" ) {
388
390 + 5E2-1i XYZ
391 - 1E-20i IXY
392 + 1 - 6E-5i IIX
393 0 III
394 5. XXX
395 .5 ZZZ
396 )");
397
398 REQUIRE( sum.numTerms == 6 );
399 REQUIRE( sum.strings[3].lowPaulis == 0ULL );
400 REQUIRE_AGREE( sum.coeffs[5], qcomp(.5,0) ); // should be strict
401
403 }
404 }
405
406 SECTION( LABEL_VALIDATION ) {
407
408 SECTION( "env not init" ) {
409
410 // no way to test this
411 SUCCEED( );
412 }
413
414 SECTION( "empty" ) {
415
416 auto str = GENERATE( "", " ", "\n", " \n " );
417
418 REQUIRE_THROWS_WITH( createInlinePauliStrSum(str), ContainsSubstring("empty") );
419 }
420
421 SECTION( "uninterpretable" ) {
422
423 auto str = GENERATE( "X", "1", "a X", "-1 H", "0 .3", "1 23456" );
424
425 REQUIRE_THROWS_WITH( createInlinePauliStrSum(str), ContainsSubstring("Could not interpret") );
426
427 REQUIRE_NOTHROW( createInlinePauliStrSum("1 2 3") ); // = 1 * YZ and is legal
428 }
429
430 SECTION( "out of range" ) {
431
432 // the max/min qcomp depend upon QUEST_FLOAT_PRECISION but we'll lazily use something even quad-prec cannot store
433 REQUIRE_THROWS_WITH( createInlinePauliStrSum("-1E-9999 XYZ"), ContainsSubstring("exceeds the range which can be stored in a qcomp") );
434 }
435
436 SECTION( "inconsistent number of qubits" ) {
437
438 REQUIRE_THROWS_WITH( createInlinePauliStrSum("3 XYZ \n 2 YX"), ContainsSubstring("inconsistent") );
439 }
440
441 SECTION( "too many qubits" ) {
442
443 // C++ interface permits both literal AND passing existing string
444 std::string str = "1 XXXXXYYYYYZZZZZIIIIIXXXXXYYYYYZZZZZIIIIIXXXXXYYYYYZZZZZIIIIIXXXXX"; // 65 paulis
445
446 REQUIRE_THROWS_WITH( createInlinePauliStrSum(str), ContainsSubstring("exceeds the maximum of 64") );
447 }
448 }
449}
PauliStrSum createInlinePauliStrSum(const char *str)
Definition paulis.cpp:198
void destroyPauliStrSum(PauliStrSum sum)
Definition paulis.cpp:251

◆ TEST_CASE() [2/9]

TEST_CASE ( "createPauliStrSum" ,
TEST_CATEGORY  )

Definition at line 273 of file paulis.cpp.

273 {
274
275 SECTION( LABEL_CORRECTNESS ) {
276
277 // the utilities for automatically checking
278 // correctness of this function would "beg the
279 // question", so we instead compare to a
280 // hardcoded problem solved externally
281
282 int numQubits = 2;
283
284 vector<PauliStr> strings = {
285 getPauliStr("XY", {0,1}),
286 getPauliStr("ZX", {0,1}),
287 getPauliStr("YZ", {0,1})
288 };
289 vector<qcomp> coeffs = {1, 2, 3_i};
290
291 qmatrix ref = {
292 { 0, 3, 2, -1_i},
293 { -3, 0, -1_i, -2},
294 { 2, 1_i, 0, -3},
295 {1_i, -2, 3, 0}};
296
297 SECTION( LABEL_C_INTERFACE ) {
298
299 PauliStrSum sum = createPauliStrSum(strings.data(), coeffs.data(), coeffs.size());
300
301 REQUIRE( sum.numTerms == (qindex) strings.size() );
302 REQUIRE( *(sum.isApproxHermitian) == -1 );
303
304 REQUIRE_AGREE( getMatrix(sum,numQubits), ref );
305
307 }
308
309 SECTION( LABEL_CPP_INTERFACE ) {
310
311 PauliStrSum sum = createPauliStrSum(strings, coeffs);
312
313 REQUIRE( sum.numTerms == (qindex) strings.size() );
314 REQUIRE( *(sum.isApproxHermitian) == -1 );
315
316 REQUIRE_AGREE( getMatrix(sum,numQubits), ref );
317
319 }
320 }
321
322 SECTION( LABEL_VALIDATION ) {
323
324 SECTION( "number of terms" ) {
325
326 int numTerms = GENERATE( -1, 0 );
327
328 REQUIRE_THROWS_WITH( createPauliStrSum(nullptr, nullptr, numTerms), ContainsSubstring("number of terms must be a positive integer") );
329 }
330
331 SECTION( "overflows size_t" ) {
332
333 REQUIRE_THROWS_WITH( createPauliStrSum(nullptr, nullptr, 1LL << 60), ContainsSubstring("overflow size_t") );
334 }
335
336 SECTION( "exceeds memory" ) {
337
338 REQUIRE_THROWS_WITH( createPauliStrSum(nullptr, nullptr, 1LL << 50), ContainsSubstring("cannot fit in the available RAM") );
339 }
340
341 SECTION( "mismatching lengths" ) {
342
343 // specific to the C++ interface
344
345 REQUIRE_THROWS_WITH( createPauliStrSum({}, {.1}), ContainsSubstring("different number of Pauli strings") && ContainsSubstring("coefficients") );
346 }
347 }
348}
PauliStrSum createPauliStrSum(PauliStr *strings, qcomp *coeffs, qindex numTerms)
Definition paulis.cpp:166
PauliStr getPauliStr(const char *paulis, int *indices, int numPaulis)
Definition paulis.cpp:76

◆ TEST_CASE() [3/9]

TEST_CASE ( "createPauliStrSumFromFile" ,
TEST_CATEGORY  )

Definition at line 452 of file paulis.cpp.

452 {
453
454 SECTION( LABEL_CORRECTNESS ) {
455
456 std::string fn = "test.txt";
457
458 // file contents can be identical to createInlinePauliStrSum input above
459 if (getQuESTEnv().rank == 0) {
460 std::ofstream file;
461 file.open(fn);
462 file << R"(
463 + 5E2-1i XYZ
464 - 1E-20i IXY
465 + 1 - 6E-5i IIX
466 0 III
467 5. IXX
468 .5 ZYX
469 )";
470 file.close();
471 }
472
473 // all nodes must wait for root to finish writing
474 syncQuESTEnv();
475
477
478 REQUIRE( sum.strings[0].lowPaulis == 3 + 2*4 + 1*4*4 );
479
480 REQUIRE( sum.numTerms == 6 );
481 REQUIRE( sum.coeffs[0] == qcomp(500, -1) );
482 REQUIRE( sum.strings[3].lowPaulis == 0ULL );
483 REQUIRE( sum.coeffs[5] == qcomp(.5,0) );
484
486 }
487
488 SECTION( LABEL_VALIDATION ) {
489
490 // we skip all tests which overlap createInlinePauliStrSum
491 // above, since the function simplify parses the file then
492 // calls createInlinePauliStrSum(), and writing everything
493 // to file to subsequently test this function is a chore
494
495 SECTION( "bad file name" ) {
QuESTEnv getQuESTEnv()
void syncQuESTEnv()
PauliStrSum createPauliStrSumFromFile(const char *fn)
Definition paulis.cpp:211

◆ TEST_CASE() [4/9]

TEST_CASE ( "createPauliStrSumFromReversedFile" ,
TEST_CATEGORY  )

Definition at line 498 of file paulis.cpp.

505 {
506
507 SECTION( LABEL_CORRECTNESS ) {
508
509 std::string fn = "test.txt";
510
511 // file contents can be identical to createInlinePauliStrSum input above
512 if (getQuESTEnv().rank == 0) {
513 std::ofstream file;
514 file.open(fn);
515 file << R"(
516 + 5E2-1i XYZ
517 - 1E-20i IXY
518 + 1 - 6E-5i IIX
519 0 III
520 5. IXX
521 .5 ZYX
522 )";
523 file.close();
524 }
525
526 // all nodes must wait for root to finish writing
527 syncQuESTEnv();
528
530
531 // reversed order from createPauliStrSumFromFile() above
532 REQUIRE( sum.strings[0].lowPaulis == 1 + 2*4 + 3*4*4 );
533
534 REQUIRE( sum.numTerms == 6 );
535 REQUIRE( sum.coeffs[0] == qcomp(500, -1) );
536 REQUIRE( sum.strings[3].lowPaulis == 0ULL );
537 REQUIRE( sum.coeffs[5] == qcomp(.5,0) );
538
540 }
541
542 SECTION( LABEL_VALIDATION ) {
PauliStrSum createPauliStrSumFromReversedFile(const char *fn)
Definition paulis.cpp:228

◆ TEST_CASE() [5/9]

TEST_CASE ( "destroyPauliStrSum" ,
TEST_CATEGORY  )

Definition at line 545 of file paulis.cpp.

549 {
550
551 auto fn = GENERATE( "", " ", "\n", "nonexistentfile.txt" );
552
553 REQUIRE_THROWS_WITH( createPauliStrSumFromReversedFile(fn), ContainsSubstring("Could not load and read the given file") );
554 }
555 }
556}
557
558
559TEST_CASE( "destroyPauliStrSum", TEST_CATEGORY ) {
560
561 SECTION( LABEL_CORRECTNESS ) {
562
564 REQUIRE_NOTHROW( destroyPauliStrSum(sum) );
565 }
566
567 SECTION( LABEL_VALIDATION ) {
568
569 /// @todo fails in MSVC for unknown reason
570 #ifndef _MSC_VER
571 // sanitizer messes with default initialisation
572 #ifndef SANITIZER_IS_ACTIVE
573 SECTION( "not created" ) {
574
575 PauliStrSum sum;
576
577 // uninitialised sum fields can be coincidentally
578 // valid on some platforms (Github Actions linux
TEST_CASE("getPauliStr", TEST_CATEGORY)
Definition paulis.cpp:53

◆ TEST_CASE() [6/9]

TEST_CASE ( "getInlinePauliStr" ,
TEST_CATEGORY  )

Definition at line 212 of file paulis.cpp.

212 {
213
214 SECTION( LABEL_CORRECTNESS ) {
215
216 PauliStr str;
217 long long unsigned val;
218
219 val = 1 + 2*4 + 3*4*4 + 0*4*4*4;
220 str = getInlinePauliStr("XYZI", {0,1,2,3});
221 REQUIRE( str.lowPaulis == val );
222 str = getInlinePauliStr("xyzi", {0,1,2,3});
223 REQUIRE( str.lowPaulis == val );
224 str = getInlinePauliStr("1230", {0,1,2,3});
225 REQUIRE( str.lowPaulis == val );
226
227 val = (1*4*4*4 + 2*4*4 + 3*4 + 0*4);
228 str = getInlinePauliStr("XYZI", {3,2,1,0});
229 REQUIRE( str.lowPaulis == val );
230 str = getInlinePauliStr("xyzi", {3,2,1,0});
231 REQUIRE( str.lowPaulis == val );
232 str = getInlinePauliStr("1230", {3,2,1,0});
233 REQUIRE( str.lowPaulis == val );
234
235 val *= (1ULL << (2 * (63 - 3 - 32)));
236 str = getInlinePauliStr("XYZ", {63,62,61});
237 REQUIRE( str.highPaulis == val );
238 str = getInlinePauliStr("xyz", {63,62,61});
239 REQUIRE( str.highPaulis == val );
240 str = getInlinePauliStr("123", {63,62,61});
241 REQUIRE( str.highPaulis == val );
242 }
243
244 SECTION( LABEL_VALIDATION ) {
245
246 // here, only the C++ interface can be tested
247
248 SECTION( "invalid target" ) {
249
250 int target = GENERATE( -1, 64, 65, 9999 );
251
252 REQUIRE_THROWS_WITH( getInlinePauliStr("X", {target}), ContainsSubstring("Invalid index") );
253 }
254
255 SECTION( "duplicated target" ) {
256
257 REQUIRE_THROWS_WITH( getInlinePauliStr("XY", {0,0}), ContainsSubstring("duplicate") );
258 }
259
260 SECTION( "string terminated early" ) {
261
262 REQUIRE_THROWS_WITH( getInlinePauliStr("X", {1,2}), ContainsSubstring("different number of Pauli operators") && ContainsSubstring("qubit indices") );
263 }
264
265 SECTION( "unrecognised char" ) {
266
267 REQUIRE_THROWS_WITH( getInlinePauliStr("ABC", {1,2,3}), ContainsSubstring("unrecognised Pauli character") );
268 }
269 }
270}
PauliStr getInlinePauliStr(const char *paulis, { list })

◆ TEST_CASE() [7/9]

TEST_CASE ( "getPauliStr" ,
TEST_CATEGORY  )

TESTS

Definition at line 53 of file paulis.cpp.

53 {
54
55 SECTION( LABEL_CORRECTNESS ) {
56
57 GENERATE( range(0,10) );
58
59 std::string charSet = GENERATE( "IXYZ", "ixyz", "0123", "iX2z" );
60
61 int numPaulis = GENERATE( 1, 2, 5, 10, 20, 30, 31, 32, 33, 60, 64 );
62 auto targets = getRandomSubRange(0, 64, numPaulis);
63
64 // not necessary to add a terminal char when we specify numPaulis
65 vector<char> pauliChars(numPaulis, 'I');
66 vector<int> pauliInts(numPaulis, 0);
67 long long unsigned lowValue = 0;
68 long long unsigned highValue = 0;
69
70 for (int i=0; i<numPaulis; i++) {
71 int v = getRandomInt(1, 3+1);
72 pauliInts[i] = v;
73 pauliChars[i] = charSet[v];
74
75 int t = targets[i];
76 (t < 32)?
77 (lowValue += v * getPow2(2 * t)): // pow4
78 (highValue += v * getPow2(2 * (t-32))); // pow4
79 }
80
81 SECTION( LABEL_C_INTERFACE ) {
82
83 SECTION( "from chars" ) {
84
85 CAPTURE( targets, pauliChars );
86
87 PauliStr str = getPauliStr(pauliChars.data(), targets.data(), numPaulis);
88
89 REQUIRE( str.lowPaulis == lowValue );
90 REQUIRE( str.highPaulis == highValue );
91 }
92
93 SECTION( "from ints" ) {
94
95 CAPTURE( targets, pauliChars );
96
97 PauliStr str = getPauliStr(pauliInts.data(), targets.data(), numPaulis);
98
99 REQUIRE( str.lowPaulis == lowValue );
100 REQUIRE( str.highPaulis == highValue );
101 }
102
103 SECTION( "from literal" ) {
104
105 // lazily ignores some above prepared vars
106
107 int targ = targets[0];
108 CAPTURE( targ );
109
110 const char* in = "X";
111 PauliStr str = getPauliStr(in, &targ, 1);
112 REQUIRE( str.lowPaulis == ((targ < 32)? getPow2(2*targ) : 0) );
113 REQUIRE( str.highPaulis == ((targ >= 32)? getPow2(2*(targ-32)) : 0) );
114 }
115 }
116
117 SECTION( LABEL_CPP_INTERFACE ) {
118
119 // std::string() requires pauliChars includes a terminal char
120 pauliChars.push_back('\0');
121 std::string in = std::string(pauliChars.data());
122
123 SECTION( "from string" ) {
124
125 CAPTURE( targets, pauliChars );
126
127 PauliStr str = getPauliStr(in, targets.data(), numPaulis);
128
129 REQUIRE( str.lowPaulis == lowValue );
130 REQUIRE( str.highPaulis == highValue );
131 }
132
133 SECTION( "from vector" ) {
134
135 CAPTURE( targets, pauliChars );
136
137 PauliStr str = getPauliStr(in, targets);
138
139 REQUIRE( str.lowPaulis == lowValue );
140 REQUIRE( str.highPaulis == highValue );
141 }
142
143 SECTION( "from literal" ) {
144
145 // lazily ignores some above prepared vars
146
147 int targ = targets[0];
148 CAPTURE( targ );
149
150 PauliStr str = getPauliStr("X", &targ, 1);
151 REQUIRE( str.lowPaulis == ((targ < 32)? getPow2(2*targ) : 0) );
152 REQUIRE( str.highPaulis == ((targ >= 32)? getPow2(2*(targ-32)) : 0) );
153 }
154
155 SECTION( "from only string" ) {
156
157 CAPTURE( targets, pauliChars );
158
159 char chars[65]; // 64 + terminal char
160 chars[64] = '\0';
161 for (int i=0; i<64; i++)
162 chars[i] = 'I';
163
164 // string is DECREASING significance
165 for (int i=0; i<numPaulis; i++)
166 chars[64-targets[i]-1] = pauliChars[i];
167
168 std::string all = std::string(chars);
169 PauliStr str = getPauliStr(all);
170
171 CAPTURE( all );
172 REQUIRE( str.lowPaulis == lowValue );
173 REQUIRE( str.highPaulis == highValue );
174 }
175 }
176 }
177
178 SECTION( LABEL_VALIDATION ) {
179
180 SECTION( "invalid target" ) {
181
182 int target = GENERATE( -1, 64, 65, 9999 );
183
184 REQUIRE_THROWS_WITH( getPauliStr("X", {target}), ContainsSubstring("Invalid index") );
185 }
186
187 SECTION( "duplicated target" ) {
188
189 REQUIRE_THROWS_WITH( getPauliStr("XY", {0,0}), ContainsSubstring("duplicate") );
190 }
191
192 SECTION( "invalid number of paulis" ) {
193
194 int numPaulis = GENERATE( -1, 0 );
195
196 REQUIRE_THROWS_WITH( getPauliStr("X", nullptr, numPaulis), ContainsSubstring("must contain at least one Pauli operator") );
197 }
198
199 SECTION( "string terminated early" ) {
200
201 REQUIRE_THROWS_WITH( getPauliStr("X", {1,2}), ContainsSubstring("different number of Pauli operators") && ContainsSubstring("qubit indices") );
202 }
203
204 SECTION( "unrecognised char" ) {
205
206 REQUIRE_THROWS_WITH( getPauliStr("hi", {1,2}), ContainsSubstring("unrecognised Pauli character") );
207 }
208 }
209}
int getRandomInt(int min, int maxExcl)
Definition random.cpp:90

◆ TEST_CASE() [8/9]

TEST_CASE ( "sortPauliStrSumLexicographic" ,
TEST_CATEGORY  )

Definition at line 580 of file paulis.cpp.

594 {
595
596 SECTION( LABEL_CORRECTNESS ) {
597
598 vector<qcomp> coeffs = {0.1_i, 2+1_i, 5, 3+4_i};
599 vector<PauliStr> strings = {
600 getPauliStr("XY", {31,32}),
601 getPauliStr("YX", {0,1}),
602 getPauliStr("II", {0,1}),
603 getPauliStr("YY", {31,32})
604 };
605
606 PauliStrSum sum = createPauliStrSum(strings, coeffs);

◆ TEST_CASE() [9/9]

TEST_CASE ( "sortPauliStrSumMagnitude" ,
TEST_CATEGORY  )

Definition at line 608 of file paulis.cpp.

622 {
623
624 SECTION( LABEL_CORRECTNESS ) {
625
626 vector<qcomp> coeffs = {0.1_i, 2+1_i, 5, 3+4_i};
627 vector<PauliStr> strings = {
628 getPauliStr("XY", {0,1}),
629 getPauliStr("ZX", {0,1}),
630 getPauliStr("II", {0,1}),
631 getPauliStr("YZ", {0,1})
632 };
633