The Quantum Exact Simulation Toolkit v4.2.0
Loading...
Searching...
No Matches
Initialisation
 TEST_CASE ("initBlankState", TEST_CATEGORY)
 
 TEST_CASE ("initZeroState", TEST_CATEGORY)
 
 TEST_CASE ("initPlusState", TEST_CATEGORY)
 
 TEST_CASE ("initClassicalState", TEST_CATEGORY)
 
 TEST_CASE ("initDebugState", TEST_CATEGORY)
 
 TEST_CASE ("initRandomPureState", TEST_CATEGORY)
 
 TEST_CASE ("initRandomMixedState", TEST_CATEGORY)
 
 TEST_CASE ("initArbitraryPureState", TEST_CATEGORY)
 
 TEST_CASE ("setQuregAmps", TEST_CATEGORY)
 
 TEST_CASE ("setDensityQuregFlatAmps", TEST_CATEGORY)
 
 TEST_CASE ("setDensityQuregAmps", TEST_CATEGORY)
 
 TEST_CASE ("setQuregToRenormalized", TEST_CATEGORY)
 
 TEST_CASE ("setQuregToPauliStrSum", TEST_CATEGORY)
 
 TEST_CASE ("setQuregToWeightedSum", TEST_CATEGORY)
 
 TEST_CASE ("setQuregToMixture", TEST_CATEGORY)
 

Detailed Description

Function Documentation

◆ TEST_CASE() [1/15]

TEST_CASE ( "initArbitraryPureState" ,
TEST_CATEGORY  )

Definition at line 227 of file initialisations.cpp.

227 {
228
229 SECTION( LABEL_CORRECTNESS ) {
230
231 // works for unnormalised states
232 qvector refVec = getRandomVector(getPow2(getNumCachedQubits()));
233 qmatrix refMat = getOuterProduct(refVec, refVec);
234
235 auto apiFunc = [&](Qureg qureg) { initArbitraryPureState(qureg, refVec.data()); };
236
237 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), apiFunc, refVec); }
238 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFunc, refMat); }
239 }
240
241 /// @todo input validation
242}
void initArbitraryPureState(Qureg qureg, qcomp *amps)
Definition qureg.h:49

◆ TEST_CASE() [2/15]

TEST_CASE ( "initBlankState" ,
TEST_CATEGORY  )

TESTS

Definition at line 75 of file initialisations.cpp.

75 {
76
77 SECTION( LABEL_CORRECTNESS ) {
78
79 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), initBlankState, getRefStatevec()); }
80 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), initBlankState, getRefDensmatr()); }
81 }
82
83 /// @todo input validation
84}
void initBlankState(Qureg qureg)

◆ TEST_CASE() [3/15]

TEST_CASE ( "initClassicalState" ,
TEST_CATEGORY  )

Definition at line 121 of file initialisations.cpp.

121 {
122
123 SECTION( LABEL_CORRECTNESS ) {
124
125 int numQubits = getNumCachedQubits();
126 int numInds = (int) getPow2(numQubits);
127 int stateInd = GENERATE_COPY( range(0,numInds) );
128
129 qvector refVec = getRefStatevec(); refVec[stateInd] = 1; // |i> = {0, ..., 1, 0, ...}
130 qmatrix refMat = getRefDensmatr(); refMat[stateInd][stateInd] = 1; // |i><i|
131
132 auto apiFunc = [&](Qureg qureg) { initClassicalState(qureg, stateInd); };
133
134 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), apiFunc, refVec); }
135 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFunc, refMat); }
136 }
137
138 /// @todo input validation
139}
void initClassicalState(Qureg qureg, qindex stateInd)

◆ TEST_CASE() [4/15]

TEST_CASE ( "initDebugState" ,
TEST_CATEGORY  )

Definition at line 142 of file initialisations.cpp.

142 {
143
144 SECTION( LABEL_CORRECTNESS ) {
145
146 qvector refVec = getRefStatevec(); setToDebugState(refVec); // |debug>
147 qmatrix refMat = getRefDensmatr(); setToDebugState(refMat); // ||debug>>
148
149 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), initDebugState, refVec); }
150 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), initDebugState, refMat); }
151 }
152
153 /// @todo input validation
154}
void initDebugState(Qureg qureg)

