9#include <catch2/catch_test_macros.hpp>
10#include <catch2/generators/catch_generators.hpp>
13#include "test_utilities.hpp"
24 #if (FLOAT_PRECISION == 1)
25 #define MPI_QCOMP MPI_CXX_FLOAT_COMPLEX
26 #elif (FLOAT_PRECISION == 2)
27 #define MPI_QCOMP MPI_CXX_DOUBLE_COMPLEX
28 #elif (FLOAT_PRECISION == 4) && defined(MPI_CXX_LONG_DOUBLE_COMPLEX)
29 #define MPI_QCOMP MPI_CXX_LONG_DOUBLE_COMPLEX
31 #define MPI_QCOMP MPI_C_LONG_DOUBLE_COMPLEX
34 #ifdef MPI_MAX_AMPS_IN_MSG
35 #undef MPI_MAX_AMPS_IN_MSG
37 #define MPI_MAX_AMPS_IN_MSG (1 << 30)
54qreal absReal(qreal x) {
57qreal absComp(qcomp x) {
68static std::mt19937 randomGenerator;
78#define DEMAND( cond ) if (!(cond)) FAIL( );
81 DEMAND( v1.size() == v2.size() );
83 for (
size_t i=0; i<v2.size(); i++)
88 DEMAND( v1.size() == v2.size() );
90 for (
size_t i=0; i<v2.size(); i++)
96 for (
size_t i=0; i<v.size(); i++)
104 DEMAND( abs(a) != 0 );
106 for (
size_t i=0; i<v.size(); i++)
112 DEMAND( v1.size() == v2.size() );
114 for (
size_t i=0; i<v1.size(); i++)
115 out += v1[i] * conj(v2[i]);
124void operator *= (
QVector& v1,
const qcomp& a) {
127void operator /= (
QVector& v1,
const qcomp& a) {
131 DEMAND( m1.size() == m2.size() );
133 for (
size_t r=0; r<m1.size(); r++)
134 for (
size_t c=0; c<m1.size(); c++)
135 out[r][c] += m2[r][c];
139 DEMAND( m1.size() == m2.size() );
141 for (
size_t r=0; r<m1.size(); r++)
142 for (
size_t c=0; c<m1.size(); c++)
143 out[r][c] -= m2[r][c];
148 for (
size_t r=0; r<m.size(); r++)
149 for (
size_t c=0; c<m.size(); c++)
158 for (
size_t r=0; r<m.size(); r++)
159 for (
size_t c=0; c<m.size(); c++)
165 for (
size_t r=0; r<m1.size(); r++)
166 for (
size_t c=0; c<m1.size(); c++) {
168 for (
size_t k=0; k<m1.size(); k++)
169 prod[r][c] += m1[r][k] * m2[k][c];
179void operator *= (
QMatrix& m1,
const qreal& a) {
182void operator /= (
QMatrix& m1,
const qreal& a) {
189 DEMAND( m.size() == v.size() );
191 for (
size_t r=0; r<v.size(); r++)
192 for (
size_t c=0; c<v.size(); c++)
193 prod[r] += m[r][c] * v[c];
202 std::random_device cspnrg;
203 unsigned seed = cspnrg();
208 MPI_Bcast(&seed, 1, MPI_UNSIGNED, sendRank, MPI_COMM_WORLD);
213 randomGenerator.seed(seed);
217 DEMAND( qureg.isDensityMatrix == 0 );
218 DEMAND( qureg.numAmps == (
long long int) ref.size() );
221 for (
size_t i=0; i<ref.size(); i++) {
222 qcomp val = qcomp(.2*i, .2*i+.1);
223 DEMAND( abs(ref[i] - val) < REAL_EPS );
231 DEMAND( qureg.isDensityMatrix == 1 );
232 DEMAND( (1LL << qureg.numQubits) == (
long long int) ref.size() );
236 for (
size_t c=0; c<ref.size(); c++) {
237 for (
size_t r=0; r<ref.size(); r++) {
238 qcomp val = qcomp(.2*i, .2*i+.1);
239 DEMAND( abs(ref[r][c] - val) < REAL_EPS );
252 for (
size_t i=0; i<prod.size(); i++)
253 prod[i] = b[i / a.size()] * a[i % a.size()];
261 for (
size_t i=0; i<dim; i++)
269 for (
size_t i=0; i<dim; i++)
275 DEMAND( ket.size() == bra.size() );
278 for (
size_t r=0; r<ket.size(); r++)
279 for (
size_t c=0; c<ket.size(); c++)
280 mat[r][c] = ket[r] * conj(bra[c]);
286 for (
size_t r=0; r<b.size(); r++)
287 for (
size_t c=0; c<b.size(); c++)
288 for (
size_t i=0; i<a.size(); i++)
289 for (
size_t j=0; j<a.size(); j++)
290 prod[r+b.size()*i][c+b.size()*j] = a[i][j] * b[r][c];
296 for (
size_t r=0; r<a.size(); r++)
297 for (
size_t c=0; c<a.size(); c++)
304 for (
size_t r=0; r<a.size(); r++)
305 for (
size_t c=0; c<a.size(); c++)
306 b[r][c] = conj(a[c][r]);
313 for (
size_t r=0; r<a.size(); r++)
314 for (
size_t c=0; c<a.size(); c++) {
317 DEMAND( real(a[r][c]) == 0. );
318 DEMAND( imag(a[r][c]) == 0. );
323 for (
size_t i=0; i<a.size(); i++)
324 diag[i][i] = exp(diag[i][i]);
331 QMatrix expo = (cos(angle/2) * iden) + ((qcomp) -1i * sin(angle/2) * a);
336 DEMAND( sub.size() + r <= dest.size() );
337 DEMAND( sub.size() + c <= dest.size() );
338 for (
size_t i=0; i<sub.size(); i++)
339 for (
size_t j=0; j<sub.size(); j++)
340 dest[r+i][c+j] = sub[i][j];
345 DEMAND( (qb1 >= 0 && qb1 < numQb) );
346 DEMAND( (qb2 >= 0 && qb2 < numQb) );
356 if (qb2 == qb1 + 1) {
358 swap =
QMatrix{{1,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,1}};
362 int block = 1 << (qb2 - qb1);
400void updateIndices(
int oldEl,
int newEl,
int* list1,
int len1,
int* list2,
int len2) {
402 for (
int i=0; i<len1; i++) {
403 if (list1[i] == oldEl) {
409 for (
int i=0; i<len2; i++) {
410 if (list2[i] == oldEl) {
418 int* ctrls,
int numCtrls,
int *targs,
int numTargs,
QMatrix op,
int numQubits
420 DEMAND( numCtrls >= 0 );
421 DEMAND( numTargs >= 0 );
422 DEMAND( numQubits >= (numCtrls+numTargs) );
423 DEMAND( op.size() == (1u << numTargs) );
426 vector<int> ctrlsCopy(ctrls, ctrls+numCtrls);
427 vector<int> targsCopy(targs, targs+numTargs);
435 for (
int i=0; i<numTargs; i++) {
438 swaps = matr * swaps;
439 unswaps = unswaps * matr;
443 i, targs[i], (i < numTargs-1)? &targs[i+1] : NULL,
444 numTargs-i-1, ctrls, numCtrls);
449 for (
int i=0; i<numCtrls; i++) {
450 int newInd = numTargs+i;
451 if (newInd != ctrls[i]) {
453 swaps = matr * swaps;
454 unswaps = unswaps * matr;
458 updateIndices(newInd, ctrls[i], NULL, 0, &ctrls[i+1], numCtrls-i-1);
463 size_t dim = 1 << (numCtrls+numTargs);
468 if (numQubits > numCtrls+numTargs) {
469 size_t pad = 1 << (numQubits - numCtrls - numTargs);
474 fullOp = unswaps * fullOp * swaps;
477 for (
int i=0; i<numCtrls; i++)
478 ctrls[i] = ctrlsCopy[i];
479 for (
int i=0; i<numTargs; i++)
480 targs[i] = targsCopy[i];
496 for (
int i=0; i<dim; i++) {
497 for (
int j=0; j<dim; j++) {
500 qreal a = rand()/(qreal) RAND_MAX;
501 qreal b = rand()/(qreal) RAND_MAX;
502 if (a == 0) a = REAL_EPS;
503 qreal r1 = sqrt(-2 * log(a)) * cos(2 * 3.14159265 * b);
504 qreal r2 = sqrt(-2 * log(a)) * sin(2 * 3.14159265 * b);
506 matr[i][j] = r1 + r2 * (qcomp) 1i;
513 DEMAND( a.size() == b.size() );
515 for (
size_t i=0; i<a.size(); i++)
516 if (abs(a[i] - b[i]) > REAL_EPS)
522 DEMAND( a.size() == b.size() );
524 for (
size_t i=0; i<a.size(); i++)
525 for (
size_t j=0; j<b.size(); j++)
526 if (abs(a[i][j] - b[i][j]) > REAL_EPS)
531qcomp expI(qreal phase) {
532 return qcomp(cos(phase), sin(phase));
536 DEMAND( min <= max );
537 qreal r = min + (max - min) * (rand() / (qreal) RAND_MAX);
551 for (
int i=0; i<dim; i++)
564 for (
size_t i=0; i<vec.size(); i++) {
565 y = real(vec[i])*real(vec[i]) - c;
567 c = ( t - norm ) - y;
570 y = imag(vec[i])*imag(vec[i]) - c;
572 c = ( t - norm ) - y;
576 for (
size_t i=0; i<vec.size(); i++)
577 vec[i] /= sqrt(norm);
590 for (
int i=0; i<numProbs; i++) {
592 probs.push_back(prob);
597 for (
int i=0; i<numProbs; i++)
612 for (
int i=0; i<dim; i++) {
614 dens += probs[i] *
getKetBra(pure, pure);
633 for (
size_t i=0; i<vec.size(); i++)
646 for (
size_t i=0; i<matr.size(); i++) {
650 for (
int k=i-1; k>=0; k--) {
653 qcomp prod = row * matr[k];
656 matr[i] -= prod * matr[k];
667QMatrix getRandomDiagonalUnitary(
int numQb) {
668 DEMAND( numQb >= 1 );
671 for (
size_t i=0; i<matr.size(); i++)
678 DEMAND( numQb >= 1 );
681 size_t dim = 1 << numQb;
683 QMatrix matrZT = getTranspose(matrZ);
686 QMatrix matrQT = getOrthonormalisedRows(matrZ);
687 QMatrix matrQ = getTranspose(matrQT);
691 for (
size_t r=0; r<dim; r++)
692 for (
size_t c=r; c<dim; c++)
693 matrR[r][c] = matrZT[c] * matrQT[r];
697 for (
size_t i=0; i<dim; i++)
698 matrD[i][i] = matrR[i][i] / abs(matrR[i][i]);
708 matrU = getRandomDiagonalUnitary(numQb);
714 DEMAND( numOps >= 1 );
715 DEMAND( numOps <= 4*numQb*numQb );
719 for (
int i=0; i<numOps; i++)
723 vector<qreal> weights(numOps);
724 for (
int i=0; i<numOps; i++)
729 for (
int i=0; i<numOps; i++)
730 weightSum += weights[i];
731 for (
int i=0; i<numOps; i++)
732 weights[i] = sqrt((qreal) weights[i]/weightSum);
735 for (
int i=0; i<numOps; i++)
736 ops[i] *= weights[i];
741 for (
int i=0; i<numOps; i++)
747 for (
int i=0; i<numOps; i++)
748 ops[i] = weights[i] * getRandomDiagonalUnitary(numQb);
754 DEMAND( numQb >= 1 );
755 DEMAND( numStates >= 1);
758 vector<QVector> vecs;
760 for (
int n=0; n<numStates; n++) {
765 for (
int m=0; m<n; m++) {
766 qcomp prod = vec * vecs[m];
767 vec -= (prod * vecs[m]);
781 DEMAND( probs.size() == states.size() );
782 DEMAND( probs.size() >= 1 );
786 for (
size_t i=0; i<probs.size(); i++)
793 REQUIRE( in.size() > 0 );
795 size_t dim = in.size();
796 qreal ampFac = 1 / sqrt( dim );
797 qreal phaseFac = 2 * M_PI / dim;
801 for (
size_t x=0; x<dim; x++) {
803 for (
size_t y=0; y<dim; y++)
804 dftVec[x] += expI(phaseFac * x * y) * in[y];
813 long long int val = 0;
815 for (
int t=0; t<numTargs; t++)
816 val += ((ind >> targs[t]) & 1) * (1LL << t);
821long long int setBit(
long long int num,
int bitInd,
int bitVal) {
822 DEMAND( (bitVal == 0 || bitVal == 1) );
824 DEMAND( bitInd >= 0 );
826 return (num & ~(1UL << bitInd)) | (bitVal << bitInd);
829long long int getIndexOfTargetValues(
long long int ref,
int* targs,
int numTargs,
long long int targVal) {
833 for (
int t=0; t<numTargs; t++) {
834 int bit = (targVal >> t) & 1;
835 ref = setBit(ref, targs[t], bit);
843 long long int inDim = (
long long int) in.size();
844 long long int targDim = (1LL << numTargs);
846 for (
long long int j=0; j<inDim; j++) {
851 for (
long long int y=0; y<targDim; y++) {
854 long long int outInd = getIndexOfTargetValues(j, targs, numTargs, y);
856 qcomp elem = (in[j] / sqrt(pow(2,numTargs))) * expI(2*M_PI * x * y / pow(2,numTargs));
870 QVector &state,
int* ctrls,
int numCtrls,
int *targs,
int numTargs,
QMatrix op
872 int numQubits =
calcLog2(state.size());
874 state = fullOp * state;
877 QVector &state,
int* ctrls,
int numCtrls,
int targ1,
int targ2,
QMatrix op
879 int targs[2] = {targ1, targ2};
885 int targs[1] = {target};
896 int ctrls[1] = {ctrl};
897 int targs[1] = {targ};
903 int ctrls[1] = {ctrl};
909 int ctrls[1] = {ctrl};
910 int targs[2] = {targ1, targ2};
916 int targs[1] = {targ};
926 QMatrix &state,
int* ctrls,
int numCtrls,
int *targs,
int numTargs,
QMatrix op
928 int numQubits =
calcLog2(state.size());
931 state = leftOp * state * rightOp;
934 QMatrix &state,
int* ctrls,
int numCtrls,
int targ1,
int targ2,
QMatrix op
936 int targs[2] = {targ1, targ2};
942 int targs[1] = {target};
953 int ctrls[1] = {ctrl};
954 int targs[1] = {targ};
960 int ctrls[1] = {ctrl};
966 int ctrls[1] = {ctrl};
967 int targs[2] = {targ1, targ2};
973 int targs[1] = {targ};
983 QVector &state,
int* ctrls,
int numCtrls,
int *targs,
int numTargs,
QMatrix op
995 QMatrix &state,
int* ctrls,
int numCtrls,
int *targs,
int numTargs,
QMatrix op
998 int numQubits =
calcLog2(state.size());
1000 state = leftOp * state;
1009 DEMAND( qureg1.isDensityMatrix == qureg2.isDensityMatrix );
1010 DEMAND( qureg1.numAmps == qureg2.numAmps );
1012 copyStateFromGPU(qureg1);
1013 copyStateFromGPU(qureg2);
1018 for (
long long int i=0; ampsAgree && i<qureg1.numAmpsPerNode; i++)
1019 ampsAgree = absComp(qureg1.cpuAmps[i] - qureg2.cpuAmps[i]) < precision;
1022 int allAmpsAgree = ampsAgree;
1024 MPI_Allreduce(&sAgree, &allAmpsAgree, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
1027 return allAmpsAgree;
1030 return areEqual(qureg1, qureg2, REAL_EPS);
1034 DEMAND( !qureg.isDensityMatrix );
1035 DEMAND( (
int) vec.size() == qureg.numAmps );
1037 copyStateFromGPU(qureg);
1041 long long int startInd = qureg.rank * qureg.numAmpsPerNode;
1044 for (
long long int i=0; i<qureg.numAmpsPerNode; i++) {
1045 qcomp dif = (qureg.cpuAmps[i] - vec[startInd+i]);
1047 if (absComp(dif) > precision) {
1052 snprintf(buff, 200,
"Disagreement at %lld of (%s) + i(%s):\n\t%s + i(%s) VS %s + i(%s)\n",
1057 real(dif), imag(dif),
1058 real(qureg.cpuAmps[i]), imag(qureg.cpuAmps[i]),
1059 real(vec[startInd+i]), imag(vec[startInd+i]));
1066 int allAmpsAgree = ampsAgree;
1068 MPI_Allreduce(&sAgree, &allAmpsAgree, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
1071 return allAmpsAgree;
1074 return areEqual(qureg, vec, REAL_EPS);
1078 DEMAND( qureg.isDensityMatrix );
1079 DEMAND( (
long long int) (matr.size()*matr.size()) == qureg.numAmps );
1082 copyStateFromGPU(qureg);
1086 long long int startInd = qureg.rank * qureg.numAmpsPerNode;
1087 long long int globalInd, row, col, i;
1091 for (i=0; i<qureg.numAmpsPerNode; i++) {
1092 globalInd = startInd + i;
1093 row = globalInd % matr.size();
1094 col = globalInd / matr.size();
1096 qreal realDif = absReal(real(qureg.cpuAmps[i]) - real(matr[row][col]));
1097 qreal imagDif = absReal(imag(qureg.cpuAmps[i]) - imag(matr[row][col]));
1098 ampsAgree = (realDif < precision && imagDif < precision);
1103 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",
1104 qureg.rank, startInd+i,
1109 real(qureg.cpuAmps[i]), imag(qureg.cpuAmps[i]),
1110 real(matr[row][col]), imag(matr[row][col]));
1129 int allAmpsAgree = ampsAgree;
1131 MPI_Allreduce(&sAgree, &allAmpsAgree, 1, MPI_INT, MPI_LAND, MPI_COMM_WORLD);
1134 return allAmpsAgree;
1137 return areEqual(qureg, matr, REAL_EPS);
1143 for (
size_t i=0; i<vec.size(); i++) {
1144 dif = absReal(real(vec[i]) - reals[i]);
1147 dif = absReal(imag(vec[i]) - imags[i]);
1155 for (
size_t i=0; i<vec.size(); i++) {
1156 DEMAND( imag(vec[i]) == 0. );
1158 qreal dif = abs(real(vec[i]) - reals[i]);
1166#define macro_copyQMatrixToDeprecatedComplexMatrix(dest, src) { \
1167 for (size_t i=0; i<src.size(); i++) { \
1168 for (size_t j=0; j<src.size(); j++) { \
1169 dest.real[i][j] = real(src[i][j]); \
1170 dest.imag[i][j] = imag(src[i][j]); \
1175 DEMAND( qm.size() == 2 );
1177 macro_copyQMatrixToDeprecatedComplexMatrix(cm, qm);
1181 DEMAND( qm.size() == 4 );
1183 macro_copyQMatrixToDeprecatedComplexMatrix(cm, qm);
1188#define macro_copyComplexMatrix(dest, src, dim) \
1189 for (size_t i=0; i<dim; i++) \
1190 for (size_t j=0; j<dim; j++) \
1191 dest[i][j] = src[i][j];
1194 DEMAND( qm.size() == (1u<<cm.numQubits) );
1195 macro_copyComplexMatrix(cm.cpuElems, qm, qm.size());
1201 macro_copyComplexMatrix(dest, src.elems, dest.size());
1206 macro_copyComplexMatrix(dest, src.elems, dest.size());
1211 macro_copyComplexMatrix(dest, src.cpuElems, dest.size());
1216 DEMAND( qureg.isDensityMatrix );
1218 DEMAND( qureg.numAmps < MPI_MAX_AMPS_IN_MSG );
1222 copyStateFromGPU(qureg);
1226 qcomp* allAmps = qureg.cpuAmps;
1230 if (qureg.isDistributed) {
1231 allAmps = (qcomp*) malloc(qureg.numAmps *
sizeof *allAmps);
1233 qureg.cpuAmps, qureg.numAmpsPerNode, MPI_QCOMP,
1234 allAmps, qureg.numAmpsPerNode, MPI_QCOMP, MPI_COMM_WORLD);
1239 long long int dim = (1LL << qureg.numQubits);
1241 for (
long long int n=0; n<qureg.numAmps; n++)
1242 matr[n%dim][n/dim] = allAmps[n];
1245 if (qureg.isDistributed)
1251 DEMAND( !qureg.isDensityMatrix );
1253 DEMAND( qureg.numAmps < MPI_MAX_AMPS_IN_MSG );
1257 copyStateFromGPU(qureg);
1260 qcomp* allAmps = qureg.cpuAmps;
1264 if (qureg.isDistributed) {
1265 allAmps = (qcomp*) malloc(qureg.numAmps *
sizeof *allAmps);
1268 qureg.cpuAmps, qureg.numAmpsPerNode, MPI_QCOMP,
1269 allAmps, qureg.numAmpsPerNode, MPI_QCOMP, MPI_COMM_WORLD);
1275 for (
long long int i=0; i<qureg.numAmps; i++)
1276 vec[i] = allAmps[i];
1279 if (qureg.isDistributed)
1287 return vector<qcomp>(matr.cpuElems, matr.cpuElems + matr.numElems);
1293 DEMAND( matr.numElems < MPI_MAX_AMPS_IN_MSG );
1296 vector<qcomp> vec(matr.numElems);
1299 if (matr.isDistributed) {
1302 matr.cpuElems, matr.numElemsPerNode, MPI_QCOMP,
1303 vec.data(), matr.numElemsPerNode, MPI_QCOMP, MPI_COMM_WORLD);
1306 vec.assign(matr.cpuElems, matr.cpuElems + matr.numElems);
1315 for (
size_t i=0; i<mat.size(); i++)
1322 for (
size_t i=0; i<mat.size(); i++)
1323 mat[i][i] = in.cpuElems[i];
1328 DEMAND( !qureg.isDensityMatrix );
1329 DEMAND( qureg.numAmps == (
long long int) vec.size() );
1333 for (
int i=0; i<qureg.numAmpsPerNode; i++) {
1334 int ind = qureg.rank*qureg.numAmpsPerNode + i;
1335 qureg.cpuAmps[i] = vec[ind];
1337 copyStateToGPU(qureg);
1340 DEMAND( qureg.isDensityMatrix );
1341 DEMAND( (1LL << qureg.numQubits) == (
long long int) mat.size() );
1345 int len = (1 << qureg.numQubits);
1346 for (
int i=0; i<qureg.numAmpsPerNode; i++) {
1347 int ind = qureg.rank*qureg.numAmpsPerNode + i;
1348 qureg.cpuAmps[i] = mat[ind%len][ind/len];
1350 copyStateToGPU(qureg);
1353PauliStr getRandomPauliStr(
int numQubits) {
1355 std::string paulis =
"";
1356 for (
int i=0; i<numQubits; i++)
1361PauliStr getRandomDiagPauliStr(
int numQubits) {
1363 std::string paulis =
"";
1364 for (
int i=0; i<numQubits; i++)
1372 for (
int n=0; n<numTerms; n++) {
1374 for (
int q=0; q<numQubits; q++)
1381 for (
int n=0; n<hamil.numTerms; n++) {
1383 hamil.strings[n] = getRandomPauliStr(numQubits);
1388 for (
int n=0; n<hamil.numTerms; n++) {
1390 hamil.strings[n] = getRandomDiagPauliStr(numQubits);
1395 DEMAND( numQb >= 1 );
1396 DEMAND( numTargs >= 1);
1397 DEMAND( numTargs <= numQb );
1400 vector<int> allQb(numQb);
1401 for (
int q=0; q<numQb; q++)
1405 std::shuffle(&allQb[0], &allQb[numQb], randomGenerator);
1408 for (
int i=0; i<numTargs; i++)
1409 targs[i] = allQb[i];
1421 QMatrix yMatr{{0,-qcomp(0,1)},{qcomp(0,1),0}};
1425 for (
int t=0; t<numTerms; t++) {
1428 for (
int q=0; q<numQubits; q++) {
1429 int i = q + t*numQubits;
1432 pauliOpType code = paulis[i];
1433 if (code == PAULI_I) fac = iMatr;
1434 if (code == PAULI_X) fac = xMatr;
1435 if (code == PAULI_Y) fac = yMatr;
1436 if (code == PAULI_Z) fac = zMatr;
1439 pauliSum += coeffs[t] * pauliProd;
1452 DEMAND( decimal >= 0 );
1453 DEMAND( numBits >= 2 );
1454 DEMAND( decimal < (1LL << numBits) );
1456 long long int maxMag = 1LL << (numBits-1);
1457 if (decimal >= maxMag)
1458 return -maxMag + (decimal - maxMag);
1464 DEMAND( numBits >= 2 );
1465 DEMAND( twosComp < (1LL << (numBits-1)) );
1466 DEMAND( twosComp >= - (1LL << (numBits-1)) );
1471 return (1<<numBits) + twosComp;
1476 for (
size_t i=0; i<vec.size(); i++)
1521static int fn_unique_suffix_id = 0;
1524 snprintf(outFn, maxlen,
"%s_%d.txt", prefix, fn_unique_suffix_id++);
1531 FILE* file = fopen(fn,
"w");
1532 fputs(contents.c_str(), file);
1545 snprintf(cmd, 200,
"exec rm %s*", prefix);
1554class SubListGenerator :
public Catch::Generators::IGenerator<int*> {
1559 vector<bool> featured;
1561 void createSublist() {
1564 sublist = (
int*) malloc(sublen *
sizeof *sublist);
1567 featured = vector<bool>(len);
1568 fill(featured.end() - sublen, featured.end(),
true);
1571 void prepareSublist() {
1575 for (
int i=0; i<len; i++)
1577 sublist[j++] = list[i];
1580 std::sort(sublist, sublist+sublen);
1583 SubListGenerator(
int* elems,
int numElems,
int numSamps) {
1585 DEMAND( numSamps <= numElems );
1589 list = (
int*) malloc(len *
sizeof *list);
1590 for (
int i=0; i<len; i++)
1600 Catch::Generators::GeneratorWrapper<int>&& gen,
1601 int numSamps,
const int* exclude,
int numExclude
1604 vector<int> elems = vector<int>();
1605 do { elems.push_back(gen.get()); }
while (gen.next());
1609 list = (
int*) malloc(elems.size() *
sizeof *list);
1610 for (
size_t i=0; i<elems.size(); i++) {
1611 int elem = elems[i];
1612 bool present =
false;
1613 for (
int j=0; j<numExclude; j++)
1614 if (elem == exclude[j]) {
1622 DEMAND( numSamps <= len );
1630 int*
const& get()
const override {
1634 bool next()
override {
1637 if (std::next_permutation(sublist, sublist+sublen))
1641 if (std::next_permutation(featured.begin(), featured.end())) {
1649 ~SubListGenerator() {
1655 int* list,
int len,
int sublen
1657 return Catch::Generators::GeneratorWrapper<int*>(
1658 Catch::Detail::make_unique<SubListGenerator>(list, len, sublen));
1660Catch::Generators::GeneratorWrapper<int*>
sublists(
1661 Catch::Generators::GeneratorWrapper<int>&& gen,
int numSamps,
const int* exclude,
int numExclude
1663 return Catch::Generators::GeneratorWrapper<int*>(
1664 Catch::Detail::make_unique<SubListGenerator>(std::move(gen), numSamps, exclude, numExclude));
1666Catch::Generators::GeneratorWrapper<int*>
sublists(
1667 Catch::Generators::GeneratorWrapper<int>&& gen,
int numSamps,
int excluded
1669 int exclude[] = {excluded};
1670 return Catch::Generators::GeneratorWrapper<int*>(
1671 Catch::Detail::make_unique<SubListGenerator>(std::move(gen), numSamps, exclude, 1));
1673Catch::Generators::GeneratorWrapper<int*>
sublists(
1674 Catch::Generators::GeneratorWrapper<int>&& gen,
int numSamps
1676 int exclude[] = {-1};
1677 return Catch::Generators::GeneratorWrapper<int*>(
1678 Catch::Detail::make_unique<SubListGenerator>(std::move(gen), numSamps, exclude, 0));
1682template <
typename T>
1683class SequenceGenerator :
public Catch::Generators::IGenerator<T*> {
1690 SequenceGenerator(T maxDigit_,
int numDigits) {
1693 maxDigit = maxDigit_;
1694 seqLen = (int) pow(1 + (
int) maxDigit, len);
1695 digits = (T*) malloc(numDigits *
sizeof *digits);
1696 for (
int i=0; i<numDigits; i++)
1701 T*
const& get()
const override {
1705 bool next()
override {
1706 bool isNext = (ind++) < seqLen;
1709 while (digits[i] == maxDigit)
1710 digits[i++] = (T) 0;
1711 digits[i] = (T) ((
int) digits[i] + 1);
1716 ~SequenceGenerator() {
1720Catch::Generators::GeneratorWrapper<int*>
bitsets(
int numBits) {
1721 return Catch::Generators::GeneratorWrapper<int*>(
1722 Catch::Detail::make_unique<SequenceGenerator<int>>(1, numBits));
1724Catch::Generators::GeneratorWrapper<int*>
sequences(
int base,
int numDigits) {
1725 return Catch::Generators::GeneratorWrapper<int*>(
1726 Catch::Detail::make_unique<SequenceGenerator<int>>(base-1, numDigits));
1728Catch::Generators::GeneratorWrapper<pauliOpType*>
pauliseqs(
int numPaulis) {
1729 return Catch::Generators::GeneratorWrapper<pauliOpType*>(
1730 Catch::Detail::make_unique<SequenceGenerator<pauliOpType>>(PAULI_Z, numPaulis));
QMatrix getExponentialOfPauliMatrix(qreal angle, QMatrix a)
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)
const char * QREAL_FORMAT_SPECIFIER
QMatrix getConjugateTranspose(QMatrix a)
QMatrix getExponentialOfDiagonalMatrix(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()
qreal getRandomReal(qreal min, qreal max)
QMatrix getRandomDensityMatrix(int numQb)
vector< qreal > getRandomProbabilities(int numProbs)
vector< QMatrix > getRandomKrausMap(int numQb, int numOps)
int getRandomInt(int min, int max)