@@ -1130,90 +1130,145 @@ void multiplyPauliStrSum(Qureg qureg, PauliStrSum sum, Qureg workspace) {
1130
1130
// workspace -> qureg, and qureg -> sum * qureg
1131
1131
}
1132
1132
1133
- void applyFirstOrderTrotter (Qureg qureg, PauliStrSum sum, qcomp angle, bool reverse) {
1134
-
1135
- // (internal, invoked by applyTrotterizedPauliStrSumGadget)
1136
-
1133
+ void internal_applyFirstOrderTrotterRepetition (
1134
+ Qureg qureg, vector<int >& ketCtrls, vector<int >& braCtrls,
1135
+ vector<int >& states, PauliStrSum sum, qcomp angle, bool reverse
1136
+ ) {
1137
+ // apply each sum term as a gadget, in forward or reverse order
1137
1138
for (qindex i=0 ; i<sum.numTerms ; i++) {
1138
1139
int j = reverse? sum.numTerms - i - 1 : i;
1140
+ qcomp coeff = sum.coeffs [j];
1141
+ PauliStr str = sum.strings [j];
1139
1142
1140
- // effect exp(i angle * sum) by undoing gadget pre-factor
1141
- qcomp arg = angle * sum.coeffs [j] / util_getPhaseFromGateAngle (1 );
1142
- applyNonUnitaryPauliGadget (qureg, sum.strings [j], arg); // caller disabled valiation therein
1143
- }
1144
- }
1143
+ // effect |psi> -> exp(i angle * sum)|psi>
1144
+ qcomp arg = angle * coeff;
1145
+ localiser_statevec_anyCtrlPauliGadget (qureg, ketCtrls, states, str, arg);
1145
1146
1146
- void applyHigherOrderTrotter (Qureg qureg, PauliStrSum sum, qcomp angle, int order) {
1147
+ if (!qureg.isDensityMatrix )
1148
+ continue ;
1147
1149
1148
- // (internal, invoked by applyTrotterizedPauliStrSumGadget)
1150
+ // effect rho -> rho dagger(i angle * sum)
1151
+ arg *= paulis_hasOddNumY (str) ? 1 : -1 ;
1152
+ str = paulis_getShiftedPauliStr (str, qureg.numQubits );
1153
+ localiser_statevec_anyCtrlPauliGadget (qureg, braCtrls, states, str, arg);
1154
+ }
1155
+ }
1149
1156
1157
+ void internal_applyHigherOrderTrotterRepetition (
1158
+ Qureg qureg, vector<int >& ketCtrls, vector<int >& braCtrls,
1159
+ vector<int >& states, PauliStrSum sum, qcomp angle, int order
1160
+ ) {
1150
1161
if (order == 1 ) {
1151
- applyFirstOrderTrotter (qureg, sum, angle, false );
1162
+ internal_applyFirstOrderTrotterRepetition (qureg, ketCtrls, braCtrls, states , sum, angle, false );
1152
1163
1153
1164
} else if (order == 2 ) {
1154
- applyFirstOrderTrotter (qureg, sum, angle/2 , false );
1155
- applyFirstOrderTrotter (qureg, sum, angle/2 , true );
1165
+ internal_applyFirstOrderTrotterRepetition (qureg, ketCtrls, braCtrls, states , sum, angle/2 , false );
1166
+ internal_applyFirstOrderTrotterRepetition (qureg, ketCtrls, braCtrls, states , sum, angle/2 , true );
1156
1167
1157
1168
} else {
1158
1169
qreal p = 1 . / (4 - std::pow (4 , 1 ./(order-1 )));
1159
1170
qcomp a = p * angle;
1160
1171
qcomp b = (1 -4 *p) * angle;
1161
1172
1162
1173
int lower = order - 2 ;
1163
- applyFirstOrderTrotter (qureg, sum, a, lower);
1164
- applyFirstOrderTrotter (qureg, sum, a, lower);
1165
- applyFirstOrderTrotter (qureg, sum, b, lower);
1166
- applyFirstOrderTrotter (qureg, sum, a, lower);
1167
- applyFirstOrderTrotter (qureg, sum, a, lower);
1174
+ internal_applyFirstOrderTrotterRepetition (qureg, ketCtrls, braCtrls, states , sum, a, lower);
1175
+ internal_applyFirstOrderTrotterRepetition (qureg, ketCtrls, braCtrls, states , sum, a, lower);
1176
+ internal_applyFirstOrderTrotterRepetition (qureg, ketCtrls, braCtrls, states , sum, b, lower);
1177
+ internal_applyFirstOrderTrotterRepetition (qureg, ketCtrls, braCtrls, states , sum, a, lower);
1178
+ internal_applyFirstOrderTrotterRepetition (qureg, ketCtrls, braCtrls, states , sum, a, lower);
1168
1179
}
1169
1180
}
1170
1181
1171
- void applyNonUnitaryTrotterizedPauliStrSumGadget (Qureg qureg, PauliStrSum sum, qcomp angle, int order, int reps) {
1172
- validate_quregFields (qureg, __func__);
1173
- validate_pauliStrSumFields (sum, __func__);
1174
- validate_pauliStrSumTargets (sum, qureg, __func__);
1175
- validate_trotterParams (qureg, order, reps, __func__);
1176
- // sum is permitted to be non-Hermitian
1177
-
1182
+ void internal_applyAllTrotterRepetitions (
1183
+ Qureg qureg, int * controls, int * states, int numControls,
1184
+ PauliStrSum sum, qcomp angle, int order, int reps
1185
+ ) {
1178
1186
// exp(i angle sum) = identity when angle=0
1179
1187
if (angle == qcomp (0 ,0 ))
1180
1188
return ;
1181
1189
1182
- // record validation state then disable to avoid repeated
1183
- // re-validations in each invoked applyPauliGadget() below
1184
- bool wasValidationEnabled = validateconfig_isEnabled () ;
1185
- validateconfig_disable ( );
1190
+ // prepare control-qubit lists once for all invoked gadgets below
1191
+ auto ketCtrlsVec = util_getVector (controls, numControls);
1192
+ auto braCtrlsVec = (qureg. isDensityMatrix )? util_getBraQubits (ketCtrlsVec, qureg) : vector< int >{} ;
1193
+ auto statesVec = util_getVector (states, numControls );
1186
1194
1187
- // perform sequence of applyPauliGadget()
1188
- for (int r=0 ; r<reps; r++)
1189
- applyHigherOrderTrotter (qureg, sum, angle/reps, order);
1195
+ qcomp arg = angle / reps;
1190
1196
1191
- // potentially restore validation
1192
- if (wasValidationEnabled)
1193
- validateconfig_enable ();
1197
+ // perform carefully-ordered sequence of gadgets
1198
+ for (int r=0 ; r<reps; r++)
1199
+ internal_applyHigherOrderTrotterRepetition (
1200
+ qureg, ketCtrlsVec, braCtrlsVec, statesVec, sum, arg, order);
1194
1201
1195
1202
// / @todo
1196
1203
// / the accuracy of Trotterisation is greatly improved by randomisation
1197
1204
// / or (even sub-optimal) grouping into commuting terms. Should we
1198
1205
// / implement these above or into another function?
1199
1206
}
1200
1207
1201
- void applyTrotterizedPauliStrSumGadget (Qureg qureg, PauliStrSum sum, qreal angle, int order, int reps) {
1208
+ void applyNonUnitaryTrotterizedPauliStrSumGadget (Qureg qureg, PauliStrSum sum, qcomp angle, int order, int reps) {
1209
+ validate_quregFields (qureg, __func__);
1210
+ validate_pauliStrSumFields (sum, __func__);
1211
+ validate_pauliStrSumTargets (sum, qureg, __func__);
1212
+ validate_trotterParams (qureg, order, reps, __func__);
1213
+ // sum is permitted to be non-Hermitian
1214
+
1215
+ internal_applyAllTrotterRepetitions (qureg, nullptr , nullptr , 0 , sum, angle, order, reps);
1216
+ }
1202
1217
1203
- // validate inputs here despite re-validation below so that func name is correct in error message
1218
+ void applyTrotterizedPauliStrSumGadget (Qureg qureg, PauliStrSum sum, qreal angle, int order, int reps) {
1204
1219
validate_quregFields (qureg, __func__);
1205
1220
validate_pauliStrSumFields (sum, __func__);
1206
1221
validate_pauliStrSumTargets (sum, qureg, __func__);
1207
1222
validate_trotterParams (qureg, order, reps, __func__);
1223
+ validate_pauliStrSumIsHermitian (sum, __func__);
1224
+
1225
+ internal_applyAllTrotterRepetitions (qureg, nullptr , nullptr , 0 , sum, angle, order, reps);
1226
+ }
1227
+
1228
+ void applyControlledTrotterizedPauliStrSumGadget (Qureg qureg, int control, PauliStrSum sum, qreal angle, int order, int reps) {
1229
+ validate_quregFields (qureg, __func__);
1230
+ validate_pauliStrSumFields (sum, __func__);
1231
+ validate_controlAndPauliStrSumTargets (qureg, control, sum, __func__);
1232
+ validate_trotterParams (qureg, order, reps, __func__);
1233
+ validate_pauliStrSumIsHermitian (sum, __func__);
1208
1234
1209
- // crucially, require that sum coefficients are real
1235
+ internal_applyAllTrotterRepetitions (qureg, &control, nullptr , 1 , sum, angle, order, reps);
1236
+ }
1237
+
1238
+ void applyMultiControlledTrotterizedPauliStrSumGadget (Qureg qureg, int * controls, int numControls, PauliStrSum sum, qreal angle, int order, int reps) {
1239
+ validate_quregFields (qureg, __func__);
1240
+ validate_pauliStrSumFields (sum, __func__);
1241
+ validate_controlsAndPauliStrSumTargets (qureg, controls, numControls, sum, __func__);
1242
+ validate_trotterParams (qureg, order, reps, __func__);
1210
1243
validate_pauliStrSumIsHermitian (sum, __func__);
1211
1244
1212
- applyNonUnitaryTrotterizedPauliStrSumGadget (qureg, sum, angle, order, reps);
1245
+ internal_applyAllTrotterRepetitions (qureg, controls, nullptr , numControls, sum, angle, order, reps);
1246
+ }
1247
+
1248
+ void applyMultiStateControlledTrotterizedPauliStrSumGadget (Qureg qureg, int * controls, int * states, int numControls, PauliStrSum sum, qreal angle, int order, int reps) {
1249
+ validate_quregFields (qureg, __func__);
1250
+ validate_pauliStrSumFields (sum, __func__);
1251
+ validate_controlsAndPauliStrSumTargets (qureg, controls, numControls, sum, __func__);
1252
+ validate_controlStates (states, numControls, __func__); // permits states==nullptr
1253
+ validate_trotterParams (qureg, order, reps, __func__);
1254
+ validate_pauliStrSumIsHermitian (sum, __func__);
1255
+
1256
+ internal_applyAllTrotterRepetitions (qureg, controls, states, numControls, sum, angle, order, reps);
1213
1257
}
1214
1258
1215
1259
} // end de-mangler
1216
1260
1261
+ void applyMultiControlledTrotterizedPauliStrSumGadget (Qureg qureg, vector<int > controls, PauliStrSum sum, qreal angle, int order, int reps) {
1262
+
1263
+ applyMultiControlledTrotterizedPauliStrSumGadget (qureg, controls.data (), controls.size (), sum, angle, order, reps);
1264
+ }
1265
+
1266
+ void applyMultiStateControlledTrotterizedPauliStrSumGadget (Qureg qureg, vector<int > controls, vector<int > states, PauliStrSum sum, qreal angle, int order, int reps) {
1267
+ validate_controlsMatchStates (controls.size (), states.size (), __func__);
1268
+
1269
+ applyMultiStateControlledTrotterizedPauliStrSumGadget (qureg, controls.data (), states.data (), controls.size (), sum, angle, order, reps);
1270
+ }
1271
+
1217
1272
1218
1273
1219
1274
/*
0 commit comments