◆ TEST_CASE() [5/15]

TEST_CASE ( "initPlusState" ,
TEST_CATEGORY  )

Definition at line 102 of file initialisations.cpp.

102 {
103
104 SECTION( LABEL_CORRECTNESS ) {
105
106 int numQubits = getNumCachedQubits();
107 qreal vecElem = 1. / std::sqrt(getPow2(numQubits));
108 qreal matElem = 1. / getPow2(numQubits);
109
110 qvector refVec = getConstantVector(getPow2(numQubits), vecElem); // |+> = 1/sqrt(2^N) {1, ...}
111 qmatrix refMat = getConstantMatrix(getPow2(numQubits), matElem); // |+><+| = 1/2^N {{1, ...}, ...}
112
113 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), initPlusState, refVec); }
114 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), initPlusState, refMat); }
115 }
116
117 /// @todo input validation
118}
void initPlusState(Qureg qureg)

◆ TEST_CASE() [6/15]

TEST_CASE ( "initRandomMixedState" ,
TEST_CATEGORY  )

Definition at line 190 of file initialisations.cpp.

190 {
191
192 SECTION( LABEL_CORRECTNESS ) {
193
194 // this test does not use reference states
195
196 GENERATE( range(0,10) );
197 int numPureStates = GENERATE( 1, 2, 10 );
198
199 auto testFunc = [&](Qureg qureg) {
200
201 initRandomMixedState(qureg, numPureStates);
202
203 /// @todo
204 /// these not-all-same-amp checks can be made much more rigorous,
205 /// by e.g. asserting distinct nodes haven't generated all the same
206 /// amplitudes (we currently observe this by eye)
207 syncQuregFromGpu(qureg);
208 REQUIRE( qureg.cpuAmps[0] != qureg.cpuAmps[1] ); // performed on all nodes
209
210 qreal prob = calcTotalProb(qureg);
211 REQUIRE_AGREE( prob, 1 );
212
213 qreal purity = calcPurity(qureg);
214 if (numPureStates == 1)
215 REQUIRE_AGREE( purity, 1 );
216 else
217 REQUIRE( purity < 1 );
218 };
219
220 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), testFunc); }
221 }
222
223 /// @todo input validation
224}
qreal calcPurity(Qureg qureg)
qreal calcTotalProb(Qureg qureg)
void initRandomMixedState(Qureg qureg, qindex numPureStates)
void syncQuregFromGpu(Qureg qureg)
Definition qureg.cpp:403

◆ TEST_CASE() [7/15]

TEST_CASE ( "initRandomPureState" ,
TEST_CATEGORY  )

Definition at line 157 of file initialisations.cpp.

157 {
158
159 SECTION( LABEL_CORRECTNESS ) {
160
161 // this test does not use reference states
162 GENERATE( range(0,10) );
163
164 auto testFunc = [&](Qureg qureg) {
165
166 initRandomPureState(qureg);
167
168 /// @todo
169 /// these not-all-same-amp checks can be made much more rigorous,
170 /// by e.g. asserting distinct nodes haven't generated all the same
171 /// amplitudes (we currently observe this by eye)
172 syncQuregFromGpu(qureg);
173 REQUIRE( qureg.cpuAmps[0] != qureg.cpuAmps[1] );
174
175 qreal prob = calcTotalProb(qureg);
176 REQUIRE_AGREE( prob, 1 );
177
178 qreal purity = calcPurity(qureg);
179 REQUIRE_AGREE( purity, 1 );
180 };
181
182 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), testFunc); }
183 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), testFunc); }
184 }
185
186 /// @todo input validation
187}
void initRandomPureState(Qureg qureg)

◆ TEST_CASE() [8/15]

TEST_CASE ( "initZeroState" ,
TEST_CATEGORY  )

Definition at line 87 of file initialisations.cpp.

87 {
88
89 SECTION( LABEL_CORRECTNESS ) {
90
91 qvector refVec = getRefStatevec(); refVec[0] = 1; // |0> = {1, 0...}
92 qmatrix refMat = getRefDensmatr(); refMat[0][0] = 1; // |0><0| = {{1,0...},{0...}...}
93
94 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), initZeroState, refVec); }
95 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), initZeroState, refMat); }
96 }
97
98 /// @todo input validation
99}
void initZeroState(Qureg qureg)

