9#include "quest/include/qureg.h"
10#include "quest/include/paulis.h"
11#include "quest/include/matrices.h"
13#include "quest/src/core/validation.hpp"
14#include "quest/src/core/utilities.hpp"
15#include "quest/src/core/localiser.hpp"
16#include "quest/src/core/paulilogic.hpp"
17#include "quest/src/core/errors.hpp"
29void internal_applyFirstOrderTrotterRepetition(
30 Qureg qureg, vector<int>& ketCtrls, vector<int>& braCtrls,
31 vector<int>& states,
PauliStrSum sum, qcomp angle,
bool onlyLeftApply,
bool reverse
34 for (qindex i=0; i<sum.numTerms; i++) {
35 int j = reverse? sum.numTerms - i - 1 : i;
36 qcomp coeff = sum.coeffs[j];
40 qcomp arg = angle * coeff;
41 localiser_statevec_anyCtrlPauliGadget(qureg, ketCtrls, states, str, arg);
44 if (!qureg.isDensityMatrix)
54 arg = - std::conj(arg) * paulis_getSignOfPauliStrConj(str);
55 str = paulis_getShiftedPauliStr(str, qureg.numQubits);
56 localiser_statevec_anyCtrlPauliGadget(qureg, braCtrls, states, str, arg);
60void internal_applyHigherOrderTrotterRepetition(
61 Qureg qureg, vector<int>& ketCtrls, vector<int>& braCtrls,
62 vector<int>& states,
PauliStrSum sum, qcomp angle,
int order,
bool onlyLeftApply
65 internal_applyFirstOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, angle, onlyLeftApply,
false);
67 }
else if (order == 2) {
68 internal_applyFirstOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, angle/2, onlyLeftApply,
false);
69 internal_applyFirstOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, angle/2, onlyLeftApply,
true);
72 qreal p = 1. / (4 - std::pow(4, 1./(order-1)));
74 qcomp b = (1-4*p) * angle;
76 int lower = order - 2;
77 internal_applyHigherOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, a, lower, onlyLeftApply);
78 internal_applyHigherOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, a, lower, onlyLeftApply);
79 internal_applyHigherOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, b, lower, onlyLeftApply);
80 internal_applyHigherOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, a, lower, onlyLeftApply);
81 internal_applyHigherOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, a, lower, onlyLeftApply);
85void internal_applyAllTrotterRepetitions(
86 Qureg qureg,
int* controls,
int* states,
int numControls,
87 PauliStrSum sum, qcomp angle,
int order,
int reps,
bool onlyLeftApply
90 if (angle == qcomp(0,0))
94 auto ketCtrlsVec = util_getVector(controls, numControls);
95 auto braCtrlsVec = (qureg.isDensityMatrix)? util_getBraQubits(ketCtrlsVec, qureg) : vector<int>{};
96 auto statesVec = util_getVector(states, numControls);
98 qcomp arg = angle / reps;
101 for (
int r=0; r<reps; r++)
102 internal_applyHigherOrderTrotterRepetition(
103 qureg, ketCtrlsVec, braCtrlsVec, statesVec, sum, arg, order, onlyLeftApply);
115 int OVERFLOW_FLAG = 0;
117 if (util_willProdOverflow({2,hamil.numTerms}))
118 return OVERFLOW_FLAG;
121 qindex numTerms = 2 * hamil.numTerms;
123 for (
int i=0; i<numJumps; i++) {
124 qindex n = jumps[i].numTerms;
126 if (util_willProdOverflow({n,n,3}))
127 return OVERFLOW_FLAG;
128 if (util_willSumOverflow({numTerms, 3*n*n}))
129 return OVERFLOW_FLAG;
135 numTerms += 2 * paulis_getNumTermsInPauliStrSumProdOfAdjointWithSelf(jumps[i]);
151 validate_quregFields(qureg, __func__);
152 validate_pauliStrSumFields(sum, __func__);
153 validate_pauliStrSumTargets(sum, qureg, __func__);
154 validate_trotterParams(qureg, order, reps, __func__);
158 bool onlyLeftApply =
false;
159 internal_applyAllTrotterRepetitions(qureg,
nullptr,
nullptr, 0, sum, angle, order, reps, onlyLeftApply);
163 validate_quregFields(qureg, __func__);
164 validate_pauliStrSumFields(sum, __func__);
165 validate_pauliStrSumTargets(sum, qureg, __func__);
166 validate_pauliStrSumIsHermitian(sum, __func__);
167 validate_trotterParams(qureg, order, reps, __func__);
169 bool onlyLeftApply =
false;
170 internal_applyAllTrotterRepetitions(qureg,
nullptr,
nullptr, 0, sum, angle, order, reps, onlyLeftApply);
174 validate_quregFields(qureg, __func__);
175 validate_pauliStrSumFields(sum, __func__);
176 validate_pauliStrSumIsHermitian(sum, __func__);
177 validate_controlAndPauliStrSumTargets(qureg, control, sum, __func__);
178 validate_trotterParams(qureg, order, reps, __func__);
180 bool onlyLeftApply =
false;
181 internal_applyAllTrotterRepetitions(qureg, &control,
nullptr, 1, sum, angle, order, reps, onlyLeftApply);
185 validate_quregFields(qureg, __func__);
186 validate_pauliStrSumFields(sum, __func__);
187 validate_pauliStrSumIsHermitian(sum, __func__);
188 validate_controlsAndPauliStrSumTargets(qureg, controls, numControls, sum, __func__);
189 validate_trotterParams(qureg, order, reps, __func__);
191 bool onlyLeftApply =
false;
192 internal_applyAllTrotterRepetitions(qureg, controls,
nullptr, numControls, sum, angle, order, reps, onlyLeftApply);
196 validate_quregFields(qureg, __func__);
197 validate_pauliStrSumFields(sum, __func__);
198 validate_pauliStrSumIsHermitian(sum, __func__);
199 validate_controlsAndPauliStrSumTargets(qureg, controls, numControls, sum, __func__);
200 validate_controlStates(states, numControls, __func__);
201 validate_trotterParams(qureg, order, reps, __func__);
203 bool onlyLeftApply =
false;
204 internal_applyAllTrotterRepetitions(qureg, controls, states, numControls, sum, angle, order, reps, onlyLeftApply);
215 validate_controlsMatchStates(controls.size(), states.size(), __func__);
229 validate_quregFields(qureg, __func__);
230 validate_pauliStrSumFields(hamil, __func__);
231 validate_pauliStrSumTargets(hamil, qureg, __func__);
232 validate_pauliStrSumIsHermitian(hamil, __func__);
233 validate_trotterParams(qureg, order, reps, __func__);
236 qcomp angle = - time;
237 bool onlyLeftApply =
false;
238 internal_applyAllTrotterRepetitions(qureg,
nullptr,
nullptr, 0, hamil, angle, order, reps, onlyLeftApply);
242 validate_quregFields(qureg, __func__);
243 validate_pauliStrSumFields(hamil, __func__);
244 validate_pauliStrSumTargets(hamil, qureg, __func__);
245 validate_pauliStrSumIsHermitian(hamil, __func__);
246 validate_trotterParams(qureg, order, reps, __func__);
249 qcomp angle = qcomp(0, tau);
250 bool onlyLeftApply =
false;
251 internal_applyAllTrotterRepetitions(qureg,
nullptr,
nullptr, 0, hamil, angle, order, reps, onlyLeftApply);
265 validate_quregFields(qureg, __func__);
266 validate_quregIsDensityMatrix(qureg, __func__);
267 validate_pauliStrSumFields(hamil, __func__);
268 validate_pauliStrSumTargets(hamil, qureg, __func__);
269 validate_pauliStrSumIsHermitian(hamil, __func__);
270 validate_trotterParams(qureg, order, reps, __func__);
271 validate_lindbladJumpOps(jumps, numJumps, qureg, __func__);
272 validate_lindbladDampingRates(damps, numJumps, __func__);
274 qindex numSuperTerms = internal_getNumTotalSuperPropagatorTerms(hamil, jumps, numJumps);
275 validate_numLindbladSuperPropagatorTerms(numSuperTerms, __func__);
278 vector<PauliStr> superStrings;
279 vector<qcomp> superCoeffs;
280 auto callbackString = [&]() { validate_tempAllocSucceeded(
false, numSuperTerms,
sizeof(
PauliStr), __func__); };
281 auto callbackCoeff = [&]() { validate_tempAllocSucceeded(
false, numSuperTerms,
sizeof(qcomp), __func__); };
282 util_tryAllocVector(superStrings, numSuperTerms, callbackString);
283 util_tryAllocVector(superCoeffs, numSuperTerms, callbackCoeff);
285 qindex superTermInd = 0;
288 for (qindex n=0; n<hamil.numTerms; n++) {
290 qcomp oldCoeff = hamil.coeffs[n];
293 superStrings[superTermInd] = oldStr;
294 superCoeffs [superTermInd] = -1_i * oldCoeff;
298 superStrings[superTermInd] = paulis_getShiftedPauliStr(oldStr, qureg.numQubits);
299 superCoeffs [superTermInd] = 1_i * paulis_getSignOfPauliStrConj(oldStr) * std::conj(oldCoeff);
305 int flagForDebugSafety = -1;
306 temp.isApproxHermitian = &flagForDebugSafety;
309 for (
int n=0; n<numJumps; n++) {
312 temp.strings = &superStrings[superTermInd];
313 temp.coeffs = &superCoeffs[superTermInd];
314 temp.numTerms = jumps[n].numTerms * jumps[n].numTerms;
315 superTermInd += temp.numTerms;
316 paulis_setPauliStrSumToScaledTensorProdOfConjWithSelf(temp, damps[n], jumps[n], qureg.numQubits);
319 temp.strings = &superStrings[superTermInd];
320 temp.coeffs = &superCoeffs[superTermInd];
321 temp.numTerms = paulis_getNumTermsInPauliStrSumProdOfAdjointWithSelf(jumps[n]);
322 superTermInd += temp.numTerms;
323 paulis_setPauliStrSumToScaledProdOfAdjointWithSelf(temp, -damps[n]/2, jumps[n]);
327 temp2.strings = &superStrings[superTermInd];
328 temp2.coeffs = &superCoeffs[superTermInd];
329 temp2.numTerms = temp.numTerms;
330 superTermInd += temp2.numTerms;
331 paulis_setPauliStrSumToShiftedConj(temp2, temp, qureg.numQubits);
336 if (superTermInd != numSuperTerms)
337 error_unexpectedNumLindbladSuperpropTerms();
341 superSum.numTerms = numSuperTerms;
342 superSum.strings = superStrings.data();
343 superSum.coeffs = superCoeffs.data();
344 superSum.isApproxHermitian =
nullptr;
347 qcomp angle = qcomp(0, -time);
348 bool onlyLeftApply =
true;
349 internal_applyAllTrotterRepetitions(qureg,
nullptr,
nullptr, 0, superSum, angle, order, reps, onlyLeftApply);
void applyTrotterizedMultiControlledPauliStrSumGadget(Qureg qureg, int *controls, int numControls, PauliStrSum sum, qreal angle, int order, int reps)
void applyTrotterizedPauliStrSumGadget(Qureg qureg, PauliStrSum sum, qreal angle, int order, int reps)
void applyTrotterizedNonUnitaryPauliStrSumGadget(Qureg qureg, PauliStrSum sum, qcomp angle, int order, int reps)
void applyTrotterizedControlledPauliStrSumGadget(Qureg qureg, int control, PauliStrSum sum, qreal angle, int order, int reps)
void applyTrotterizedMultiStateControlledPauliStrSumGadget(Qureg qureg, int *controls, int *states, int numControls, PauliStrSum sum, qreal angle, int order, int reps)
void applyTrotterizedUnitaryTimeEvolution(Qureg qureg, PauliStrSum hamil, qreal time, int order, int reps)
void applyTrotterizedNoisyTimeEvolution(Qureg qureg, PauliStrSum hamil, qreal *damps, PauliStrSum *jumps, int numJumps, qreal time, int order, int reps)
void applyTrotterizedImaginaryTimeEvolution(Qureg qureg, PauliStrSum hamil, qreal tau, int order, int reps)