test_data_structures.cpp
Go to the documentation of this file.
1 
2 #include "catch.hpp"
3 #include "QuEST.h"
4 #include "utilities.hpp"
5 
6 /* allows concise use of Contains in catch's REQUIRE_THROWS_WITH */
7 using Catch::Matchers::Contains;
8 
9 
10 
15 TEST_CASE( "fromComplex", "[data_structures]" ) {
16 
17  Complex a = {.real=.5, .imag=-.2};
18  qcomp b = fromComplex(a);
19 
20  REQUIRE( a.real == real(b) );
21  REQUIRE( a.imag == imag(b) );
22 }
23 
24 
25 
30 TEST_CASE( "getStaticComplexMatrixN", "[data_structures]" ) {
31 
32  /* use of this function is illegal in C++ */
33  SUCCEED( );
34 }
35 
36 
37 
42 TEST_CASE( "toComplex", "[data_structures]" ) {
43 
44  qcomp a = .5 - .2i;
45  Complex b = toComplex(a);
46 
47  REQUIRE( real(a) == b.real );
48  REQUIRE( imag(a) == b.imag );
49 }
50 
51 
52 
57 TEST_CASE( "createCloneQureg", "[data_structures]" ) {
58 
59  SECTION( "state-vector" ) {
60 
63 
64  // check properties are the same
65  REQUIRE( b.isDensityMatrix == a.isDensityMatrix );
67  REQUIRE( b.numQubitsInStateVec == a.numQubitsInStateVec );
68  REQUIRE( b.numAmpsPerChunk == a.numAmpsPerChunk );
69  REQUIRE( b.numAmpsTotal == a.numAmpsTotal );
70 
71  // check state-vector is the same (works for GPU and distributed)
72  REQUIRE( areEqual(a, b) );
73 
76  }
77  SECTION( "density-matrix" ) {
78 
81 
82  // check properties are the same
83  REQUIRE( b.isDensityMatrix == a.isDensityMatrix );
85  REQUIRE( b.numQubitsInStateVec == a.numQubitsInStateVec );
86  REQUIRE( b.numAmpsPerChunk == a.numAmpsPerChunk );
87  REQUIRE( b.numAmpsTotal == a.numAmpsTotal );
88 
89  // check state-vector is the same (works for GPU and distributed)
90  REQUIRE( areEqual(a, b) );
91 
94  }
95 }
96 
97 
98 
103 TEST_CASE( "createComplexMatrixN", "[data_structures]" ) {
104 
105  SECTION( "correctness" ) {
106 
107  int numQb = GENERATE( range(1,10+1) );
109 
110  // ensure elems are created and initialised to 0
111  REQUIRE( areEqual(toQMatrix(m), getZeroMatrix(1<<numQb)) );
112 
114  }
115  SECTION( "input validation" ) {
116 
117  SECTION( "number of qubits" ) {
118 
119  int numQb = GENERATE( -1, 0 );
120  REQUIRE_THROWS_WITH( createComplexMatrixN(numQb), Contains("Invalid number of qubits") );
121  }
122  }
123 }
124 
125 
126 
131 TEST_CASE( "createDensityQureg", "[data_structures]" ) {
132 
133  // must be at least one amplitude per node
134  int minNumQb = calcLog2(QUEST_ENV.numRanks) - 1; // density matrix has 2*numQb in state-vec
135  if (minNumQb <= 0)
136  minNumQb = 1;
137 
138  SECTION( "correctness" ) {
139 
140  // try 10 valid number of qubits
141  int numQb = GENERATE_COPY( range(minNumQb, minNumQb+10) );
142  Qureg reg = createDensityQureg(numQb, QUEST_ENV);
143 
144  // ensure elems (CPU and/or GPU) are created, and reg begins in |0><0|
145  QMatrix ref = getZeroMatrix(1<<numQb);
146  ref[0][0] = 1; // |0><0|
147  REQUIRE( areEqual(reg, ref) );
148 
149  destroyQureg(reg, QUEST_ENV);
150  }
151  SECTION( "input validation") {
152 
153  SECTION( "number of qubits" ) {
154 
155  int numQb = GENERATE( -1, 0 );
156  REQUIRE_THROWS_WITH( createDensityQureg(numQb, QUEST_ENV), Contains("Invalid number of qubits") );
157  }
158  SECTION( "number of amplitudes" ) {
159 
160  // use local QuESTEnv to safely modify
161  QuESTEnv env = QUEST_ENV;
162 
163  // too many amplitudes to store in type
164  int maxQb = (int) calcLog2(SIZE_MAX) - 1;
165  REQUIRE_THROWS_WITH( createDensityQureg(maxQb+1, env), Contains("Too many qubits") && Contains("size_t type") );
166 
167  /* n-qubit density matrix contains 2^(2n) amplitudes
168  * so can be spread between at most 2^(2n) ranks
169  */
170  int minQb = GENERATE( range(3,10) );
171  env.numRanks = (int) pow(2, 2*minQb);
172  int numQb = GENERATE_COPY( range(1,minQb) );
173  REQUIRE_THROWS_WITH( createDensityQureg(numQb, env), Contains("Too few qubits") );
174  }
175  SECTION( "available memory" ) {
176 
177  /* there is no reliable way to force the malloc statements to
178  * fail, and hence trigger the matrixInit validation */
179  SUCCEED( );
180  }
181  }
182 }
183 
184 
185 
190 TEST_CASE( "createQuESTEnv", "[data_structures]" ) {
191 
192  /* there is no meaningful way to test this */
193  SUCCEED( );
194 }
195 
196 
197 
202 TEST_CASE( "createQureg", "[data_structures]" ) {
203 
204  // must be at least one amplitude per node
205  int minNumQb = calcLog2(QUEST_ENV.numRanks);
206  if (minNumQb == 0)
207  minNumQb = 1;
208 
209  SECTION( "correctness" ) {
210 
211  // try 10 valid number of qubits
212  int numQb = GENERATE_COPY( range(minNumQb, minNumQb+10) );
213  Qureg reg = createQureg(numQb, QUEST_ENV);
214 
215  // ensure elems (CPU and/or GPU) are created, and reg begins in |0>
216  QVector ref = QVector(1<<numQb);
217  ref[0] = 1; // |0>
218  REQUIRE( areEqual(reg, ref) );
219 
220  destroyQureg(reg, QUEST_ENV);
221  }
222  SECTION( "input validation") {
223 
224  SECTION( "number of qubits" ) {
225 
226  int numQb = GENERATE( -1, 0 );
227  REQUIRE_THROWS_WITH( createQureg(numQb, QUEST_ENV), Contains("Invalid number of qubits") );
228  }
229  SECTION( "number of amplitudes" ) {
230 
231  // use local QuESTEnv to safely modify
232  QuESTEnv env = QUEST_ENV;
233 
234  // too many amplitudes to store in type
235  int maxQb = (int) calcLog2(SIZE_MAX);
236  REQUIRE_THROWS_WITH( createQureg(maxQb+1, env), Contains("Too many qubits") && Contains("size_t type") );
237 
238  // too few amplitudes to distribute
239  int minQb = GENERATE( range(2,10) );
240  env.numRanks = (int) pow(2, minQb);
241  int numQb = GENERATE_COPY( range(1,minQb) );
242  REQUIRE_THROWS_WITH( createQureg(numQb, env), Contains("Too few qubits") );
243  }
244  SECTION( "available memory" ) {
245 
246  /* there is no reliable way to force the malloc statements to
247  * fail, and hence trigger the matrixInit validation */
248  SUCCEED( );
249  }
250  }
251 }
252 
253 
254 
259 TEST_CASE( "destroyComplexMatrixN", "[data_structures]" ) {
260 
261  SECTION( "correctness" ) {
262 
263  /* there is no meaningful way to test this */
264  SUCCEED( );
265  }
266  SECTION( "input validation" ) {
267 
268  SECTION( "matrix not created" ) {
269 
270  /* this is an artificial test case since nothing in the QuEST API
271  * automatically sets un-initialised ComplexMatrixN fields to
272  * the NULL pointer.
273  */
274  ComplexMatrixN m;
275  m.real = NULL;
276 
277  /* the error message is also somewhat unrelated, but oh well
278  */
279  REQUIRE_THROWS_WITH( destroyComplexMatrixN(m), Contains("The ComplexMatrixN was not successfully created") );
280  }
281  }
282 }
283 
284 
285 
290 TEST_CASE( "destroyQuESTEnv", "[data_structures]" ) {
291 
292  /* there is no meaningful way to test this */
293  SUCCEED( );
294 }
295 
296 
297 
302 TEST_CASE( "destroyQureg", "[data_structures]" ) {
303 
304  /* there is no meaningful way to test this.
305  * We e.g. cannot check that the pointers are NULL because
306  * they are not updated; this function passes the struct by value,
307  * not by reference. We also cannot reliably monitor the
308  * memory used in the heap at runtime.
309  */
310  SUCCEED( );
311 }
312 
313 
314 
319 TEST_CASE( "initComplexMatrixN", "[data_structures]" ) {
320 
321  /* use of this function is illegal in C++ */
322  SUCCEED( );
323 }
QuESTEnv QUEST_ENV
The global QuESTEnv instance, to be created and destroyed once in this main(), so that the MPI enviro...
Definition: main.cpp:20
#define fromComplex(comp)
void destroyComplexMatrixN(ComplexMatrixN m)
Destroy a ComplexMatrixN instance created with createComplexMatrixN()
Definition: QuEST.c:1021
TEST_CASE("fromComplex", "[data_structures]")
ComplexMatrixN createComplexMatrixN(int numQubits)
Create (dynamically) a square complex matrix which can be passed to the multi-qubit general unitary f...
Definition: QuEST.c:1000
#define NUM_QUBITS
The default number of qubits in the registers created for unit testing (both statevectors and density...
Definition: utilities.hpp:36
Information about the environment the program is running in.
Definition: QuEST.h:199
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:136
QMatrix toQMatrix(ComplexMatrix2 src)
Returns a copy of the given 2-by-2 matrix.
Definition: utilities.cpp:835
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
int numQubitsInStateVec
Number of qubits in the state-vector - this is double the number represented for mixed states.
Definition: QuEST.h:167
std::vector< qcomp > QVector
A complex vector, which can be zero-initialised with QVector(numAmps).
Definition: utilities.hpp:60
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:170
#define qcomp
#define toComplex(scalar)
int numRanks
Definition: QuEST.h:202
void destroyQureg(Qureg qureg, QuESTEnv env)
Deallocate a Qureg object representing a set of qubits.
Definition: QuEST.c:75
qreal ** real
Definition: QuEST.h:139
Represents a system of qubits.
Definition: QuEST.h:160
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:163
Qureg createCloneQureg(Qureg qureg, QuESTEnv env)
Create a new Qureg which is an exact clone of the passed qureg, which can be either a statevector or ...
Definition: QuEST.c:62
std::vector< std::vector< qcomp > > QMatrix
A complex square matrix.
Definition: utilities.hpp:49
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:165
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:172
qreal real
Definition: QuEST.h:105
Qureg createQureg(int numQubits, QuESTEnv env)
Create a Qureg object representing a set of qubits which will remain in a pure state.
Definition: QuEST.c:34
qreal imag
Definition: QuEST.h:106
QMatrix getZeroMatrix(size_t dim)
Returns a dim-by-dim square complex matrix, initialised to all zeroes.
Definition: utilities.cpp:143
Represents one complex number.
Definition: QuEST.h:103
bool areEqual(QVector a, QVector b)
Returns true if the absolute value of the difference between every amplitude in vectors a and b is le...
Definition: utilities.cpp:387
Qureg createDensityQureg(int numQubits, QuESTEnv env)
Create a Qureg for qubits which are represented by a density matrix, and can be in mixed states.
Definition: QuEST.c:48