◆ TEST_CASE() [9/15]

TEST_CASE ( "setDensityQuregAmps" ,
TEST_CATEGORY  )

Definition at line 316 of file initialisations.cpp.

316 {
317
318 SECTION( LABEL_CORRECTNESS ) {
319
320 int numTotalRowsCols = getPow2(getNumCachedQubits());
321
322 // systematic iteration is WAY too slow
323 GENERATE( range(0,1000) );
324 int numSetRows = getRandomInt(1, numTotalRowsCols+1);
325 int numSetCols = getRandomInt(1, numTotalRowsCols+1);
326 int startRow = getRandomInt(0, numTotalRowsCols - numSetRows);
327 int startCol = getRandomInt(0, numTotalRowsCols - numSetCols);
328
329 // caution that amps is 'qmatrix' despite not being square
330 qmatrix amps = getRandomNonSquareMatrix(numSetRows, numSetCols);
331
332 auto testFunc = [&](Qureg qureg) {
333
334 // initialise qureg randomly
335 qmatrix refMat = getRandomMatrix(numTotalRowsCols);
336 setQuregToReference(qureg, refMat);
337
338 // API needs nested pointers
339 std::vector<qcomp*> rowPtrs(numSetRows);
340 for (size_t r=0; r<numSetRows; r++)
341 rowPtrs[r] = amps[r].data();
342
343 // overwrite a sub-matrix of refMat and Qureg
344 setSubMatrix(refMat, amps, startRow, startCol);
345 setDensityQuregAmps(qureg, startRow, startCol, rowPtrs.data(), numSetRows, numSetCols);
346
347 // check that both targeted and non-targeted amps agree
348 REQUIRE_AGREE( qureg, refMat );
349 };
350
351 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), testFunc); }
352
353 }
354
355 /// @todo input validation
356}
void setDensityQuregAmps(Qureg qureg, qindex startRow, qindex startCol, qcomp **amps, qindex numRows, qindex numCols)
void setSubMatrix(qmatrix &dest, qmatrix sub, size_t r, size_t c)
Definition qmatrix.cpp:203
int getRandomInt(int min, int maxExcl)
Definition random.cpp:90

◆ TEST_CASE() [10/15]

TEST_CASE ( "setDensityQuregFlatAmps" ,
TEST_CATEGORY  )

Definition at line 278 of file initialisations.cpp.

278 {
279
280 SECTION( LABEL_CORRECTNESS ) {
281
282 int numTotalRows = getPow2(getNumCachedQubits());
283 int numTotalAmps = numTotalRows * numTotalRows;
284
285 // systematic iteration is WAY too slow
286 GENERATE( range(0,1000) );
287 int numSetAmps = getRandomInt(0, numTotalAmps + 1);
288 int startInd = getRandomInt(0, numTotalAmps - numSetAmps);
289 qvector amps = getRandomVector(numSetAmps);
290
291 auto testFunc = [&](Qureg qureg) {
292
293 // initialise qureg randomly
294 qmatrix refMat = getRandomMatrix(numTotalRows);
295 setQuregToReference(qureg, refMat);
296
297 // overwrite a contiguous region of row-major refMat, column-wise
298 refMat = getTranspose(refMat);
299 setSubMatrix(refMat, amps, startInd);
300 refMat = getTranspose(refMat);
301
302 // modify the same contiguous region of column-major qureg
303 setDensityQuregFlatAmps(qureg, startInd, amps.data(), numSetAmps);
304
305 // check that both targeted and non-targeted amps agree
306 REQUIRE_AGREE( qureg, refMat );
307 };
308
309 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), testFunc); }
310 }
311
312 /// @todo input validation
313}
void setDensityQuregFlatAmps(Qureg qureg, qindex startInd, qcomp *amps, qindex numAmps)

◆ TEST_CASE() [11/15]

TEST_CASE ( "setQuregAmps" ,
TEST_CATEGORY  )

Definition at line 247 of file initialisations.cpp.

