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))
98int paulis_getPauliAt(
PauliStr str,
int ind) {
100 return (ind < MAX_NUM_PAULIS_PER_MASK)?
101 getPauliFromMaskAt(str.lowPaulis, ind) :
102 getPauliFromMaskAt(str.highPaulis, ind - MAX_NUM_PAULIS_PER_MASK);
106int paulis_getIndOfLefmostNonIdentityPauli(
PauliStr str) {
108 int ind = (str.highPaulis == 0)? 0 : MAX_NUM_PAULIS_PER_MASK;
109 auto mask = (str.highPaulis == 0)? str.lowPaulis : str.highPaulis;
120int paulis_getIndOfLefmostNonIdentityPauli(
PauliStr* strings, qindex numStrings) {
124 for (qindex i=0; i<numStrings; i++) {
125 int ind = paulis_getIndOfLefmostNonIdentityPauli(strings[i]);
134int paulis_getIndOfLefmostNonIdentityPauli(
PauliStrSum sum) {
136 return paulis_getIndOfLefmostNonIdentityPauli(sum.strings, sum.numTerms);
140bool paulis_containsXOrY(
PauliStr str) {
142 int maxInd = paulis_getIndOfLefmostNonIdentityPauli(str);
144 for (
int i=0; i<=maxInd; i++) {
145 int pauli = paulis_getPauliAt(str, i);
147 if (pauli == 1 || pauli == 2)
157 for (qindex i=0; i<sum.numTerms; i++)
158 if (paulis_containsXOrY(sum.strings[i]))
165bool paulis_hasOddNumY(
PauliStr str) {
169 for (
int targ=0; targ < MAX_NUM_PAULIS_PER_STR; targ++)
170 if (paulis_getPauliAt(str, targ) == 2)
177int paulis_getPrefixZSign(
Qureg qureg, vector<int> prefixZ) {
182 for (
int qubit : prefixZ)
183 sign *= util_getRankBitOfQubit(qubit, qureg)? -1 : 1;
189qcomp paulis_getPrefixPaulisElem(
Qureg qureg, vector<int> prefixY, vector<int> prefixZ) {
192 qcomp elem = paulis_getPrefixZSign(qureg, prefixZ);
195 for (
int qubit : prefixY)
196 elem *= 1_i * (util_getRankBitOfQubit(qubit, qureg)? 1 : -1);
202vector<int> paulis_getInds(
PauliStr str) {
204 int maxInd = paulis_getIndOfLefmostNonIdentityPauli(str);
207 inds.reserve(maxInd+1);
209 for (
int i=0; i<=maxInd; i++)
210 if (paulis_getPauliAt(str, i) != 0)
217array<vector<int>,3> paulis_getSeparateInds(
PauliStr str,
Qureg qureg) {
219 vector<int> iXYZ = paulis_getInds(str);
220 vector<int> iX, iY, iZ;
222 vector<int>* ptrs[] = {&iX, &iY, &iZ};
225 ptrs[paulis_getPauliAt(str, i) - 1]->push_back(i);
233 if (pauliShift <= 0 || pauliShift >= MAX_NUM_PAULIS_PER_MASK)
234 error_pauliStrShiftedByIllegalAmount();
236 int numBitsPerPauli = 2;
237 int numMaskBits = numBitsPerPauli * MAX_NUM_PAULIS_PER_MASK;
238 int bitShift = numBitsPerPauli * pauliShift;
241 PAULI_MASK_TYPE lostBits = getBitsLeftOfIndex(str.lowPaulis, numMaskBits - bitShift - 1);
244 PAULI_MASK_TYPE lowerBits = getBitsRightOfIndex(str.lowPaulis, numMaskBits - bitShift) << bitShift;
247 PAULI_MASK_TYPE upperBits = concatenateBits(str.highPaulis, lostBits, bitShift);
250 .lowPaulis = lowerBits,
251 .highPaulis = upperBits
258 PauliStr shifted = paulis_getShiftedPauliStr(str, qureg.numQubits);
261 .lowPaulis = str.lowPaulis | shifted.lowPaulis,
262 .highPaulis = str.highPaulis | shifted.highPaulis
276 int maxInd = paulis_getIndOfLefmostNonIdentityPauli(str);
278 for (
int i=0; i<=maxInd; i++) {
279 int pauli = paulis_getPauliAt(str, i);
280 int isXY = (pauli == 1 || pauli == 2);
297 validate_newPauliStrParams(paulis, indices, numPaulis, MAX_NUM_PAULIS_PER_STR, __func__);
304 for (
int i=0; i<numPaulis; i++) {
310 if (indices[i] < MAX_NUM_PAULIS_PER_MASK)
311 lowPaulis |= pauli << (2*indices[i]);
313 highPaulis |= pauli << (2*(indices[i] - MAX_NUM_PAULIS_PER_MASK));
318 .lowPaulis = lowPaulis,
319 .highPaulis = highPaulis
325 validate_newPauliStrParams(paulis, indices, numPaulis, MAX_NUM_PAULIS_PER_STR, __func__);
328 char pauliChars[MAX_NUM_PAULIS_PER_STR + 1];
331 for (
int i=0; i<numPaulis; i++)
332 pauliChars[i] =
"IXYZ"[paulis[i]];
335 pauliChars[numPaulis] =
'\0';
337 return getPauliStr(pauliChars, indices, numPaulis);
341extern "C" PauliStr _getPauliStrFromInts(
int* paulis,
int* indices,
int numPaulis) {
350 validate_newPauliStrNumChars(paulis.length(), numPaulis, __func__);
352 return getPauliStr(paulis.data(), indices, numPaulis);
358 validate_newPauliStrNumChars(paulis.length(), indices.size(), __func__);
360 return getPauliStr(paulis.data(), indices.data(), indices.size());
366 validate_newPauliStrNumPaulis(paulis.size(), MAX_NUM_PAULIS_PER_STR, __func__);
369 vector<int> indices(paulis.size());
370 for (
size_t i=0; i<paulis.size(); i++)
371 indices[i] = paulis.size() - 1 - i;
388 validate_newPauliStrSumParams(numTerms, __func__);
392 .numTerms = numTerms,
393 .strings = cpu_allocPauliStrings(numTerms),
394 .coeffs = cpu_allocArray(numTerms),
395 .isApproxHermitian = util_allocEpsilonSensitiveHeapFlag(),
399 freeAllMemoryIfAnyAllocsFailed(out);
400 validate_newPauliStrSumAllocs(out, numTerms*
sizeof(
PauliStr), numTerms*
sizeof(qcomp), __func__);
403 cpu_copyPauliStrSum(out, strings, coeffs);
404 util_setFlagToUnknown(out.isApproxHermitian);
412 validate_newPauliStrSumMatchingListLens(strings.size(), coeffs.size(), __func__);
426 bool rightIsLeastSig =
true;
427 return parser_validateAndParsePauliStrSum(str, rightIsLeastSig, __func__);
438 validate_canReadFile(fn, __func__);
441 string str = parser_loadFile(fn);
443 bool rightIsLeastSig =
true;
444 return parser_validateAndParsePauliStrSum(str, rightIsLeastSig, __func__);
455 validate_canReadFile(fn, __func__);
458 string str = parser_loadFile(fn);
460 bool rightIsLeastSig =
false;
461 return parser_validateAndParsePauliStrSum(str, rightIsLeastSig, __func__);
472 validate_pauliStrSumFields(sum, __func__);
474 freePauliStrSum(sum);
488 print_elemsWithoutNewline(str, indent);
496 validate_pauliStrSumFields(sum, __func__);
497 validate_numReportedNewlinesAboveZero(__func__);
500 qindex numStrBytes = sum.numTerms *
sizeof *sum.strings;
501 qindex numCoeffBytes = sum.numTerms *
sizeof *sum.coeffs;
502 qindex numStrucBytes =
sizeof(sum);
506 qindex numTotalBytes = numStrBytes + numCoeffBytes + numStrucBytes;
508 print_header(sum, numTotalBytes);
512 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