8#include "quest/include/precision.h"
9#include "quest/include/paulis.h"
11#include "quest/src/core/validation.hpp"
12#include "quest/src/core/printer.hpp"
13#include "quest/src/core/utilities.hpp"
14#include "quest/src/core/parser.hpp"
15#include "quest/src/core/memory.hpp"
16#include "quest/src/core/errors.hpp"
17#include "quest/src/core/bitwise.hpp"
18#include "quest/src/cpu/cpu_config.hpp"
19#include "quest/src/comm/comm_config.hpp"
20#include "quest/src/comm/comm_routines.hpp"
38static const int MAX_NUM_PAULIS_PER_MASK =
sizeof(
PAULI_MASK_TYPE) * 8 / 2;
39static const int MAX_NUM_PAULIS_PER_STR = MAX_NUM_PAULIS_PER_MASK * 2;
50 return getTwoAdjacentBits(mask, 2*ind);
57 ! mem_isAllocated(sum.strings) ||
58 ! mem_isAllocated(sum.coeffs) ||
59 ! mem_isAllocated(sum.isApproxHermitian) );
62 anyFail = comm_isTrueOnAllNodes(anyFail);
71 cpu_deallocPauliStrings(sum.strings);
72 cpu_deallocArray(sum.coeffs);
73 util_deallocEpsilonSensitiveHeapFlag(sum.isApproxHermitian);
77void freeAllMemoryIfAnyAllocsFailed(
PauliStrSum sum) {
80 if (!didAnyAllocsFailOnAnyNode(sum))
98bool paulis_isIdentity(
PauliStr str) {
101 (str.lowPaulis == 0) &&
102 (str.highPaulis == 0);
106int paulis_getPauliAt(
PauliStr str,
int ind) {
108 return (ind < MAX_NUM_PAULIS_PER_MASK)?
109 getPauliFromMaskAt(str.lowPaulis, ind) :
110 getPauliFromMaskAt(str.highPaulis, ind - MAX_NUM_PAULIS_PER_MASK);
114int paulis_getIndOfLefmostNonIdentityPauli(
PauliStr str) {
116 int ind = (str.highPaulis == 0)? 0 : MAX_NUM_PAULIS_PER_MASK;
117 auto mask = (str.highPaulis == 0)? str.lowPaulis : str.highPaulis;
128int paulis_getIndOfLefmostNonIdentityPauli(
PauliStr* strings, qindex numStrings) {
132 for (qindex i=0; i<numStrings; i++) {
133 int ind = paulis_getIndOfLefmostNonIdentityPauli(strings[i]);
142int paulis_getIndOfLefmostNonIdentityPauli(
PauliStrSum sum) {
144 return paulis_getIndOfLefmostNonIdentityPauli(sum.strings, sum.numTerms);
148bool paulis_containsXOrY(
PauliStr str) {
150 int maxInd = paulis_getIndOfLefmostNonIdentityPauli(str);
152 for (
int i=0; i<=maxInd; i++) {
153 int pauli = paulis_getPauliAt(str, i);
155 if (pauli == 1 || pauli == 2)
165 for (qindex i=0; i<sum.numTerms; i++)
166 if (paulis_containsXOrY(sum.strings[i]))
173bool paulis_hasOddNumY(
PauliStr str) {
177 for (
int targ=0; targ < MAX_NUM_PAULIS_PER_STR; targ++)
178 if (paulis_getPauliAt(str, targ) == 2)
185int paulis_getPrefixZSign(
Qureg qureg, vector<int> prefixZ) {
190 for (
int qubit : prefixZ)
191 sign *= util_getRankBitOfQubit(qubit, qureg)? -1 : 1;
197qcomp paulis_getPrefixPaulisElem(
Qureg qureg, vector<int> prefixY, vector<int> prefixZ) {
200 qcomp elem = paulis_getPrefixZSign(qureg, prefixZ);
203 for (
int qubit : prefixY)
204 elem *= 1_i * (util_getRankBitOfQubit(qubit, qureg)? 1 : -1);
210vector<int> paulis_getInds(
PauliStr str) {
212 int maxInd = paulis_getIndOfLefmostNonIdentityPauli(str);
215 inds.reserve(maxInd+1);
217 for (
int i=0; i<=maxInd; i++)
218 if (paulis_getPauliAt(str, i) != 0)
225array<vector<int>,3> paulis_getSeparateInds(
PauliStr str,
Qureg qureg) {
227 vector<int> iXYZ = paulis_getInds(str);
228 vector<int> iX, iY, iZ;
230 vector<int>* ptrs[] = {&iX, &iY, &iZ};
233 ptrs[paulis_getPauliAt(str, i) - 1]->push_back(i);
241 if (pauliShift <= 0 || pauliShift >= MAX_NUM_PAULIS_PER_MASK)
242 error_pauliStrShiftedByIllegalAmount();
244 int numBitsPerPauli = 2;
245 int numMaskBits = numBitsPerPauli * MAX_NUM_PAULIS_PER_MASK;
246 int bitShift = numBitsPerPauli * pauliShift;
249 PAULI_MASK_TYPE lostBits = getBitsLeftOfIndex(str.lowPaulis, numMaskBits - bitShift - 1);
252 PAULI_MASK_TYPE lowerBits = getBitsRightOfIndex(str.lowPaulis, numMaskBits - bitShift) << bitShift;
255 PAULI_MASK_TYPE upperBits = concatenateBits(str.highPaulis, lostBits, bitShift);
259 out.lowPaulis = lowerBits;
260 out.highPaulis = upperBits;
267 PauliStr shifted = paulis_getShiftedPauliStr(str, qureg.numQubits);
271 out.lowPaulis = str.lowPaulis | shifted.lowPaulis;
272 out.highPaulis = str.highPaulis | shifted.highPaulis;
286 int maxInd = paulis_getIndOfLefmostNonIdentityPauli(str);
288 for (
int i=0; i<=maxInd; i++) {
289 int pauli = paulis_getPauliAt(str, i);
290 int isXY = (pauli == 1 || pauli == 2);
307 validate_newPauliStrParams(paulis, indices, numPaulis, MAX_NUM_PAULIS_PER_STR, __func__);
314 for (
int i=0; i<numPaulis; i++) {
320 if (indices[i] < MAX_NUM_PAULIS_PER_MASK)
321 lowPaulis |= pauli << (2*indices[i]);
323 highPaulis |= pauli << (2*(indices[i] - MAX_NUM_PAULIS_PER_MASK));
328 out.lowPaulis = lowPaulis;
329 out.highPaulis = highPaulis;
335 validate_newPauliStrParams(paulis, indices, numPaulis, MAX_NUM_PAULIS_PER_STR, __func__);
338 char pauliChars[MAX_NUM_PAULIS_PER_STR + 1];
342 for (
int i=0; i<numPaulis; i++)
343 pauliChars[i] =
"IXYZ"[paulis[i]];
346 pauliChars[numPaulis] =
'\0';
348 return getPauliStr(pauliChars, indices, numPaulis);
352extern "C" PauliStr _getPauliStrFromInts(
int* paulis,
int* indices,
int numPaulis) {
361 validate_newPauliStrNumChars(paulis.length(), numPaulis, __func__);
363 return getPauliStr(paulis.data(), indices, numPaulis);
369 validate_newPauliStrNumChars(paulis.length(), indices.size(), __func__);
371 return getPauliStr(paulis.data(), indices.data(), indices.size());
377 validate_newPauliStrNumPaulis(paulis.size(), MAX_NUM_PAULIS_PER_STR, __func__);
380 vector<int> indices(paulis.size());
381 for (
size_t i=0; i<paulis.size(); i++)
382 indices[i] = paulis.size() - 1 - i;
399 validate_newPauliStrSumParams(numTerms, __func__);
403 out.numTerms = numTerms;
404 out.strings = cpu_allocPauliStrings(numTerms);
405 out.coeffs = cpu_allocArray(numTerms);
406 out.isApproxHermitian = util_allocEpsilonSensitiveHeapFlag();
409 freeAllMemoryIfAnyAllocsFailed(out);
410 validate_newPauliStrSumAllocs(out, numTerms*
sizeof(
PauliStr), numTerms*
sizeof(qcomp), __func__);
413 cpu_copyPauliStrSum(out, strings, coeffs);
414 util_setFlagToUnknown(out.isApproxHermitian);
422 validate_newPauliStrSumMatchingListLens(strings.size(), coeffs.size(), __func__);
436 bool rightIsLeastSig =
true;
437 return parser_validateAndParsePauliStrSum(str, rightIsLeastSig, __func__);
448 validate_canReadFile(fn, __func__);
451 string str = parser_loadFile(fn);
453 bool rightIsLeastSig =
true;
454 return parser_validateAndParsePauliStrSum(str, rightIsLeastSig, __func__);
465 validate_canReadFile(fn, __func__);
468 string str = parser_loadFile(fn);
470 bool rightIsLeastSig =
false;
471 return parser_validateAndParsePauliStrSum(str, rightIsLeastSig, __func__);
482 validate_pauliStrSumFields(sum, __func__);
484 freePauliStrSum(sum);
498 print_elemsWithoutNewline(str, indent);
506 validate_pauliStrSumFields(sum, __func__);
507 validate_numReportedNewlinesAboveZero(__func__);
510 qindex numStrBytes = sum.numTerms *
sizeof *sum.strings;
511 qindex numCoeffBytes = sum.numTerms *
sizeof *sum.coeffs;
512 qindex numStrucBytes =
sizeof(sum);
516 qindex numTotalBytes = numStrBytes + numCoeffBytes + numStrucBytes;
518 print_header(sum, numTotalBytes);
522 print_oneFewerNewlines();
PauliStrSum createPauliStrSumFromFile(const char *fn)
PauliStrSum createPauliStrSum(PauliStr *strings, qcomp *coeffs, qindex numTerms)
PauliStrSum createInlinePauliStrSum(const char *str)
PauliStrSum createPauliStrSumFromReversedFile(const char *fn)
PauliStr getPauliStr(const char *paulis, int *indices, int numPaulis)
void destroyPauliStrSum(PauliStrSum sum)
void reportPauliStrSum(PauliStrSum sum)
void reportPauliStr(PauliStr str)
long long unsigned int PAULI_MASK_TYPE