247 {
248
249 SECTION( LABEL_CORRECTNESS ) {
250
251 int numTotalAmps = getPow2(getNumCachedQubits());
252 int numSetAmps = GENERATE_COPY( range(0,numTotalAmps+1) );
253 int startInd = GENERATE_COPY( range(0,numTotalAmps-numSetAmps) );
254 qvector amps = getRandomVector(numSetAmps);
255
256 auto testFunc = [&](Qureg qureg) {
257
258 // initialise qureg randomly
259 qvector refVec = getRandomVector(numTotalAmps);
260 setQuregToReference(qureg, refVec);
261
262 // modify only subset of refVec amps and qureg...
263 setSubVector(refVec, amps, startInd);
264 setQuregAmps(qureg, startInd, amps.data(), numSetAmps);
265
266 // so that we simultaneously check targeted amps
267 // are modified while non-targeted are not
268 REQUIRE_AGREE( qureg, refVec );
269 };
270
271 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), testFunc); }
272 }
273
274 /// @todo input validation
275}
void setQuregAmps(Qureg qureg, qindex startInd, qcomp *amps, qindex numAmps)

◆ TEST_CASE() [12/15]

TEST_CASE ( "setQuregToMixture" ,
TEST_CATEGORY  )

Definition at line 615 of file initialisations.cpp.

