The Quantum Exact Simulation Toolkit v4.3.0
Loading...
Searching...
No Matches
trotterisation.cpp
1/** @file
2 * Unit tests of the trotterisation module.
3 *
4 * @author Tyson Jones
5 * @author Vasco Ferreira (initial Pauli permutation tests)
6 * @author Maurice Jamieson (real and imaginary time evolution tests)
7 * @author Oliver Thomson Brown (real and imaginary time evolution tests)
8 *
9 * @defgroup unittrotter Trotterisation
10 * @ingroup unittests
11 */
12
13#include "quest.h"
14
15#include <catch2/catch_test_macros.hpp>
16#include <catch2/generators/catch_generators_range.hpp>
17#include <catch2/matchers/catch_matchers_floating_point.hpp>
18#include <catch2/matchers/catch_matchers_string.hpp>
19
20#include "tests/utils/macros.hpp"
21#include "tests/utils/cache.hpp"
22#include "tests/utils/compare.hpp"
23#include "tests/utils/random.hpp"
24
25#include <vector>
26#include <string>
27
28using std::vector;
29using std::string;
30using namespace Catch::Matchers;
31
32/*
33 * UTILITIES
34 */
35
36#define TEST_CATEGORY \
37 LABEL_UNIT_TAG "[trotterisation]"
38
39void TEST_ON_CACHED_QUREGS(quregCache quregs, auto& refFunc, auto& regularFunc, auto& randFunc) {
40 for (auto& [label, refQureg]: quregs) {
41
42 DYNAMIC_SECTION( label ) {
43 initDebugState(refQureg);
44
45 Qureg regularQureg = createCloneQureg(refQureg);
46 Qureg randQureg = createCloneQureg(refQureg);
47
48 refFunc(refQureg);
49 regularFunc(regularQureg);
50 randFunc(randQureg);
51
52 double regularDistance = calcDistance(regularQureg, refQureg);
53 double randDistance = calcDistance(randQureg, refQureg);
54
55 REQUIRE( randDistance < regularDistance );
56
57 destroyQureg(regularQureg);
58 destroyQureg(randQureg);
59 }
60 }
61}
62
63void TEST_ON_CACHED_QUREGS(quregCache quregs, qvector& referenceResult, auto& testFunction, PauliStrSum& testHamiltonian) {
64 for (auto& [label, qureg]: quregs) {
65
66 DYNAMIC_SECTION( label ) {
67 testFunction(qureg, testHamiltonian);
68 REQUIRE_AGREE(qureg, referenceResult);
69 }
70
71 }
72
73 return;
74}
75
76void TEST_ON_CACHED_QUREGS(quregCache quregs, qmatrix& referenceResult, auto& testFunction, PauliStrSum& testHamiltonian) {
77 for (auto& [label, qureg]: quregs) {
78
79 DYNAMIC_SECTION( label ) {
80 testFunction(qureg, testHamiltonian);
81 REQUIRE_AGREE(qureg, referenceResult);
82 }
83
84 }
85
86 return;
87}
88
89void TEST_OBSERVABLES_ON_QUREGS(quregCache quregs, qvector& referenceResult, auto& testFunction, PauliStrSum testHamiltonian, PauliStrSum testObservable) {
90 for (auto& [label, qureg]: quregs) {
91
92 DYNAMIC_SECTION( label ) {
93 qvector testResult = testFunction(qureg, testHamiltonian, testObservable);
94 REQUIRE_AGREE(calcTotalProb(qureg), 1.0);
95 REQUIRE_AGREE(testResult, referenceResult);
96 }
97
98 }
99
100 return;
101}
102
103
104/*
105 * Prepare a Hamiltonian H under which dynamical
106 * evolution will be simulated via Trotterisation
107 * of unitary-time evolution operator e^(-itH).
108 * If the Hamiltonian was fixed/known in advance,
109 * we could instead use createInlinePauliStrSum()
110 *
111 * (Adapted from dynamics.cpp, @author Tyson Jones)
112 */
113PauliStrSum createHeisenbergHamiltonian(int numQubits) {
114
115 // we prepare a Heisenberg XYZ spin-ring Hamiltonian,
116 // i.e. H = -1/2 sum( Jx XX + Jy YY + Jz ZZ + h Z )
117 // upon all nearest neighbour qubits, with periodicity.
118 // The coefficients must be real for H to be Hermitian
119 // and ergo its time-evolution operator to be unitary,
120 // although they must be represented with a qcomp type.
121 vector<string> operators = {"XX", "YY", "ZZ", "Z"};
122 vector<qcomp> coefficients = {.1, .2, .3, .4}; // Jx,Jy,Jz,h
123
124 // we will populate the below vectors with 4*numQubits
125 // elements which we could pre-allocate with .reserve,
126 // but we might incur Donald Knuth's justified wrath.
127 vector<PauliStr> allStrings;
128 vector<qcomp> allCoeffs;
129
130 // prepare all XX + YY + ZZ
131 for (int p=0; p<3; p++) {
132 for (int i=0; i<numQubits; i++) {
133
134 // A_i, A_i+1
135 vector<int> targs = {i, (i+1)%numQubits};
136 PauliStr str = getPauliStr(operators[p], targs);
137
138 allStrings.push_back(str);
139 allCoeffs.push_back(coefficients[p]);
140 }
141 }
142
143 // prepare Z
144 for (int i=0; i<numQubits; i++) {
145 allStrings.push_back(getPauliStr(operators[3], {i}));
146 allCoeffs.push_back(coefficients[3]);
147 }
148
149 // must be freed by caller
150 return createPauliStrSum(allStrings, allCoeffs);
151}
152
153/*
154 * Prepare the observable operator O under which the
155 * evolved state (under H above) will be measured.
156 * If this were one term (a single tensor product of
157 * Pauli operators), we could return instead a PauliStr
158 * but we here return an arbitrary weighted sum thereof.
159 *
160 * (Adapted from dynamics.cpp, @author Tyson Jones)
161 */
162PauliStrSum createAlternatingPauliObservable(int numQubits) {
163
164 // we prepare a weighted sum of alternating Paulis
165 // upon each qubit, i.e. 1 X0 + 2 Y1 + 3 Z2 + 1 X3 + ...
166 // where the coefficients are real such that the
167 // output observable is Hermitian.
168
169 vector<PauliStr> strings(numQubits);
170 vector<qcomp> coeffs(numQubits);
171
172 for (int i=0; i<numQubits; i++) {
173 strings[i] = getPauliStr({"XYZ"[i%3]}, {i});
174 coeffs[i] = getQcomp(i%4 + 1, 0);
175 }
176
177 // must be freed by caller
178 return createPauliStrSum(strings, coeffs);
179}
180
181/*
182 * Constructs a PauliStrSum representing a 1D Hamiltonian of the form
183 * H = - \mu \sum^{N}_{j} Z_{j} - J \sum_{<ij>}^{N} Z_{i}Z_{j}
184 * where,
185 * \mu = magField,
186 * J = interactionStrength,
187 * <ij> indicates nearest-neighbour interactions only,
188 * and boundary conditions are periodic such that site N-1 interacts with site 0.
189 *
190 * The asymmetricBias term can be used to break the symmetry of the system
191 * in order to 'choose' a preferred antiferromagnetic state, and ensure repeatable
192 * predictable outcomes.
193 * It adds a term of the form:
194 * -BZ_{0}
195 */
196PauliStrSum createIsingHamiltonian(int numQubits, qreal magField,
197 qreal interactionStrength, qreal asymmetricBias) {
198 const int NTERMS = 2 * numQubits + 1;
199
200 vector<qcomp> coeffs;
201 vector<PauliStr> pauli_terms;
202 coeffs.reserve(NTERMS);
203 pauli_terms.reserve(NTERMS);
204
205 for (int i = 0; i < numQubits; ++i) {
206 pauli_terms.push_back(getPauliStr("Z", {i}));
207 coeffs.push_back(getQcomp(-magField, 0));
208
209 int next = (i + 1) % numQubits;
210 pauli_terms.push_back(getPauliStr("ZZ", {i, next}));
211 coeffs.push_back(getQcomp(-interactionStrength, 0));
212 }
213
214 pauli_terms.push_back(getPauliStr("Z", {0}));
215 coeffs.push_back(getQcomp(-asymmetricBias, 0));
216
217 return createPauliStrSum(pauli_terms, coeffs);
218}
219
220
221/*
222 * TESTS
223 */
224
225
226/**
227 * @todo
228 * Basic validation for randomisation, should be expanded and merged
229 * once the Trotterisation function tests have been implemented.
230 */
231TEST_CASE( "randomisedTrotter", TEST_CATEGORY ) {
232
233 SECTION( LABEL_CORRECTNESS ) {
234
235 int numQubits = getNumCachedQubits();
236 int numTerms = 25;
237 int reps = 50;
238 double time = 1.0;
239
240 int refOrder = 4;
241 int order = GENERATE_COPY(1, 2);
242
243 GENERATE( range(0, 10) );
244 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
245
246 auto refFunc = [&](Qureg qureg) { applyTrotterizedUnitaryTimeEvolution(qureg, sum, time, refOrder, reps, false); };
247 auto regularFunc = [&](Qureg qureg) { applyTrotterizedUnitaryTimeEvolution(qureg, sum, time, order, reps, false); };
248 auto randFunc = [&](Qureg qureg) { applyTrotterizedUnitaryTimeEvolution(qureg, sum, time, order, reps, true); };
249
250 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), refFunc, regularFunc, randFunc);
251 TEST_ON_CACHED_QUREGS(getCachedStatevecs(), refFunc, regularFunc, randFunc);
252
254
255 }
256}
257
258/*
259* Time evolution tests
260* @todo Add Pauli permutation variants
261*/
262TEST_CASE( "applyTrotterizedUnitaryTimeEvolution", TEST_CATEGORY ) {
263
264 SECTION( LABEL_CORRECTNESS ) {
265 // nudge the epsilon used by internal validation functions up a bit
266 // as the time evolution operation plays badly with single precision
267 // Defaults for validation epsilon are:
268 // - 1E-5 at single precision
269 // - 1E-12 at double precision
270 // - 1E-13 at quad precision
271 qreal initialValidationEps = getQuESTValidationEpsilon();
272 setQuESTValidationEpsilon(2 * initialValidationEps);
273
274 const int NUM_QUBITS = 8;
275 qreal dt = 0.1;
276 int order = 4;
277 int reps = 5;
278 const int STEPS = 20;
279 bool permutePaulis = GENERATE(true, false);
280
281 auto unitaryTimeEvoFunc =
282 [dt, order, reps, STEPS, permutePaulis](Qureg qureg, PauliStrSum& hamil, PauliStrSum& observable)
283 -> qvector {
284 qvector observations = getZeroVector(STEPS);
285 initPlusState(qureg);
286
287 for (int i = 0; i < STEPS; i++) {
288 applyTrotterizedUnitaryTimeEvolution(qureg, hamil, dt, order, reps, permutePaulis);
289 observations.at(i) = calcExpecPauliStrSum(qureg, observable);
290 }
291
292 return observations;
293 };
294
295 PauliStrSum hamil = createHeisenbergHamiltonian(NUM_QUBITS);
296 PauliStrSum observ = createAlternatingPauliObservable(NUM_QUBITS);
297
298 qvector refObservables = {
299 8.521995598825049,
300 8.963711845322115,
301 9.32005226684505,
302 9.587768088649602,
303 9.765522600223822,
304 9.85387668440598,
305 9.855195944206464,
306 9.773484879367675,
307 9.614158409472378,
308 9.383765238225045,
309 9.089680663909942,
310 8.739788123639109,
311 8.342168826039893,
312 7.904817272753528,
313 7.435397472039873,
314 6.94105054616863,
315 6.428259679798389,
316 5.90277345392904,
317 5.369584051930907,
318 4.832953030744839
319 };
320
321 SECTION("Time Evolve Statevectors") {
322 quregCache eightQubitSVCache = createCustomCachedQuregs(NUM_QUBITS, false);
323 TEST_OBSERVABLES_ON_QUREGS(eightQubitSVCache, refObservables, unitaryTimeEvoFunc, hamil, observ);
324 destroyCustomCachedQuregs(eightQubitSVCache);
325 }
326
327 SECTION("Time Evolve Density Matrices") {
328 quregCache eightQubitDMCache = createCustomCachedQuregs(NUM_QUBITS, true);
329 TEST_OBSERVABLES_ON_QUREGS(eightQubitDMCache, refObservables, unitaryTimeEvoFunc, hamil, observ);
330 destroyCustomCachedQuregs(eightQubitDMCache);
331 }
332
333 // Restore validation epsilon
334 setQuESTValidationEpsilon(initialValidationEps);
335
336 destroyPauliStrSum(hamil);
337 destroyPauliStrSum(observ);
338 }
339
340 SECTION( LABEL_VALIDATION ) {
341
342 Qureg qureg = getArbitraryCachedStatevec();
343 PauliStrSum hamil = createHeisenbergHamiltonian(qureg.numQubits);
344 bool permuteTerms = false;
345
346 SECTION( "qureg uninitialised" ) {
347
348 Qureg badQureg = qureg;
349 badQureg.numQubits = -1;
350 REQUIRE_THROWS_WITH(
351 applyTrotterizedUnitaryTimeEvolution(badQureg, hamil, 0.1, 4, 5, permuteTerms),
352 ContainsSubstring("invalid Qureg")
353 );
354 }
355
356 SECTION( "pauli sum uninitialized" ) {
357
358 PauliStrSum badHamil = hamil;
359 badHamil.numTerms = 0;
360 REQUIRE_THROWS_WITH(
361 applyTrotterizedUnitaryTimeEvolution(qureg, badHamil, 0.1, 4, 5, permuteTerms),
362 ContainsSubstring("Pauli")
363 );
364 }
365
366 SECTION( "hamiltonian not hermitian" ) {
367
368 vector<PauliStr> strings;
369 vector<qcomp> coeffs;
370 strings.push_back(getPauliStr("X", {0}));
371 coeffs.push_back(getQcomp(1.0, 1.0));
372 PauliStrSum nonHermitian = createPauliStrSum(strings, coeffs);
373
374 REQUIRE_THROWS_WITH(
375 applyTrotterizedUnitaryTimeEvolution(qureg, nonHermitian, 0.1, 4, 5, permuteTerms),
376 ContainsSubstring("Hermitian")
377 );
378 destroyPauliStrSum(nonHermitian);
379 }
380
381 SECTION( "pauli sum exceeds qureg qubits" ) {
382
383 PauliStrSum largeHamil = createHeisenbergHamiltonian(qureg.numQubits + 1);
384 REQUIRE_THROWS_WITH(
385 applyTrotterizedUnitaryTimeEvolution(qureg, largeHamil, 0.1, 4, 5, permuteTerms),
386 ContainsSubstring("only compatible")
387 );
388 destroyPauliStrSum(largeHamil);
389 }
390
391 SECTION( "invalid trotter order (zero)" ) {
392
393 REQUIRE_THROWS_WITH(
394 applyTrotterizedUnitaryTimeEvolution(qureg, hamil, 0.1, 0, 5, permuteTerms),
395 ContainsSubstring("order")
396 );
397 }
398
399 SECTION( "invalid trotter order (negative)" ) {
400
401 REQUIRE_THROWS_WITH(
402 applyTrotterizedUnitaryTimeEvolution(qureg, hamil, 0.1, -2, 5, permuteTerms),
403 ContainsSubstring("order")
404 );
405 }
406
407 SECTION( "invalid trotter order (odd, not 1)" ) {
408
409 REQUIRE_THROWS_WITH(
410 applyTrotterizedUnitaryTimeEvolution(qureg, hamil, 0.1, 3, 5, permuteTerms),
411 ContainsSubstring("order")
412 );
413 }
414
415 SECTION( "invalid trotter reps (zero)" ) {
416
417 REQUIRE_THROWS_WITH(
418 applyTrotterizedUnitaryTimeEvolution(qureg, hamil, 0.1, 4, 0, permuteTerms),
419 ContainsSubstring("repetitions")
420 );
421 }
422
423 SECTION( "invalid trotter reps (negative)" ) {
424
425 REQUIRE_THROWS_WITH(
426 applyTrotterizedUnitaryTimeEvolution(qureg, hamil, 0.1, 4, -3, permuteTerms),
427 ContainsSubstring("repetitions")
428 );
429 }
430
431 SECTION( "sum ordering allocation failure" ) {
432
433 // there is no reliable way to force the allocs to fail
434 SUCCEED( );
435 }
436
437 destroyPauliStrSum(hamil);
438 }
439}
440
441
442TEST_CASE( "applyTrotterizedImaginaryTimeEvolution", TEST_CATEGORY ) {
443 int numQubits = getNumCachedQubits();
444 auto statevecQuregs = getCachedStatevecs();
445 auto densmatrQuregs = getCachedDensmatrs();
446
447 SECTION( LABEL_CORRECTNESS ) {
448
449 qreal tau = 0.1;
450 int order = 6;
451 int reps = 5;
452 int steps = 10;
453 bool permutePaulis = GENERATE(true, false);
454
455 auto driveToGroundFunc = [steps, tau, order, reps, permutePaulis](Qureg qureg, PauliStrSum& hamil) {
456 initPlusState(qureg);
457
458 for (int i = 0; i < steps; ++i) {
459 applyTrotterizedImaginaryTimeEvolution(qureg, hamil, tau, order, reps, permutePaulis);
461 }
462 };
463
464
465#if QUEST_FLOAT_PRECISION == 4
466 /*
467 * The numerical exponent is sufficiently inaccurate to breach the default
468 * tolerances at quad precision, so we apply the following kludge to prevent irritating test failures.
469 * The real lessons from these tests are:
470 * - Don't do time-evolution at single precision.
471 * - Don't do time-evolution in serial.
472 */
473
474 qreal initialEps = getTestAbsoluteEpsilon();
475 setTestAbsoluteEpsilon(300 * initialEps);
476#endif
477
478
479 // Ground state: all qubits align down (driven by strong magnetic field)
480 SECTION("Spin Down Field")
481 {
482 PauliStrSum ising = createIsingHamiltonian(numQubits, 10.0, 0.0, 0.0);
483
484 qvector statevecRef = getZeroVector(getPow2(numQubits));
485 statevecRef.at(0) = 1;
486
487 qmatrix densmatrRef = getZeroMatrix(getPow2(numQubits));
488 densmatrRef[0][0] = 1;
489
490 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, driveToGroundFunc, ising);
491 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, driveToGroundFunc, ising);
492
493 destroyPauliStrSum(ising);
494 }
495
496 // Ground state: all qubits align up (driven by opposite magnetic field)
497 SECTION("Spin Up Field")
498 {
499 PauliStrSum ising = createIsingHamiltonian(numQubits, -10.0, 0.0, 0.0);
500
501 qindex namps = getPow2(numQubits);
502
503 qvector statevecRef = getZeroVector(namps);
504 statevecRef.at(namps - 1) = 1;
505
506 qmatrix densmatrRef = getZeroMatrix(namps);
507 densmatrRef[namps-1][namps-1] = 1;
508
509 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, driveToGroundFunc, ising);
510 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, driveToGroundFunc, ising);
511
512 destroyPauliStrSum(ising);
513 }
514
515 // Ground state: all qubits align down (driven by ferromagnetic interactions and bias)
516 SECTION("Ferromagnetic Interaction")
517 {
518 PauliStrSum ising = createIsingHamiltonian(numQubits, 0.0, 10.0, 10.0);
519
520 qvector statevecRef = getZeroVector(getPow2(numQubits));
521 statevecRef.at(0) = 1;
522
523 qmatrix densmatrRef = getZeroMatrix(getPow2(numQubits));
524 densmatrRef[0][0] = 1;
525
526 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, driveToGroundFunc, ising);
527 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, driveToGroundFunc, ising);
528
529 destroyPauliStrSum(ising);
530 }
531
532 // Ground state: alternating pattern (driven by antiferromagnetic interactions)
533 SECTION("Antiferromagnetic Interaction")
534 {
535 PauliStrSum ising = createIsingHamiltonian(numQubits, 0.0, -10.0, 10.0);
536
537 // This should correctly pick out the non-zero amplitude
538 // Qubit 0 is always 0 thanks to asymmetric bias
539 unsigned long long idx = 0;
540 for (int i = 0; i < numQubits / 2; ++i) {
541 idx += (1ULL << (2*i + 1));
542 }
543
544 qvector statevecRef = getZeroVector(getPow2(numQubits));
545 statevecRef.at(idx) = 1;
546
547 qmatrix densmatrRef = getZeroMatrix(getPow2(numQubits));
548 densmatrRef[idx][idx] = 1;
549
550 TEST_ON_CACHED_QUREGS(statevecQuregs, statevecRef, driveToGroundFunc, ising);
551 TEST_ON_CACHED_QUREGS(densmatrQuregs, densmatrRef, driveToGroundFunc, ising);
552
553 destroyPauliStrSum(ising);
554 }
555
556#if QUEST_FLOAT_PRECISION == 4
557 setTestEpsilon(initialEps);
558#endif
559 }
560
561 SECTION( LABEL_VALIDATION ) {
562
563 Qureg qureg = getArbitraryCachedStatevec();
564 PauliStrSum ising = createIsingHamiltonian(qureg.numQubits, 1.0, 1.0, 0.0);
565 bool permuteTerms = false;
566
567 SECTION( "qureg uninitialised" ) {
568
569 Qureg badQureg = qureg;
570 badQureg.numQubits = -1;
571 REQUIRE_THROWS_WITH(
572 applyTrotterizedImaginaryTimeEvolution(badQureg, ising, 0.1, 4, 5, permuteTerms),
573 ContainsSubstring("invalid Qureg")
574 );
575 }
576
577 SECTION( "pauli sum uninitialized" ) {
578
579 PauliStrSum badIsing = ising;
580 badIsing.numTerms = 0;
581 REQUIRE_THROWS_WITH(
582 applyTrotterizedImaginaryTimeEvolution(qureg, badIsing, 0.1, 4, 5, permuteTerms),
583 ContainsSubstring("Pauli")
584 );
585 }
586
587 SECTION( "pauli sum exceeds qureg qubits" ) {
588
589 PauliStrSum largeIsing = createIsingHamiltonian(qureg.numQubits+1, 1.0, 1.0, 0.0);
590 REQUIRE_THROWS_WITH(
591 applyTrotterizedImaginaryTimeEvolution(qureg, largeIsing, 0.1, 4, 5, permuteTerms),
592 ContainsSubstring("only compatible")
593 );
594 destroyPauliStrSum(largeIsing);
595 }
596
597 SECTION( "hamiltonian not hermitian" ) {
598
599 vector<PauliStr> strings;
600 vector<qcomp> coeffs;
601 strings.push_back(getPauliStr("X", {0}));
602 coeffs.push_back(getQcomp(1.0, 1.0));
603 PauliStrSum nonHermitian = createPauliStrSum(strings, coeffs);
604
605 REQUIRE_THROWS_WITH(
606 applyTrotterizedImaginaryTimeEvolution(qureg, nonHermitian, 0.1, 4, 5, permuteTerms),
607 ContainsSubstring("Hermitian")
608 );
609 destroyPauliStrSum(nonHermitian);
610 }
611
612 SECTION( "invalid trotter order (zero)" ) {
613
614 REQUIRE_THROWS_WITH(
615 applyTrotterizedImaginaryTimeEvolution(qureg, ising, 0.1, 0, 5, permuteTerms),
616 ContainsSubstring("order")
617 );
618 }
619
620 SECTION( "invalid trotter order (negative)" ) {
621
622 REQUIRE_THROWS_WITH(
623 applyTrotterizedImaginaryTimeEvolution(qureg, ising, 0.1, -2, 5, permuteTerms),
624 ContainsSubstring("order")
625 );
626 }
627
628 SECTION( "invalid trotter order (odd, not 1)" ) {
629
630 REQUIRE_THROWS_WITH(
631 applyTrotterizedImaginaryTimeEvolution(qureg, ising, 0.1, 3, 5, permuteTerms),
632 ContainsSubstring("order")
633 );
634 }
635
636 SECTION( "invalid trotter reps (zero)" ) {
637
638 REQUIRE_THROWS_WITH(
639 applyTrotterizedImaginaryTimeEvolution(qureg, ising, 0.1, 4, 0, permuteTerms),
640 ContainsSubstring("repetitions")
641 );
642 }
643
644 SECTION( "invalid trotter reps (negative)" ) {
645
646 REQUIRE_THROWS_WITH(
647 applyTrotterizedImaginaryTimeEvolution(qureg, ising, 0.1, 4, -3, permuteTerms),
648 ContainsSubstring("repetitions")
649 );
650 }
651
652 SECTION( "sum ordering allocation failure" ) {
653
654 // there is no reliable way to force the allocs to fail
655 SUCCEED( );
656 }
657
658 destroyPauliStrSum(ising);
659 }
660}
661
662
663/**
664 * @todo
665 * UNTESTED FUNCTIONS (NOT YET VALIDATED BY REFERENCE TESTS)
666 */
667
668void applyTrotterizedNonUnitaryPauliStrSumGadget(Qureg qureg, PauliStrSum sum, qcomp angle, int order, int reps, bool permuteTerms);
669
670void applyTrotterizedPauliStrSumGadget(Qureg qureg, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms);
671
672void applyTrotterizedControlledPauliStrSumGadget(Qureg qureg, int control, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms);
673
674void applyTrotterizedMultiControlledPauliStrSumGadget(Qureg qureg, int* controls, int numControls, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms);
675
676void applyTrotterizedMultiStateControlledPauliStrSumGadget(Qureg qureg, int* controls, int* states, int numControls, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms);
677
678void applyTrotterizedNoisyTimeEvolution(Qureg qureg, PauliStrSum hamil, qreal* damps, PauliStr* jumps, int numJumps, qreal time, int order, int reps, bool permuteTerms);
qreal calcDistance(Qureg qureg, Qureg other)
qreal calcExpecPauliStrSum(Qureg qureg, PauliStrSum sum)
qreal calcTotalProb(Qureg qureg)
qreal getQuESTValidationEpsilon()
Definition debug.cpp:115
void setQuESTValidationEpsilon(qreal eps)
Definition debug.cpp:100
qreal setQuregToRenormalized(Qureg qureg)
void initPlusState(Qureg qureg)
void initDebugState(Qureg qureg)
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
void destroyPauliStrSum(PauliStrSum sum)
Definition paulis.cpp:251
Qureg createCloneQureg(Qureg qureg)
Definition qureg.cpp:325
void destroyQureg(Qureg qureg)
Definition qureg.cpp:340
qmatrix getZeroMatrix(size_t dim)
Definition qmatrix.cpp:18
void applyTrotterizedMultiControlledPauliStrSumGadget(Qureg qureg, int *controls, int numControls, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms)
void applyTrotterizedPauliStrSumGadget(Qureg qureg, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms)
void applyTrotterizedControlledPauliStrSumGadget(Qureg qureg, int control, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms)
void applyTrotterizedNonUnitaryPauliStrSumGadget(Qureg qureg, PauliStrSum sum, qcomp angle, int order, int reps, bool permuteTerms)
void applyTrotterizedMultiStateControlledPauliStrSumGadget(Qureg qureg, int *controls, int *states, int numControls, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms)
void applyTrotterizedNoisyTimeEvolution(Qureg qureg, PauliStrSum hamil, qreal *damps, PauliStrSum *jumps, int numJumps, qreal time, int order, int reps, bool permuteTerms)
void applyTrotterizedUnitaryTimeEvolution(Qureg qureg, PauliStrSum hamil, qreal time, int order, int reps, bool permuteTerms)
void applyTrotterizedImaginaryTimeEvolution(Qureg qureg, PauliStrSum hamil, qreal tau, int order, int reps, bool permuteTerms)
static qcomp getQcomp(qreal re, qreal im)
Definition types.h:91
TEST_CASE("calcExpecPauliStr", TEST_CATEGORY)
Definition qureg.h:49