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/lists.hpp"
15#include "quest/src/core/utilities.hpp"
16#include "quest/src/core/localiser.hpp"
17#include "quest/src/core/paulilogic.hpp"
18#include "quest/src/core/errors.hpp"
19#include "quest/src/core/randomiser.hpp"
32void internal_applyFirstOrderTrotterRepetition(
33 Qureg qureg, ConstList64 ketCtrls, ConstList64 braCtrls,
34 ConstList64 states,
PauliStrSum sum, vector<qindex>& sumOrdering,
35 qcomp angle,
bool onlyLeftApply,
bool reverse
38 for (qindex i=0; i<sum.numTerms; i++) {
39 int j = reverse? sum.numTerms - i - 1 : i;
40 qindex k = (sumOrdering.empty())? j : sumOrdering[j];
41 qcomp coeff = sum.coeffs[k];
45 qcomp arg = angle * coeff;
46 localiser_statevec_anyCtrlPauliGadget(qureg, ketCtrls, states, str, arg);
49 if (!qureg.isDensityMatrix)
59 arg = - std::conj(arg) * paulis_getSignOfPauliStrConj(str);
60 str = paulis_getShiftedPauliStr(str, qureg.numQubits);
61 localiser_statevec_anyCtrlPauliGadget(qureg, braCtrls, states, str, arg);
65void internal_applyHigherOrderTrotterRepetition(
66 Qureg qureg, ConstList64 ketCtrls, ConstList64 braCtrls,
67 ConstList64 states,
PauliStrSum sum, vector<qindex>& sumOrdering,
68 qcomp angle,
int order,
bool onlyLeftApply
71 internal_applyFirstOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, sumOrdering, angle, onlyLeftApply,
false);
73 }
else if (order == 2) {
74 internal_applyFirstOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, sumOrdering, angle/2, onlyLeftApply,
false);
75 internal_applyFirstOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, sumOrdering, angle/2, onlyLeftApply,
true);
78 qreal p = 1. / (4 - std::pow(4, 1./(order-1)));
80 qcomp b = (1-4*p) * angle;
82 int lower = order - 2;
83 internal_applyHigherOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, sumOrdering, a, lower, onlyLeftApply);
84 internal_applyHigherOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, sumOrdering, a, lower, onlyLeftApply);
85 internal_applyHigherOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, sumOrdering, b, lower, onlyLeftApply);
86 internal_applyHigherOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, sumOrdering, a, lower, onlyLeftApply);
87 internal_applyHigherOrderTrotterRepetition(qureg, ketCtrls, braCtrls, states, sum, sumOrdering, a, lower, onlyLeftApply);
91void internal_applyAllTrotterRepetitions(
92 Qureg qureg,
int* controls,
int* states,
int numControls,
93 PauliStrSum sum, qcomp angle,
int order,
int reps,
bool onlyLeftApply,
bool permuteTerms,
97 if (angle == qcomp(0,0))
103 vector<qindex> sumOrdering;
105 auto callback = [&]() { validate_tempListAllocSucceeded(
false, sum.numTerms,
sizeof(qindex), caller); };
106 util_tryAllocVector(sumOrdering, sum.numTerms, callback);
107 std::iota(sumOrdering.begin(), sumOrdering.end(), 0);
111 auto ketCtrlsList = lists_getList64(controls, numControls);
112 auto braCtrlsList = (qureg.isDensityMatrix)? util_getBraQubits(ketCtrlsList, qureg) : lists_getEmptyList64();
113 auto statesList = lists_getList64(states, numControls * (states !=
nullptr));
115 qcomp arg = angle / reps;
118 for (
int r=0; r<reps; r++){
121 rand_setListToShuffled(sumOrdering);
123 internal_applyHigherOrderTrotterRepetition(
124 qureg, ketCtrlsList, braCtrlsList, statesList, sum, sumOrdering, arg, order, onlyLeftApply);
132 int OVERFLOW_FLAG = 0;
134 if (util_willProdOverflow({2,hamil.numTerms}))
135 return OVERFLOW_FLAG;
138 qindex numTerms = 2 * hamil.numTerms;
140 for (
int i=0; i<numJumps; i++) {
141 qindex n = jumps[i].numTerms;
143 if (util_willProdOverflow({n,n,3}))
144 return OVERFLOW_FLAG;
145 if (util_willSumOverflow({numTerms, 3*n*n}))
146 return OVERFLOW_FLAG;
152 numTerms += 2 * paulis_getNumTermsInPauliStrSumProdOfAdjointWithSelf(jumps[i]);
168 validate_quregFields(qureg, __func__);
169 validate_pauliStrSumFields(sum, __func__);
170 validate_pauliStrSumTargets(sum, qureg, __func__);
171 validate_trotterParams(order, reps, __func__);
175 bool onlyLeftApply =
false;
176 internal_applyAllTrotterRepetitions(qureg,
nullptr,
nullptr, 0, sum, angle, order, reps, onlyLeftApply, permuteTerms, __func__);
180 validate_quregFields(qureg, __func__);
181 validate_pauliStrSumFields(sum, __func__);
182 validate_pauliStrSumTargets(sum, qureg, __func__);
183 validate_pauliStrSumIsHermitian(sum, __func__);
184 validate_trotterParams(order, reps, __func__);
186 bool onlyLeftApply =
false;
187 internal_applyAllTrotterRepetitions(qureg,
nullptr,
nullptr, 0, sum, angle, order, reps, onlyLeftApply, permuteTerms, __func__);
192 qreal angle,
int order,
int reps,
bool permuteTerms
194 validate_quregFields(qureg, __func__);
195 validate_pauliStrSumFields(sum, __func__);
196 validate_pauliStrSumIsHermitian(sum, __func__);
197 validate_controlAndPauliStrSumTargets(qureg, control, sum, __func__);
198 validate_trotterParams(order, reps, __func__);
200 bool onlyLeftApply =
false;
201 internal_applyAllTrotterRepetitions(qureg, &control,
nullptr, 1, sum, angle, order, reps, onlyLeftApply, permuteTerms, __func__);
206 qreal angle,
int order,
int reps,
bool permuteTerms
208 validate_quregFields(qureg, __func__);
209 validate_pauliStrSumFields(sum, __func__);
210 validate_pauliStrSumIsHermitian(sum, __func__);
211 validate_controlsAndPauliStrSumTargets(qureg, controls, numControls, sum, __func__);
212 validate_trotterParams(order, reps, __func__);
214 bool onlyLeftApply =
false;
215 internal_applyAllTrotterRepetitions(qureg, controls,
nullptr, numControls, sum, angle, order, reps, onlyLeftApply, permuteTerms, __func__);
220 qreal angle,
int order,
int reps,
bool permuteTerms
222 validate_quregFields(qureg, __func__);
223 validate_pauliStrSumFields(sum, __func__);
224 validate_pauliStrSumIsHermitian(sum, __func__);
225 validate_controlsAndPauliStrSumTargets(qureg, controls, numControls, sum, __func__);
226 validate_controlStates(states, numControls, __func__);
227 validate_trotterParams(order, reps, __func__);
229 bool onlyLeftApply =
false;
230 internal_applyAllTrotterRepetitions(qureg, controls, states, numControls, sum, angle, order, reps, onlyLeftApply, permuteTerms, __func__);
237 qreal angle,
int order,
int reps,
bool permuteTerms
244 qreal angle,
int order,
int reps,
bool permuteTerms
246 validate_controlsMatchStates(controls.size(), states.size(), __func__);
260 validate_quregFields(qureg, __func__);
261 validate_pauliStrSumFields(hamil, __func__);
262 validate_pauliStrSumTargets(hamil, qureg, __func__);
263 validate_pauliStrSumIsHermitian(hamil, __func__);
264 validate_trotterParams(order, reps, __func__);
267 qcomp angle = - time;
268 bool onlyLeftApply =
false;
269 internal_applyAllTrotterRepetitions(qureg,
nullptr,
nullptr, 0, hamil, angle, order, reps, onlyLeftApply, permuteTerms, __func__);
273 validate_quregFields(qureg, __func__);
274 validate_pauliStrSumFields(hamil, __func__);
275 validate_pauliStrSumTargets(hamil, qureg, __func__);
276 validate_pauliStrSumIsHermitian(hamil, __func__);
277 validate_trotterParams(order, reps, __func__);
280 qcomp angle = qcomp(0, tau);
281 bool onlyLeftApply =
false;
282 internal_applyAllTrotterRepetitions(qureg,
nullptr,
nullptr, 0, hamil, angle, order, reps, onlyLeftApply, permuteTerms, __func__);
297 int numJumps, qreal time,
int order,
int reps,
bool permuteTerms
299 validate_quregFields(qureg, __func__);
300 validate_quregIsDensityMatrix(qureg, __func__);
301 validate_pauliStrSumFields(hamil, __func__);
302 validate_pauliStrSumTargets(hamil, qureg, __func__);
303 validate_pauliStrSumIsHermitian(hamil, __func__);
304 validate_trotterParams(order, reps, __func__);
305 validate_lindbladJumpOps(jumps, numJumps, qureg, __func__);
306 validate_lindbladDampingRates(damps, numJumps, __func__);
308 qindex numSuperTerms = internal_getNumTotalSuperPropagatorTerms(hamil, jumps, numJumps);
309 validate_numLindbladSuperPropagatorTerms(numSuperTerms, __func__);
312 vector<PauliStr> superStrings;
313 vector<qcomp> superCoeffs;
314 auto callbackString = [&]() { validate_tempListAllocSucceeded(
false, numSuperTerms,
sizeof(
PauliStr), __func__); };
315 auto callbackCoeff = [&]() { validate_tempListAllocSucceeded(
false, numSuperTerms,
sizeof(qcomp), __func__); };
316 util_tryAllocVector(superStrings, numSuperTerms, callbackString);
317 util_tryAllocVector(superCoeffs, numSuperTerms, callbackCoeff);
319 qindex superTermInd = 0;
322 for (qindex n=0; n<hamil.numTerms; n++) {
324 qcomp oldCoeff = hamil.coeffs[n];
327 superStrings[superTermInd] = oldStr;
328 superCoeffs [superTermInd] = -1_i * oldCoeff;
332 superStrings[superTermInd] = paulis_getShiftedPauliStr(oldStr, qureg.numQubits);
333 superCoeffs [superTermInd] = 1_i * paulis_getSignOfPauliStrConj(oldStr) * std::conj(oldCoeff);
339 int flagForDebugSafety = -1;
340 temp.isApproxHermitian = &flagForDebugSafety;
343 for (
int n=0; n<numJumps; n++) {
346 temp.strings = &superStrings[superTermInd];
347 temp.coeffs = &superCoeffs[superTermInd];
348 temp.numTerms = jumps[n].numTerms * jumps[n].numTerms;
349 superTermInd += temp.numTerms;
350 paulis_setPauliStrSumToScaledTensorProdOfConjWithSelf(temp, damps[n], jumps[n], qureg.numQubits);
353 temp.strings = &superStrings[superTermInd];
354 temp.coeffs = &superCoeffs[superTermInd];
355 temp.numTerms = paulis_getNumTermsInPauliStrSumProdOfAdjointWithSelf(jumps[n]);
356 superTermInd += temp.numTerms;
357 paulis_setPauliStrSumToScaledProdOfAdjointWithSelf(temp, -damps[n]/2, jumps[n]);
361 temp2.strings = &superStrings[superTermInd];
362 temp2.coeffs = &superCoeffs[superTermInd];
363 temp2.numTerms = temp.numTerms;
364 superTermInd += temp2.numTerms;
365 paulis_setPauliStrSumToShiftedConj(temp2, temp, qureg.numQubits);
370 if (superTermInd != numSuperTerms)
371 error_unexpectedNumLindbladSuperpropTerms();
375 superSum.numTerms = numSuperTerms;
376 superSum.strings = superStrings.data();
377 superSum.coeffs = superCoeffs.data();
378 superSum.isApproxHermitian =
nullptr;
381 qcomp angle = qcomp(0, -time);
382 bool onlyLeftApply =
true;
383 internal_applyAllTrotterRepetitions(qureg,
nullptr,
nullptr, 0, superSum, angle, order, reps, onlyLeftApply, permuteTerms, __func__);
void applyTrotterizedMultiControlledPauliStrSumGadget(Qureg qureg, int *controls, int numControls, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms)
void applyTrotterizedPauliStrSumGadget(Qureg qureg, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms)
void applyTrotterizedControlledPauliStrSumGadget(Qureg qureg, int control, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms)
void applyTrotterizedNonUnitaryPauliStrSumGadget(Qureg qureg, PauliStrSum sum, qcomp angle, int order, int reps, bool permuteTerms)
void applyTrotterizedMultiStateControlledPauliStrSumGadget(Qureg qureg, int *controls, int *states, int numControls, PauliStrSum sum, qreal angle, int order, int reps, bool permuteTerms)
void applyTrotterizedNoisyTimeEvolution(Qureg qureg, PauliStrSum hamil, qreal *damps, PauliStrSum *jumps, int numJumps, qreal time, int order, int reps, bool permuteTerms)
void applyTrotterizedUnitaryTimeEvolution(Qureg qureg, PauliStrSum hamil, qreal time, int order, int reps, bool permuteTerms)
void applyTrotterizedImaginaryTimeEvolution(Qureg qureg, PauliStrSum hamil, qreal tau, int order, int reps, bool permuteTerms)