615 {
616
617 SECTION( LABEL_CORRECTNESS ) {
618
619 // @todo
620 // below, we test when every inQureg is unqiue and distinct
621 // from the outQureg, and so do not test the valid scenarios of:
622 // - outQureg being among inQuregs
623 // - one or more inQuregs being repeated
624 // However, both CPU and GPU implementations are sufficiently
625 // trivial to validate by inspection (eep...)
626
627 // compile-time optimisations apply for <= 5
628 int numInQuregs = GENERATE( 1, 2, 3, 4, 5, 6, 20 );
629 CAPTURE( numInQuregs );
630
631 vector<qreal> probs = getRandomProbabilities(numInQuregs);
632
633 // we must pass identically-deployed inQureg as outQureg,
634 // which itself gets tested being each possible deployment,
635 // so we defer allocation of the inQuregs
636 vector<Qureg> inQuregs(numInQuregs);
637
638 SECTION( LABEL_DENSMATR ) {
639
640 // generate (unnormalised) input reference matrices
641 vector<qmatrix> inMatrRefs(numInQuregs);
642 for (int i=0; i<numInQuregs; i++)
643 inMatrRefs[i] = getRandomMatrix(getPow2(getNumCachedQubits()));
644
645 // compute output reference matrix
646 qmatrix outMatrRef = getZeroMatrix(getPow2(getNumCachedQubits()));
647 for (int i=0; i<numInQuregs; i++)
648 outMatrRef += probs[i] * inMatrRefs[i];
649
650 auto apiFunc = [&](Qureg outQureg) {
651
652 // prepare input quregs
653 for (int i=0; i<numInQuregs; i++) {
654 inQuregs[i] = createCloneQureg(outQureg);
655 setQuregToReference(inQuregs[i], inMatrRefs[i]);
656 }
657
658 // modify outQureg
659 setQuregToMixture(outQureg, probs.data(), inQuregs.data(), numInQuregs);
660
661 // free input quregs
662 for (int i=0; i<numInQuregs; i++)
663 destroyQureg(inQuregs[i]);
664 };
665
666 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFunc, outMatrRef);
667 }
668 }
669
670 SECTION( LABEL_VALIDATION ) {
671
672 // arbitrary existing qureg
673 Qureg qureg = getCachedDensmatrs().begin()->second;
674
675 SECTION( "out qureg uninitialised" ) {
676
677 // spoof uninitialised value to be sure
678 Qureg badQureg;
679 badQureg.numQubits = -123;
680
681 REQUIRE_THROWS_WITH(
682 setQuregToMixture(badQureg, nullptr, nullptr, 1),
683 ContainsSubstring("invalid Qureg") );
684 }
685
686 SECTION( "in qureg uninitialised" ) {
687
688 // set all inQureg to arbitrary existing qureg
689 int numIn = 5;
690 vector<Qureg> inQuregs(numIn, qureg);
691
692 // hide an unitialised qureg among them
693 Qureg badQureg;
694 badQureg.numQubits = -123;
695 int badInd = GENERATE_COPY( range(0,numIn) );
696 inQuregs[badInd] = badQureg;
697
698 REQUIRE_THROWS_WITH(
699 setQuregToMixture(qureg, nullptr, inQuregs.data(), numIn),
700 ContainsSubstring("invalid Qureg") );
701 }
702
703 SECTION( "out qureg is statevector" ) {
704
705 Qureg badQureg = getCachedStatevecs().begin()->second;
706
707 REQUIRE_THROWS_WITH(
708 setQuregToMixture(badQureg, nullptr, nullptr, 1),
709 ContainsSubstring("received a statevector") );
710 }
711
712 SECTION( "in qureg is statevector" ) {
713
714 // set all inQureg to arbitrary existing density matrix
715 int numIn = 5;
716 vector<Qureg> inQuregs(numIn, qureg);
717
718 // hide a statevector among them
719 int badInd = GENERATE_COPY( range(0,numIn) );
720 inQuregs[badInd] = getCachedStatevecs().begin()->second;;
721
722 REQUIRE_THROWS_WITH(
723 setQuregToMixture(qureg, nullptr, inQuregs.data(), numIn),
724 ContainsSubstring("One or more Quregs were statevectors") );
725 }
726
727 SECTION( "number of quregs" ) {
728
729 int numIn = GENERATE( -1, 0 );
730
731 REQUIRE_THROWS_WITH(
732 setQuregToMixture(qureg, nullptr, nullptr, numIn),
733 ContainsSubstring("number of passed Quregs") && ContainsSubstring("is invalid") );
734 }
735
736 SECTION( "inconsistent qureg sizes" ) {
737
738 // must create new Quregs to ensure they are identically deployed
739 Qureg quregA = createCustomQureg(getNumCachedQubits(), 1,0,0,0);
740 Qureg quregB = createCustomQureg(getNumCachedQubits() + 1, 1,0,0,0);
741
742 // set all inQureg to quregA (as will be outQureg)
743 int numIn = 5;
744 vector<Qureg> inQuregs(numIn, quregA);
745
746 // set one to quregB
747 int badInd = GENERATE_COPY( range(0,numIn) );
748 inQuregs[badInd] = quregB;
749
750 REQUIRE_THROWS_WITH(
751 setQuregToMixture(quregA, nullptr, inQuregs.data(), numIn),
752 ContainsSubstring("inconsistent attributes") );
753
754 destroyQureg(quregA);
755 destroyQureg(quregB);
756 }
757
758 SECTION( "inconsistent qureg deployments" ) {
759
760 // we do not necessarily have differently-distributed/GPU Quregs at
761 // runtime, so we enumerate all deployments and test when they differ
762
763 for (auto& [label, badQureg]: getCachedDensmatrs()) {
764
765 if ((badQureg.isGpuAccelerated == qureg.isGpuAccelerated) &&
766 (badQureg.isDistributed == qureg.isDistributed))
767 continue;
768
769 // set all inQureg to qureg (as will be outQureg)
770 int numIn = 5;
771 vector<Qureg> inQuregs(numIn, qureg);
772
773 // set one to badQureg
774 int badInd = GENERATE_COPY( range(0,numIn) );
775 inQuregs[badInd] = badQureg;
776
777 REQUIRE_THROWS_WITH(
778 setQuregToMixture(qureg, nullptr, inQuregs.data(), numIn),
779 ContainsSubstring("inconsistent attributes") );
780 }
781
782 // automatically pass when there are no differing deployments
783 SUCCEED( );
784 }
785
786 SECTION( "invalid probs" ) {
787
788 // set all inQureg to arbitrary existing density matrix
789 int numIn = 5;
790 vector<Qureg> inQuregs(numIn, qureg);
791
792 // get valid probabilities then mess one up
793 int badInd = GENERATE_COPY( range(0,numIn) );
794 vector<qreal> probs = getRandomProbabilities(numIn);
795 probs[badInd] = GENERATE( -1., -0.1, 1.1, 2. );
796
797 REQUIRE_THROWS_WITH(
798 setQuregToMixture(qureg, probs.data(), inQuregs.data(), numIn),
799 ContainsSubstring("One or more given probabilities are invalid") );
800 }
801
802 SECTION( "unnormalised probs" ) {
803
804 // set all inQureg to arbitrary existing density matrix
805 int numIn = 5;
806 vector<Qureg> inQuregs(numIn, qureg);
807
808 // these illegal non-unity values assume eps < 0.1
809 qreal probSum = GENERATE( 0.9, 1.1 );
810 vector<qreal> probs(numIn, probSum / numIn);
811
812 REQUIRE_THROWS_WITH(
813 setQuregToMixture(qureg, probs.data(), inQuregs.data(), numIn),
814 ContainsSubstring("probabilities do not sum to") && ContainsSubstring("one") );
815 }
816
817 SECTION( "different number of quregs and probs") {
818
819 // relevant only to the C++ overload
820
821 qreal prob = 0;
822
823 REQUIRE_THROWS_WITH(
824 setQuregToMixture(qureg, {prob,prob}, {qureg}),
825 ContainsSubstring("different number of probabilities") );
826 }
827 }
828}
void setQuregToMixture(Qureg out, qreal *probs, Qureg *in, int numIn)
Qureg createCloneQureg(Qureg qureg)
Definition qureg.cpp:319
Qureg createCustomQureg(int numQubits, int isDensMatr, int useDistrib, int useGpuAccel, int useMultithread)
Definition qureg.cpp:277
void destroyQureg(Qureg qureg)
Definition qureg.cpp:334
qmatrix getZeroMatrix(size_t dim)
Definition qmatrix.cpp:18
vector< qreal > getRandomProbabilities(int numProbs)
Definition random.cpp:160

