Skip to content

Commit 835208e

Browse files
optimised applyPauliGadget edgecase
When the passed PauliStr is identity and no control qubits are imposed, the function merely effects a change in global phase. For density matrices, this induces no change at all; the two constituent operations upon the Choi vector cancel one-another, wasting time and numerical accuracy. So, we abort in that scenario. This is truly an insignificant runtime and accuracy optimisation, and this scenario is superfluously handled mostly to document the validity of the scenario (i.e. the use of gadgets to effect arbitrary phase changes)
1 parent 8db1c06 commit 835208e

File tree

2 files changed

+18
-5
lines changed

2 files changed

+18
-5
lines changed

quest/src/api/operations.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ using std::vector;
2929
* PRVIATE UTILITIES
3030
*/
3131

32+
extern bool paulis_isIdentity(PauliStr str);
3233
extern bool paulis_hasOddNumY(PauliStr str);
3334
extern PauliStr paulis_getShiftedPauliStr(PauliStr str, int pauliShift);
3435
extern PauliStr paulis_getKetAndBraPauliStr(PauliStr str, Qureg qureg);
@@ -1450,11 +1451,15 @@ void applyMultiStateControlledPauliGadget(Qureg qureg, int* controls, int* state
14501451
validate_controlsAndPauliStrTargets(qureg, controls, numControls, str, __func__);
14511452
validate_controlStates(states, numControls, __func__); // permits states==nullptr
14521453

1453-
/// @todo
1454-
/// CRUCIAL NOTE:
1455-
/// exp(theta I..I) might be algorithmically ok (I'm not sure), but it WILL NOT
1456-
/// effect a global phase change of theta (I think). Should validate against this
1457-
/// sitaution just in case, or make the doc extremely explicit
1454+
// a non-controlled str=I effects a global phase change (of -angle/2) which does not
1455+
// at all change a density matrix; the subsequent dagger operation would undo it,
1456+
// which we avoid to preserve numerical accuracy
1457+
if (paulis_isIdentity(str) && numControls == 0 && qureg.isDensityMatrix)
1458+
return;
1459+
1460+
// when numControls >= 1, all amps satisfying the control condition undergo a phase
1461+
// change of -angle/2, as if all non-control-qubits were targeted by exp(-angle/2)I,
1462+
// which is sufficiently efficient using the existing gadget backend function
14581463

14591464
qreal phase = util_getPhaseFromGateAngle(angle);
14601465
auto ctrlVec = util_getVector(controls, numControls);

quest/src/api/paulis.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ void freeAllMemoryIfAnyAllocsFailed(PauliStrSum sum) {
9595
*/
9696

9797

98+
bool paulis_isIdentity(PauliStr str) {
99+
100+
return
101+
(str.lowPaulis == 0) &&
102+
(str.highPaulis == 0);
103+
}
104+
105+
98106
int paulis_getPauliAt(PauliStr str, int ind) {
99107

100108
return (ind < MAX_NUM_PAULIS_PER_MASK)?

0 commit comments

Comments
 (0)