QuEST_validation.c
Go to the documentation of this file.
1 // Distributed under MIT licence. See https://github.com/QuEST-Kit/QuEST/blob/master/LICENCE.txt for details
2 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 # include "QuEST.h"
18 # include "QuEST_precision.h"
19 # include "QuEST_internal.h"
20 # include "QuEST_validation.h"
21 
22 # include <stdio.h>
23 # include <stdlib.h>
24 # include <stdint.h>
25 
26 /* buffer for an error message which contains formatters. This must be global,
27  * since if a function writes to a local buffer then throws an error, the
28  * local buffer may be cleared and dangle before the error catcher can process it.
29  */
30 char errMsgBuffer[1024];
31 
32 typedef enum {
114 } ErrorCode;
115 
116 static const char* errorMessages[] = {
117  [E_INVALID_NUM_RANKS] = "Invalid number of nodes. Distributed simulation can only make use of a power-of-2 number of node.",
118  [E_INVALID_NUM_CREATE_QUBITS] = "Invalid number of qubits. Must create >0.",
119  [E_INVALID_QUBIT_INDEX] = "Invalid qubit index. Must be >=0 and <numQubits.",
120  [E_INVALID_TARGET_QUBIT] = "Invalid target qubit. Must be >=0 and <numQubits.",
121  [E_INVALID_CONTROL_QUBIT] = "Invalid control qubit. Must be >=0 and <numQubits.",
122  [E_INVALID_STATE_INDEX] = "Invalid state index. Must be >=0 and <2^numQubits.",
123  [E_INVALID_AMP_INDEX] = "Invalid amplitude index. Must be >=0 and <2^numQubits.",
124  [E_INVALID_ELEM_INDEX] = "Invalid element index. Must be >=0 and <2^numQubits.",
125  [E_INVALID_NUM_AMPS] = "Invalid number of amplitudes. Must be >=0 and <=2^numQubits.",
126  [E_INVALID_NUM_ELEMS] = "Invalid number of elements. Must be >=0 and <=2^numQubits.",
127  [E_INVALID_OFFSET_NUM_AMPS_QUREG] = "More amplitudes given than exist in the statevector from the given starting index.",
128  [E_INVALID_OFFSET_NUM_ELEMS_DIAG] = "More elements given than exist in the diagonal operator from the given starting index.",
129  [E_TARGET_IS_CONTROL] = "Control qubit cannot equal target qubit.",
130  [E_TARGET_IN_CONTROLS] = "Control qubits cannot include target qubit.",
131  [E_CONTROL_TARGET_COLLISION] = "Control and target qubits must be disjoint.",
132  [E_QUBITS_NOT_UNIQUE] = "The qubits must be unique.",
133  [E_TARGETS_NOT_UNIQUE] = "The target qubits must be unique.",
134  [E_CONTROLS_NOT_UNIQUE] = "The control qubits should be unique.",
135  [E_INVALID_NUM_QUBITS] = "Invalid number of qubits. Must be >0 and <=numQubits.",
136  [E_INVALID_NUM_TARGETS] = "Invalid number of target qubits. Must be >0 and <=numQubits.",
137  [E_INVALID_NUM_CONTROLS] = "Invalid number of control qubits. Must be >0 and <numQubits.",
138  [E_NON_UNITARY_MATRIX] = "Matrix is not unitary.",
139  [E_NON_UNITARY_COMPLEX_PAIR] = "Compact matrix formed by given complex numbers is not unitary.",
140  [E_ZERO_VECTOR] = "Invalid axis vector. Must be non-zero.",
141  [E_SYS_TOO_BIG_TO_PRINT] = "Invalid system size. Cannot print output for systems greater than 5 qubits.",
142  [E_COLLAPSE_STATE_ZERO_PROB] = "Can't collapse to state with zero probability.",
143  [E_INVALID_QUBIT_OUTCOME] = "Invalid measurement outcome -- must be either 0 or 1.",
144  [E_CANNOT_OPEN_FILE] = "Could not open file (%s).",
145  [E_SECOND_ARG_MUST_BE_STATEVEC] = "Second argument must be a state-vector.",
146  [E_MISMATCHING_QUREG_DIMENSIONS] = "Dimensions of the qubit registers don't match.",
147  [E_MISMATCHING_QUREG_TYPES] = "Registers must both be state-vectors or both be density matrices.",
148  [E_DEFINED_ONLY_FOR_STATEVECS] = "Operation valid only for state-vectors.",
149  [E_DEFINED_ONLY_FOR_DENSMATRS] = "Operation valid only for density matrices.",
150  [E_INVALID_PROB] = "Probabilities must be in [0, 1].",
151  [E_UNNORM_PROBS] = "Probabilities must sum to ~1.",
152  [E_INVALID_ONE_QUBIT_DEPHASE_PROB] = "The probability of a single qubit dephase error cannot exceed 1/2, which maximally mixes.",
153  [E_INVALID_TWO_QUBIT_DEPHASE_PROB] = "The probability of a two-qubit qubit dephase error cannot exceed 3/4, which maximally mixes.",
154  [E_INVALID_ONE_QUBIT_DEPOL_PROB] = "The probability of a single qubit depolarising error cannot exceed 3/4, which maximally mixes.",
155  [E_INVALID_TWO_QUBIT_DEPOL_PROB] = "The probability of a two-qubit depolarising error cannot exceed 15/16, which maximally mixes.",
156  [E_INVALID_ONE_QUBIT_PAULI_PROBS] = "The probability of any X, Y or Z error cannot exceed the probability of no error.",
157  [E_INVALID_CONTROLS_BIT_STATE] = "The state of the control qubits must be a bit sequence (0s and 1s).",
158  [E_INVALID_PAULI_CODE] = "Invalid Pauli code. Codes must be 0 (or PAULI_I), 1 (PAULI_X), 2 (PAULI_Y) or 3 (PAULI_Z) to indicate the identity, X, Y and Z operators respectively.",
159  [E_INVALID_NUM_SUM_TERMS] = "Invalid number of terms in the Pauli sum. The number of terms must be >0.",
160  [E_CANNOT_FIT_MULTI_QUBIT_MATRIX] = "The specified matrix targets too many qubits; the batches of amplitudes to modify cannot all fit in a single distributed node's memory allocation.",
161  [E_INVALID_UNITARY_SIZE] = "The matrix size does not match the number of target qubits.",
162  [E_COMPLEX_MATRIX_NOT_INIT] = "The ComplexMatrixN was not successfully created (possibly insufficient memory available).",
163  [E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS] = "At least 1 and at most 4 single qubit Kraus operators may be specified.",
164  [E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS] = "At least 1 and at most 16 two-qubit Kraus operators may be specified.",
165  [E_INVALID_NUM_N_QUBIT_KRAUS_OPS] = "At least 1 and at most 4*N^2 of N-qubit Kraus operators may be specified.",
166  [E_INVALID_KRAUS_OPS] = "The specified Kraus map is not a completely positive, trace preserving map.",
167  [E_MISMATCHING_NUM_TARGS_KRAUS_SIZE] = "Every Kraus operator must be of the same number of qubits as the number of targets.",
168  [E_DISTRIB_QUREG_TOO_SMALL] = "Too few qubits. The created qureg must have at least one amplitude per node used in distributed simulation.",
169  [E_DISTRIB_DIAG_OP_TOO_SMALL] = "Too few qubits. The created DiagonalOp must contain at least one element per node used in distributed simulation.",
170  [E_NUM_AMPS_EXCEED_TYPE] = "Too many qubits (max of log2(SIZE_MAX)). Cannot store the number of amplitudes per-node in the size_t type.",
171  [E_INVALID_PAULI_HAMIL_PARAMS] = "The number of qubits and terms in the PauliHamil must be strictly positive.",
172  [E_INVALID_PAULI_HAMIL_FILE_PARAMS] = "The number of qubits and terms in the PauliHamil file (%s) must be strictly positive.",
173  [E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF] = "Failed to parse the next expected term coefficient in PauliHamil file (%s).",
174  [E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI] = "Failed to parse the next expected Pauli code in PauliHamil file (%s).",
175  [E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE] = "The PauliHamil file (%s) contained an invalid pauli code (%d). Codes must be 0 (or PAULI_I), 1 (PAULI_X), 2 (PAULI_Y) or 3 (PAULI_Z) to indicate the identity, X, Y and Z operators respectively.",
176  [E_MISMATCHING_PAULI_HAMIL_QUREG_NUM_QUBITS] = "The PauliHamil must act on the same number of qubits as exist in the Qureg.",
177  [E_INVALID_TROTTER_ORDER] = "The Trotterisation order must be 1, or an even number (for higher-order Suzuki symmetrized expansions).",
178  [E_INVALID_TROTTER_REPS] = "The number of Trotter repetitions must be >=1.",
179  [E_MISMATCHING_QUREG_DIAGONAL_OP_SIZE] = "The qureg must represent an equal number of qubits as that in the applied diagonal operator.",
180  [E_DIAGONAL_OP_NOT_INITIALISED] = "The diagonal operator has not been initialised through createDiagonalOperator().",
181  [E_PAULI_HAMIL_NOT_DIAGONAL] = "The Pauli Hamiltonian contained operators other than PAULI_Z and PAULI_I, and hence cannot be expressed as a diagonal matrix.",
182  [E_MISMATCHING_PAULI_HAMIL_DIAGONAL_OP_SIZE] = "The Pauli Hamiltonian and diagonal operator have different, incompatible dimensions.",
183  [E_INVALID_NUM_SUBREGISTERS] = "Invalid number of qubit subregisters, which must be >0 and <=100.",
184  [E_INVALID_NUM_PHASE_FUNC_TERMS] = "Invalid number of terms in the phase function specified. Must be >0.",
185  [E_INVALID_NUM_PHASE_FUNC_OVERRIDES] = "Invalid number of phase function overrides specified. Must be >=0, and for single-variable phase functions, <=2^numQubits (the maximum unique binary values of the sub-register). Note that uniqueness of overriding indices is not checked.",
186  [E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX] = "Invalid phase function override index, in the UNSIGNED encoding. Must be >=0, and <= the maximum index possible of the corresponding qubit subregister (2^numQubits-1).",
187  [E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX] = "Invalid phase function override index, in the TWOS_COMPLEMENT encoding. Must be between (inclusive) -2^(N-1) and +2^(N-1)-1, where N is the number of qubits (including the sign qubit).",
188  [E_INVALID_PHASE_FUNC_NAME] = "Invalid named phase function, which must be one of {NORM, SCALED_NORM, INVERSE_NORM, SCALED_INVERSE_NORM, PRODUCT, SCALED_PRODUCT, INVERSE_PRODUCT, SCALED_INVERSE_PRODUCT, DISTANCE, SCALED_DISTANCE, INVERSE_DISTANCE, SCALED_INVERSE_DISTANCE}.",
189  [E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS] = "Invalid number of parameters passed for the given named phase function. {NORM, PRODUCT, DISTANCE} accept 0 parameters, {INVERSE_NORM, INVERSE_PRODUCT, INVERSE_DISTANCE} accept 1 parameter (the phase at the divergence), {SCALED_NORM, SCALED_INVERSE_NORM, SCALED_PRODUCT} accept 1 parameter (the scaling coefficient), {SCALED_INVERSE_PRODUCT, SCALED_DISTANCE, SCALED_INVERSE_DISTANCE} accept 2 parameters (the coefficient then divergence phase), SCALED_INVERSE_SHIFTED_NORM accepts 2 + (number of sub-registers) parameters (the coefficient, then the divergence phase, followed by the offset for each sub-register), SCALED_INVERSE_SHIFTED_DISTANCE accepts 2 + (number of sub-registers) / 2 parameters (the coefficient, then the divergence phase, followed by the offset for each pair of sub-registers).",
190  [E_INVALID_BIT_ENCODING] = "Invalid bit encoding. Must be one of {UNSIGNED, TWOS_COMPLEMENT}.",
191  [E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT] = "A sub-register contained too few qubits to employ TWOS_COMPLEMENT encoding. Must use >1 qubits (allocating one for the sign).",
192  [E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE] = "The phase function contained a negative exponent which would diverge at zero, but the zero index was not overriden.",
193  [E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE] = "The phase function contained a fractional exponent, which in TWOS_COMPLEMENT encoding, requires all negative indices are overriden. However, one or more negative indices were not overriden.",
194  [E_NEGATIVE_EXPONENT_MULTI_VAR] = "The phase function contained an illegal negative exponent. One must instead call applyPhaseFuncOverrides() once for each register, so that the zero index of each register is overriden, independent of the indices of all other registers.",
195  [E_FRACTIONAL_EXPONENT_MULTI_VAR] = "The phase function contained a fractional exponent, which is illegal in TWOS_COMPLEMENT encoding, since it cannot be (efficiently) checked that all negative indices were overriden. One must instead call applyPhaseFuncOverrides() once for each register, so that each register's negative indices can be overriden, independent of the indices of all other registers.",
196  [E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC] = "Phase functions DISTANCE, INVERSE_DISTANCE, SCALED_DISTANCE and SCALED_INVERSE_DISTANCE require a strictly even number of sub-registers."
197 };
198 
199 void default_invalidQuESTInputError(const char* errMsg, const char* errFunc) {
200  printf("!!!\n");
201  printf("QuEST Error in function %s: %s\n", errFunc, errMsg);
202  printf("!!!\n");
203  printf("exiting..\n");
204  exit(1);
205 }
206 
207 #ifndef _WIN32
208 #pragma weak invalidQuESTInputError
209 void invalidQuESTInputError(const char* errMsg, const char* errFunc) {
210  default_invalidQuESTInputError(errMsg, errFunc);
211 }
212 #else
213 #pragma comment(linker, "/alternatename:invalidQuESTInputError=default_invalidQuESTInputError")
214 #endif
215 
216 void QuESTAssert(int isValid, ErrorCode code, const char* func){
217  if (!isValid) invalidQuESTInputError(errorMessages[code], func);
218 }
219 
220 int isComplexUnit(Complex alpha) {
221  return (absReal(1 - sqrt(alpha.real*alpha.real + alpha.imag*alpha.imag)) < REAL_EPS);
222 }
223 
224 int isVectorUnit(qreal ux, qreal uy, qreal uz) {
225  return (absReal(1 - sqrt(ux*ux + uy*uy + uz*uz)) < REAL_EPS );
226 }
227 
229  return ( absReal( -1
230  + alpha.real*alpha.real
231  + alpha.imag*alpha.imag
232  + beta.real*beta.real
233  + beta.imag*beta.imag) < REAL_EPS );
234 }
235 
236 #define macro_isMatrixUnitary(m, dim, retVal) { \
237  /* elemRe_ and elemIm_ must not exist in caller scope */ \
238  qreal elemRe_, elemIm_; \
239  retVal = 1; \
240  /* check m * ConjugateTranspose(m) == Identity */ \
241  for (int r=0; r < (dim); r++) { \
242  for (int c=0; c < (dim); c++) { \
243  /* m[r][...] * ConjugateTranspose(m)[...][c] */ \
244  elemRe_ = 0; \
245  elemIm_ = 0; \
246  for (int i=0; i < (dim); i++) { \
247  /* m[r][i] * conj(m[c][i]) */ \
248  elemRe_ += m.real[r][i]*m.real[c][i] + m.imag[r][i]*m.imag[c][i]; \
249  elemIm_ += m.imag[r][i]*m.real[c][i] - m.real[r][i]*m.imag[c][i]; \
250  } \
251  /* check distance from identity */ \
252  if ((absReal(elemIm_) > REAL_EPS) || \
253  (r == c && absReal(elemRe_ - 1) > REAL_EPS) || \
254  (r != c && absReal(elemRe_ ) > REAL_EPS)) { \
255  retVal = 0; \
256  break; \
257  } \
258  } \
259  if (retVal == 0) \
260  break; \
261  } \
262 }
264  int dim = 2;
265  int retVal;
266  macro_isMatrixUnitary(u, dim, retVal);
267  return retVal;
268 }
270  int dim = 4;
271  int retVal;
272  macro_isMatrixUnitary(u, dim, retVal);
273  return retVal;
274 }
276  int dim = 1 << u.numQubits;
277  int retVal;
278  macro_isMatrixUnitary(u, dim, retVal);
279  return retVal;
280 }
281 
282 #define macro_isCompletelyPositiveMap(ops, numOps, opDim) { \
283  for (int r=0; r<(opDim); r++) { \
284  for (int c=0; c<(opDim); c++) { \
285  qreal elemRe_ = 0; \
286  qreal elemIm_ = 0; \
287  for (int n=0; n<(numOps); n++) { \
288  for (int k=0; k<(opDim); k++) { \
289  elemRe_ += ops[n].real[k][r]*ops[n].real[k][c] + ops[n].imag[k][r]*ops[n].imag[k][c]; \
290  elemIm_ += ops[n].real[k][r]*ops[n].imag[k][c] - ops[n].imag[k][r]*ops[n].real[k][c]; \
291  } \
292  } \
293  qreal dist_ = absReal(elemIm_) + absReal(elemRe_ - ((r==c)? 1:0)); \
294  if (dist_ > REAL_EPS) \
295  return 0; \
296  } \
297  } \
298  return 1; \
299 }
301  macro_isCompletelyPositiveMap(ops, numOps, 2);
302 }
304  macro_isCompletelyPositiveMap(ops, numOps, 4);
305 }
307  int opDim = 1 << ops[0].numQubits;
308  macro_isCompletelyPositiveMap(ops, numOps, opDim);
309 }
310 
312  return (code==PAULI_I || code==PAULI_X || code==PAULI_Y || code==PAULI_Z);
313 }
314 
315 int areUniqueQubits(int* qubits, int numQubits) {
316  long long int mask = 0;
317  long long int bit;
318  for (int q=0; q < numQubits; q++) {
319  bit = 1LL << qubits[q];
320  if (mask & bit)
321  return 0;
322  mask |= bit;
323  }
324  return 1;
325 }
326 
328 unsigned int calcLog2(long unsigned int num) {
329  unsigned int l = 0;
330  while (num >>= 1)
331  l++;
332  return l;
333 }
334 
335 void validateNumRanks(int numRanks, const char* caller) {
336 
337  /* silly but robust way to determine if numRanks is a power of 2,
338  * in lieu of bit-twiddling (e.g. AND with all-ones) which may be
339  * system / precsision dependent
340  */
341  int isValid = 0;
342  for (int exp2 = 1; exp2 <= numRanks; exp2 *= 2)
343  if (exp2 == numRanks)
344  isValid = 1;
345 
346  QuESTAssert(isValid, E_INVALID_NUM_RANKS, caller);
347 }
348 
349 void validateNumQubitsInQureg(int numQubits, int numRanks, const char* caller) {
350  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
351 
352  // mustn't be more amplitudes than can fit in the type
353  unsigned int maxQubits = calcLog2(SIZE_MAX);
354  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
355 
356  // must be at least one amplitude per node
357  long unsigned int numAmps = (1UL<<numQubits);
358  QuESTAssert(numAmps >= numRanks, E_DISTRIB_QUREG_TOO_SMALL, caller);
359 }
360 
361 void validateNumQubitsInMatrix(int numQubits, const char* caller) {
362  QuESTAssert(numQubits>0, E_INVALID_NUM_QUBITS, caller);
363 }
364 
365 void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char* caller) {
366  QuESTAssert(numQubits>0, E_INVALID_NUM_CREATE_QUBITS, caller);
367 
368  // mustn't be more amplitudes than can fit in the type
369  unsigned int maxQubits = calcLog2(SIZE_MAX);
370  QuESTAssert( numQubits <= maxQubits, E_NUM_AMPS_EXCEED_TYPE, caller);
371 
372  // must be at least one amplitude per node
373  long unsigned int numAmps = (1UL<<numQubits);
374  QuESTAssert(numAmps >= numRanks, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
375 }
376 
377 void validateStateIndex(Qureg qureg, long long int stateInd, const char* caller) {
378  long long int stateMax = 1LL << qureg.numQubitsRepresented;
379  QuESTAssert(stateInd>=0 && stateInd<stateMax, E_INVALID_STATE_INDEX, caller);
380 }
381 
382 void validateAmpIndex(Qureg qureg, long long int ampInd, const char* caller) {
383  long long int indMax = 1LL << qureg.numQubitsRepresented;
384  QuESTAssert(ampInd>=0 && ampInd<indMax, E_INVALID_AMP_INDEX, caller);
385 }
386 
387 void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char* caller) {
388  validateAmpIndex(qureg, startInd, caller);
389  QuESTAssert(numAmps >= 0 && numAmps <= qureg.numAmpsTotal, E_INVALID_NUM_AMPS, caller);
390  QuESTAssert(numAmps + startInd <= qureg.numAmpsTotal, E_INVALID_OFFSET_NUM_AMPS_QUREG, caller);
391 }
392 
393 void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char* caller) {
394  long long int indMax = 1LL << op.numQubits;
395  QuESTAssert(startInd >= 0 && startInd < indMax, E_INVALID_ELEM_INDEX, caller);
396  QuESTAssert(numElems >= 0 && numElems <= indMax, E_INVALID_NUM_ELEMS, caller);
397  QuESTAssert(numElems + startInd <= indMax, E_INVALID_OFFSET_NUM_ELEMS_DIAG, caller);
398 }
399 
400 void validateTarget(Qureg qureg, int targetQubit, const char* caller) {
401  QuESTAssert(targetQubit>=0 && targetQubit<qureg.numQubitsRepresented, E_INVALID_TARGET_QUBIT, caller);
402 }
403 
404 void validateControl(Qureg qureg, int controlQubit, const char* caller) {
405  QuESTAssert(controlQubit>=0 && controlQubit<qureg.numQubitsRepresented, E_INVALID_CONTROL_QUBIT, caller);
406 }
407 
408 void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char* caller) {
409  validateTarget(qureg, targetQubit, caller);
410  validateControl(qureg, controlQubit, caller);
411  QuESTAssert(controlQubit != targetQubit, E_TARGET_IS_CONTROL, caller);
412 }
413 
414 void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char* caller) {
415  validateTarget(qureg, qubit1, caller);
416  validateTarget(qureg, qubit2, caller);
417  QuESTAssert(qubit1 != qubit2, E_TARGETS_NOT_UNIQUE, caller);
418 }
419 
420 void validateNumTargets(Qureg qureg, int numTargetQubits, const char* caller) {
421  QuESTAssert(numTargetQubits>0 && numTargetQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_TARGETS, caller);
422 }
423 
424 void validateNumControls(Qureg qureg, int numControlQubits, const char* caller) {
425  QuESTAssert(numControlQubits>0 && numControlQubits<qureg.numQubitsRepresented, E_INVALID_NUM_CONTROLS, caller);
426 }
427 
428 void validateMultiTargets(Qureg qureg, int* targetQubits, int numTargetQubits, const char* caller) {
429  validateNumTargets(qureg, numTargetQubits, caller);
430  for (int i=0; i < numTargetQubits; i++)
431  validateTarget(qureg, targetQubits[i], caller);
432 
433  QuESTAssert(areUniqueQubits(targetQubits, numTargetQubits), E_TARGETS_NOT_UNIQUE, caller);
434 }
435 
436 void validateMultiControls(Qureg qureg, int* controlQubits, int numControlQubits, const char* caller) {
437  validateNumControls(qureg, numControlQubits, caller);
438  for (int i=0; i < numControlQubits; i++)
439  validateControl(qureg, controlQubits[i], caller);
440 
441  QuESTAssert(areUniqueQubits(controlQubits, numControlQubits), E_CONTROLS_NOT_UNIQUE, caller);
442 }
443 
444 void validateMultiQubits(Qureg qureg, int* qubits, int numQubits, const char* caller) {
445  QuESTAssert(numQubits>0 && numQubits<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
446  for (int i=0; i < numQubits; i++)
447  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
448 
449  QuESTAssert(areUniqueQubits(qubits, numQubits), E_QUBITS_NOT_UNIQUE, caller);
450 }
451 
452 void validateMultiControlsTarget(Qureg qureg, int* controlQubits, int numControlQubits, int targetQubit, const char* caller) {
453  validateTarget(qureg, targetQubit, caller);
454  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
455  for (int i=0; i < numControlQubits; i++)
456  QuESTAssert(controlQubits[i] != targetQubit, E_TARGET_IN_CONTROLS, caller);
457 }
458 
459 void validateMultiControlsMultiTargets(Qureg qureg, int* controlQubits, int numControlQubits, int* targetQubits, int numTargetQubits, const char* caller) {
460  validateMultiControls(qureg, controlQubits, numControlQubits, caller);
461  validateMultiTargets(qureg, targetQubits, numTargetQubits, caller);
462  long long int ctrlMask = getQubitBitMask(controlQubits, numControlQubits);
463  long long int targMask = getQubitBitMask(targetQubits, numTargetQubits);
464  int overlap = ctrlMask & targMask;
465  QuESTAssert(!overlap, E_CONTROL_TARGET_COLLISION, caller);
466 }
467 
468 void validateControlState(int* controlState, int numControlQubits, const char* caller) {
469  for (int i=0; i < numControlQubits; i++)
470  QuESTAssert(controlState[i] == 0 || controlState[i] == 1, E_INVALID_CONTROLS_BIT_STATE, caller);
471 }
472 
473 void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char* caller) {
474  QuESTAssert(qureg.numAmpsPerChunk >= (1LL << numTargets), E_CANNOT_FIT_MULTI_QUBIT_MATRIX, caller);
475 }
476 
477 void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char* caller) {
479 }
480 
481 void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char* caller) {
482  validateMultiQubitMatrixFitsInNode(qureg, 2, caller);
484 }
485 
486 void validateMatrixInit(ComplexMatrixN matr, const char* caller) {
487 
488  /* note that for (most) compilers which don't automatically initialise
489  * pointers to NULL, this can only be used to check the mallocs in createComplexMatrixN
490  * succeeded. It can not be used to differentiate whether a user actually attempted
491  * to initialise or create their ComplexMatrixN instance.
492  */
493  QuESTAssert(matr.real != NULL && matr.imag != NULL, E_COMPLEX_MATRIX_NOT_INIT, caller);
494 }
495 
496 void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char* caller) {
497  validateMatrixInit(u, caller);
498  validateMultiQubitMatrixFitsInNode(qureg, numTargs, caller);
499  QuESTAssert(numTargs == u.numQubits, E_INVALID_UNITARY_SIZE, caller);
500 }
501 
502 void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char* caller) {
503  validateMultiQubitMatrix(qureg, u, numTargs, caller);
505 }
506 
507 void validateUnitaryComplexPair(Complex alpha, Complex beta, const char* caller) {
509 }
510 
511 void validateVector(Vector vec, const char* caller) {
512  QuESTAssert(getVectorMagnitude(vec) > REAL_EPS, E_ZERO_VECTOR, caller);
513 }
514 
515 void validateStateVecQureg(Qureg qureg, const char* caller) {
517 }
518 
519 void validateDensityMatrQureg(Qureg qureg, const char* caller) {
521 }
522 
523 void validateOutcome(int outcome, const char* caller) {
524  QuESTAssert(outcome==0 || outcome==1, E_INVALID_QUBIT_OUTCOME, caller);
525 }
526 
527 void validateMeasurementProb(qreal prob, const char* caller) {
528  QuESTAssert(prob>REAL_EPS, E_COLLAPSE_STATE_ZERO_PROB, caller);
529 }
530 
531 void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller) {
533 }
534 
535 void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller) {
537 }
538 
539 void validateSecondQuregStateVec(Qureg qureg2, const char *caller) {
541 }
542 
543 void validateFileOpened(int opened, char* fn, const char* caller) {
544  if (!opened) {
545 
548  }
549 }
550 
551 void validateProb(qreal prob, const char* caller) {
552  QuESTAssert(prob >= 0 && prob <= 1, E_INVALID_PROB, caller);
553 }
554 
555 void validateNormProbs(qreal prob1, qreal prob2, const char* caller) {
556  validateProb(prob1, caller);
557  validateProb(prob2, caller);
558 
559  qreal sum = prob1 + prob2;
560  QuESTAssert(absReal(1 - sum) < REAL_EPS, E_UNNORM_PROBS, caller);
561 }
562 
563 void validateOneQubitDephaseProb(qreal prob, const char* caller) {
564  validateProb(prob, caller);
565  QuESTAssert(prob <= 1/2.0, E_INVALID_ONE_QUBIT_DEPHASE_PROB, caller);
566 }
567 
568 void validateTwoQubitDephaseProb(qreal prob, const char* caller) {
569  validateProb(prob, caller);
570  QuESTAssert(prob <= 3/4.0, E_INVALID_TWO_QUBIT_DEPHASE_PROB, caller);
571 }
572 
573 void validateOneQubitDepolProb(qreal prob, const char* caller) {
574  validateProb(prob, caller);
575  QuESTAssert(prob <= 3/4.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
576 }
577 
578 void validateOneQubitDampingProb(qreal prob, const char* caller) {
579  validateProb(prob, caller);
580  QuESTAssert(prob <= 1.0, E_INVALID_ONE_QUBIT_DEPOL_PROB, caller);
581 }
582 
583 void validateTwoQubitDepolProb(qreal prob, const char* caller) {
584  validateProb(prob, caller);
585  QuESTAssert(prob <= 15/16.0, E_INVALID_TWO_QUBIT_DEPOL_PROB, caller);
586 }
587 
588 void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char* caller) {
589  validateProb(probX, caller);
590  validateProb(probY, caller);
591  validateProb(probZ, caller);
592 
593  qreal probNoError = 1 - probX - probY - probZ;
594  QuESTAssert(probX <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
595  QuESTAssert(probY <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
596  QuESTAssert(probZ <= probNoError, E_INVALID_ONE_QUBIT_PAULI_PROBS, caller);
597 }
598 
599 void validatePauliCodes(enum pauliOpType* pauliCodes, int numPauliCodes, const char* caller) {
600  for (int i=0; i < numPauliCodes; i++) {
601  enum pauliOpType code = pauliCodes[i];
603  }
604 }
605 
606 void validateNumPauliSumTerms(int numTerms, const char* caller) {
607  QuESTAssert(numTerms > 0, E_INVALID_NUM_SUM_TERMS, caller);
608 }
609 
610 void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2* ops, int numOps, const char* caller) {
611  int opNumQubits = 1;
612  int superOpNumQubits = 2*opNumQubits;
613  int maxNumOps = superOpNumQubits*superOpNumQubits;
614  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS, caller);
615 
616  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
617 
618  int isPos = isCompletelyPositiveMap2(ops, numOps);
619  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
620 }
621 
622 void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4* ops, int numOps, const char* caller) {
623  int opNumQubits = 2;
624  int superOpNumQubits = 2*opNumQubits;
625  int maxNumOps = superOpNumQubits*superOpNumQubits;
626  QuESTAssert(numOps > 0 && numOps <= maxNumOps, E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS, caller);
627 
628  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
629 
630  int isPos = isCompletelyPositiveMap4(ops, numOps);
631  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
632 }
633 
634 void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN* ops, int numOps, const char* caller) {
635  int opNumQubits = numTargs;
636  int superOpNumQubits = 2*opNumQubits;
637  int maxNumOps = superOpNumQubits*superOpNumQubits;
638  QuESTAssert(numOps>0 && numOps <= maxNumOps, E_INVALID_NUM_N_QUBIT_KRAUS_OPS, caller);
639 
640  for (int n=0; n<numOps; n++) {
641  validateMatrixInit(ops[n], __func__);
642  QuESTAssert(ops[n].numQubits == numTargs, E_MISMATCHING_NUM_TARGS_KRAUS_SIZE, caller);
643  }
644 
645  validateMultiQubitMatrixFitsInNode(qureg, superOpNumQubits, caller);
646 
647  int isPos = isCompletelyPositiveMapN(ops, numOps);
648  QuESTAssert(isPos, E_INVALID_KRAUS_OPS, caller);
649 }
650 
651 void validateHamilParams(int numQubits, int numTerms, const char* caller) {
652  QuESTAssert(numQubits > 0 && numTerms > 0, E_INVALID_PAULI_HAMIL_PARAMS, caller);
653 }
654 
655 void validatePauliHamil(PauliHamil hamil, const char* caller) {
656  validateHamilParams(hamil.numQubits, hamil.numSumTerms, caller);
657  validatePauliCodes(hamil.pauliCodes, hamil.numSumTerms*hamil.numQubits, caller);
658 }
659 
660 void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char* caller) {
662 }
663 
664 void validateHamilFileParams(int numQubits, int numTerms, FILE* file, char* fn, const char* caller) {
665  if (!(numQubits > 0 && numTerms > 0)) {
666  fclose(file);
667 
670  }
671 }
672 
673 void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE* file, char* fn, const char* caller) {
674  if (!parsed) {
676  fclose(file);
677 
680  }
681 }
682 
683 void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE* file, char* fn, const char* caller) {
684  if (!parsed) {
686  fclose(file);
687 
690  }
691 }
692 
693 void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE* file, char* fn, const char* caller) {
694  if (!isValidPauliCode(code)) {
696  fclose(file);
697 
700  }
701 }
702 
703 void validateTrotterParams(int order, int reps, const char* caller) {
704  int isEven = (order % 2) == 0;
705  QuESTAssert(order > 0 && (isEven || order==1), E_INVALID_TROTTER_ORDER, caller);
706  QuESTAssert(reps > 0, E_INVALID_TROTTER_REPS, caller);
707 }
708 
709 void validateDiagOpInit(DiagonalOp op, const char* caller) {
710  QuESTAssert(op.real != NULL && op.imag != NULL, E_DIAGONAL_OP_NOT_INITIALISED, caller);
711 }
712 
713 void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char* caller) {
714  validateDiagOpInit(op, caller);
716 }
717 
718 void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller) {
720 
721  for (int p=0; p<hamil.numSumTerms*hamil.numQubits; p++)
722  QuESTAssert(
723  hamil.pauliCodes[p] == PAULI_I || hamil.pauliCodes[p] == PAULI_Z,
725 }
726 
727 void validateDiagPauliHamilFromFile(PauliHamil hamil, int numRanks, const char *caller) {
728  // hamil itself already validated as general Pauli Hamiltonian
729 
730  // destroy hamil before raising exceptions if validation fails
731  int isValid;
732 
733  // mustn't be more elements than can fit in the type
734  unsigned int maxQubits = calcLog2(SIZE_MAX);
735  isValid = hamil.numQubits <= maxQubits;
736  if (!isValid)
737  destroyPauliHamil(hamil);
738  QuESTAssert(isValid, E_NUM_AMPS_EXCEED_TYPE, caller);
739 
740  // must be at least one amplitude per node
741  long unsigned int numElems = (1UL<<hamil.numQubits);
742  isValid = numElems >= numRanks;
743  if (!isValid)
744  destroyPauliHamil(hamil);
745  QuESTAssert(isValid, E_DISTRIB_DIAG_OP_TOO_SMALL, caller);
746 
747  // must contain only I and Z
748  for (int p=0; p<hamil.numSumTerms*hamil.numQubits; p++) {
749  isValid = hamil.pauliCodes[p] == PAULI_I || hamil.pauliCodes[p] == PAULI_Z;
750  if (!isValid)
751  destroyPauliHamil(hamil);
752 
753  QuESTAssert(isValid, E_PAULI_HAMIL_NOT_DIAGONAL, caller);
754  }
755 }
756 
757 void validateQubitSubregs(Qureg qureg, int* qubits, int* numQubitsPerReg, const int numRegs, const char* caller) {
759 
760  int i=0;
761  for (int r=0; r<numRegs; r++) {
762  QuESTAssert(numQubitsPerReg[r]>0 && numQubitsPerReg[r]<=qureg.numQubitsRepresented, E_INVALID_NUM_QUBITS, caller);
763 
764  for (int q=0; q < numQubitsPerReg[r]; q++) {
765  QuESTAssert(qubits[i]>=0 && qubits[i]<qureg.numQubitsRepresented, E_INVALID_QUBIT_INDEX, caller);
766  i++;
767  }
768  }
769 
770  QuESTAssert(areUniqueQubits(qubits, i), E_QUBITS_NOT_UNIQUE, caller);
771 }
772 
773 void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal* coeffs, qreal* exponents, int numTerms, long long int* overrideInds, int numOverrides, const char* caller) {
774  QuESTAssert(numTerms>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
775 
776  int hasFractionExpo = 0;
777  int hasNegativeExpo = 0;
778  for (int t=0; t<numTerms; t++) {
779  // this is only true if exponent is precisely an integer, else pow() will NaN
780  if (floor(exponents[t]) != exponents[t])
781  hasFractionExpo = 1;
782  if (exponents[t] < 0)
783  hasNegativeExpo = 1;
784  }
785 
786  // ensure negative exponents are supplied along with a zero-index override
787  if (hasNegativeExpo) {
788  int hasZeroOverride = 0;
789  for (int v=0; v<numOverrides; v++) {
790  if (overrideInds[v] == 0LL) {
791  hasZeroOverride = 1;
792  break;
793  }
794  }
795  QuESTAssert(hasZeroOverride, E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE, caller);
796  }
797 
798  // ensure fractional powers not used with negative numbers, unless overriden
799  if (hasFractionExpo && encoding == TWOS_COMPLEMENT) {
800  long long int numNegInds = (1LL << (numQubits-1));
801 
802  // immediately disqualify if insufficient overrides are given to cover every negative number
803  QuESTAssert(numOverrides >= numNegInds, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
804 
805  int allNegsOverriden;
806 
807  // if there are 16 or fewer qubits (0.5mB cache), use a stack array to tick off overrides
808  if (numQubits < 16) {
809 
810  // flags for {-1,-2,...}; at index {abs(-1)-1, abs(-2)-2, ...}
811  long long int negIsOverriden[32768]; // [numNegInds];
812  for (int i=0; i<numNegInds; i++)
813  negIsOverriden[i] = 0;
814 
815  for (int v=0; v<numOverrides; v++)
816  if (overrideInds[v] < 0)
817  negIsOverriden[ -1 - overrideInds[v] ] = 1;
818 
819  allNegsOverriden = 1;
820  for (int i=0; i<numNegInds; i++) {
821  if (!negIsOverriden[i]) {
822  allNegsOverriden = 0;
823  break;
824  }
825  }
826  }
827  // otherwise, we must trust the user, else impose significant slowdowns on good users
828  else {
829  allNegsOverriden = 1;
830  }
831 
832  QuESTAssert(allNegsOverriden, E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE, caller);
833  }
834 }
835 
836 void validateMultiVarPhaseFuncTerms(int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal* exponents, int* numTermsPerReg, const char* caller) {
838  for (int r=0; r<numRegs; r++)
839  QuESTAssert(numTermsPerReg[r]>0, E_INVALID_NUM_PHASE_FUNC_TERMS, caller);
840 
841  int numTotalTerms = 0;
842  for (int r=0; r<numRegs; r++)
843  numTotalTerms += numTermsPerReg[r];
844 
845  int hasFractionExpo = 0;
846  int hasNegativeExpo = 0;
847  for (int t=0; t<numTotalTerms; t++) {
848  // this is only true if exponent is precisely an integer, else pow() will NaN
849  if (floor(exponents[t]) != exponents[t])
850  hasFractionExpo = 1;
851  if (exponents[t] < 0)
852  hasNegativeExpo = 1;
853  }
854 
855  QuESTAssert(!hasNegativeExpo, E_NEGATIVE_EXPONENT_MULTI_VAR, caller);
856 
857  if (encoding == TWOS_COMPLEMENT)
858  QuESTAssert(!hasFractionExpo, E_FRACTIONAL_EXPONENT_MULTI_VAR, caller);
859 }
860 
861 
862 void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int* overrideInds, int numOverrides, const char* caller) {
863  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
864  QuESTAssert(numOverrides<=(1<<numQubits), E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
865 
866  long long int maxInd;
867  long long int minInd;
868 
869  if (encoding == UNSIGNED) {
870  minInd = 0;
871  maxInd = (1LL << numQubits) - 1;
872  for (int v=0; v<numOverrides; v++)
873  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
874  }
875 
876  if (encoding == TWOS_COMPLEMENT) {
877  int numValQubits = numQubits - 1; // removing sign bit
878  minInd = - (1LL << numValQubits);
879  maxInd = (1LL << numValQubits) - 1;
880  for (int v=0; v<numOverrides; v++)
881  QuESTAssert(overrideInds[v]>=minInd && overrideInds[v]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
882  }
883 
884 }
885 
886 void validateMultiVarPhaseFuncOverrides(int* numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int* overrideInds, int numOverrides, const char* caller) {
887  QuESTAssert(numOverrides>=0, E_INVALID_NUM_PHASE_FUNC_OVERRIDES, caller);
888 
889  if (encoding == UNSIGNED) {
890  int i=0;
891  for (int v=0; v<numOverrides; v++) {
892  for (int r=0; r<numRegs; r++) {
893  long long int maxInd = (1LL << numQubitsPerReg[r]) - 1;
894  QuESTAssert(overrideInds[i]>=0 && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX, caller);
895  i++;
896  }
897  }
898  }
899  else if (encoding == TWOS_COMPLEMENT) {
900  int i=0;
901  for (int v=0; v<numOverrides; v++) {
902  for (int r=0; r<numRegs; r++) {
903  int numValQubits = numQubitsPerReg[r] - 1; // removing sign bit
904  long long int minInd = - (1LL << numValQubits);
905  long long int maxInd = (1LL << numValQubits) - 1;
906  QuESTAssert(overrideInds[i]>=minInd && overrideInds[i]<=maxInd, E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX, caller);
907  i++;
908  }
909  }
910  }
911 }
912 
913 void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char* caller) {
914 
915  QuESTAssert(
916  funcCode == NORM ||
917  funcCode == INVERSE_NORM ||
918  funcCode == SCALED_NORM ||
919  funcCode == SCALED_INVERSE_NORM ||
920  funcCode == SCALED_INVERSE_SHIFTED_NORM ||
921  funcCode == PRODUCT ||
922  funcCode == INVERSE_PRODUCT ||
923  funcCode == SCALED_PRODUCT ||
924  funcCode == SCALED_INVERSE_PRODUCT ||
925  funcCode == DISTANCE ||
926  funcCode == INVERSE_DISTANCE ||
927  funcCode == SCALED_DISTANCE ||
928  funcCode == SCALED_INVERSE_DISTANCE ||
930  E_INVALID_PHASE_FUNC_NAME, caller);
931 
932  if (funcCode == NORM ||
933  funcCode == PRODUCT ||
934  funcCode == DISTANCE)
935  QuESTAssert(numParams == 0, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
936 
937  if (funcCode == INVERSE_NORM ||
938  funcCode == INVERSE_PRODUCT ||
939  funcCode == INVERSE_DISTANCE)
940  QuESTAssert(numParams == 1, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
941 
942  if (funcCode == SCALED_NORM ||
943  funcCode == SCALED_PRODUCT ||
944  funcCode == SCALED_DISTANCE)
945  QuESTAssert(numParams == 1, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
946 
947  if (funcCode == SCALED_INVERSE_NORM ||
948  funcCode == SCALED_INVERSE_PRODUCT ||
949  funcCode == SCALED_INVERSE_DISTANCE)
950  QuESTAssert(numParams == 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
951 
952  if (funcCode == SCALED_INVERSE_SHIFTED_NORM)
953  QuESTAssert(numParams == 2 + numRegs, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
954 
955  if (funcCode == SCALED_INVERSE_SHIFTED_DISTANCE)
956  QuESTAssert(numParams == 2 + numRegs / 2, E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS, caller);
957 
958  if (funcCode == DISTANCE ||
959  funcCode == INVERSE_DISTANCE ||
960  funcCode == SCALED_DISTANCE ||
961  funcCode == SCALED_INVERSE_DISTANCE ||
963  QuESTAssert(numRegs%2 == 0, E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC, caller);
964 }
965 
966 void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char* caller) {
967  QuESTAssert(
968  encoding == UNSIGNED ||
969  encoding == TWOS_COMPLEMENT,
970  E_INVALID_BIT_ENCODING, caller);
971 
972  if (encoding == TWOS_COMPLEMENT)
973  QuESTAssert(numQubits > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
974 }
975 
976 void validateMultiRegBitEncoding(int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char* caller) {
977  QuESTAssert(
978  encoding == UNSIGNED ||
979  encoding == TWOS_COMPLEMENT,
980  E_INVALID_BIT_ENCODING, caller);
981 
982  if (encoding == TWOS_COMPLEMENT)
983  for (int r=0; r<numRegs; r++)
984  QuESTAssert(numQubitsPerReg[r] > 1, E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT, caller);
985 }
986 
987 #ifdef __cplusplus
988 }
989 #endif
@ INVERSE_PRODUCT
Definition: QuEST.h:233
void validateDensityMatrQureg(Qureg qureg, const char *caller)
Represents a 3-vector of real numbers.
Definition: QuEST.h:198
void validateMultiControlsTarget(Qureg qureg, int *controlQubits, int numControlQubits, int targetQubit, const char *caller)
pauliOpType
Codes for specifying Pauli operators.
Definition: QuEST.h:96
@ E_INVALID_TWO_QUBIT_DEPOL_PROB
void validateMeasurementProb(qreal prob, const char *caller)
@ E_NUM_AMPS_EXCEED_TYPE
void validateTarget(Qureg qureg, int targetQubit, const char *caller)
@ E_MISMATCHING_PAULI_HAMIL_DIAGONAL_OP_SIZE
@ E_INVALID_QUBIT_OUTCOME
void validateBitEncoding(int numQubits, enum bitEncoding encoding, const char *caller)
void validateMultiRegBitEncoding(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, const char *caller)
void validateOutcome(int outcome, const char *caller)
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_COEFF
void validateMultiVarPhaseFuncOverrides(int *numQubitsPerReg, const int numRegs, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
int isMatrix2Unitary(ComplexMatrix2 u)
@ E_PAULI_HAMIL_NOT_DIAGONAL
@ PAULI_Z
Definition: QuEST.h:96
@ DISTANCE
Definition: QuEST.h:234
@ E_INVALID_NUM_PHASE_FUNC_TERMS
void validateHamilFileCoeffParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
@ E_INVALID_PAULI_CODE
void validateStateIndex(Qureg qureg, long long int stateInd, const char *caller)
@ E_NON_UNITARY_MATRIX
void validateHamilParams(int numQubits, int numTerms, const char *caller)
@ PAULI_I
Definition: QuEST.h:96
@ E_INVALID_ONE_QUBIT_DEPHASE_PROB
void validateStateVecQureg(Qureg qureg, const char *caller)
void validateMultiQubitMatrixFitsInNode(Qureg qureg, int numTargets, const char *caller)
@ E_INVALID_NUM_REGS_DISTANCE_PHASE_FUNC
void validateNumAmps(Qureg qureg, long long int startInd, long long int numAmps, const char *caller)
@ E_CANNOT_FIT_MULTI_QUBIT_MATRIX
@ E_INVALID_NUM_N_QUBIT_KRAUS_OPS
@ E_INVALID_ELEM_INDEX
int isMatrix4Unitary(ComplexMatrix4 u)
void validateNumQubitsInQureg(int numQubits, int numRanks, const char *caller)
@ TWOS_COMPLEMENT
Definition: QuEST.h:269
void validateMultiQubitUnitaryMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
void validateHamilFilePauliParsed(int parsed, PauliHamil h, FILE *file, char *fn, const char *caller)
@ E_MISMATCHING_QUREG_TYPES
void validateNumControls(Qureg qureg, int numControlQubits, const char *caller)
int isCompletelyPositiveMap4(ComplexMatrix4 *ops, int numOps)
@ E_CANNOT_PARSE_PAULI_HAMIL_FILE_PAULI
#define macro_isCompletelyPositiveMap(ops, numOps, opDim)
@ E_INVALID_QUBIT_INDEX
void validateHamilFilePauliCode(enum pauliOpType code, PauliHamil h, FILE *file, char *fn, const char *caller)
@ E_INVALID_PHASE_FUNC_NAME
void validateProb(qreal prob, const char *caller)
@ E_INVALID_BIT_ENCODING
@ NORM
Definition: QuEST.h:232
void validateMultiVarPhaseFuncTerms(int *numQubitsPerReg, int numRegs, enum bitEncoding encoding, qreal *exponents, int *numTermsPerReg, const char *caller)
@ E_NON_UNITARY_COMPLEX_PAIR
int isVectorUnit(qreal ux, qreal uy, qreal uz)
void validatePhaseFuncOverrides(const int numQubits, enum bitEncoding encoding, long long int *overrideInds, int numOverrides, const char *caller)
Represents a 4x4 matrix of complex numbers.
Definition: QuEST.h:175
@ SCALED_INVERSE_DISTANCE
Definition: QuEST.h:234
@ UNSIGNED
Definition: QuEST.h:269
@ E_INVALID_NUM_SUBREGISTERS
@ E_INVALID_CONTROLS_BIT_STATE
@ E_INVALID_TROTTER_ORDER
@ E_INVALID_NUM_TWO_QUBIT_KRAUS_OPS
@ E_DISTRIB_DIAG_OP_TOO_SMALL
Represents a general 2^N by 2^N matrix of complex numbers.
Definition: QuEST.h:186
@ INVERSE_DISTANCE
Definition: QuEST.h:234
void validateTwoQubitDepolProb(qreal prob, const char *caller)
@ E_SECOND_ARG_MUST_BE_STATEVEC
@ E_INVALID_CONTROL_QUBIT
void validateNumPauliSumTerms(int numTerms, const char *caller)
@ E_INVALID_NUM_SUM_TERMS
@ E_DEFINED_ONLY_FOR_STATEVECS
#define qreal
void validateMatrixInit(ComplexMatrixN matr, const char *caller)
void validateFileOpened(int opened, char *fn, const char *caller)
int isCompletelyPositiveMap2(ComplexMatrix2 *ops, int numOps)
@ E_INVALID_PAULI_HAMIL_FILE_PAULI_CODE
unsigned int calcLog2(long unsigned int num)
returns log2 of numbers which must be gauranteed to be 2^n
@ E_NEGATIVE_EXPONENT_MULTI_VAR
void validateControl(Qureg qureg, int controlQubit, const char *caller)
#define macro_isMatrixUnitary(m, dim, retVal)
@ PAULI_X
Definition: QuEST.h:96
int isComplexUnit(Complex alpha)
@ E_INVALID_PROB
void validateNumTargets(Qureg qureg, int numTargetQubits, const char *caller)
int isMatrixNUnitary(ComplexMatrixN u)
@ E_QUBITS_NOT_UNIQUE
void validateVector(Vector vec, const char *caller)
@ E_INVALID_PHASE_FUNC_OVERRIDE_TWOS_COMPLEMENT_INDEX
void validateMultiQubits(Qureg qureg, int *qubits, int numQubits, const char *caller)
@ E_CONTROL_TARGET_COLLISION
void invalidQuESTInputError(const char *errMsg, const char *errFunc)
An internal function called when invalid arguments are passed to a QuEST API call,...
@ E_DEFINED_ONLY_FOR_DENSMATRS
@ E_INVALID_KRAUS_OPS
@ E_INVALID_OFFSET_NUM_AMPS_QUREG
@ E_INVALID_STATE_INDEX
void validateControlTarget(Qureg qureg, int controlQubit, int targetQubit, const char *caller)
void validateDiagonalOp(Qureg qureg, DiagonalOp op, const char *caller)
qreal * imag
The imaginary values of the 2^numQubits complex elements.
Definition: QuEST.h:310
int areUniqueQubits(int *qubits, int numQubits)
@ E_TARGET_IN_CONTROLS
phaseFunc
Flags for specifying named phase functions.
Definition: QuEST.h:231
@ E_INVALID_NUM_QUBITS
long long int numAmpsPerChunk
Number of probability amplitudes held in stateVec by this process In the non-MPI version,...
Definition: QuEST.h:332
@ E_TARGET_IS_CONTROL
@ E_INVALID_PAULI_HAMIL_PARAMS
@ E_INVALID_UNITARY_SIZE
@ E_INVALID_ONE_QUBIT_PAULI_PROBS
void validateOneQubitDephaseProb(qreal prob, const char *caller)
enum pauliOpType * pauliCodes
The Pauli operators acting on each qubit, flattened over every operator.
Definition: QuEST.h:281
@ E_MISMATCHING_NUM_TARGS_KRAUS_SIZE
void validateControlState(int *controlState, int numControlQubits, const char *caller)
@ SCALED_PRODUCT
Definition: QuEST.h:233
void validateMultiTargets(Qureg qureg, int *targetQubits, int numTargetQubits, const char *caller)
int isValidPauliCode(enum pauliOpType code)
#define MAX_NUM_REGS_APPLY_ARBITRARY_PHASE
@ E_INVALID_TARGET_QUBIT
@ E_COMPLEX_MATRIX_NOT_INIT
void validateMatchingQuregDims(Qureg qureg1, Qureg qureg2, const char *caller)
@ E_CANNOT_OPEN_FILE
@ E_DISTRIB_QUREG_TOO_SMALL
int numQubits
The number of qubits this operator can act on (informing its size)
Definition: QuEST.h:300
@ E_INVALID_NUM_ONE_QUBIT_KRAUS_OPS
int numSumTerms
The number of terms in the weighted sum, or the number of Pauli products.
Definition: QuEST.h:285
long long int getQubitBitMask(int *qubits, int numQubits)
Definition: QuEST_common.c:50
@ E_MISMATCHING_QUREG_DIAGONAL_OP_SIZE
Represents a diagonal complex operator on the full Hilbert state of a Qureg.
Definition: QuEST.h:297
@ PAULI_Y
Definition: QuEST.h:96
A Pauli Hamiltonian, expressed as a real-weighted sum of pauli products, and which can hence represen...
Definition: QuEST.h:277
void validateNumElems(DiagonalOp op, long long int startInd, long long int numElems, const char *caller)
@ E_INVALID_AMP_INDEX
void validateOneQubitKrausMap(Qureg qureg, ComplexMatrix2 *ops, int numOps, const char *caller)
@ SCALED_INVERSE_SHIFTED_NORM
Definition: QuEST.h:232
qreal ** real
Definition: QuEST.h:189
void validateQubitSubregs(Qureg qureg, int *qubits, int *numQubitsPerReg, const int numRegs, const char *caller)
@ E_INVALID_NUM_RANKS
@ E_INVALID_TWO_QUBIT_DEPHASE_PROB
@ E_MISMATCHING_PAULI_HAMIL_QUREG_NUM_QUBITS
static const char * errorMessages[]
void QuESTAssert(int isValid, ErrorCode code, const char *func)
void validateDiagPauliHamil(DiagonalOp op, PauliHamil hamil, const char *caller)
@ E_INVALID_NUM_AMPS
void validateOneQubitDepolProb(qreal prob, const char *caller)
@ E_COLLAPSE_STATE_ZERO_PROB
void validateTwoQubitKrausMap(Qureg qureg, ComplexMatrix4 *ops, int numOps, const char *caller)
@ E_TARGETS_NOT_UNIQUE
@ INVERSE_NORM
Definition: QuEST.h:232
Represents a system of qubits.
Definition: QuEST.h:322
void validateDiagPauliHamilFromFile(PauliHamil hamil, int numRanks, const char *caller)
void validateNumQubitsInMatrix(int numQubits, const char *caller)
qreal ** imag
Definition: QuEST.h:190
void validatePhaseFuncName(enum phaseFunc funcCode, int numRegs, int numParams, const char *caller)
@ E_MISMATCHING_QUREG_DIMENSIONS
ErrorCode
@ E_INVALID_TROTTER_REPS
@ E_INVALID_NUM_CONTROLS
@ PRODUCT
Definition: QuEST.h:233
void validatePauliHamil(PauliHamil hamil, const char *caller)
void validateTwoQubitUnitaryMatrix(Qureg qureg, ComplexMatrix4 u, const char *caller)
char errMsgBuffer[1024]
@ E_INVALID_NUM_CREATE_QUBITS
void validateDiagOpInit(DiagonalOp op, const char *caller)
@ E_INVALID_NUM_NAMED_PHASE_FUNC_PARAMS
void validateMatchingQuregPauliHamilDims(Qureg qureg, PauliHamil hamil, const char *caller)
int isDensityMatrix
Whether this instance is a density-state representation.
Definition: QuEST.h:325
void validateMatchingQuregTypes(Qureg qureg1, Qureg qureg2, const char *caller)
int numQubits
Definition: QuEST.h:188
void validateAmpIndex(Qureg qureg, long long int ampInd, const char *caller)
@ E_INVALID_OFFSET_NUM_ELEMS_DIAG
qreal getVectorMagnitude(Vector vec)
Definition: QuEST_common.c:79
void validateHamilFileParams(int numQubits, int numTerms, FILE *file, char *fn, const char *caller)
void validateOneQubitUnitaryMatrix(ComplexMatrix2 u, const char *caller)
@ E_INVALID_PAULI_HAMIL_FILE_PARAMS
void validateSecondQuregStateVec(Qureg qureg2, const char *caller)
int numQubits
The number of qubits informing the Hilbert dimension of the Hamiltonian.
Definition: QuEST.h:287
@ E_UNNORM_PROBS
int numQubitsRepresented
The number of qubits represented in either the state-vector or density matrix.
Definition: QuEST.h:327
@ E_INVALID_NUM_PHASE_FUNC_OVERRIDES
@ E_INVALID_PHASE_FUNC_OVERRIDE_UNSIGNED_INDEX
long long int numAmpsTotal
Total number of amplitudes, which are possibly distributed among machines.
Definition: QuEST.h:334
@ SCALED_DISTANCE
Definition: QuEST.h:234
void validateMultiControlsMultiTargets(Qureg qureg, int *controlQubits, int numControlQubits, int *targetQubits, int numTargetQubits, const char *caller)
qreal * real
The real values of the 2^numQubits complex elements.
Definition: QuEST.h:308
@ E_FRACTIONAL_EXPONENT_MULTI_VAR
qreal real
Definition: QuEST.h:105
void validatePhaseFuncTerms(int numQubits, enum bitEncoding encoding, qreal *coeffs, qreal *exponents, int numTerms, long long int *overrideInds, int numOverrides, const char *caller)
@ E_INVALID_NUM_QUBITS_TWOS_COMPLEMENT
void destroyPauliHamil(PauliHamil h)
Destroy a PauliHamil instance, created with either createPauliHamil() or createPauliHamilFromFile().
Definition: QuEST.c:1414
int isCompletelyPositiveMapN(ComplexMatrixN *ops, int numOps)
qreal imag
Definition: QuEST.h:106
void validateMultiControls(Qureg qureg, int *controlQubits, int numControlQubits, const char *caller)
@ E_INVALID_NUM_ELEMS
void validateMultiQubitKrausMap(Qureg qureg, int numTargs, ComplexMatrixN *ops, int numOps, const char *caller)
void validateMultiQubitMatrix(Qureg qureg, ComplexMatrixN u, int numTargs, const char *caller)
void validateNumQubitsInDiagOp(int numQubits, int numRanks, const char *caller)
@ E_NEGATIVE_EXPONENT_WITHOUT_ZERO_OVERRIDE
@ E_INVALID_NUM_TARGETS
@ E_SYS_TOO_BIG_TO_PRINT
void validateNumRanks(int numRanks, const char *caller)
@ SCALED_INVERSE_SHIFTED_DISTANCE
Definition: QuEST.h:234
Represents one complex number.
Definition: QuEST.h:103
@ SCALED_NORM
Definition: QuEST.h:232
@ SCALED_INVERSE_PRODUCT
Definition: QuEST.h:233
void validateTrotterParams(int order, int reps, const char *caller)
int isComplexPairUnitary(Complex alpha, Complex beta)
void validatePauliCodes(enum pauliOpType *pauliCodes, int numPauliCodes, const char *caller)
@ E_DIAGONAL_OP_NOT_INITIALISED
void validateUnitaryComplexPair(Complex alpha, Complex beta, const char *caller)
@ E_INVALID_ONE_QUBIT_DEPOL_PROB
void validateNormProbs(qreal prob1, qreal prob2, const char *caller)
@ E_SUCCESS
void validateOneQubitDampingProb(qreal prob, const char *caller)
@ E_ZERO_VECTOR
void default_invalidQuESTInputError(const char *errMsg, const char *errFunc)
@ E_CONTROLS_NOT_UNIQUE
@ E_FRACTIONAL_EXPONENT_WITHOUT_NEG_OVERRIDE
void validateUniqueTargets(Qureg qureg, int qubit1, int qubit2, const char *caller)
bitEncoding
Flags for specifying how the bits in sub-register computational basis states are mapped to indices in...
Definition: QuEST.h:269
void validateTwoQubitDephaseProb(qreal prob, const char *caller)
Represents a 2x2 matrix of complex numbers.
Definition: QuEST.h:137
void validateOneQubitPauliProbs(qreal probX, qreal probY, qreal probZ, const char *caller)
@ SCALED_INVERSE_NORM
Definition: QuEST.h:232