9#include <catch2/catch_test_macros.hpp>
10#include <catch2/generators/catch_generators.hpp>
12#define INCLUDE_DEPRECATED_FUNCTIONS 1
13#define DISABLE_DEPRECATION_WARNINGS 1
14#include "quest/include/quest.h"
16#include "test_utilities.hpp"
27 #if (FLOAT_PRECISION == 1)
28 #define MPI_QCOMP MPI_CXX_FLOAT_COMPLEX
29 #elif (FLOAT_PRECISION == 2)
30 #define MPI_QCOMP MPI_CXX_DOUBLE_COMPLEX
31 #elif (FLOAT_PRECISION == 4) && defined(MPI_CXX_LONG_DOUBLE_COMPLEX)
32 #define MPI_QCOMP MPI_CXX_LONG_DOUBLE_COMPLEX
34 #define MPI_QCOMP MPI_C_LONG_DOUBLE_COMPLEX
37 #ifdef MPI_MAX_AMPS_IN_MSG
38 #undef MPI_MAX_AMPS_IN_MSG
40 #define MPI_MAX_AMPS_IN_MSG (1 << 30)
57qreal absReal(qreal x) {
60qreal absComp(qcomp x) {
71static std::mt19937 randomGenerator;
81#define DEMAND( cond ) if (!(cond)) FAIL( );
84 DEMAND( v1.size() == v2.size() );
86 for (
size_t i=0; i<v2.size(); i++)
91 DEMAND( v1.size() == v2.size() );
93 for (
size_t i=0; i<v2.size(); i++)
99 for (
size_t i=0; i<v.size(); i++)
107 DEMAND( abs(a) != 0 );
109 for (
size_t i=0; i<v.size(); i++)
115 DEMAND( v1.size() == v2.size() );
117 for (
size_t i=0; i<v1.size(); i++)
118 out += v1[i] * conj(v2[i]);
127void operator *= (
QVector& v1,
const qcomp& a) {
130void operator /= (
QVector& v1,
const qcomp& a) {
134 DEMAND( m1.size() == m2.size() );
136 for (
size_t r=0; r<m1.size(); r++)
137 for (
size_t c=0; c<m1.size(); c++)
138 out[r][c] += m2[r][c];
142 DEMAND( m1.size() == m2.size() );
144 for (
size_t r=0; r<m1.size(); r++)
145 for (
size_t c=0; c<m1.size(); c++)
146 out[r][c] -= m2[r][c];
151 for (
size_t r=0; r<m.size(); r++)
152 for (
size_t c=0; c<m.size(); c++)
161 for (
size_t r=0; r<m.size(); r++)
162 for (
size_t c=0; c<m.size(); c++)
168 for (
size_t r=0; r<m1.size(); r++)
169 for (
size_t c=0; c<m1.size(); c++) {
171 for (
size_t k=0; k<m1.size(); k++)
172 prod[r][c] += m1[r][k] * m2[k][c];
182void operator *= (
QMatrix& m1,
const qreal& a) {
185void operator /= (
QMatrix& m1,
const qreal& a) {
192 DEMAND( m.size() == v.size() );
194 for (
size_t r=0; r<v.size(); r++)
195 for (
size_t c=0; c<v.size(); c++)
196 prod[r] += m[r][c] * v[c];
205 std::random_device cspnrg;
206 unsigned seed = cspnrg();
211 MPI_Bcast(&seed, 1, MPI_UNSIGNED, sendRank, MPI_COMM_WORLD);
216 randomGenerator.seed(seed);
220 DEMAND( qureg.isDensityMatrix == 0 );
221 DEMAND( qureg.numAmps == (
long long int) ref.size() );
224 for (
size_t i=0; i<ref.size(); i++) {
225 qcomp val = qcomp(.2*i, .2*i+.1);
226 DEMAND( abs(ref[i] - val) < REAL_EPS );
234 DEMAND( qureg.isDensityMatrix == 1 );
235 DEMAND( (1LL << qureg.numQubits) == (
long long int) ref.size() );
239 for (
size_t c=0; c<ref.size(); c++) {
240 for (
size_t r=0; r<ref.size(); r++) {
241 qcomp val = qcomp(.2*i, .2*i+.1);
242 DEMAND( abs(ref[r][c] - val) < REAL_EPS );
255 for (
size_t i=0; i<prod.size(); i++)
256 prod[i] = b[i / a.size()] * a[i % a.size()];
264 for (
size_t i=0; i<dim; i++)
272 for (
size_t i=0; i<dim; i++)
278 DEMAND( ket.size() == bra.size() );
281 for (
size_t r=0; r<ket.size(); r++)
282 for (
size_t c=0; c<ket.size(); c++)
283 mat[r][c] = ket[r] * conj(bra[c]);
289 for (
size_t r=0; r<b.size(); r++)
290 for (
size_t c=0; c<b.size(); c++)
291 for (
size_t i=0; i<a.size(); i++)
292 for (
size_t j=0; j<a.size(); j++)
293 prod[r+b.size()*i][c+b.size()*j] = a[i][j] * b[r][c];
299 for (
size_t r=0; r<a.size(); r++)
300 for (
size_t c=0; c<a.size(); c++)
307 for (
size_t r=0; r<a.size(); r++)
308 for (
size_t c=0; c<a.size(); c++)
309 b[r][c] = conj(a[c][r]);
316 for (
size_t r=0; r<a.size(); r++)
317 for (
size_t c=0; c<a.size(); c++) {
320 DEMAND( real(a[r][c]) == 0. );
321 DEMAND( imag(a[r][c]) == 0. );
326 for (
size_t i=0; i<a.size(); i++)
327 diag[i][i] = exp(diag[i][i]);
334 QMatrix expo = (cos(angle/2) * iden) + ((qcomp) -1i * sin(angle/2) * a);
339 DEMAND( sub.size() + r <= dest.size() );
340 DEMAND( sub.size() + c <= dest.size() );
341 for (
size_t i=0; i<sub.size(); i++)
342 for (
size_t j=0; j<sub.size(); j++)
343 dest[r+i][c+j] = sub[i][j];
348 DEMAND( (qb1 >= 0 && qb1 < numQb) );
349 DEMAND( (qb2 >= 0 && qb2 < numQb) );
359 if (qb2 == qb1 + 1) {
361 swap =
QMatrix{{1,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,1}};
365 int block = 1 << (qb2 - qb1);
403void updateIndices(
int oldEl,
int newEl,
int* list1,
int len1,
int* list2,
int len2) {
405 for (
int i=0; i<len1; i++) {
406 if (list1[i] == oldEl) {
412 for (
int i=0; i<len2; i++) {
413 if (list2[i] == oldEl) {
421 int* ctrls,
int numCtrls,
int *targs,
int numTargs,
QMatrix op,
int numQubits
423 DEMAND( numCtrls >= 0 );
424 DEMAND( numTargs >= 0 );
425 DEMAND( numQubits >= (numCtrls+numTargs) );
426 DEMAND( op.size() == (1u << numTargs) );
429 vector<int> ctrlsCopy(ctrls, ctrls+numCtrls);
430 vector<int> targsCopy(targs, targs+numTargs);
438 for (
int i=0; i<numTargs; i++) {
441 swaps = matr * swaps;
442 unswaps = unswaps * matr;
446 i, targs[i], (i < numTargs-1)? &targs[i+1] : NULL,
447 numTargs-i-1, ctrls, numCtrls);
452 for (
int i=0; i<numCtrls; i++) {
453 int newInd = numTargs+i;
454 if (newInd != ctrls[i]) {
456 swaps = matr * swaps;
457 unswaps = unswaps * matr;
461 updateIndices(newInd, ctrls[i], NULL, 0, &ctrls[i+1], numCtrls-i-1);
466 size_t dim = 1 << (numCtrls+numTargs);
471 if (numQubits > numCtrls+numTargs) {
472 size_t pad = 1 << (numQubits - numCtrls - numTargs);
477 fullOp = unswaps * fullOp * swaps;
480 for (
int i=0; i<numCtrls; i++)
481 ctrls[i] = ctrlsCopy[i];
482 for (
int i=0; i<numTargs; i++)
483 targs[i] = targsCopy[i];
499 for (
int i=0; i<dim; i++) {
500 for (
int j=0; j<dim; j++) {
503 qreal a = rand()/(qreal) RAND_MAX;
504 qreal b = rand()/(qreal) RAND_MAX;
505 if (a == 0) a = REAL_EPS;
506 qreal r1 = sqrt(-2 * log(a)) * cos(2 * 3.14159265 * b);
507 qreal r2 = sqrt(-2 * log(a)) * sin(2 * 3.14159265 * b);
509 matr[i][j] = r1 + r2 * (qcomp) 1i;
516 DEMAND( a.size() == b.size() );
518 for (
size_t i=0; i<a.size(); i++)
519 if (abs(a[i] - b[i]) > REAL_EPS)
525 DEMAND( a.size() == b.size() );
527 for (
size_t i=0; i<a.size(); i++)
528 for (
size_t j=0; j<b.size(); j++)
529 if (abs(a[i][j] - b[i][j]) > REAL_EPS)
534qcomp expI(qreal phase) {
535 return qcomp(cos(phase), sin(phase));
539 DEMAND( min <= max );
540 qreal r = min + (max - min) * (rand() / (qreal) RAND_MAX);
554 for (
int i=0; i<dim; i++)
567 for (
size_t i=0; i<vec.size(); i++) {
568 y = real(vec[i])*real(vec[i]) - c;
570 c = ( t - norm ) - y;
573 y = imag(vec[i])*imag(vec[i]) - c;
575 c = ( t - norm ) - y;
579 for (
size_t i=0; i<vec.size(); i++)
580 vec[i] /= sqrt(norm);
593 for (
int i=0; i<numProbs; i++) {
595 probs.push_back(prob);
600 for (
int i=0; i<numProbs; i++)
615 for (
int i=0; i<dim; i++) {
617 dens += probs[i] *
getKetBra(pure, pure);
636 for (
size_t i=0; i<vec.size(); i++)
649 for (
size_t i=0; i<matr.size(); i++) {
653 for (
int k=i-1; k>=0; k--) {
656 qcomp prod = row * matr[k];
659 matr[i] -= prod * matr[k];
670QMatrix getRandomDiagonalUnitary(
int numQb) {
671 DEMAND( numQb >= 1 );
674 for (
size_t i=0; i<matr.size(); i++)
681 DEMAND( numQb >= 1 );
684 size_t dim = 1 << numQb;
686 QMatrix matrZT = getTranspose(matrZ);
689 QMatrix matrQT = getOrthonormalisedRows(matrZ);
690 QMatrix matrQ = getTranspose(matrQT);
694 for (
size_t r=0; r<dim; r++)
695 for (
size_t c=r; c<dim; c++)
696 matrR[r][c] = matrZT[c] * matrQT[r];
700 for (
size_t i=0; i<dim; i++)
701 matrD[i][i] = matrR[i][i] / abs(matrR[i][i]);
711 matrU = getRandomDiagonalUnitary(numQb);
717 DEMAND( numOps >= 1 );
718 DEMAND( numOps <= 4*numQb*numQb );
722 for (
int i=0; i<numOps; i++)
726 vector<qreal> weights(numOps);
727 for (
int i=0; i<numOps; i++)
732 for (
int i=0; i<numOps; i++)
733 weightSum += weights[i];
734 for (
int i=0; i<numOps; i++)
735 weights[i] = sqrt((qreal) weights[i]/weightSum);
738 for (
int i=0; i<numOps; i++)
739 ops[i] *= weights[i];
744 for (
int i=0; i<numOps; i++)
750 for (
int i=0; i<numOps; i++)
751 ops[i] = weights[i] * getRandomDiagonalUnitary(numQb);
757 DEMAND( numQb >= 1 );
758 DEMAND( numStates >= 1);
761 vector<QVector> vecs;
763 for (
int n=0; n<numStates; n++) {
768 for (
int m=0; m<n; m++) {
769 qcomp prod = vec * vecs[m];
770 vec -= (prod * vecs[m]);
784 DEMAND( probs.size() == states.size() );
785 DEMAND( probs.size() >= 1 );
789 for (
size_t i=0; i<probs.size(); i++)
796 REQUIRE( in.size() > 0 );
798 size_t dim = in.size();
799 qreal ampFac = 1 / sqrt( dim );
800 qreal phaseFac = 2 * M_PI / dim;
804 for (
size_t x=0; x<dim; x++) {
806 for (
size_t y=0; y<dim; y++)
807 dftVec[x] += expI(phaseFac * x * y) * in[y];
816 long long int val = 0;
818 for (
int t=0; t<numTargs; t++)
819 val += ((ind >> targs[t]) & 1) * (1LL << t);
824long long int setBit(
long long int num,
int bitInd,
int bitVal) {
825 DEMAND( (bitVal == 0 || bitVal == 1) );
827 DEMAND( bitInd >= 0 );
829 return (num & ~(1UL << bitInd)) | (bitVal << bitInd);
832long long int getIndexOfTargetValues(
long long int ref,
int* targs,
int numTargs,
long long int targVal) {
836 for (
int t=0; t<numTargs; t++) {
837 int bit = (targVal >> t) & 1;
838 ref = setBit(ref, targs[t], bit);
846 long long int inDim = (
long long int) in.size();
847 long long int targDim = (1LL << numTargs);
849 for (
long long int j=0; j<inDim; j++) {
854 for (
long long int y=0; y<targDim; y++) {
857 long long int outInd = getIndexOfTargetValues(j, targs, numTargs, y);
859 qcomp elem = (in[j] / sqrt(pow(2,numTargs))) * expI(2*M_PI * x * y / pow(2,numTargs));
873 QVector &state,
int* ctrls,
int numCtrls,
int *targs,
int numTargs,
QMatrix op
875 int numQubits =
calcLog2(state.size());
877 state = fullOp * state;
880 QVector &state,
int* ctrls,
int numCtrls,
int targ1,
int targ2,
QMatrix op
882 int targs[2] = {targ1, targ2};
888 int targs[1] = {target};
899 int ctrls[1] = {ctrl};
900 int targs[1] = {targ};
906 int ctrls[1] = {ctrl};
912 int ctrls[1] = {ctrl};
913 int targs[2] = {targ1, targ2};
919 int targs[1] = {targ};
929 QMatrix &state,
int* ctrls,
int numCtrls,
int *targs,
int numTargs,
QMatrix op
931 int numQubits =
calcLog2(state.size());
934 state = leftOp * state * rightOp;
937 QMatrix &state,
int* ctrls,
int numCtrls,
int targ1,
int targ2,
QMatrix op
939 int targs[2] = {targ1, targ2};
945 int targs[1] = {target};
956 int ctrls[1] = {ctrl};
957 int targs[1] = {targ};
963 int ctrls[1] = {ctrl};
969 int ctrls[1] = {ctrl};
970 int targs[2] = {targ1, targ2};
976 int targs[1] = {targ};
986 QVector &state,
int* ctrls,
int numCtrls,
int *targs,
int numTargs,
QMatrix op
998 QMatrix &state,
int* ctrls,
int numCtrls,
int *targs,
int numTargs,
QMatrix op
1001 int numQubits =
calcLog2(state.size());
1003 state = leftOp * state;
1012 DEMAND( qureg1.isDensityMatrix == qureg2.isDensityMatrix );
1013 DEMAND( qureg1.numAmps == qureg2.numAmps );
1015 copyStateFromGPU(qureg1);
1016 copyStateFromGPU(qureg2);
1021 for (
long long int i=0; ampsAgree && i<qureg1.numAmpsPerNode; i++)
1022 ampsAgree = absComp(qureg1.cpuAmps[i] - qureg2.cpuAmps[i]) < precision;
1025 int allAmpsAgree = ampsAgree;
1027 MPI_Allreduce(&sAgree, &allAmpsAgree, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
1030 return allAmpsAgree;
1033 return areEqual(qureg1, qureg2, REAL_EPS);
1037 DEMAND( !qureg.isDensityMatrix );
1038 DEMAND( (
int) vec.size() == qureg.numAmps );
1040 copyStateFromGPU(qureg);
1044 long long int startInd = qureg.rank * qureg.numAmpsPerNode;
1047 for (
long long int i=0; i<qureg.numAmpsPerNode; i++) {
1048 qcomp dif = (qureg.cpuAmps[i] - vec[startInd+i]);
1050 if (absComp(dif) > precision) {
1055 snprintf(buff, 200,
"Disagreement at %lld of (%s) + i(%s):\n\t%s + i(%s) VS %s + i(%s)\n",
1057 QREAL_FORMAT_SPECIFIER, QREAL_FORMAT_SPECIFIER, QREAL_FORMAT_SPECIFIER,
1058 QREAL_FORMAT_SPECIFIER, QREAL_FORMAT_SPECIFIER, QREAL_FORMAT_SPECIFIER);
1060 real(dif), imag(dif),
1061 real(qureg.cpuAmps[i]), imag(qureg.cpuAmps[i]),
1062 real(vec[startInd+i]), imag(vec[startInd+i]));
1069 int allAmpsAgree = ampsAgree;
1071 MPI_Allreduce(&sAgree, &allAmpsAgree, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
1074 return allAmpsAgree;
1077 return areEqual(qureg, vec, REAL_EPS);
1081 DEMAND( qureg.isDensityMatrix );
1082 DEMAND( (
long long int) (matr.size()*matr.size()) == qureg.numAmps );
1085 copyStateFromGPU(qureg);
1089 long long int startInd = qureg.rank * qureg.numAmpsPerNode;
1090 long long int globalInd, row, col, i;
1094 for (i=0; i<qureg.numAmpsPerNode; i++) {
1095 globalInd = startInd + i;
1096 row = globalInd % matr.size();
1097 col = globalInd / matr.size();
1099 qreal realDif = absReal(real(qureg.cpuAmps[i]) - real(matr[row][col]));
1100 qreal imagDif = absReal(imag(qureg.cpuAmps[i]) - imag(matr[row][col]));
1101 ampsAgree = (realDif < precision && imagDif < precision);
1106 snprintf(buff, 200,
"[msg from utilities.cpp] node %d has a disagreement at %lld of (%s) + i(%s):\n\t[qureg] %s + i(%s) VS [ref] %s + i(%s)\n",
1107 qureg.rank, startInd+i,
1108 QREAL_FORMAT_SPECIFIER, QREAL_FORMAT_SPECIFIER, QREAL_FORMAT_SPECIFIER,
1109 QREAL_FORMAT_SPECIFIER, QREAL_FORMAT_SPECIFIER, QREAL_FORMAT_SPECIFIER);
1112 real(qureg.cpuAmps[i]), imag(qureg.cpuAmps[i]),
1113 real(matr[row][col]), imag(matr[row][col]));
1132 int allAmpsAgree = ampsAgree;
1134 MPI_Allreduce(&sAgree, &allAmpsAgree, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
1137 return allAmpsAgree;
1140 return areEqual(qureg, matr, REAL_EPS);
1146 for (
size_t i=0; i<vec.size(); i++) {
1147 dif = absReal(real(vec[i]) - reals[i]);
1150 dif = absReal(imag(vec[i]) - imags[i]);
1158 for (
size_t i=0; i<vec.size(); i++) {
1159 DEMAND( imag(vec[i]) == 0. );
1161 qreal dif = abs(real(vec[i]) - reals[i]);
1169#define macro_copyQMatrixToDeprecatedComplexMatrix(dest, src) { \
1170 for (size_t i=0; i<src.size(); i++) { \
1171 for (size_t j=0; j<src.size(); j++) { \
1172 dest.real[i][j] = real(src[i][j]); \
1173 dest.imag[i][j] = imag(src[i][j]); \
1178 DEMAND( qm.size() == 2 );
1180 macro_copyQMatrixToDeprecatedComplexMatrix(cm, qm);
1184 DEMAND( qm.size() == 4 );
1186 macro_copyQMatrixToDeprecatedComplexMatrix(cm, qm);
1191#define macro_copyComplexMatrix(dest, src, dim) \
1192 for (size_t i=0; i<dim; i++) \
1193 for (size_t j=0; j<dim; j++) \
1194 dest[i][j] = src[i][j];
1197 DEMAND( qm.size() == (1u<<cm.numQubits) );
1198 macro_copyComplexMatrix(cm.cpuElems, qm, qm.size());
1204 macro_copyComplexMatrix(dest, src.elems, dest.size());
1209 macro_copyComplexMatrix(dest, src.elems, dest.size());
1214 macro_copyComplexMatrix(dest, src.cpuElems, dest.size());
1219 DEMAND( qureg.isDensityMatrix );
1221 DEMAND( qureg.numAmps < MPI_MAX_AMPS_IN_MSG );
1225 copyStateFromGPU(qureg);
1229 qcomp* allAmps = qureg.cpuAmps;
1233 if (qureg.isDistributed) {
1234 allAmps = (qcomp*) malloc(qureg.numAmps *
sizeof *allAmps);
1236 qureg.cpuAmps, qureg.numAmpsPerNode, MPI_QCOMP,
1237 allAmps, qureg.numAmpsPerNode, MPI_QCOMP, MPI_COMM_WORLD);
1242 long long int dim = (1LL << qureg.numQubits);
1244 for (
long long int n=0; n<qureg.numAmps; n++)
1245 matr[n%dim][n/dim] = allAmps[n];
1248 if (qureg.isDistributed)
1254 DEMAND( !qureg.isDensityMatrix );
1256 DEMAND( qureg.numAmps < MPI_MAX_AMPS_IN_MSG );
1260 copyStateFromGPU(qureg);
1263 qcomp* allAmps = qureg.cpuAmps;
1267 if (qureg.isDistributed) {
1268 allAmps = (qcomp*) malloc(qureg.numAmps *
sizeof *allAmps);
1271 qureg.cpuAmps, qureg.numAmpsPerNode, MPI_QCOMP,
1272 allAmps, qureg.numAmpsPerNode, MPI_QCOMP, MPI_COMM_WORLD);
1278 for (
long long int i=0; i<qureg.numAmps; i++)
1279 vec[i] = allAmps[i];
1282 if (qureg.isDistributed)
1290 return vector<qcomp>(matr.cpuElems, matr.cpuElems + matr.numElems);
1296 DEMAND( matr.numElems < MPI_MAX_AMPS_IN_MSG );
1299 vector<qcomp> vec(matr.numElems);
1302 if (matr.isDistributed) {
1305 matr.cpuElems, matr.numElemsPerNode, MPI_QCOMP,
1306 vec.data(), matr.numElemsPerNode, MPI_QCOMP, MPI_COMM_WORLD);
1309 vec.assign(matr.cpuElems, matr.cpuElems + matr.numElems);
1318 for (
size_t i=0; i<mat.size(); i++)
1325 for (
size_t i=0; i<mat.size(); i++)
1326 mat[i][i] = in.cpuElems[i];
1331 DEMAND( !qureg.isDensityMatrix );
1332 DEMAND( qureg.numAmps == (
long long int) vec.size() );
1336 for (
int i=0; i<qureg.numAmpsPerNode; i++) {
1337 int ind = qureg.rank*qureg.numAmpsPerNode + i;
1338 qureg.cpuAmps[i] = vec[ind];
1340 copyStateToGPU(qureg);
1343 DEMAND( qureg.isDensityMatrix );
1344 DEMAND( (1LL << qureg.numQubits) == (
long long int) mat.size() );
1348 int len = (1 << qureg.numQubits);
1349 for (
int i=0; i<qureg.numAmpsPerNode; i++) {
1350 int ind = qureg.rank*qureg.numAmpsPerNode + i;
1351 qureg.cpuAmps[i] = mat[ind%len][ind/len];
1353 copyStateToGPU(qureg);
1356PauliStr getRandomPauliStr(
int numQubits) {
1358 std::string paulis =
"";
1359 for (
int i=0; i<numQubits; i++)
1364PauliStr getRandomDiagPauliStr(
int numQubits) {
1366 std::string paulis =
"";
1367 for (
int i=0; i<numQubits; i++)
1375 for (
int n=0; n<numTerms; n++) {
1377 for (
int q=0; q<numQubits; q++)
1384 for (
int n=0; n<hamil.numTerms; n++) {
1386 hamil.strings[n] = getRandomPauliStr(numQubits);
1391 for (
int n=0; n<hamil.numTerms; n++) {
1393 hamil.strings[n] = getRandomDiagPauliStr(numQubits);
1398 DEMAND( numQb >= 1 );
1399 DEMAND( numTargs >= 1);
1400 DEMAND( numTargs <= numQb );
1403 vector<int> allQb(numQb);
1404 for (
int q=0; q<numQb; q++)
1408 std::shuffle(&allQb[0], &allQb[numQb], randomGenerator);
1411 for (
int i=0; i<numTargs; i++)
1412 targs[i] = allQb[i];
1424 QMatrix yMatr{{0,-qcomp(0,1)},{qcomp(0,1),0}};
1428 for (
int t=0; t<numTerms; t++) {
1431 for (
int q=0; q<numQubits; q++) {
1432 int i = q + t*numQubits;
1435 pauliOpType code = paulis[i];
1436 if (code == PAULI_I) fac = iMatr;
1437 if (code == PAULI_X) fac = xMatr;
1438 if (code == PAULI_Y) fac = yMatr;
1439 if (code == PAULI_Z) fac = zMatr;
1442 pauliSum += coeffs[t] * pauliProd;
1455 DEMAND( decimal >= 0 );
1456 DEMAND( numBits >= 2 );
1457 DEMAND( decimal < (1LL << numBits) );
1459 long long int maxMag = 1LL << (numBits-1);
1460 if (decimal >= maxMag)
1461 return -maxMag + (decimal - maxMag);
1467 DEMAND( numBits >= 2 );
1468 DEMAND( twosComp < (1LL << (numBits-1)) );
1469 DEMAND( twosComp >= - (1LL << (numBits-1)) );
1474 return (1<<numBits) + twosComp;
1479 for (
size_t i=0; i<vec.size(); i++)
1524static int fn_unique_suffix_id = 0;
1527 snprintf(outFn, maxlen,
"%s_%d.txt", prefix, fn_unique_suffix_id++);
1534 FILE* file = fopen(fn,
"w");
1535 fputs(contents.c_str(), file);
1548 snprintf(cmd, 200,
"exec rm %s*", prefix);
1557class SubListGenerator :
public Catch::Generators::IGenerator<int*> {
1562 vector<bool> featured;
1564 void createSublist() {
1567 sublist = (
int*) malloc(sublen *
sizeof *sublist);
1570 featured = vector<bool>(len);
1571 fill(featured.end() - sublen, featured.end(),
true);
1574 void prepareSublist() {
1578 for (
int i=0; i<len; i++)
1580 sublist[j++] = list[i];
1583 std::sort(sublist, sublist+sublen);
1586 SubListGenerator(
int* elems,
int numElems,
int numSamps) {
1588 DEMAND( numSamps <= numElems );
1592 list = (
int*) malloc(len *
sizeof *list);
1593 for (
int i=0; i<len; i++)
1603 Catch::Generators::GeneratorWrapper<int>&& gen,
1604 int numSamps,
const int* exclude,
int numExclude
1607 vector<int> elems = vector<int>();
1608 do { elems.push_back(gen.get()); }
while (gen.next());
1612 list = (
int*) malloc(elems.size() *
sizeof *list);
1613 for (
size_t i=0; i<elems.size(); i++) {
1614 int elem = elems[i];
1615 bool present =
false;
1616 for (
int j=0; j<numExclude; j++)
1617 if (elem == exclude[j]) {
1625 DEMAND( numSamps <= len );
1633 int*
const& get()
const override {
1637 bool next()
override {
1640 if (std::next_permutation(sublist, sublist+sublen))
1644 if (std::next_permutation(featured.begin(), featured.end())) {
1652 ~SubListGenerator() {
1658 int* list,
int len,
int sublen
1660 return Catch::Generators::GeneratorWrapper<int*>(
1661 Catch::Detail::make_unique<SubListGenerator>(list, len, sublen));
1663Catch::Generators::GeneratorWrapper<int*>
sublists(
1664 Catch::Generators::GeneratorWrapper<int>&& gen,
int numSamps,
const int* exclude,
int numExclude
1666 return Catch::Generators::GeneratorWrapper<int*>(
1667 Catch::Detail::make_unique<SubListGenerator>(std::move(gen), numSamps, exclude, numExclude));
1669Catch::Generators::GeneratorWrapper<int*>
sublists(
1670 Catch::Generators::GeneratorWrapper<int>&& gen,
int numSamps,
int excluded
1672 int exclude[] = {excluded};
1673 return Catch::Generators::GeneratorWrapper<int*>(
1674 Catch::Detail::make_unique<SubListGenerator>(std::move(gen), numSamps, exclude, 1));
1676Catch::Generators::GeneratorWrapper<int*>
sublists(
1677 Catch::Generators::GeneratorWrapper<int>&& gen,
int numSamps
1679 int exclude[] = {-1};
1680 return Catch::Generators::GeneratorWrapper<int*>(
1681 Catch::Detail::make_unique<SubListGenerator>(std::move(gen), numSamps, exclude, 0));
1685template <
typename T>
1686class SequenceGenerator :
public Catch::Generators::IGenerator<T*> {
1693 SequenceGenerator(T maxDigit_,
int numDigits) {
1696 maxDigit = maxDigit_;
1697 seqLen = (int) pow(1 + (
int) maxDigit, len);
1698 digits = (T*) malloc(numDigits *
sizeof *digits);
1699 for (
int i=0; i<numDigits; i++)
1704 T*
const& get()
const override {
1708 bool next()
override {
1709 bool isNext = (ind++) < seqLen;
1712 while (digits[i] == maxDigit)
1713 digits[i++] = (T) 0;
1714 digits[i] = (T) ((
int) digits[i] + 1);
1719 ~SequenceGenerator() {
1723Catch::Generators::GeneratorWrapper<int*>
bitsets(
int numBits) {
1724 return Catch::Generators::GeneratorWrapper<int*>(
1725 Catch::Detail::make_unique<SequenceGenerator<int>>(1, numBits));
1727Catch::Generators::GeneratorWrapper<int*>
sequences(
int base,
int numDigits) {
1728 return Catch::Generators::GeneratorWrapper<int*>(
1729 Catch::Detail::make_unique<SequenceGenerator<int>>(base-1, numDigits));
1731Catch::Generators::GeneratorWrapper<pauliOpType*>
pauliseqs(
int numPaulis) {
1732 return Catch::Generators::GeneratorWrapper<pauliOpType*>(
1733 Catch::Detail::make_unique<SequenceGenerator<pauliOpType>>(PAULI_Z, numPaulis));
void applyReferenceMatrix(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
void setRandomPauliSum(qreal *coeffs, pauliOpType *codes, int numQubits, int numTerms)
void setUniqueFilename(char *outFn, int maxlen, char *prefix)
Catch::Generators::GeneratorWrapper< 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)
QMatrix getKetBra(QVector ket, QVector bra)
Catch::Generators::GeneratorWrapper< int * > sublists(int *list, int len, int sublen)
QMatrix getSwapMatrix(int qb1, int qb2, int numQb)
QMatrix getMixedDensityMatrix(vector< qreal > probs, vector< QVector > states)
bool areEqual(QVector a, QVector b)
long long int getTwosComplement(long long int decimal, int numBits)
long long int getValueOfTargets(long long int ind, int *targs, int numTargs)
QVector getNormalised(QVector vec)
void assertQuregAndRefInDebugState(Qureg qureg, QVector ref)
vector< vector< qcomp > > QMatrix
ComplexMatrix2 toComplexMatrix2(QMatrix qm)
void applyReferenceOp(QVector &state, int *ctrls, int numCtrls, int *targs, int numTargs, QMatrix op)
Catch::Generators::GeneratorWrapper< pauliOpType * > pauliseqs(int numPaulis)
QVector getDFT(QVector in)
void toComplexMatrixN(QMatrix qm, ComplexMatrixN cm)
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)
QMatrix toQMatrix(CompMatr1 src)
QVector getKroneckerProduct(QVector b, QVector a)
void deleteFilesWithPrefixSynch(char *prefix)
QVector toQVector(Qureg qureg)
QMatrix getPureDensityMatrix(QVector state)
long long int getUnsigned(long long int twosComp, int numBits)
Catch::Generators::GeneratorWrapper< int * > bitsets(int numBits)
void toQureg(Qureg qureg, QVector vec)
void syncCompMatr(CompMatr matr)
PauliStr getPauliStr(const char *paulis, int *indices, int numPaulis)
QMatrix getConjugateTranspose(QMatrix a)
QMatrix getExponentialOfDiagonalMatrix(QMatrix a)
QMatrix getExponentialOfPauliMatrix(qreal angle, QMatrix a)
QMatrix getIdentityMatrix(size_t dim)
void setSubMatrix(QMatrix &dest, QMatrix sub, size_t r, size_t c)
QMatrix getZeroMatrix(size_t dim)
QVector getRandomStateVector(int numQb)
QMatrix getRandomPureDensityMatrix(int numQb)
QMatrix getRandomUnitary(int numQb)
void setRandomTestStateSeeds()
QMatrix getRandomDensityMatrix(int numQb)
qreal getRandomReal(qreal min, qreal max)
vector< qreal > getRandomProbabilities(int numProbs)
vector< QMatrix > getRandomKrausMap(int numQb, int numOps)
int getRandomInt(int min, int max)