The Quantum Exact Simulation Toolkit v4.0.0
Loading...
Searching...
No Matches
test_utilities.hpp
1/** @file
2 * Utility signatures used by the ported v3 tests of QuEST's deprecated v3 API.
3 *
4 * @author Tyson Jones
5 * @author Oliver Thomson Brown (ported to Catch2 v3)
6 * @author Ali Rezaei (tested porting to QuEST v4)
7 */
8
9#ifndef QUEST_TEST_UTILS_H
10#define QUEST_TEST_UTILS_H
11
12#include "quest/include/quest.h"
13
14#include <catch2/generators/catch_generators.hpp>
15
16#include <string>
17#include <vector>
18
19using std::string;
20using std::vector;
21
22/** The default number of qubits in the registers created for unit testing
23 * (both statevectors and density matrices). Creation of non-NUM_QUBITS sized
24 * Quregs should be justified in a comment.
25 * Note that the smaller this number is, the fewer nodes can be employed in
26 * distribution testing, since each node must contain at least one amplitude.
27 * Furthermore, the larger this number is, the greater the deviation of correct
28 * results from their expected value, due to numerical error; this is especially
29 * apparent for density matrices.
30 */
31#define NUM_QUBITS 5
32
33
34// replace REAL_EPS macro with constant
35#undef REAL_EPS
36#if FLOAT_PRECISION == 1
37 constexpr qreal REAL_EPS = 1E-1;
38#elif FLOAT_PRECISION == 2
39 constexpr qreal REAL_EPS = 1E-8;
40#elif FLOAT_PRECISION == 4
41 constexpr qreal REAL_EPS = 1E-10;
42#endif
43
44
45#ifndef M_PI
46#define M_PI 3.141592653589793238
47#endif
48
49/** A complex square matrix.
50 * Should be initialised with getZeroMatrix().
51 * These have all the natural linear-algebra operator overloads, including
52 * left-multiplication onto a vector.
53 *
54 * This data-structure is not partitioned between nodes in distributed mode.
55 * That is, every node has a complete copy, allowing for safe comparisons.
56 *
57 * @ingroup deprecatedutils
58 * @author Tyson Jones
59 */
60typedef vector<vector<qcomp>> QMatrix;
61
62/** A complex vector, which can be zero-initialised with QVector(numAmps).
63 * These have all the natural linear-algebra operator overloads.
64 *
65 * This data-structure is not partitioned between nodes in distributed mode.
66 * That is, every node has a complete copy, allowing for safe comparisons.
67 *
68 * @ingroup deprecatedutils
69 * @author Tyson Jones
70 */
71typedef vector<qcomp> QVector;
72
73/** Seed the C and C++ RNGs using hardware CSPRNG
74 *
75 * @ingroup deprecatedutils
76 * @author Tyson Jones
77 */
79
80#ifdef absReal
81#undef absReal
82#endif
83qreal absReal(qreal x);
84qreal absComp(qcomp x);
85
86/** Asserts the given statevector qureg and reference agree, and are properly initialised in the debug state.
87 * Assertion uses the DEMAND() macro, calling Catch2's FAIL() if unsatisfied, so does not contribute
88 * toward unit test statistics. This should be called within every PREPARE_TEST macro, to ensure that
89 * the test states themselves are initially correct, and do not accidentally agree by (e.g.) being all-zero.
90 *
91 * @ingroup deprecatedutils
92 * @author Tyson Jones
93 */
95
96/** Asserts the given density qureg and reference agree, and are properly initialised in the debug state.
97 * Assertion uses the DEMAND() macro, calling Catch2's FAIL() if unsatisfied, so does not contribute
98 * toward unit test statistics. This should be called within every PREPARE_TEST macro, to ensure that
99 * the test states themselves are initially correct, and do not accidentally agree by (e.g.) being all-zero.
100 *
101 * @ingroup deprecatedutils
102 * @author Tyson Jones
103 */
105
106/* (Excluded from Doxygen doc)
107 *
108 * Define QVector and QMatrix operator overloads.
109 * Note that QMatrix overloads don't simply use QVector
110 * overloads, since the complex vector dot product involves
111 * conjugation, which doesn't occur in complex matrix multiplication.
112 * Note too we also avoid defining operators in terms of other operators
113 * (e.g. minus is plus(negative times)) since compiler optimisations
114 * may change the order of operations and confuse the overloads invoked.
115 * Definition of division using multiplication can furthermore
116 * heighten numerical errors.
117 *
118 * @ingroup deprecatedutils
119 * @author Tyson Jones
120 */
121QVector operator + (const QVector& v1, const QVector& v2);
122QVector operator - (const QVector& v1, const QVector& v2);
123QVector operator * (const qcomp& a, const QVector& v);
124QVector operator * (const QVector& v, const qcomp& a);
125QVector operator / (const QVector& v, const qcomp& a);
126qcomp operator * (const QVector &v1, const QVector& v2);
127void operator += (QVector& v1, const QVector& v2);
128void operator -= (QVector& v1, const QVector& v2);
129void operator *= (QVector& v1, const qcomp& a);
130void operator /= (QVector& v1, const qcomp& a);
131QMatrix operator + (const QMatrix& m1, const QMatrix& m2);
132QMatrix operator - (const QMatrix& m1, const QMatrix& m2);
133QMatrix operator * (const qcomp& a, const QMatrix& m);
134QMatrix operator * (const QMatrix& m, const qcomp& a);
135QMatrix operator / (const QMatrix& m, const qcomp& a);
136QMatrix operator * (const QMatrix& m1, const QMatrix& m2);
137void operator += (QMatrix& m1, const QMatrix& m2);
138void operator -= (QMatrix& m1, const QMatrix& m2);
139void operator *= (QMatrix& m1, const qreal& a);
140void operator /= (QMatrix& m1, const qreal& a);
141void operator *= (QMatrix& m1, const QMatrix& m2);
142QVector operator * (const QMatrix& m, const QVector& v);
143
144/** Returns an equal-size copy of the given state-vector \p qureg.
145 * In GPU mode, this function involves a copy of \p qureg from GPU memory to RAM.
146 * In distributed mode, this involves an all-to-all broadcast of \p qureg.
147 *
148 * @ingroup deprecatedutils
149 * @author Tyson Jones
150 */
151QVector toQVector(Qureg qureg);
152
153/** Returns a vector with the given diagonal's elements.
154 * In distributed mode, this involves an all-to-all broadcast of \p op.
155 *
156 * @ingroup deprecatedutils
157 * @author Tyson Jones
158 */
160
161/** Returns a vector with the given diagonal's elements.
162 * In distributed mode, this involves an all-to-all broadcast of \p op.
163 *
164 * @ingroup deprecatedutils
165 * @author Tyson Jones
166 */
168
169/** Returns an equal-size copy of the given density matrix \p qureg.
170 * In GPU mode, this function involves a copy of \p qureg from GPU memory to RAM.
171 * In distributed mode, this involves an all-to-all broadcast of \p qureg.
172 *
173 * @ingroup deprecatedutils
174 * @author Tyson Jones
175 */
176QMatrix toQMatrix(Qureg qureg);
177
178/** Returns a copy of the given 2-by-2 matrix.
179 *
180 * @ingroup deprecatedutils
181 * @author Tyson Jones
182 */
184
185/** Returns a copy of the given 4-by-4 matrix.
186 *
187 * @ingroup deprecatedutils
188 * @author Tyson Jones
189 */
191
192/** Returns a copy of the given matrix
193 *
194 * @ingroup deprecatedutils
195 * @author Tyson Jones
196 */
198
199/** Returns a 2^\p N-by-2^\p N Hermitian matrix form of the specified
200 * weighted sum of Pauli products
201 *
202 * @ingroup deprecatedutils
203 * @author Tyson Jones
204 */
205QMatrix toQMatrix(qreal* coeffs, pauliOpType* paulis, int numQubits, int numTerms);
206
207/** Returns a 2^\p N-by-2^\p N Hermitian matrix form of the PauliHamil
208 *
209 * @ingroup deprecatedutils
210 * @author Tyson Jones
211 */
212QMatrix toQMatrix(PauliHamil hamil);
213
214/** Returns a 2^\p N-by-2^\p N Hermitian Z-basis
215 * matrix of the given complex-weighted sum of Pauli
216 * strings, where N is the number of non-Identity
217 * operators.
218 *
219 * @ingroup deprecatedutils
220 * @author Tyson Jones
221 */
223
224/** Returns a dense matrix equivalent to the given diagonal
225 *
226 * @ingroup deprecatedutils
227 * @author Tyson Jones
228 */
230
231/** Returns a dense matrix equivalent to the given diagonal
232 *
233 * @ingroup deprecatedutils
234 * @author Tyson Jones
235 */
237
238/** Returns a \p ComplexMatrix2 copy of QMatix \p qm.
239 * Demands that \p qm is a 2-by-2 matrix.
240 *
241 * @ingroup deprecatedutils
242 * @author Tyson Jones
243 */
245
246/** Returns a \p ComplexMatrix4 copy of QMatix \p qm.
247 * Demands that \p qm is a 4-by-4 matrix.
248 *
249 * @ingroup deprecatedutils
250 * @author Tyson Jones
251 */
253
254/** Populates the ComplexMatrixN with the contents of a QMatrix. In
255 * GPU-mode, this will then sync the elements ot the matrix's
256 * persistent GPU memory
257 *
258 * @ingroup deprecatedutils
259 * @author Tyson Jones
260 */
261void toComplexMatrixN(QMatrix qm, ComplexMatrixN cm);
262
263/** Returns a diagonal complex matrix formed by the given vector
264 *
265 * @ingroup deprecatedutils
266 * @author Tyson Jones
267 */
269
270/** Initialises the state-vector \p qureg to have the same amplitudes as \p vec.
271 * Demands \p qureg is a state-vector of an equal size to \p vec.
272 * In GPU mode, this function involves a copy from RAM to GPU memory.
273 * This function has no communication cost in distributed mode.
274 *
275 * @ingroup deprecatedutils
276 * @author Tyson Jones
277 */
278void toQureg(Qureg qureg, QVector vec);
279
280/** Initialises the density matrix \p qureg to have the same amplitudes as \p mat.
281 * Demands \p qureg is a density matrix of equal dimensions to \p mat.
282 * In GPU mode, this function involves a copy from RAM to GPU memory.
283 * This function has no communication cost in distributed mode.
284 *
285 * @ingroup deprecatedutils
286 * @author Tyson Jones
287 */
288void toQureg(Qureg qureg, QMatrix mat);
289
290/** Returns b (otimes) a. If b and a are state-vectors, the resulting kronecker
291 * product is the seperable state formed by joining the qubits in the state-vectors,
292 * producing |b>|a> (a is least significant)
293 *
294 * @ingroup deprecatedutils
295 * @author Tyson Jones
296 */
298
299/** Returns a dim-by-dim square complex matrix, initialised to all zeroes.
300 *
301 * @ingroup deprecatedutils
302 * @author Tyson Jones
303 */
304QMatrix getZeroMatrix(size_t dim);
305
306/** Returns a dim-by-dim identity matrix
307 *
308 * @ingroup deprecatedutils
309 * @author Tyson Jones
310 */
311QMatrix getIdentityMatrix(size_t dim);
312
313/** Returns the matrix exponential of a diagonal, square, complex matrix.
314 * This method explicitly checks that the passed matrix \p a is diagonal.
315 *
316 * @ingroup deprecatedutils
317 * @author Tyson Jones
318 */
320
321/** Returns the matrix exponential of a kronecker product of pauli matrices
322 * (or of any involutory matrices), with exponent factor (-i \p angle / 2).
323 * This method will not explicitly check that the passed matrix \p a is
324 * kronecker product of involutory matrices, but will otherwise return an
325 * incorrect exponential.
326 *
327 * @ingroup deprecatedutils
328 * @author Tyson Jones
329 */
331
332/** Returns the kronecker product of \p a and \p b, where \p a and \p b are
333 * square but possibly differently-sized complex matrices.
334 *
335 * @ingroup deprecatedutils
336 * @author Tyson Jones
337 */
339
340/** Returns the 2^\p numQb-by-2^\p numQb unitary matrix which swaps qubits
341 * \p qb1 and \p qb2; the SWAP gate of not-necessarily-adjacent qubits.
342 * If \p qb1 == \p qb2, returns the identity matrix.
343 *
344 * @ingroup deprecatedutils
345 * @author Tyson Jones
346 */
347QMatrix getSwapMatrix(int qb1, int qb2, int numQb);
348
349/** Takes a 2^\p numTargs-by-2^\p numTargs matrix \p op and a returns a
350 * 2^\p numQubits-by-2^\p numQubits matrix where \p op is controlled on the given
351 * \p ctrls qubits. The union of {\p ctrls} and {\p targs} must be unique (though
352 * this is not explicitly checked), and every element must be >= 0 (not checked).
353 * The passed {\p ctrls} and {\p targs} arrays are unmodified.
354 *
355 * This funciton works by first swapping {\p targs} and {\p ctrls} (via swap unitaries)
356 * to be strictly increasing {0,1,...}, building controlled(\p op), tensoring it to
357 * the full Hilbert space, and then 'unswapping'. The returned matrix has form:
358 * swap1 ... swapN . controlled(\p op) . swapN ... swap1
359 *
360 * @ingroup deprecatedutils
361 * @author Tyson Jones
362 */
363QMatrix getFullOperatorMatrix(int* ctrls, int numCtrls, int *targs, int numTargs, QMatrix op, int numQubits);
364
365/** Returns the matrix |\p ket><\p bra|, with ith-jth element \p ket(i) conj(\p bra(j)), since
366 * |\p ket><\p bra| = sum_i a_i|i> sum_j b_j* <j| = sum_{ij} a_i b_j* |i><j|.
367 * The dimensions of bra and ket must agree, and the returned square complex matrix
368 * has dimensions size(bra) x size(bra).
369 *
370 * @ingroup deprecatedutils
371 * @author Tyson Jones
372 */
374
375/** Returns the conjugate transpose of the complex square matrix \p a
376 *
377 * @ingroup deprecatedutils
378 * @author Tyson Jones
379 */
381
382/** Returns a random integer between \p min (inclusive) and \p max (exclusive),
383 * from the uniform distribution.
384 * Demands that \p max > \p min.
385 *
386 * @ingroup deprecatedutils
387 * @author Tyson Jones
388 */
389int getRandomInt(int min, int max);
390
391/** Returns a random real between \p min (inclusive) and \p max (exclusive),
392 * from the uniform distribution.
393 * Demands that \p max > \p min.
394 *
395 * @ingroup deprecatedutils
396 * @author Tyson Jones
397 */
398qreal getRandomReal(qreal min, qreal max);
399
400/** Returns a random complex number within the square closing (-1-i) and (1+i),
401 * from a distribution uniformly randomising the individual real and imaginary
402 * components in their domains.
403 *
404 * @ingroup deprecatedutils
405 * @author Tyson Jones
406 */
407qcomp getRandomComplex();
408
409/** Returns a \p dim-length vector with random complex amplitudes in the
410 * square joining {-1-i, 1+i}, of an undisclosed distribution. The resulting
411 * vector is NOT L2-normalised.
412 *
413 * @ingroup deprecatedutils
414 * @author Tyson Jones
415 */
417
418/** Returns a \p dim-by-\p dim complex matrix, where the real and imaginary value of
419 * each element are independently random, under the standard normal distribution
420 * (mean 0, standard deviation 1).
421 *
422 * @ingroup deprecatedutils
423 * @author Tyson Jones
424 */
426
427/** Returns a uniformly random (under Haar) 2^\p numQb-by-2^\p numQb unitary matrix.
428 * This function works by first generating a complex matrix where
429 * each element is independently random; the real and imaginary component thereof are
430 * independent standard normally-distributed (mean 0, standard-dev 1).
431 * Then, the matrix is orthonormalised via the Gram Schmidt algorithm.
432 * The resulting unitary matrix MAY be uniformly distributed under the Haar
433 * measure, but we make no assurance.
434 * This routine may return an identity matrix if it was unable to sufficiently
435 * precisely produce a unitary of the given size.
436 *
437 * @ingroup deprecatedutils
438 * @author Tyson Jones
439 */
440QMatrix getRandomUnitary(int numQb);
441
442/** Returns a random \p numQb-length L2-normalised state-vector from an
443 * undisclosed distribution. This function works by randomly generating each
444 * complex amplitude, then L2-normalising.
445 *
446 * @ingroup deprecatedutils
447 * @author Tyson Jones
448 */
450
451/** Returns a random \p numQb-by-\p numQb density matrix, from an undisclosed
452 * distribution, in a very mixed state. This function works by generating
453 * 2^\p numQb random pure states, and mixing them with random probabilities.
454 *
455 * @ingroup deprecatedutils
456 * @author Tyson Jones
457 */
459
460/** Returns a random \p numQb-by-\p numQb density matrix, from an undisclosed
461 * distribution, which is pure (corresponds to a random state-vector)
462 *
463 * @ingroup deprecatedutils
464 * @author Tyson Jones
465 */
467
468/** Returns a density matrix initialised into the given pure state
469 *
470 * @ingroup deprecatedutils
471 * @author Tyson Jones
472 */
474
475/** Returns the diagonal vector of the given matrix
476 *
477 * @ingroup deprecatedutils
478 * @author Tyson Jones
479 */
481
482/** Returns a random Kraus map of #`numOps` 2^\p numQb-by-2^\p numQb operators,
483 * from an undisclosed distribution.
484 * Note this method is very simple and cannot generate all possible Kraus maps.
485 * It works by generating \p numOps random unitary matrices, and randomly
486 * re-normalising them, such that the sum of ops[j]^dagger ops[j] = 1
487 *
488 * @ingroup deprecatedutils
489 * @author Tyson Jones
490 */
491vector<QMatrix> getRandomKrausMap(int numQb, int numOps);
492
493/** Returns a list of random real scalars, each in [0, 1], which sum to unity.
494 *
495 * @ingroup deprecatedutils
496 * @author Tyson Jones
497 */
498vector<qreal> getRandomProbabilities(int numProbs);
499
500/** Returns a list of random orthonormal complex vectors, from an undisclosed
501 * distribution.
502 *
503 * @ingroup deprecatedutils
504 * @author Tyson Jones
505 */
506vector<QVector> getRandomOrthonormalVectors(int numQb, int numStates);
507
508/** Returns a mixed density matrix formed from mixing the given pure states,
509 * which are assumed normalised, but not necessarily orthogonal.
510 *
511 * @ingroup deprecatedutils
512 * @author Tyson Jones
513 */
514QMatrix getMixedDensityMatrix(vector<qreal> probs, vector<QVector> states);
515
516/** Returns an L2-normalised copy of \p vec, using Kahan summation for improved accuracy.
517 *
518 * @ingroup deprecatedutils
519 * @author Tyson Jones
520 */
522
523/** Returns the discrete fourier transform of vector in
524 *
525 * @ingroup deprecatedutils
526 * @author Tyson Jones
527 */
529
530/** Returns the discrete fourier transform of a sub-partition of the vector in.
531 *
532 * @ingroup deprecatedutils
533 * @author Tyson Jones
534 */
535QVector getDFT(QVector in, int* targs, int numTargs);
536
537/** Returns the integer value of the targeted sub-register for the given
538 * full state index \p ind.
539 *
540 * @ingroup deprecatedutils
541 * @author Tyson Jones
542 */
543long long int getValueOfTargets(long long int ind, int* targs, int numTargs);
544
545/** Modifies \p dest by overwriting its submatrix (from top-left corner
546 * (\p r, \p c) to bottom-right corner (\p r + \p dest.size(), \p c + \p dest.size())
547 * with the complete elements of sub.
548 * This demands that dest.size() >= sub.size() + max(r,c).
549 *
550 * @ingroup deprecatedutils
551 * @author Tyson Jones
552 */
553void setSubMatrix(QMatrix &dest, QMatrix sub, size_t r, size_t c);
554
555 /** Modifies the density matrix \p state to be the result of applying the multi-target operator
556 * matrix \p op, with the specified control and target qubits (in \p ctrls and \p targs
557 * respectively). This updates \p state under
558 * \f[
559 \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger
560 * \f]
561 * even if \p op is not unitary (which is useful for applying Kraus operators).
562 *
563 * \p op must be a 2^\p numTargs-by-2^\p numTargs matrix. Furthermore, every element of \p targs
564 * must not appear in \p ctrls (and vice-versa), though this is not explicitly checked.
565 * Elements of \p targs and \p ctrls should be unique.
566 *
567 * This function works by computing getFullOperatorMatrix() from the given
568 * arguments, and left-multipling it to \p state, then right-multiplying its
569 * conjugate transpose onto the result.
570 *
571 * @ingroup deprecatedutils
572 * @author Tyson Jones
573 */
574void applyReferenceOp(QMatrix &state, int* ctrls, int numCtrls, int *targs, int numTargs, QMatrix op);
575
576/** Modifies the density matrix \p state to be the result of applying the two-target operator
577 * matrix \p op, with the specified control qubits (in \p ctrls).
578 * This updates \p state under
579 * \f[
580 \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger
581 * \f]
582 * even if \p op is not unitary (which is useful for applying Kraus operators).
583 *
584 * \p op must be a 4-by-4 matrix. Both \p targ1 and \p targ2 must not appear in \p ctrls,
585 * though this is not explicitly checked. Elements of \p ctrls, and \p targ1 and \p targ2,
586 * should be unique.
587 *
588 * This function works by computing getFullOperatorMatrix() from the given
589 * arguments, and left-multipling it to \p state, then right-multiplying its
590 * conjugate transpose onto the result.
591 *
592 * @ingroup deprecatedutils
593 * @author Tyson Jones
594 */
595void applyReferenceOp(QMatrix &state, int* ctrls, int numCtrls, int targ1, int targ2, QMatrix op);
596
597/** Modifies the density matrix \p state to be the result of applying the single-target
598 * operator matrix \p op, with the specified control qubits (in \p ctrls).
599 * This updates \p state under
600 * \f[
601 \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger
602 * \f]
603 * even if \p op is not unitary (which is useful for applying Kraus operators).
604 *
605 * \p op must be a 2-by-2 matrix. \p target must not appear in \p ctrls,
606 * though this is not explicitly checked.
607 *
608 * This function works by computing getFullOperatorMatrix() from the given
609 * arguments, and left-multipling it to \p state, then right-multiplying its
610 * conjugate transpose onto the result.
611 *
612 * @ingroup deprecatedutils
613 * @author Tyson Jones
614 */
615void applyReferenceOp(QMatrix &state, int* ctrls, int numCtrls, int target, QMatrix op);
616
617/** Modifies the density matrix \p state to be the result of applying the multi-target
618 * operator matrix \p op, with no control qubits.
619 * This updates \p state under
620 * \f[
621 \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger
622 * \f]
623 * even if \p op is not unitary (which is useful for applying Kraus operators).
624 *
625 * \p op must be a 2^\p numTargs-by-2^\p numTargs matrix.
626 * Every element in \p targs should be unique, though this is not explicitly checked.
627 *
628 * This function works by computing getFullOperatorMatrix() from the given
629 * arguments, and left-multipling it to \p state, then right-multiplying its
630 * conjugate transpose onto the result.
631 *
632 * @ingroup deprecatedutils
633 * @author Tyson Jones
634 */
635void applyReferenceOp(QMatrix &state, int *targs, int numTargs, QMatrix op);
636
637/** Modifies the density matrix \p state to be the result of applying the single-control
638 * single-target operator matrix \p op.
639 * This updates \p state under
640 * \f[
641 \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger
642 * \f]
643 * even if \p op is not unitary (which is useful for applying Kraus operators).
644 *
645 * \p op must be a 2-by-2 matrix, and \p ctrl and \p targ should be different.
646 *
647 * This function works by computing getFullOperatorMatrix() from the given
648 * arguments, and left-multipling it to \p state, then right-multiplying its
649 * conjugate transpose onto the result.
650 *
651 * @ingroup deprecatedutils
652 * @author Tyson Jones
653 */
654void applyReferenceOp(QMatrix &state, int ctrl, int targ, QMatrix op);
655
656/** Modifies the density matrix \p state to be the result of applying the multi-target
657 * operator matrix \p op, with a single control qubit \p ctrl.
658 * This updates \p state under
659 * \f[
660 \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger
661 * \f]
662 * even if \p op is not unitary (which is useful for applying Kraus operators).
663 *
664 * \p op must be a 2^\p numTargs-by-2^\p numTargs matrix, and \p ctrl must not
665 * appear in \p targs (though this is not explicitly checked).
666 *
667 * This function works by computing getFullOperatorMatrix() from the given
668 * arguments, and left-multipling it to \p state, then right-multiplying its
669 * conjugate transpose onto the result.
670 *
671 * @ingroup deprecatedutils
672 * @author Tyson Jones
673 */
674void applyReferenceOp(QMatrix &state, int ctrl, int* targs, int numTargs, QMatrix op);
675
676/** Modifies the density matrix \p state to be the result of applying the two-target
677 * operator matrix \p op, with a single control qubit \p ctrl.
678 * This updates \p state under
679 * \f[
680 \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger
681 * \f]
682 * even if \p op is not unitary (which is useful for applying Kraus operators).
683 *
684 * \p op must be a 4-by-4 matrix, and \p ctrl, \p targ1 and \p targ2 must be unique.
685 *
686 * This function works by computing getFullOperatorMatrix() from the given
687 * arguments, and left-multipling it to \p state, then right-multiplying its
688 * conjugate transpose onto the result.
689 *
690 * @ingroup deprecatedutils
691 * @author Tyson Jones
692 */
693void applyReferenceOp(QMatrix &state, int ctrl, int targ1, int targ2, QMatrix op);
694
695/** Modifies the density matrix \p state to be the result of applying the single-target
696 * operator matrix \p op, with no control qubit.
697 * This updates \p state under
698 * \f[
699 \text{state} \to \text{op} \, \text{state} \, \text{op}^\dagger
700 * \f]
701 * even if \p op is not unitary (which is useful for applying Kraus operators).
702 *
703 * \p op must be a 2-by-2 matrix.
704 *
705 * This function works by computing getFullOperatorMatrix() from the given
706 * arguments, and left-multipling it to \p state, then right-multiplying its
707 * conjugate transpose onto the result.
708 *
709 * @ingroup deprecatedutils
710 * @author Tyson Jones
711 */
712void applyReferenceOp(QMatrix &state, int targ, QMatrix op);
713
714/** Modifies the state-vector \p state to be the result of applying the multi-target operator
715 * matrix \p op, with the specified control and target qubits (in \p ctrls and \p targs
716 * respectively). This updates \p state under
717 * \f[
718 \text{state} \to \text{op} \, \text{state}
719 * \f]
720 * even if \p op is not unitary.
721 *
722 * \p op must be a 2^\p numTargs-by-2^\p numTargs matrix. Furthermore, every element of \p targs
723 * must not appear in \p ctrls (and vice-versa), though this is not explicitly checked.
724 * Elements of \p targs and \p ctrls should be unique.
725 *
726 * This function works by computing getFullOperatorMatrix() from the given
727 * arguments, and left-multiplying it onto \p state.
728 *
729 * @ingroup deprecatedutils
730 * @author Tyson Jones
731 */
732void applyReferenceOp(QVector &state, int* ctrls, int numCtrls, int *targs, int numTargs, QMatrix op);
733
734/** Modifies the state-vector \p state to be the result of applying the two-target operator
735 * matrix \p op, with the specified control qubits (in \p ctrls). This updates \p state under
736 * \f[
737 \text{state} \to \text{op} \, \text{state}
738 * \f]
739 * even if \p op is not unitary.
740 *
741 * \p op must be a 4-by-4 matrix. Furthermore, \p ctrls, \p targ1 and \p targ2 should
742 * all be unique.
743 *
744 * This function works by computing getFullOperatorMatrix() from the given
745 * arguments, and left-multiplying it onto \p state.
746 *
747 * @ingroup deprecatedutils
748 * @author Tyson Jones
749 */
750void applyReferenceOp(QVector &state, int* ctrls, int numCtrls, int targ1, int targ2, QMatrix op);
751
752/** Modifies the state-vector \p state to be the result of applying the single-target operator
753 * matrix \p op, with the specified control qubits (in \p ctrls). This updates \p state under
754 * \f[
755 \text{state} \to \text{op} \, \text{state}
756 * \f]
757 * even if \p op is not unitary.
758 *
759 * \p op must be a 2-by-2 matrix. Furthermore, elements in \p ctrls and \p target should
760 * all be unique.
761 *
762 * This function works by computing getFullOperatorMatrix() from the given
763 * arguments, and left-multiplying it onto \p state.
764 *
765 * @ingroup deprecatedutils
766 * @author Tyson Jones
767 */
768void applyReferenceOp(QVector &state, int* ctrls, int numCtrls, int target, QMatrix op);
769
770/** Modifies the state-vector \p state to be the result of applying the multi-target operator
771 * matrix \p op, with no contorl qubits. This updates \p state under
772 * \f[
773 \text{state} \to \text{op} \, \text{state}
774 * \f]
775 * even if \p op is not unitary.
776 *
777 * \p op must be a 2^\p numTargs-by-2^\p numTargs matrix. Furthermore, elements in \p targs should be unique.
778 *
779 * This function works by computing getFullOperatorMatrix() from the given
780 * arguments, and left-multiplying it onto \p state.
781 *
782 * @ingroup deprecatedutils
783 * @author Tyson Jones
784 */
785void applyReferenceOp(QVector &state, int *targs, int numTargs, QMatrix op);
786
787/** Modifies the state-vector \p state to be the result of applying the single-target operator
788 * matrix \p op, with a single control qubit (\p ctrl). This updates \p state under
789 * \f[
790 \text{state} \to \text{op} \, \text{state}
791 * \f]
792 * even if \p op is not unitary.
793 *
794 * \p op must be a 2-by-2 matrix. Furthermore, \p ctrl and \p targ must be different.
795 *
796 * This function works by computing getFullOperatorMatrix() from the given
797 * arguments, and left-multiplying it onto \p state.
798 *
799 * @ingroup deprecatedutils
800 * @author Tyson Jones
801 */
802void applyReferenceOp(QVector &state, int ctrl, int targ, QMatrix op);
803
804/** Modifies the state-vector \p state to be the result of applying the multi-target operator
805 * matrix \p op, with a single control qubit (\p ctrl) This updates \p state under
806 * \f[
807 \text{state} \to \text{op} \, \text{state}
808 * \f]
809 * even if \p op is not unitary.
810 *
811 * \p op must be a 2^\p numTargs-by-2^\p numTargs matrix. Furthermore, elements
812 * in \p targs and \p ctrl should be unique.
813 *
814 * This function works by computing getFullOperatorMatrix() from the given
815 * arguments, and left-multiplying it onto \p state.
816 *
817 * @ingroup deprecatedutils
818 * @author Tyson Jones
819 */
820void applyReferenceOp(QVector &state, int ctrl, int* targs, int numTargs, QMatrix op);
821
822/** Modifies the state-vector \p state to be the result of applying the two-target operator
823 * matrix \p op, with a single control qubit (\p ctrl). This updates \p state under
824 * \f[
825 \text{state} \to \text{op} \, \text{state}
826 * \f]
827 * even if \p op is not unitary.
828 *
829 * \p op must be a 4-by-4 matrix. Furthermore, \p ctrl, \p targ1 and \p targ2 should
830 * all be unique.
831 *
832 * This function works by computing getFullOperatorMatrix() from the given
833 * arguments, and left-multiplying it onto \p state.
834 *
835 * @ingroup deprecatedutils
836 * @author Tyson Jones
837 */
838void applyReferenceOp(QVector &state, int ctrl, int targ1, int targ2, QMatrix op);
839
840/** Modifies the state-vector \p state to be the result of applying the single-target operator
841 * matrix \p op, with no contorl qubits. This updates \p state under
842 * \f[
843 \text{state} \to \text{op} \, \text{state}
844 * \f]
845 * even if \p op is not unitary.
846 *
847 * \p op must be a 2-by-2 matrix.
848 *
849 * This function works by computing getFullOperatorMatrix() from the given
850 * arguments, and left-multiplying it onto \p state.
851 *
852 * @ingroup deprecatedutils
853 * @author Tyson Jones
854 */
855void applyReferenceOp(QVector &state, int targ, QMatrix op);
856
857/** Modifies the state-vector \p state to be the result of left-multiplying the multi-target operator
858 * matrix \p op, with the specified control and target qubits (in \p ctrls and \p targs
859 * respectively). This is an alias of applyReferenceOp(), since operators are always
860 * left-multiplied as matrices onto state-vectors.
861 *
862 * @ingroup deprecatedutils
863 * @author Tyson Jones
864 */
865void applyReferenceMatrix(QVector &state, int* ctrls, int numCtrls, int *targs, int numTargs, QMatrix op);
866
867/** Modifies the state-vector \p state to be the result of left-multiplying the multi-target operator
868 * matrix \p op, with the specified target qubits (assuming no control qubits). T
869 *
870 * @ingroup deprecatedutils
871 * @author Tyson Jones
872 */
873void applyReferenceMatrix(QVector &state, int *targs, int numTargs, QMatrix op);
874
875/** Modifies the density matrix \p state to be the result of left-multiplying the multi-target operator
876 * matrix \p op, with the specified control and target qubits (in \p ctrls and \p targs
877 * respectively). Here, \p op is treated like a simple matrix and is hence left-multiplied
878 * onto the state once.
879 *
880 * @ingroup deprecatedutils
881 * @author Tyson Jones
882 */
883void applyReferenceMatrix(QMatrix &state, int* ctrls, int numCtrls, int *targs, int numTargs, QMatrix op);
884
885/** Modifies the density matrix \p state to be the result of left-multiplying the multi-target operator
886 * matrix \p op, with the target qubits (assuming no control qubits).
887 * Here, \p op is treated like a simple matrix and is hence left-multiplied onto the state once.
888 *
889 * @ingroup deprecatedutils
890 * @author Tyson Jones
891 */
892void applyReferenceMatrix(QMatrix &state, int *targs, int numTargs, QMatrix op);
893
894/** Performs a hardware-agnostic comparison of the given quregs, checking
895 * whether the difference between the real and imaginary components of every amplitude
896 * is smaller than the QuEST_PREC-specific REAL_EPS (defined in QuEST_precision) precision.
897 * This function demands that \p qureg1 and \p qureg2 are of the same type
898 * (i.e. both state-vectors or both density matrices), and of an equal number
899 * of qubits.
900 *
901 * In GPU mode, this function involves a GPU to CPU memory copy overhead.
902 * In distributed mode, it involves a all-to-all single-int broadcast.
903 *
904 * @ingroup deprecatedutils
905 * @author Tyson Jones
906 */
907bool areEqual(Qureg qureg1, Qureg qureg2);
908
909/** Performs a hardware-agnostic comparison of state-vector \p qureg to \p vec, checking
910 * whether the difference between the real and imaginary components of every amplitude
911 * is smaller than the QuEST_PREC-specific REAL_EPS (defined in QuEST_precision) precision.
912 * This function demands \p qureg is a state-vector, and that \p qureg and
913 * \p vec have the same number of amplitudes.
914 *
915 * In GPU mode, this function involves a GPU to CPU memory copy overhead.
916 * In distributed mode, it involves a all-to-all single-int broadcast.
917 *
918 * @ingroup deprecatedutils
919 * @author Tyson Jones
920 */
921bool areEqual(Qureg qureg, QVector vec);
922
923/** Performs a hardware-agnostic comparison of density-matrix \p qureg to \p matr, checking
924 * whether the difference between the real and imaginary components of every amplitude
925 * is smaller than the QuEST_PREC-specific REAL_EPS (defined in QuEST_precision) precision.
926 * This function demands \p qureg is a density matrix, and that \p qureg and \p matr have
927 * equal dimensions.
928 *
929 * In GPU mode, this function involves a GPU to CPU memory copy overhead.
930 * In distributed mode, it involves a all-to-all single-int broadcast.
931 *
932 * @ingroup deprecatedutils
933 * @author Tyson Jones
934 */
935bool areEqual(Qureg qureg, QMatrix matr);
936
937/** Performs a hardware-agnostic comparison of the given quregs, checking
938 * whether the difference between the real and imaginary components of every amplitude
939 * is smaller than \p precision.
940 * This function demands that \p qureg1 and \p qureg2 are of the same type
941 * (i.e. both state-vectors or both density matrices), and of an equal number
942 * of qubits.
943 *
944 * In GPU mode, this function involves a GPU to CPU memory copy overhead.
945 * In distributed mode, it involves a all-to-all single-int broadcast.
946 *
947 * @ingroup deprecatedutils
948 * @author Tyson Jones
949 */
950bool areEqual(Qureg qureg1, Qureg qureg2, qreal precision);
951
952/** Performs a hardware-agnostic comparison of state-vector \p qureg to \p vec, checking
953 * whether the difference between the real and imaginary components of every amplitude
954 * is smaller than \p precision.
955 * This function demands \p qureg is a state-vector, and that \p qureg and
956 * \p vec have the same number of amplitudes.
957 *
958 * In GPU mode, this function involves a GPU to CPU memory copy overhead.
959 * In distributed mode, it involves a all-to-all single-int broadcast.
960 *
961 * @ingroup deprecatedutils
962 * @author Tyson Jones
963 */
964bool areEqual(Qureg qureg, QVector vec, qreal precision);
965
966/** Performs a hardware-agnostic comparison of density-matrix \p qureg to \p matr, checking
967 * whether the difference between the real and imaginary components of every amplitude
968 * is smaller than \p precision.
969 * This function demands \p qureg is a density matrix, and that \p qureg and \p matr have
970 * equal dimensions.
971 *
972 * In GPU mode, this function involves a GPU to CPU memory copy overhead.
973 * In distributed mode, it involves a all-to-all single-int broadcast.
974 *
975 * @ingroup deprecatedutils
976 * @author Tyson Jones
977 */
978bool areEqual(Qureg qureg, QMatrix matr, qreal precision);
979
980/** Returns true if the absolute value of the difference between every amplitude in
981 * vectors \p a and \p b is less than \p REAL_EPS.
982 *
983 * @ingroup deprecatedutils
984 * @author Tyson Jones
985 */
986bool areEqual(QVector a, QVector b);
987
988/** Returns true if the absolute value of the difference between every amplitude in
989 * matrices \p a and \p b is less than \p REAL_EPS.
990 *
991 * @ingroup deprecatedutils
992 * @author Tyson Jones
993 */
994bool areEqual(QMatrix a, QMatrix b);
995
996/** Returns true if the absolute value of the difference between every element in
997 * \p vec and those implied by \p reals and \p imags, is less than \p REAL_EPS.
998 *
999 * @ingroup deprecatedutils
1000 * @author Tyson Jones
1001 */
1002bool areEqual(QVector vec, qreal* reals, qreal* imags);
1003
1004/** Returns true if the absolute value of the difference between every element in
1005 * \p vec (which must be strictly real) and those implied by \p reals, is less
1006 * than \p REAL_EPS.
1007 *
1008 * @ingroup deprecatedutils
1009 * @author Tyson Jones
1010 */
1011bool areEqual(QVector vec, qreal* reals);
1012
1013/** Returns the unit-norm complex number exp(i*\p phase). This function uses the
1014 * Euler formula, and avoids problems with calling exp(__complex__) in a platform
1015 * agnostic way
1016 */
1017qcomp expI(qreal phase);
1018
1019/** Returns log2 of numbers which must be gauranteed to be 2^n
1020 *
1021 * @ingroup deprecatedutils
1022 * @author Tyson Jones
1023 */
1024unsigned int calcLog2(long unsigned int res);
1025
1026/** Populates the \p coeffs array with random qreals in (-5, 5), and
1027 * populates \p codes with random Pauli codes
1028 *
1029 * @ingroup deprecatedutils
1030 * @author Tyson Jones
1031 */
1032void setRandomPauliSum(qreal* coeffs, pauliOpType* codes, int numQubits, int numTerms);
1033
1034/** Populates \p hamil with random coefficients and pauli codes
1035 *
1036 * @ingroup deprecatedutils
1037 * @author Tyson Jones
1038 */
1039void setRandomPauliSum(PauliHamil hamil, int numQubits);
1040
1041/** Populates \p hamil with random coefficients and a random amount number of
1042 * PAULI_I and PAULI_Z operators.
1043 *
1044 * @ingroup deprecatedutils
1045 * @author Tyson Jones
1046 */
1047void setRandomDiagPauliHamil(PauliHamil hamil, int numQubits);
1048
1049/** Populates \p targs with a random selection of \p numTargs elements from [0,\p numQb-1].
1050 * List \p targs does not need to be initialised and its elements are overwritten.
1051 *
1052 * @ingroup deprecatedutils
1053 * @author Tyson Jones
1054 */
1055void setRandomTargets(int* targs, int numTargs, int numQb);
1056
1057/** Populates \p targs with a random selection of elements from [0,\p numQb-1].
1058 * List \p targs does not need to be initialised and its elements are overwritten.
1059 *
1060 * @ingroup deprecatedutils
1061 * @author Tyson Jones
1062 */
1063void setRandomTargets(vector<int> &targs, int numQb);
1064
1065/** Returns the two's complement signed encoding of the unsigned number decimal,
1066 * which must be a number between 0 and 2^numBits (exclusive). The returned number
1067 * lies in [-2^(numBits-1), 2^(numBits-1)-1]
1068 *
1069 * @ingroup deprecatedutils
1070 * @author Tyson Jones
1071 */
1072long long int getTwosComplement(long long int decimal, int numBits);
1073
1074/** Return the unsigned value of a number, made of `#numBits` bits, which under
1075 * two's complement, encodes the signed number twosComp. The returned number
1076 * lies in [0, 2^(numBits)-1]
1077 *
1078 * @ingroup deprecatedutils
1079 * @author Tyson Jones
1080 */
1081long long int getUnsigned(long long int twosComp, int numBits);
1082
1083// /** Modifies the given diagonal matrix such that the diagonal elements which
1084// * correspond to the coordinates in overrideInds are replaced with exp(i phase), as
1085// * prescribed by overridePhases. This function assumes that the given registers
1086// * are contiguous, are in order of increasing significance, and that the matrix
1087// * is proportionately sized and structured to act on the space of all registers
1088// * combined. Overrides can be repeated, and only the first encountered for a given
1089// * index will be effected (much like applyMultiVarPhaseFuncOverrides()).
1090// *
1091// * @ingroup deprecatedutils
1092// * @author Tyson Jones
1093// */
1094// void setDiagMatrixOverrides(QMatrix &matr, int* numQubitsPerReg, int numRegs, enum bitEncoding encoding, long long int* overrideInds, qreal* overridePhases, int numOverrides);
1095
1096/** Modifies outFn to be a filename of format prefix_NUM.txt where NUM
1097 * is a new unique integer so far. This is useful for getting unique filenames for
1098 * independent test cases of functions requiring reading/writing to file, to
1099 * avoid IO locks (especially common in distributed mode).
1100 *
1101 * @ingroup deprecatedutils
1102 * @author Tyson Jones
1103 */
1104void setUniqueFilename(char* outFn, int maxlen, char* prefix);
1105
1106/** Writes contents to the file with filename fn, which is created and/or overwritten.
1107 * In distributed mode, the master node writes while the other nodes wait until complete.
1108 *
1109 * @ingroup deprecatedutils
1110 * @author Tyson Jones
1111 */
1112void writeToFileSynch(char* fn, const string& contents);
1113
1114/** Deletes all files with filename starting with prefix. In distributed mode, the
1115 * master node deletes while the other nodes wait until complete.
1116 *
1117 * @ingroup deprecatedutils
1118 * @author Tyson Jones
1119 */
1120void deleteFilesWithPrefixSynch(char* prefix);
1121
1122// makes below signatures more concise
1123template<class T> using CatchGen = Catch::Generators::GeneratorWrapper<T>;
1124
1125 /** Returns a Catch2 generator of every length-\p sublen sublist of length-\p len
1126 * \p list, in increasing lexographic order. This generates every fixed-length
1127 * combination of the given list and every permutation of each.
1128 & If the sublist length is the full list length, this generator produces every
1129 * permutation correctly. Note that the sublist must not be modified, else further
1130 & generation may break (QuEST's internal functions will indeed modify but restore
1131 * the qubit index lists given to them, which is ok).
1132 * Assumes \p list contains no duplicates, otherwise the generated sublists may be
1133 * duplicated.
1134 *
1135 * This function can be used like
1136 *
1137 * int list[4] = {1,2,3,4};
1138 * int sublen = 2;
1139 * int* sublist = GENERATE_COPY( sublists(list, 4, sublen) );
1140 *
1141 * to generate {1,2}, {1,3}, {1,4}, {2,1}, {2,3}, {2,4}, {3,1}, {3,2}, {3, 4},
1142 * {4,1}, {4,2}, {4, 3}.
1143 *
1144 * @ingroup deprecatedutils
1145 * @author Tyson Jones
1146 */
1147CatchGen<int*> sublists(int* list, int len, int sublen);
1148
1149/** Returns a Catch2 generator of every length-\p sublen sublist of the elements
1150 * generated by \p gen, which exclude all elements in \p exclude, in increasing lexographic order.
1151 * This generates every fixed-length combination of \p gen's elements the nominated exclusions,
1152 * and every permutation of each.
1153 *
1154 * There is on need for the elements of \p exclude to actually appear in those of \p gen.
1155 * \p sublen must less than or equal to the number of elements in \p gen, after
1156 * the nominated exclusions.
1157 *
1158 * Note that the sublist must not be modified, else further generation may break (QuEST's
1159 * internal functions will indeed modify but restore the qubit index lists given
1160 * to them, which is ok). Assumes \p list contains no duplicates,
1161 * otherwise the generated sublists may be duplicated.
1162 *
1163 * This function can be used like
1164 *
1165 * int sublen = 2;
1166 * int exclude[2] = {3,4};
1167 * int* sublist = GENERATE_COPY( sublists(range(1,6), sublen, exclude, 2) );
1168 *
1169 * to generate {1,2}, {1,5}, {2,1}, {2,5}, {5,1}, {5,2}
1170 *
1171 * @ingroup deprecatedutils
1172 * @author Tyson Jones
1173 */
1174CatchGen<int*> sublists(CatchGen<int>&& gen, int numSamps, const int* exclude, int numExclude);
1175
1176/** Returns a Catch2 generator of every length-\p sublen sublist of the elements
1177 * generated by \p gen which exclude element \p excluded, in increasing lexographic order.
1178 * This generates every fixed-length combination of \p gen's elements the nominated exclusions,
1179 * and every permutation of each.
1180 *
1181 * \p sublen must less than or equal to the number of elements in \p gen, after
1182 * the nominated exclusion. There is no need for \p excluded to actually appear
1183 * in the elements of \p gen.
1184 *
1185 * Note that the sublist must not be modified, else further generation may break (QuEST's
1186 * internal functions will indeed modify but restore the qubit index lists given
1187 * to them, which is ok). Assumes \p list contains no duplicates,
1188 * otherwise the generated sublists may be duplicated.
1189 *
1190 * This function can be used like
1191 *
1192 * int sublen = 2;
1193 * int excluded = 1;
1194 * int* sublist = GENERATE_COPY( sublists(range(1,4), sublen, excluded) );
1195 *
1196 * to generate {2,3}, {3,2}.
1197 *
1198 * @ingroup deprecatedutils
1199 * @author Tyson Jones
1200 */
1201CatchGen<int*> sublists(CatchGen<int>&& gen, int numSamps, int excluded);
1202
1203/** Returns a Catch2 generator of every length-\p sublen sublist of the elements
1204 * generated by \p gen, in increasing lexographic order. This generates every fixed-length
1205 * combination of \p gen's elements, and every permutation of each.
1206 * Note that the produced sublist must not be modified, else further
1207 * generation may break (QuEST's internal functions will indeed modify but restore
1208 * the qubit index lists given to them, which is ok).
1209 * Assumes \p list contains no duplicates, otherwise the generated sublists may be
1210 * duplicated.
1211 *
1212 * This function can be used like
1213 *
1214 * int sublen = 2;
1215 * int* sublist = GENERATE_COPY( sublists(list, 4, sublen) );
1216 *
1217 * to generate {1,2}, {1,3}, {1,4}, {2,1}, {2,3}, {2,4}, {3,1}, {3,2}, {3, 4},
1218 * {4,1}, {4,2}, {4, 3}.
1219 *
1220 * @ingroup deprecatedutils
1221 * @author Tyson Jones
1222 */
1223CatchGen<int*> sublists(CatchGen<int>&& gen, int sublen);
1224
1225/** Returns a Catch2 generator of every \p numBits-length bit-set,
1226 * in increasing lexographic order,
1227 * where left-most (zero index) bit is treated as LEAST significant (opposite
1228 * typical convention). Note that the produced bitset must not be modified during generation.
1229 *
1230 * This function can be used like
1231 *
1232 * int* bits = GENERATE( bitsets(3) );
1233 *
1234 * to produce {0,0,0}, {1,0,0}, {0,1,0}, {1,1,0}, {0,0,1}, {1,0,1}, {0,1,1}, {1,1,1}.
1235 *
1236 * @ingroup deprecatedutils
1237 * @author Tyson Jones
1238 */
1239CatchGen<int*> bitsets(int numBits);
1240
1241/** Returns a Catch2 generator of every \p numDigits-length sequence in the given
1242 * \p base, in increasing lexographic order,
1243 * where left-most (zero index) bit is treated as LEAST significant (opposite
1244 * typical convention). Note that the sequence must not be modified during generation.
1245 *
1246 * This function can be used like
1247 *
1248 * int base = 3;
1249 * int numDigits = 2;
1250 * int* seq = GENERATE_COPY( sequences(base, numDigits) );
1251 *
1252 * to produce {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0,2}, {1,2}, {2,2}.
1253 *
1254 * @ingroup deprecatedutils
1255 * @author Tyson Jones
1256 */
1257CatchGen<int*> sequences(int base, int numDigits);
1258
1259/** Returns a Catch2 generator of every \p numPaulis-length set of Pauli-matrix
1260 * types (or base-4 integers).
1261 * Generates in increasing lexographic order, where the left-most (zero index)
1262 * pauli is treated as LEAST significant.
1263 * Note that the sequence must not be modified during generation.
1264 *
1265 * This function can be used like
1266 *
1267 * pauliOpType* set = GENERATE( pauliseqs(2) );
1268 *
1269 * to produce {I,I}, {X,I}, {Y,I}, {Z,I}, {I,X}, {X,X}, {Y,X}, {Z,X}, {I,Y},
1270 * {X,Y}, {Y,Y}, {Z,Y}, {I,Z}, {X,Z}, {Y,Z}, {Z,Z}/
1271 *
1272 * @ingroup deprecatedutils
1273 * @author Tyson Jones
1274 */
1275CatchGen<pauliOpType*> pauliseqs(int numPaulis);
1276
1277#endif // QUEST_TEST_UTILS_H
QMatrix getExponentialOfPauliMatrix(qreal angle, QMatrix a)
Definition linalg.cpp:348
void applyReferenceMatrix(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
QMatrix getRandomPureDensityMatrix(int numQb)
Definition random.cpp:326
void setRandomPauliSum(qreal *coeffs, pauliOpType *codes, int numQubits, int numTerms)
void setUniqueFilename(char *outFn, int maxlen, char *prefix)
QMatrix getRandomUnitary(int numQb)
Definition random.cpp:348
CatchGen< int * > sequences(int base, int numDigits)
QMatrix getFullOperatorMatrix(int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op, int numQubits)
ComplexMatrix4 toComplexMatrix4(QMatrix qm)
unsigned int calcLog2(long unsigned int res)
QVector getRandomQVector(int dim)
void applyReferenceOp(QMatrix &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
QMatrix getKetBra(QVector ket, QVector bra)
CatchGen< int * > sublists(int *list, int len, int sublen)
QMatrix getSwapMatrix(int qb1, int qb2, int numQb)
Definition evolve.cpp:28
QMatrix getConjugateTranspose(QMatrix a)
Definition linalg.cpp:291
QMatrix getMixedDensityMatrix(vector< qreal > probs, vector< QVector > states)
long long int getTwosComplement(long long int decimal, int numBits)
long long int getValueOfTargets(long long int ind, int *targs, int numTargs)
QMatrix toQMatrix(Qureg qureg)
QVector getNormalised(QVector vec)
QMatrix getRandomDensityMatrix(int numQb)
Definition random.cpp:308
QMatrix getZeroMatrix(size_t dim)
Definition qmatrix.cpp:18
void assertQuregAndRefInDebugState(Qureg qureg, QVector ref)
int getRandomInt(int min, int max)
Definition random.cpp:90
vector< vector< qcomp > > QMatrix
qcomp getRandomComplex()
Definition random.cpp:107
ComplexMatrix2 toComplexMatrix2(QMatrix qm)
void setSubMatrix(QMatrix &dest, QMatrix sub, size_t r, size_t c)
Definition qmatrix.cpp:203
CatchGen< pauliOpType * > pauliseqs(int numPaulis)
QVector getDFT(QVector in)
void toComplexMatrixN(QMatrix qm, ComplexMatrixN cm)
vector< QMatrix > getRandomKrausMap(int numQb, int numOps)
Definition random.cpp:405
vector< QVector > getRandomOrthonormalVectors(int numQb, int numStates)
QVector getMatrixDiagonal(QMatrix matr)
void setRandomDiagPauliHamil(PauliHamil hamil, int numQubits)
void writeToFileSynch(char *fn, const string &contents)
QMatrix getRandomQMatrix(int dim)
void setRandomTargets(int *targs, int numTargs, int numQb)
QMatrix toDiagonalQMatrix(QVector vec)
void setRandomTestStateSeeds()
Definition random.cpp:39
QVector getKroneckerProduct(QVector b, QVector a)
vector< qcomp > QVector
bool areEqual(Qureg qureg1, Qureg qureg2)
QMatrix getIdentityMatrix(size_t dim)
Definition qmatrix.cpp:30
QMatrix getExponentialOfDiagonalMatrix(QMatrix a)
Definition linalg.cpp:336
qreal getRandomReal(qreal min, qreal max)
Definition random.cpp:63
vector< qreal > getRandomProbabilities(int numProbs)
Definition random.cpp:160
void deleteFilesWithPrefixSynch(char *prefix)
QVector toQVector(Qureg qureg)
QVector getRandomStateVector(int numQb)
Definition random.cpp:296
QMatrix getPureDensityMatrix(QVector state)
long long int getUnsigned(long long int twosComp, int numBits)
CatchGen< int * > bitsets(int numBits)
void toQureg(Qureg qureg, QVector vec)
Definition qureg.h:49