◆ TEST_CASE() [13/15]

TEST_CASE ( "setQuregToPauliStrSum" ,
TEST_CATEGORY  )

Definition at line 390 of file initialisations.cpp.

390 {
391
392 SECTION( LABEL_CORRECTNESS ) {
393
394 GENERATE( range(0,10) );
395 int numQubits = getNumCachedQubits();
396 int numTerms = GENERATE_COPY( 1, numQubits, getPow2(2*numQubits) );
397 PauliStrSum sum = createRandomPauliStrSum(numQubits, numTerms);
398 qmatrix refMat = getMatrix(sum, numQubits);
399
400 auto apiFunc = [&](Qureg qureg) { setQuregToPauliStrSum(qureg, sum); };
401
402 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFunc, refMat); }
403 }
404
405 /// @todo input validation
406}
void setQuregToPauliStrSum(Qureg qureg, PauliStrSum sum)

◆ TEST_CASE() [14/15]

TEST_CASE ( "setQuregToRenormalized" ,
TEST_CATEGORY  )

Definition at line 359 of file initialisations.cpp.

359 {
360
361 SECTION( LABEL_CORRECTNESS ) {
362
363 GENERATE( range(0,10) );
364 qindex dim = getPow2(getNumCachedQubits());
365 qvector refVec = getRandomVector(dim);
366 qmatrix refMat = getRandomMatrix(dim);
367
368 // eliminate random chance of tr(refMat)=0, triggering validation
369 if (doScalarsAgree(getTrace(refMat), 0))
370 refMat[0][0] += 1/(qreal) dim;
371
372 // [=] stores current (pre-normalised) reference objects
373 auto funcVec = [=](Qureg qureg) { setQuregToReference(qureg, refVec); setQuregToRenormalized(qureg); };
374 auto funcMat = [=](Qureg qureg) { setQuregToReference(qureg, refMat); setQuregToRenormalized(qureg); };
375
376 // setQuregToRenormalized() makes statevectors become valid
377 refVec = getNormalised(refVec);
378
379 // but it only divides density matrices by the sum of the real-elems of their diagonals
380 refMat /= getReferenceProbability(refMat);
381
382 SECTION( LABEL_STATEVEC ) { TEST_ON_CACHED_QUREGS(getCachedStatevecs(), funcVec, refVec); }
383 SECTION( LABEL_DENSMATR ) { TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), funcMat, refMat); }
384 }
385
386 /// @todo input validation
387}
qreal setQuregToRenormalized(Qureg qureg)

◆ TEST_CASE() [15/15]

TEST_CASE ( "setQuregToWeightedSum" ,
TEST_CATEGORY  )

Definition at line 409 of file initialisations.cpp.

409 {
410
411 SECTION( LABEL_CORRECTNESS ) {
412
413 // @todo
414 // below, we test when every inQureg is unqiue and distinct
415 // from the outQureg, and so do not test the valid scenarios of:
416 // - outQureg being among inQuregs
417 // - one or more inQuregs being repeated
418 // However, both CPU and GPU implementations are sufficiently
419 // trivial to validate by inspection (eep...)
420
421 qindex quregDim = getPow2(getNumCachedQubits());
422
423 // compile-time optimisations apply for <= 5
424 int numInQuregs = GENERATE( 1, 2, 3, 4, 5, 6, 20 );
425 CAPTURE( numInQuregs );
426
427 vector<qcomp> coeffs = getRandomVector(numInQuregs);
428
429 // we must pass identically-deployed inQureg as outQureg,
430 // which itself gets tested being each possible deployment,
431 // so we defer allocation of the inQuregs
432 vector<Qureg> inQuregs(numInQuregs);
433
434 // this function generates apiFunc in a way agnostic to
435 // whether outQureg is a statevector (inRefs are qvector)
436 // or a density matrix (inRefs are qmatrix)
437 auto apiFuncGen = [&](auto& inRefs) {
438
439 return [&](Qureg outQureg) {
440
441 // prepare input quregs
442 for (int i=0; i<numInQuregs; i++) {
443 inQuregs[i] = createCloneQureg(outQureg);
444 setQuregToReference(inQuregs[i], inRefs[i]);
445 }
446
447 // modify outQureg
448 setQuregToWeightedSum(outQureg, coeffs.data(), inQuregs.data(), numInQuregs);
449
450 // free input quregs
451 for (int i=0; i<numInQuregs; i++)
452 destroyQureg(inQuregs[i]);
453 };
454 };
455
456 SECTION( LABEL_STATEVEC ) {
457
458 // generate (unnormalised) input reference vectors
459 vector<qvector> inVecRefs(numInQuregs);
460 for (int i=0; i<numInQuregs; i++)
461 inVecRefs[i] = getRandomVector(quregDim);
462
463 // compute output reference vector
464 qvector outVecRef = getZeroVector(quregDim);
465 for (int i=0; i<numInQuregs; i++)
466 outVecRef += coeffs[i] * inVecRefs[i];
467
468 TEST_ON_CACHED_QUREGS(getCachedStatevecs(), apiFuncGen(inVecRefs), outVecRef);
469 }
470
471 SECTION( LABEL_DENSMATR ) {
472
473 // generate (unnormalised) input reference matrices
474 vector<qmatrix> inMatrRefs(numInQuregs);
475 for (int i=0; i<numInQuregs; i++)
476 inMatrRefs[i] = getRandomMatrix(quregDim);
477
478 // compute output reference matrix
479 qmatrix outMatrRef = getZeroMatrix(quregDim);
480 for (int i=0; i<numInQuregs; i++)
481 outMatrRef += coeffs[i] * inMatrRefs[i];
482
483 TEST_ON_CACHED_QUREGS(getCachedDensmatrs(), apiFuncGen(inMatrRefs), outMatrRef);
484 }
485 }
486
487 SECTION( LABEL_VALIDATION ) {
488
489 // arbitrary existing qureg
490 Qureg qureg = getCachedStatevecs().begin()->second;
491
492 SECTION( "out qureg uninitialised" ) {
493
494 // spoof uninitialised value to be sure
495 Qureg badQureg;
496 badQureg.numQubits = -123;
497
498 REQUIRE_THROWS_WITH(
499 setQuregToWeightedSum(badQureg, nullptr, nullptr, 1),
500 ContainsSubstring("invalid Qureg") );
501 }
502
503 SECTION( "in qureg uninitialised" ) {
504
505 // set all inQureg to arbitrary existing qureg
506 int numIn = 5;
507 vector<Qureg> inQuregs(numIn, qureg);
508
509 // hide an uninitialised qureg among them
510 Qureg badQureg;
511 badQureg.numQubits = -123;
512 int badInd = GENERATE_COPY( range(0,numIn) );
513 inQuregs[badInd] = badQureg;
514
515 REQUIRE_THROWS_WITH(
516 setQuregToWeightedSum(qureg, nullptr, inQuregs.data(), numIn),
517 ContainsSubstring("invalid Qureg") );
518 }
519
520 SECTION( "invalid number of quregs" ) {
521
522 int numIn = GENERATE( -1, 0 );
523
524 REQUIRE_THROWS_WITH(
525 setQuregToWeightedSum(qureg, nullptr, nullptr, numIn),
526 ContainsSubstring("number of passed Quregs") && ContainsSubstring("is invalid") );
527 }
528
529 SECTION( "inconsistent qureg types" ) {
530
531 // must create new Quregs to ensure they are identically deployed
532 Qureg sv = createCustomQureg(getNumCachedQubits(), 0, 0,0,0);
533 Qureg dm = createCustomQureg(getNumCachedQubits(), 1, 0,0,0);
534
535 // set all inQureg to sv (as will be outQureg)
536 int numIn = 5;
537 vector<Qureg> inQuregs(numIn, sv);
538
539 // set one to dm
540 int badInd = GENERATE_COPY( range(0,numIn) );
541 inQuregs[badInd] = dm;
542
543 REQUIRE_THROWS_WITH(
544 setQuregToWeightedSum(sv, nullptr, inQuregs.data(), numIn),
545 ContainsSubstring("inconsistent attributes") );
546
547 destroyQureg(sv);
548 destroyQureg(dm);
549 }
550
551 SECTION( "inconsistent qureg sizes" ) {
552
553 // must create new Quregs to ensure they are identically deployed
554 Qureg quregA = createCustomQureg(getNumCachedQubits(), 0,0,0,0);
555 Qureg quregB = createCustomQureg(getNumCachedQubits() + 1, 0,0,0,0);
556
557 // set all inQureg to quregA (as will be outQureg)
558 int numIn = 5;
559 vector<Qureg> inQuregs(numIn, quregA);
560
561 // set one to quregB
562 int badInd = GENERATE_COPY( range(0,numIn) );
563 inQuregs[badInd] = quregB;
564
565 REQUIRE_THROWS_WITH(
566 setQuregToWeightedSum(quregA, nullptr, inQuregs.data(), numIn),
567 ContainsSubstring("inconsistent attributes") );
568
569 destroyQureg(quregA);
570 destroyQureg(quregB);
571 }
572
573 SECTION( "inconsistent qureg deployments" ) {
574
575 // we do not necessarily have differently-distributed/GPU Quregs at
576 // runtime, so we enumerate all deployments and test when they differ
577
578 for (auto& [label, badQureg]: getCachedStatevecs()) {
579
580 if ((badQureg.isGpuAccelerated == qureg.isGpuAccelerated) &&
581 (badQureg.isDistributed == qureg.isDistributed))
582 continue;
583
584 // set all inQureg to qureg (as will be outQureg)
585 int numIn = 5;
586 vector<Qureg> inQuregs(numIn, qureg);
587
588 // set one to badQureg
589 int badInd = GENERATE_COPY( range(0,numIn) );
590 inQuregs[badInd] = badQureg;
591
592 REQUIRE_THROWS_WITH(
593 setQuregToWeightedSum(qureg, nullptr, inQuregs.data(), numIn),
594 ContainsSubstring("inconsistent attributes") );
595 }
596
597 // automatically pass when there are no differing deployments
598 SUCCEED( );
599 }
600
601 SECTION( "different number of quregs and coeffs") {
602
603 // relevant only to the C++ overload
604
605 qcomp coeff = getQcomp(0,0);
606
607 REQUIRE_THROWS_WITH(
608 setQuregToWeightedSum(qureg, {coeff,coeff}, {qureg}),
609 ContainsSubstring("different number of coefficients") );
610 }
611 }
612}
void setQuregToWeightedSum(Qureg out, qcomp *coeffs, Qureg *in, int numIn)
static qcomp getQcomp(qreal re, qreal im)
Definition types.h:91