The Quantum Exact Simulation Toolkit v4.1.0
Loading...
Searching...
No Matches
operations.cpp
1/** @file
2 * API definitions for effecting operators (including
3 * unitaries, projectors, channels, Hermitians, and
4 * arbitrary matrices) upon Quregs, which can be
5 * statevectors or density matrices.
6 *
7 * @author Tyson Jones
8 */
9
10#include "quest/include/qureg.h"
11#include "quest/include/matrices.h"
12#include "quest/include/operations.h"
13#include "quest/include/calculations.h"
14
15#include "quest/src/core/validation.hpp"
16#include "quest/src/core/utilities.hpp"
17#include "quest/src/core/randomiser.hpp"
18#include "quest/src/core/localiser.hpp"
19#include "quest/src/core/bitwise.hpp"
20#include "quest/src/core/constants.hpp"
21
22#include <vector>
23
24using std::vector;
25
26
27
28/*
29 * PRVIATE UTILITIES
30 */
31
32extern bool paulis_isIdentity(PauliStr str);
33extern bool paulis_hasOddNumY(PauliStr str);
34extern PauliStr paulis_getShiftedPauliStr(PauliStr str, int pauliShift);
35extern PauliStr paulis_getKetAndBraPauliStr(PauliStr str, Qureg qureg);
36
37// T can be CompMatr, CompMatr1, CompMatr2, DiagMatr, DiagMatr1, DiagMatr2
38template <class T>
39void validateAndApplyAnyCtrlAnyTargUnitaryMatrix(Qureg qureg, int* ctrls, int* states, int numCtrls, int* targs, int numTargs, T matr, const char* caller) {
40 validate_quregFields(qureg, caller);
41 validate_controlsAndTargets(qureg, ctrls, numCtrls, targs, numTargs, caller);
42 validate_controlStates(states, numCtrls, caller);
43 validate_matrixDimMatchesTargets(matr, numTargs, caller); // also checks fields and is-synced
44 validate_matrixIsUnitary(matr, caller); // harmlessly rechecks fields and is-synced
45 if (util_isDenseMatrixType<T>())
46 validate_mixedAmpsFitInNode(qureg, numTargs, caller);
47
48 auto ctrlVec = util_getVector(ctrls, numCtrls);
49 auto stateVec = util_getVector(states, numCtrls);
50 auto targVec = util_getVector(targs, numTargs);
51
52 bool conj = false;
53 localiser_statevec_anyCtrlAnyTargAnyMatr(qureg, ctrlVec, stateVec, targVec, matr, conj);
54
55 if (!qureg.isDensityMatrix)
56 return;
57
58 conj = true;
59 ctrlVec = util_getBraQubits(ctrlVec, qureg);
60 targVec = util_getBraQubits(targVec, qureg);
61 localiser_statevec_anyCtrlAnyTargAnyMatr(qureg, ctrlVec, stateVec, targVec, matr, conj);
62}
63
64
65
66/*
67 * CompMatr1
68 */
69
70extern "C" {
71
72void multiplyCompMatr1(Qureg qureg, int target, CompMatr1 matrix) {
73 validate_quregFields(qureg, __func__);
74 validate_target(qureg, target, __func__);
75 validate_matrixFields(matrix, __func__); // matrix can be non-unitary
76
77 bool conj = false;
78 localiser_statevec_anyCtrlOneTargDenseMatr(qureg, {}, {}, target, matrix, conj);
79}
80
81void applyCompMatr1(Qureg qureg, int target, CompMatr1 matrix) {
82
83 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, nullptr, nullptr, 0, &target, 1, matrix, __func__);
84}
85
86void applyControlledCompMatr1(Qureg qureg, int control, int target, CompMatr1 matrix) {
87
88 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, &control, nullptr, 1, &target, 1, matrix, __func__);
89}
90
91void applyMultiControlledCompMatr1(Qureg qureg, int* controls, int numControls, int target, CompMatr1 matrix) {
92
93 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, nullptr, numControls, &target, 1, matrix, __func__);
94}
95
96void applyMultiStateControlledCompMatr1(Qureg qureg, int* controls, int* states, int numControls, int target, CompMatr1 matrix) {
97
98 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, states, numControls, &target, 1, matrix, __func__);
99}
100
101} // end de-mangler
102
103void applyMultiControlledCompMatr1(Qureg qureg, vector<int> controls, int target, CompMatr1 matrix) {
104
105 applyMultiControlledCompMatr1(qureg, controls.data(), controls.size(), target, matrix);
106}
107
108void applyMultiStateControlledCompMatr1(Qureg qureg, vector<int> controls, vector<int> states, int target, CompMatr1 matrix) {
109 validate_controlsMatchStates(controls.size(), states.size(), __func__);
110
111 applyMultiStateControlledCompMatr1(qureg, controls.data(), states.data(), controls.size(), target, matrix);
112}
113
114
115
116/*
117 * CompMatr2
118 */
119
120extern "C" {
121
122void multiplyCompMatr2(Qureg qureg, int target1, int target2, CompMatr2 matrix) {
123 validate_quregFields(qureg, __func__);
124 validate_twoTargets(qureg, target1, target2, __func__);
125 validate_matrixFields(matrix, __func__); // matrix can be non-unitary
126 validate_mixedAmpsFitInNode(qureg, 2, __func__);
127
128 bool conj = false;
129 localiser_statevec_anyCtrlTwoTargDenseMatr(qureg, {}, {}, target1, target2, matrix, conj);
130}
131
132void applyCompMatr2(Qureg qureg, int target1, int target2, CompMatr2 matrix) {
133
134 int targs[] = {target1, target2};
135 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, nullptr, nullptr, 0, targs, 2, matrix, __func__);
136}
137
138void applyControlledCompMatr2(Qureg qureg, int control, int target1, int target2, CompMatr2 matrix) {
139
140 int targs[] = {target1, target2};
141 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, &control, nullptr, 1, targs, 2, matrix, __func__);
142}
143
144void applyMultiControlledCompMatr2(Qureg qureg, int* controls, int numControls, int target1, int target2, CompMatr2 matrix) {
145
146 int targs[] = {target1, target2};
147 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, nullptr, numControls, targs, 2, matrix, __func__);
148}
149
150void applyMultiStateControlledCompMatr2(Qureg qureg, int* controls, int* states, int numControls, int target1, int target2, CompMatr2 matrix) {
151
152 int targs[] = {target1, target2};
153 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, states, numControls, targs, 2, matrix, __func__);
154}
155
156} // end de-mangler
157
158void applyMultiControlledCompMatr2(Qureg qureg, vector<int> controls, int target1, int target2, CompMatr2 matr) {
159
160 applyMultiControlledCompMatr2(qureg, controls.data(), controls.size(), target1, target2, matr);
161}
162
163void applyMultiStateControlledCompMatr2(Qureg qureg, vector<int> controls, vector<int> states, int numControls, int target1, int target2, CompMatr2 matr) {
164 validate_controlsMatchStates(controls.size(), states.size(), __func__);
165
166 applyMultiStateControlledCompMatr2(qureg, controls.data(), states.data(), controls.size(), target1, target2, matr);
167}
168
169
170
171/*
172 * CompMatr
173 */
174
175extern "C" {
176
177void multiplyCompMatr(Qureg qureg, int* targets, int numTargets, CompMatr matrix) {
178 validate_quregFields(qureg, __func__);
179 validate_targets(qureg, targets, numTargets, __func__);
180 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also validates fields and is-sync, but not unitarity
181 validate_mixedAmpsFitInNode(qureg, numTargets, __func__);
182
183 bool conj = false;
184 localiser_statevec_anyCtrlAnyTargDenseMatr(qureg, {}, {}, util_getVector(targets, numTargets), matrix, conj);
185}
186
187void applyCompMatr(Qureg qureg, int* targets, int numTargets, CompMatr matrix) {
188
189 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, nullptr, nullptr, 0, targets, numTargets, matrix, __func__);
190}
191
192void applyControlledCompMatr(Qureg qureg, int control, int* targets, int numTargets, CompMatr matrix) {
193
194 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, &control, nullptr, 1, targets, numTargets, matrix, __func__);
195}
196
197void applyMultiControlledCompMatr(Qureg qureg, int* controls, int numControls, int* targets, int numTargets, CompMatr matrix) {
198
199 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, nullptr, numControls, targets, numTargets, matrix, __func__);
200}
201
202void applyMultiStateControlledCompMatr(Qureg qureg, int* controls, int* states, int numControls, int* targets, int numTargets, CompMatr matrix) {
203
204 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, states, numControls, targets, numTargets, matrix, __func__);
205}
206
207} // end de-mangler
208
209void multiplyCompMatr(Qureg qureg, vector<int> targets, CompMatr matr) {
210
211 multiplyCompMatr(qureg, targets.data(), targets.size(), matr);
212}
213
214void applyCompMatr(Qureg qureg, vector<int> targets, CompMatr matr) {
215
216 applyCompMatr(qureg, targets.data(), targets.size(), matr);
217}
218
219void applyControlledCompMatr(Qureg qureg, int control, vector<int> targets, CompMatr matr) {
220
221 applyControlledCompMatr(qureg, control, targets.data(), targets.size(), matr);
222}
223
224void applyMultiControlledCompMatr(Qureg qureg, vector<int> controls, vector<int> targets, CompMatr matr) {
225
226 applyMultiControlledCompMatr(qureg, controls.data(), controls.size(), targets.data(), targets.size(), matr);
227}
228
229void applyMultiStateControlledCompMatr(Qureg qureg, vector<int> controls, vector<int> states, vector<int> targets, CompMatr matr) {
230 validate_controlsMatchStates(controls.size(), states.size(), __func__);
231
232 applyMultiStateControlledCompMatr(qureg, controls.data(), states.data(), controls.size(), targets.data(), targets.size(), matr);
233}
234
235
236
237/*
238 * DiagMatr1
239 */
240
241extern "C" {
242
243void multiplyDiagMatr1(Qureg qureg, int target, DiagMatr1 matrix) {
244 validate_quregFields(qureg, __func__);
245 validate_target(qureg, target, __func__);
246 validate_matrixFields(matrix, __func__); // matrix can be non-unitary
247
248 bool conj = false;
249 localiser_statevec_anyCtrlOneTargDiagMatr(qureg, {}, {}, target, matrix, conj);
250}
251
252void applyDiagMatr1(Qureg qureg, int target, DiagMatr1 matrix) {
253
254 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, nullptr, nullptr, 0, &target, 1, matrix, __func__);
255}
256
257void applyControlledDiagMatr1(Qureg qureg, int control, int target, DiagMatr1 matrix) {
258
259 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, &control, nullptr, 1, &target, 1, matrix, __func__);
260}
261
262void applyMultiControlledDiagMatr1(Qureg qureg, int* controls, int numControls, int target, DiagMatr1 matrix) {
263
264 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, nullptr, numControls, &target, 1, matrix, __func__);
265}
266
267void applyMultiStateControlledDiagMatr1(Qureg qureg, int* controls, int* states, int numControls, int target, DiagMatr1 matrix) {
268
269 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, states, numControls, &target, 1, matrix, __func__);
270}
271
272} // end de-mangler
273
274void applyMultiControlledDiagMatr1(Qureg qureg, vector<int> controls, int target, DiagMatr1 matr) {
275
276 applyMultiControlledDiagMatr1(qureg, controls.data(), controls.size(), target, matr);
277}
278
279void applyMultiStateControlledDiagMatr1(Qureg qureg, vector<int> controls, vector<int> states, int target, DiagMatr1 matr) {
280 validate_controlsMatchStates(controls.size(), states.size(), __func__);
281
282 applyMultiStateControlledDiagMatr1(qureg, controls.data(), states.data(), controls.size(), target, matr);
283}
284
285
286
287/*
288 * DiagMatr2
289 */
290
291extern "C" {
292
293void multiplyDiagMatr2(Qureg qureg, int target1, int target2, DiagMatr2 matrix) {
294 validate_quregFields(qureg, __func__);
295 validate_twoTargets(qureg, target1, target2, __func__);
296 validate_matrixFields(matrix, __func__); // matrix can be non-unitary
297
298 bool conj = false;
299 localiser_statevec_anyCtrlTwoTargDiagMatr(qureg, {}, {}, target1, target2, matrix, conj);
300}
301
302void applyDiagMatr2(Qureg qureg, int target1, int target2, DiagMatr2 matrix) {
303
304 int targs[] = {target1, target2};
305 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, nullptr, nullptr, 0, targs, 2, matrix, __func__);
306}
307
308void applyControlledDiagMatr2(Qureg qureg, int control, int target1, int target2, DiagMatr2 matrix) {
309
310 int targs[] = {target1, target2};
311 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, &control, nullptr, 1, targs, 2, matrix, __func__);
312}
313
314void applyMultiControlledDiagMatr2(Qureg qureg, int* controls, int numControls, int target1, int target2, DiagMatr2 matrix) {
315
316 int targs[] = {target1, target2};
317 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, nullptr, numControls, targs, 2, matrix, __func__);
318}
319
320void applyMultiStateControlledDiagMatr2(Qureg qureg, int* controls, int* states, int numControls, int target1, int target2, DiagMatr2 matrix) {
321
322 int targs[] = {target1, target2};
323 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, states, numControls, targs, 2, matrix, __func__);
324}
325
326} // end de-mangler
327
328void applyMultiControlledDiagMatr2(Qureg qureg, vector<int> controls, int target1, int target2, DiagMatr2 matr) {
329
330 applyMultiControlledDiagMatr2(qureg, controls.data(), controls.size(), target1, target2, matr);
331}
332
333void applyMultiStateControlledDiagMatr2(Qureg qureg, vector<int> controls, vector<int> states, int target1, int target2, DiagMatr2 matr) {
334 validate_controlsMatchStates(controls.size(), states.size(), __func__);
335
336 applyMultiStateControlledDiagMatr2(qureg, controls.data(), states.data(), controls.size(), target1, target2, matr);
337}
338
339
340
341/*
342 * DiagMatr
343 */
344
345extern "C" {
346
347void multiplyDiagMatr(Qureg qureg, int* targets, int numTargets, DiagMatr matrix) {
348 validate_quregFields(qureg, __func__);
349 validate_targets(qureg, targets, numTargets, __func__);
350 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also validates fields and is-sync, but not unitarity
351
352 bool conj = false;
353 qcomp exponent = 1;
354 localiser_statevec_anyCtrlAnyTargDiagMatr(qureg, {}, {}, util_getVector(targets, numTargets), matrix, exponent, conj);
355}
356
357void applyDiagMatr(Qureg qureg, int* targets, int numTargets, DiagMatr matrix) {
358
359 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, nullptr, nullptr, 0, targets, numTargets, matrix, __func__);
360}
361
362void applyControlledDiagMatr(Qureg qureg, int control, int* targets, int numTargets, DiagMatr matrix) {
363
364 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, &control, nullptr, 1, targets, numTargets, matrix, __func__);
365}
366
367void applyMultiControlledDiagMatr(Qureg qureg, int* controls, int numControls, int* targets, int numTargets, DiagMatr matrix) {
368
369 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, nullptr, numControls, targets, numTargets, matrix, __func__);
370}
371
372void applyMultiStateControlledDiagMatr(Qureg qureg, int* controls, int* states, int numControls, int* targets, int numTargets, DiagMatr matrix) {
373
374 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, states, numControls, targets, numTargets, matrix, __func__);
375}
376
377} // end de-mangler
378
379void multiplyDiagMatr(Qureg qureg, vector<int> targets, DiagMatr matrix) {
380
381 multiplyDiagMatr(qureg, targets.data(), targets.size(), matrix);
382}
383
384void applyDiagMatr(Qureg qureg, vector<int> targets, DiagMatr matrix) {
385
386 applyDiagMatr(qureg, targets.data(), targets.size(), matrix);
387}
388
389void applyControlledDiagMatr(Qureg qureg, int control, vector<int> targets, DiagMatr matrix) {
390
391 applyControlledDiagMatr(qureg, control, targets.data(), targets.size(), matrix);
392}
393
394void applyMultiControlledDiagMatr(Qureg qureg, vector<int> controls, vector<int> targets, DiagMatr matrix) {
395
396 applyMultiControlledDiagMatr(qureg, controls.data(), controls.size(), targets.data(), targets.size(), matrix);
397}
398
399void applyMultiStateControlledDiagMatr(Qureg qureg, vector<int> controls, vector<int> states, vector<int> targets, DiagMatr matrix) {
400 validate_controlsMatchStates(controls.size(), states.size(), __func__);
401
402 applyMultiStateControlledDiagMatr(qureg, controls.data(), states.data(), controls.size(), targets.data(), targets.size(), matrix);
403}
404
405
406
407/*
408 * DiagMatrPower
409 *
410 * which still (except for multiply) assert unitarity,
411 * even though a non-real exponent is possible
412 */
413
414extern "C" {
415
416void multiplyDiagMatrPower(Qureg qureg, int* targets, int numTargets, DiagMatr matrix, qcomp exponent) {
417 validate_quregFields(qureg, __func__);
418 validate_targets(qureg, targets, numTargets, __func__);
419 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also validates fields and is-sync, but not unitarity
420 validate_matrixExpIsNonDiverging(matrix, exponent, __func__); // harmlessly re-validates fields and is-sync
421
422 bool conj = false;
423 localiser_statevec_anyCtrlAnyTargDiagMatr(qureg, {}, {}, util_getVector(targets, numTargets), matrix, exponent, conj);
424}
425
426void applyDiagMatrPower(Qureg qureg, int* targets, int numTargets, DiagMatr matrix, qcomp exponent) {
427 validate_quregFields(qureg, __func__);
428 validate_targets(qureg, targets, numTargets, __func__);
429 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also checks fields and is-synced
430 validate_matrixIsUnitary(matrix, __func__);
431 validate_matrixExpIsNonDiverging(matrix, exponent, __func__);
432 validate_unitaryExponentIsReal(exponent, __func__);
433
434 // notice exponent is a 'qcomp' not a 'qreal' despite validation; see applyMultiStateControlledDiagMatrPower()
435
436 // harmlessly re-validates
437 applyMultiStateControlledDiagMatrPower(qureg, nullptr, nullptr, 0, targets, numTargets, matrix, exponent);
438}
439
440void applyControlledDiagMatrPower(Qureg qureg, int control, int* targets, int numTargets, DiagMatr matrix, qcomp exponent) {
441 validate_quregFields(qureg, __func__);
442 validate_controlAndTargets(qureg, control, targets, numTargets, __func__);
443 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also checks fields and is-synced
444 validate_matrixIsUnitary(matrix, __func__);
445 validate_matrixExpIsNonDiverging(matrix, exponent, __func__);
446 validate_unitaryExponentIsReal(exponent, __func__);
447
448 // notice exponent is a 'qcomp' not a 'qreal' despite validation; see applyMultiStateControlledDiagMatrPower()
449
450 // harmlessly re-validates
451 applyMultiStateControlledDiagMatrPower(qureg, &control, nullptr, 1, targets, numTargets, matrix, exponent);
452}
453
454void applyMultiControlledDiagMatrPower(Qureg qureg, int* controls, int numControls, int* targets, int numTargets, DiagMatr matrix, qcomp exponent) {
455 validate_quregFields(qureg, __func__);
456 validate_controlsAndTargets(qureg, controls, numControls, targets, numTargets, __func__);
457 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also checks fields and is-synced
458 validate_matrixIsUnitary(matrix, __func__);
459 validate_matrixExpIsNonDiverging(matrix, exponent, __func__);
460 validate_unitaryExponentIsReal(exponent, __func__);
461
462 // notice exponent is a 'qcomp' not a 'qreal' despite validation; see applyMultiStateControlledDiagMatrPower()
463
464 // harmlessly re-validates
465 applyMultiStateControlledDiagMatrPower(qureg, controls, nullptr, numControls, targets, numTargets, matrix, exponent);
466}
467
468void applyMultiStateControlledDiagMatrPower(Qureg qureg, int* controls, int* states, int numControls, int* targets, int numTargets, DiagMatr matrix, qcomp exponent) {
469 validate_quregFields(qureg, __func__);
470 validate_controlsAndTargets(qureg, controls, numControls, targets, numTargets, __func__);
471 validate_controlStates(states, numControls, __func__); // can be nullptr, ignoring numControls
472 validate_matrixDimMatchesTargets(matrix, numTargets, __func__);
473 validate_matrixIsUnitary(matrix, __func__);
474 validate_matrixExpIsNonDiverging(matrix, exponent, __func__);
475 validate_unitaryExponentIsReal(exponent, __func__);
476
477 // unlike calcExpecDiagMatrPower which accepts a 'qreal' exponent,
478 // this function accepts a 'qcomp'. This is because it always
479 // evaluates the relatively numerically unstable pow(qcomp,qcomp)
480 // overload, rather than pow(qreal,qreal), since there is no reason
481 // to think matrix is real (unitarity permits it to be complex).
482 // As such, despite unitarity requiring exponent is also real, we
483 // accept a qcomp types so that complex exponents can be passed
484 // when numerical validation is disabled without a separate func.
485
486 bool conj = false;
487 auto ctrlVec = util_getVector(controls, numControls);
488 auto stateVec = util_getVector(states, numControls); // empty if states==nullptr
489 auto targVec = util_getVector(targets, numTargets);
490 localiser_statevec_anyCtrlAnyTargDiagMatr(qureg, ctrlVec, stateVec, targVec, matrix, exponent, conj);
491
492 if (!qureg.isDensityMatrix)
493 return;
494
495 conj = true;
496 ctrlVec = util_getBraQubits(ctrlVec, qureg);
497 targVec = util_getBraQubits(targVec, qureg);
498 localiser_statevec_anyCtrlAnyTargDiagMatr(qureg, ctrlVec, stateVec, targVec, matrix, exponent, conj);
499}
500
501} // end de-mangler
502
503void multiplyDiagMatrPower(Qureg qureg, vector<int> targets, DiagMatr matrix, qcomp exponent) {
504
505 multiplyDiagMatrPower(qureg, targets.data(), targets.size(), matrix, exponent);
506}
507
508void applyDiagMatrPower(Qureg qureg, vector<int> targets, DiagMatr matrix, qcomp exponent) {
509
510 applyDiagMatrPower(qureg, targets.data(), targets.size(), matrix, exponent);
511}
512
513void applyControlledDiagMatrPower(Qureg qureg, int control, vector<int> targets, DiagMatr matrix, qcomp exponent) {
514
515 applyControlledDiagMatrPower(qureg, control, targets.data(), targets.size(), matrix, exponent);
516}
517
518void applyMultiControlledDiagMatrPower(Qureg qureg, vector<int> controls, vector<int> targets, DiagMatr matrix, qcomp exponent) {
519
520 applyMultiControlledDiagMatrPower(qureg, controls.data(), controls.size(), targets.data(), targets.size(), matrix, exponent);
521}
522
523void applyMultiStateControlledDiagMatrPower(Qureg qureg, vector<int> controls, vector<int> states, vector<int> targets, DiagMatr matrix, qcomp exponent) {
524 validate_controlsMatchStates(controls.size(), states.size(), __func__);
525
526 applyMultiStateControlledDiagMatrPower(qureg, controls.data(), states.data(), controls.size(), targets.data(), targets.size(), matrix, exponent);
527}
528
529
530
531/*
532 * FullStateDiagMatr (and power)
533 */
534
535extern "C" {
536
538 validate_quregFields(qureg, __func__);
539 validate_matrixFields(matrix, __func__);
540 validate_matrixAndQuregAreCompatible(matrix, qureg, false, __func__); // matrix can be non-unitary
541
542 multiplyFullStateDiagMatrPower(qureg, matrix, 1); // harmlessly re-validates
543}
544
545void multiplyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent) {
546 validate_quregFields(qureg, __func__);
547 validate_matrixFields(matrix, __func__);
548 validate_matrixAndQuregAreCompatible(matrix, qureg, false, __func__); // matrix can be non-unitary
549 validate_matrixExpIsNonDiverging(matrix, exponent, __func__);
550
551 bool onlyMultiply = true;
552 (qureg.isDensityMatrix)?
553 localiser_densmatr_allTargDiagMatr(qureg, matrix, exponent, onlyMultiply):
554 localiser_statevec_allTargDiagMatr(qureg, matrix, exponent);
555}
556
558 validate_quregFields(qureg, __func__);
559 validate_matrixFields(matrix, __func__);
560 validate_matrixAndQuregAreCompatible(matrix, qureg, false, __func__);
561 validate_matrixIsUnitary(matrix, __func__);
562
563 applyFullStateDiagMatrPower(qureg, matrix, 1); // harmlessly re-validates
564}
565
566void applyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent) {
567 validate_quregFields(qureg, __func__);
568 validate_matrixFields(matrix, __func__);
569 validate_matrixAndQuregAreCompatible(matrix, qureg, false, __func__);
570 validate_matrixIsUnitary(matrix, __func__);
571 validate_unitaryExponentIsReal(exponent, __func__);
572 validate_matrixExpIsNonDiverging(matrix, exponent, __func__);
573
574 bool onlyMultiply = false;
575 (qureg.isDensityMatrix)?
576 localiser_densmatr_allTargDiagMatr(qureg, matrix, exponent, onlyMultiply):
577 localiser_statevec_allTargDiagMatr(qureg, matrix, exponent);
578}
579
580} // end de-mangler
581
582
583
584/*
585 * S gate
586 */
587
588extern "C" {
589
590void applyS(Qureg qureg, int target) {
591 validate_quregFields(qureg, __func__);
592 validate_target(qureg, target, __func__);
593
594 // harmlessly re-validates
595 applyMultiStateControlledS(qureg, nullptr, nullptr, 0, target);
596}
597
598void applyControlledS(Qureg qureg, int control, int target) {
599 validate_quregFields(qureg, __func__);
600 validate_controlAndTarget(qureg, control, target, __func__);
601
602 // harmlessly re-validates
603 applyMultiStateControlledS(qureg, &control, nullptr, 1, target);
604}
605
606void applyMultiControlledS(Qureg qureg, int* controls, int numControls, int target) {
607 validate_quregFields(qureg, __func__);
608 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
609
610 // harmlessly re-validates
611 applyMultiStateControlledS(qureg, controls, nullptr, numControls, target);
612}
613
614void applyMultiStateControlledS(Qureg qureg, int* controls, int* states, int numControls, int target) {
615
616 DiagMatr1 matr = getDiagMatr1({1, 1_i});
617 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, states, numControls, &target, 1, matr, __func__);
618}
619
620} // end de-mangler
621
622void applyMultiControlledS(Qureg qureg, vector<int> controls, int target) {
623
624 applyMultiControlledS(qureg, controls.data(), controls.size(), target);
625}
626
627void applyMultiStateControlledS(Qureg qureg, vector<int> controls, vector<int> states, int target) {
628 validate_controlsMatchStates(controls.size(), states.size(), __func__);
629
630 applyMultiStateControlledS(qureg, controls.data(), states.data(), controls.size(), target);
631}
632
633
634
635/*
636 * T gate
637 */
638
639extern "C" {
640
641void applyT(Qureg qureg, int target) {
642 validate_quregFields(qureg, __func__);
643 validate_target(qureg, target, __func__);
644
645 // harmlessly re-validates
646 applyMultiStateControlledT(qureg, nullptr, nullptr, 0, target);
647}
648
649void applyControlledT(Qureg qureg, int control, int target) {
650 validate_quregFields(qureg, __func__);
651 validate_controlAndTarget(qureg, control, target, __func__);
652
653 // harmlessly re-validates
654 applyMultiStateControlledT(qureg, &control, nullptr, 1, target);
655}
656
657void applyMultiControlledT(Qureg qureg, int* controls, int numControls, int target) {
658 validate_quregFields(qureg, __func__);
659 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
660
661 // harmlessly re-validates
662 applyMultiStateControlledT(qureg, controls, nullptr, numControls, target);
663}
664
665void applyMultiStateControlledT(Qureg qureg, int* controls, int* states, int numControls, int target) {
666
667 DiagMatr1 matr = getDiagMatr1({1, 1/std::sqrt(2) + 1_i/std::sqrt(2)});
668 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, states, numControls, &target, 1, matr, __func__);
669}
670
671} // end de-mangler
672
673void applyMultiControlledT(Qureg qureg, vector<int> controls, int target) {
674
675 applyMultiControlledT(qureg, controls.data(), controls.size(), target);
676}
677
678void applyMultiStateControlledT(Qureg qureg, vector<int> controls, vector<int> states, int target) {
679 validate_controlsMatchStates(controls.size(), states.size(), __func__);
680
681 applyMultiStateControlledT(qureg, controls.data(), states.data(), controls.size(), target);
682}
683
684
685
686/*
687 * Hadamard
688 */
689
690extern "C" {
691
692void applyHadamard(Qureg qureg, int target) {
693 validate_quregFields(qureg, __func__);
694 validate_target(qureg, target, __func__);
695
696 // harmlessly re-validates
697 applyMultiStateControlledHadamard(qureg, nullptr, nullptr, 0, target);
698}
699
700void applyControlledHadamard(Qureg qureg, int control, int target) {
701 validate_quregFields(qureg, __func__);
702 validate_controlAndTarget(qureg, control, target, __func__);
703
704 // harmlessly re-validates
705 applyMultiStateControlledHadamard(qureg, &control, nullptr, 1, target);
706}
707
708void applyMultiControlledHadamard(Qureg qureg, int* controls, int numControls, int target) {
709 validate_quregFields(qureg, __func__);
710 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
711
712 // harmlessly re-validates
713 applyMultiStateControlledHadamard(qureg, controls, nullptr, numControls, target);
714}
715
716void applyMultiStateControlledHadamard(Qureg qureg, int* controls, int* states, int numControls, int target) {
717
718 qcomp a = 1/std::sqrt(2);
719 CompMatr1 matr = getCompMatr1({
720 {a, a},
721 {a,-a}});
722
723 validateAndApplyAnyCtrlAnyTargUnitaryMatrix(qureg, controls, states, numControls, &target, 1, matr, __func__);
724}
725
726} // end de-mangler
727
728void applyMultiControlledHadamard(Qureg qureg, vector<int> controls, int target) {
729
730 applyMultiControlledHadamard(qureg, controls.data(), controls.size(), target);
731}
732
733void applyMultiStateControlledHadamard(Qureg qureg, vector<int> controls, vector<int> states, int target) {
734 validate_controlsMatchStates(controls.size(), states.size(), __func__);
735
736 applyMultiStateControlledHadamard(qureg, controls.data(), states.data(), controls.size(), target);
737}
738
739
740
741/*
742 * swap
743 */
744
745extern "C" {
746
747void multiplySwap(Qureg qureg, int qubit1, int qubit2) {
748 validate_quregFields(qureg, __func__);
749 validate_twoTargets(qureg, qubit1, qubit2, __func__);
750
751 localiser_statevec_anyCtrlSwap(qureg, {}, {}, qubit1, qubit2);
752}
753
754void applySwap(Qureg qureg, int qubit1, int qubit2) {
755 validate_quregFields(qureg, __func__);
756 validate_twoTargets(qureg, qubit1, qubit2, __func__);
757
758 // harmlessly re-valdiates
759 applyMultiStateControlledSwap(qureg, nullptr, nullptr, 0, qubit1, qubit2);
760}
761
762void applyControlledSwap(Qureg qureg, int control, int qubit1, int qubit2) {
763 validate_quregFields(qureg, __func__);
764 validate_controlAndTwoTargets(qureg, control, qubit1, qubit2, __func__);
765
766 // harmlessly re-valdiates
767 applyMultiStateControlledSwap(qureg, &control, nullptr, 1, qubit1, qubit2);
768}
769
770void applyMultiControlledSwap(Qureg qureg, int* controls, int numControls, int qubit1, int qubit2) {
771 validate_quregFields(qureg, __func__);
772 validate_controlsAndTwoTargets(qureg, controls, numControls, qubit1, qubit2, __func__);
773
774 // harmlessly re-valdiates
775 applyMultiStateControlledSwap(qureg, controls, nullptr, numControls, qubit1, qubit2);
776}
777
778void applyMultiStateControlledSwap(Qureg qureg, int* controls, int* states, int numControls, int qubit1, int qubit2) {
779 validate_quregFields(qureg, __func__);
780 validate_controlsAndTwoTargets(qureg, controls, numControls, qubit1, qubit2, __func__);
781 validate_controlStates(states, numControls, __func__); // permits states==nullptr
782
783 auto ctrlVec = util_getVector(controls, numControls);
784 auto stateVec = util_getVector(states, numControls); // empty if states==nullptr
785 localiser_statevec_anyCtrlSwap(qureg, ctrlVec, stateVec, qubit1, qubit2);
786
787 if (!qureg.isDensityMatrix)
788 return;
789
790 ctrlVec = util_getBraQubits(ctrlVec, qureg);
791 qubit1 = util_getBraQubit(qubit1, qureg);
792 qubit2 = util_getBraQubit(qubit2, qureg);
793 localiser_statevec_anyCtrlSwap(qureg, ctrlVec, stateVec, qubit1, qubit2);
794}
795
796} // end de-mangler
797
798void applyMultiControlledSwap(Qureg qureg, vector<int> controls, int qubit1, int qubit2) {
799
800 applyMultiControlledSwap(qureg, controls.data(), controls.size(), qubit1, qubit2);
801}
802
803void applyMultiStateControlledSwap(Qureg qureg, vector<int> controls, vector<int> states, int qubit1, int qubit2) {
804 validate_controlsMatchStates(controls.size(), states.size(), __func__);
805
806 applyMultiStateControlledSwap(qureg, controls.data(), states.data(), controls.size(), qubit1, qubit2);
807}
808
809
810
811/*
812 * sqrt swap
813 */
814
815extern "C" {
816
817void applySqrtSwap(Qureg qureg, int target1, int target2) {
818 validate_quregFields(qureg, __func__);
819 validate_twoTargets(qureg,target1, target2, __func__);
820
821 // harmlessly re-validates
822 applyMultiStateControlledSqrtSwap(qureg, nullptr, nullptr, 0, target1, target2);
823}
824
825void applyControlledSqrtSwap(Qureg qureg, int control, int target1, int target2) {
826 validate_quregFields(qureg, __func__);
827 validate_controlAndTwoTargets(qureg, control, target1, target2, __func__);
828
829 // harmlessly re-validates
830 applyMultiStateControlledSqrtSwap(qureg, &control, nullptr, 1, target1, target2);
831}
832
833void applyMultiControlledSqrtSwap(Qureg qureg, int* controls, int numControls, int target1, int target2) {
834 validate_quregFields(qureg, __func__);
835 validate_controlsAndTwoTargets(qureg, controls, numControls, target1, target2, __func__);
836
837 // harmlessly re-validates
838 applyMultiStateControlledSqrtSwap(qureg, controls, nullptr, numControls, target1, target2);
839}
840
841void applyMultiStateControlledSqrtSwap(Qureg qureg, int* controls, int* states, int numControls, int target1, int target2) {
842 validate_quregFields(qureg, __func__);
843 validate_controlsAndTwoTargets(qureg, controls, numControls, target1, target2, __func__);
844 validate_controlStates(states, numControls, __func__); // permits states==nullptr
845
846 /// @todo
847 /// this function exacts sqrtSwap as a dense 2-qubit matrix,
848 /// where as bespoke communication and simulation strategy is
849 /// clearly possible which we have not supported because the gate
850 /// is somewhat esoteric. As such, we must validate mixed-amps fit
851
852 validate_mixedAmpsFitInNode(qureg, 2, __func__); // to throw SqrtSwap error, not generic CompMatr2 error
853
854 CompMatr2 matr = getCompMatr2({
855 {1, 0, 0, 0},
856 {0, .5+.5_i, .5-.5_i, 0},
857 {0, .5-.5_i, .5+.5_i, 0},
858 {0, 0, 0, 1}});
859
860 applyMultiStateControlledCompMatr2(qureg, controls, states, numControls, target1, target2, matr);
861}
862
863} // end de-mangler
864
865void applyMultiControlledSqrtSwap(Qureg qureg, vector<int> controls, int qubit1, int qubit2) {
866
867 applyMultiControlledSqrtSwap(qureg, controls.data(), controls.size(), qubit1, qubit2);
868}
869
870void applyMultiStateControlledSqrtSwap(Qureg qureg, vector<int> controls, vector<int> states, int qubit1, int qubit2) {
871 validate_controlsMatchStates(controls.size(), states.size(), __func__);
872
873 applyMultiStateControlledSqrtSwap(qureg, controls.data(), states.data(), controls.size(), qubit1, qubit2);
874}
875
876
877
878/*
879 * individual Paulis
880 *
881 * where Y and Z are most efficiently effected as DiagMatr1,
882 * but where X is best effected as a 1-qubit PauliStr.
883 */
884
885extern "C" {
886
887void applyPauliX(Qureg qureg, int target) {
888 validate_quregFields(qureg, __func__);
889 validate_target(qureg, target, __func__);
890
891 // harmlessly re-validates
892 applyMultiStateControlledPauliX(qureg, nullptr, nullptr, 0, target);
893}
894
895void applyPauliY(Qureg qureg, int target) {
896 validate_quregFields(qureg, __func__);
897 validate_target(qureg, target, __func__);
898
899 // harmlessly re-validates
900 applyMultiStateControlledPauliY(qureg, nullptr, nullptr, 0, target);
901}
902
903void applyPauliZ(Qureg qureg, int target) {
904 validate_quregFields(qureg, __func__);
905 validate_target(qureg, target, __func__);
906
907 // harmlessly re-validates
908 applyMultiStateControlledPauliZ(qureg, nullptr, nullptr, 0, target);
909}
910
911void applyControlledPauliX(Qureg qureg, int control, int target) {
912 validate_quregFields(qureg, __func__);
913 validate_controlAndTarget(qureg, control, target, __func__);
914
915 // harmlessly re-validates
916 applyMultiStateControlledPauliX(qureg, &control, nullptr, 1, target);
917}
918
919void applyControlledPauliY(Qureg qureg, int control, int target) {
920 validate_quregFields(qureg, __func__);
921 validate_controlAndTarget(qureg, control, target, __func__);
922
923 // harmlessly re-validates
924 applyMultiStateControlledPauliY(qureg, &control, nullptr, 1, target);
925}
926
927void applyControlledPauliZ(Qureg qureg, int control, int target) {
928 validate_quregFields(qureg, __func__);
929 validate_controlAndTarget(qureg, control, target, __func__);
930
931 // harmlessly re-validates
932 applyMultiStateControlledPauliZ(qureg, &control, nullptr, 1, target);
933}
934
935void applyMultiControlledPauliX(Qureg qureg, int* controls, int numControls, int target) {
936 validate_quregFields(qureg, __func__);
937 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
938
939 // harmlessly re-validates
940 applyMultiStateControlledPauliX(qureg, controls, nullptr, numControls, target);
941}
942
943void applyMultiControlledPauliY(Qureg qureg, int* controls, int numControls, int target) {
944 validate_quregFields(qureg, __func__);
945 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
946
947 // harmlessly re-validates
948 applyMultiStateControlledPauliY(qureg, controls, nullptr, numControls, target);
949}
950
951void applyMultiControlledPauliZ(Qureg qureg, int* controls, int numControls, int target) {
952 validate_quregFields(qureg, __func__);
953 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
954
955 // harmlessly re-validates
956 applyMultiStateControlledPauliZ(qureg, controls, nullptr, numControls, target);
957}
958
959void applyMultiStateControlledPauliX(Qureg qureg, int* controls, int* states, int numControls, int target) {
960 validate_quregFields(qureg, __func__);
961 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
962 validate_controlStates(states, numControls, __func__); // permits states==nullptr
963
964 // harmlessly re-validates
965 applyMultiStateControlledPauliStr(qureg, controls, states, numControls, getPauliStr("X", {target}));
966}
967
968void applyMultiStateControlledPauliY(Qureg qureg, int* controls, int* states, int numControls, int target) {
969 validate_quregFields(qureg, __func__);
970 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
971 validate_controlStates(states, numControls, __func__); // permits states==nullptr
972
973 // harmlessly re-validates
974 applyMultiStateControlledPauliStr(qureg, controls, states, numControls, getPauliStr("Y", {target}));
975}
976
977void applyMultiStateControlledPauliZ(Qureg qureg, int* controls, int* states, int numControls, int target) {
978 validate_quregFields(qureg, __func__);
979 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
980 validate_controlStates(states, numControls, __func__); // permits states==nullptr
981
982 // harmlessly re-validates
983 DiagMatr1 matr = getDiagMatr1({1, -1});
984 applyMultiStateControlledDiagMatr1(qureg, controls, states, numControls, target, matr);
985}
986
987} // end de-mangler
988
989void applyMultiControlledPauliX(Qureg qureg, vector<int> controls, int target) {
990
991 applyMultiControlledPauliX(qureg, controls.data(), controls.size(), target);
992}
993
994void applyMultiControlledPauliY(Qureg qureg, vector<int> controls, int target) {
995
996 applyMultiControlledPauliY(qureg, controls.data(), controls.size(), target);
997}
998
999void applyMultiControlledPauliZ(Qureg qureg, vector<int> controls, int target) {
1000
1001 applyMultiControlledPauliZ(qureg, controls.data(), controls.size(), target);
1002}
1003
1004void applyMultiStateControlledPauliX(Qureg qureg, vector<int> controls, vector<int> states, int target) {
1005 validate_controlsMatchStates(controls.size(), states.size(), __func__);
1006
1007 applyMultiStateControlledPauliX(qureg, controls.data(), states.data(), controls.size(), target);
1008}
1009
1010void applyMultiStateControlledPauliY(Qureg qureg, vector<int> controls, vector<int> states, int target) {
1011 validate_controlsMatchStates(controls.size(), states.size(), __func__);
1012
1013 applyMultiStateControlledPauliY(qureg, controls.data(), states.data(), controls.size(), target);
1014}
1015
1016void applyMultiStateControlledPauliZ(Qureg qureg, vector<int> controls, vector<int> states, int target) {
1017 validate_controlsMatchStates(controls.size(), states.size(), __func__);
1018
1019 applyMultiStateControlledPauliZ(qureg, controls.data(), states.data(), controls.size(), target);
1020}
1021
1022
1023
1024/*
1025 * Pauli strings
1026 */
1027
1028extern "C" {
1029
1031 validate_quregFields(qureg, __func__);
1032 validate_pauliStrTargets(qureg, str, __func__);
1033
1034 localiser_statevec_anyCtrlPauliTensor(qureg, {}, {}, str);
1035}
1036
1037void applyPauliStr(Qureg qureg, PauliStr str) {
1038 validate_quregFields(qureg, __func__);
1039 validate_pauliStrTargets(qureg, str, __func__);
1040
1041 // harmlessly re-validates
1042 applyMultiStateControlledPauliStr(qureg, nullptr, nullptr, 0, str);
1043}
1044
1045void applyControlledPauliStr(Qureg qureg, int control, PauliStr str) {
1046 validate_quregFields(qureg, __func__);
1047 validate_controlAndPauliStrTargets(qureg, control, str, __func__);
1048
1049 // harmlessly re-validates
1050 applyMultiStateControlledPauliStr(qureg, &control, nullptr, 1, str);
1051}
1052
1053void applyMultiControlledPauliStr(Qureg qureg, int* controls, int numControls, PauliStr str) {
1054 validate_quregFields(qureg, __func__);
1055 validate_controlsAndPauliStrTargets(qureg, controls, numControls, str, __func__);
1056
1057 // harmlessly re-validates
1058 applyMultiStateControlledPauliStr(qureg, controls, nullptr, numControls, str);
1059}
1060
1061void applyMultiStateControlledPauliStr(Qureg qureg, int* controls, int* states, int numControls, PauliStr str) {
1062 validate_quregFields(qureg, __func__);
1063 validate_controlsAndPauliStrTargets(qureg, controls, numControls, str, __func__);
1064 validate_controlStates(states, numControls, __func__); // permits states==nullptr
1065
1066 qcomp factor = 1;
1067 auto ctrlVec = util_getVector(controls, numControls);
1068 auto stateVec = util_getVector(states, numControls); // empty if states==nullptr
1069
1070 // when there are no control qubits, we can merge the density matrix's
1071 // operation sinto a single tensor, i.e. +- (shift(str) (x) str), to
1072 // avoid superfluous re-enumeration of the state
1073 if (qureg.isDensityMatrix && numControls == 0) {
1074 factor = paulis_hasOddNumY(str)? -1 : 1;
1075 ctrlVec = util_getConcatenated(ctrlVec, util_getBraQubits(ctrlVec, qureg));
1076 stateVec = util_getConcatenated(stateVec, stateVec);
1077 str = paulis_getKetAndBraPauliStr(str, qureg);
1078 }
1079
1080 localiser_statevec_anyCtrlPauliTensor(qureg, ctrlVec, stateVec, str, factor);
1081
1082 // but density-matrix control qubits require two distinct operations
1083 if (qureg.isDensityMatrix && numControls > 0) {
1084 factor = paulis_hasOddNumY(str)? -1 : 1;
1085 ctrlVec = util_getBraQubits(ctrlVec, qureg);
1086 str = paulis_getShiftedPauliStr(str, qureg.numQubits);
1087 localiser_statevec_anyCtrlPauliTensor(qureg, ctrlVec, stateVec, str, factor);
1088 }
1089}
1090
1091} // end de-mangler
1092
1093void applyMultiControlledPauliStr(Qureg qureg, vector<int> controls, PauliStr str) {
1094
1095 applyMultiControlledPauliStr(qureg, controls.data(), controls.size(), str);
1096}
1097
1098void applyMultiStateControlledPauliStr(Qureg qureg, vector<int> controls, vector<int> states, PauliStr str) {
1099 validate_controlsMatchStates(controls.size(), states.size(), __func__);
1100
1101 applyMultiStateControlledPauliStr(qureg, controls.data(), states.data(), controls.size(), str);
1102}
1103
1104
1105
1106/*
1107 * Pauli string sums
1108 */
1109
1110extern "C" {
1111
1112void multiplyPauliStrSum(Qureg qureg, PauliStrSum sum, Qureg workspace) {
1113 validate_quregFields(qureg, __func__);
1114 validate_quregFields(workspace, __func__);
1115 validate_quregCanBeWorkspace(qureg, workspace, __func__);
1116 validate_pauliStrSumFields(sum, __func__);
1117 validate_pauliStrSumTargets(sum, qureg, __func__);
1118
1119 // clone qureg to workspace, set qureg to blank
1120 localiser_statevec_setQuregToSuperposition(0, workspace, 1, qureg, 0, qureg);
1121 localiser_statevec_initUniformState(qureg, 0);
1122
1123 // apply each term in-turn, mixing into output qureg, then undo using idempotency
1124 for (qindex i=0; i<sum.numTerms; i++) {
1125 localiser_statevec_anyCtrlPauliTensor(workspace, {}, {}, sum.strings[i]);
1126 localiser_statevec_setQuregToSuperposition(1, qureg, sum.coeffs[i], workspace, 0, workspace);
1127 localiser_statevec_anyCtrlPauliTensor(workspace, {}, {}, sum.strings[i]);
1128 }
1129
1130 // workspace -> qureg, and qureg -> sum * qureg
1131}
1132
1133void applyFirstOrderTrotter(Qureg qureg, PauliStrSum sum, qreal angle, bool reverse) {
1134
1135 // (internal, invoked by applyTrotterizedPauliStrSumGadget)
1136
1137 for (qindex i=0; i<sum.numTerms; i++) {
1138 int j = reverse? sum.numTerms - i - 1 : i;
1139 qreal arg = 2 * angle * std::real(sum.coeffs[j]); // 2 undoes Gadget convention
1140 applyPauliGadget(qureg, sum.strings[j], arg); // caller disabled valiation therein
1141 }
1142}
1143
1144void applyHigherOrderTrotter(Qureg qureg, PauliStrSum sum, qreal angle, int order) {
1145
1146 // (internal, invoked by applyTrotterizedPauliStrSumGadget)
1147
1148 if (order == 1) {
1149 applyFirstOrderTrotter(qureg, sum, angle, false);
1150
1151 } else if (order == 2) {
1152 applyFirstOrderTrotter(qureg, sum, angle/2, false);
1153 applyFirstOrderTrotter(qureg, sum, angle/2, true);
1154
1155 } else {
1156 qreal p = 1. / (4 - std::pow(4, 1./(order-1)));
1157 qreal a = p * angle;
1158 qreal b = (1-4*p) * angle;
1159
1160 int lower = order - 2;
1161 applyFirstOrderTrotter(qureg, sum, a, lower);
1162 applyFirstOrderTrotter(qureg, sum, a, lower);
1163 applyFirstOrderTrotter(qureg, sum, b, lower);
1164 applyFirstOrderTrotter(qureg, sum, a, lower);
1165 applyFirstOrderTrotter(qureg, sum, a, lower);
1166 }
1167}
1168
1169void applyTrotterizedPauliStrSumGadget(Qureg qureg, PauliStrSum sum, qreal angle, int order, int reps) {
1170 validate_quregFields(qureg, __func__);
1171 validate_pauliStrSumFields(sum, __func__);
1172 validate_pauliStrSumTargets(sum, qureg, __func__);
1173 validate_pauliStrSumIsHermitian(sum, __func__);
1174 validate_trotterParams(qureg, order, reps, __func__);
1175
1176 // exp(i angle sum) = identity when angle=0
1177 if (angle == 0)
1178 return;
1179
1180 // record validation state then disable to avoid repeated
1181 // re-validations in each invoked applyPauliGadget() below
1182 bool wasValidationEnabled = validateconfig_isEnabled();
1183 validateconfig_disable();
1184
1185 // perform sequence of applyPauliGadget()
1186 for (int r=0; r<reps; r++)
1187 applyHigherOrderTrotter(qureg, sum, angle/reps, order);
1188
1189 // potentially restore validation
1190 if (wasValidationEnabled)
1191 validateconfig_enable();
1192
1193 /// @todo
1194 /// the accuracy of Trotterisation is greatly improved by randomisation
1195 /// or (even sub-optimal) grouping into commuting terms. Should we
1196 /// implement these above or into another function?
1197}
1198
1199} // end de-mangler
1200
1201
1202
1203/*
1204 * individual axis rotations
1205 */
1206
1207extern "C" {
1208
1209// don't think users will ever want to left-multiply only
1210
1211void applyRotateX(Qureg qureg, int target, qreal angle) {
1212 validate_quregFields(qureg, __func__);
1213 validate_target(qureg, target, __func__);
1214
1215 // harmlessly re-validates
1216 applyMultiStateControlledRotateX(qureg, nullptr, nullptr, 0, target, angle);
1217}
1218
1219void applyRotateY(Qureg qureg, int target, qreal angle) {
1220 validate_quregFields(qureg, __func__);
1221 validate_target(qureg, target, __func__);
1222
1223 // harmlessly re-validates
1224 applyMultiStateControlledRotateY(qureg, nullptr, nullptr, 0, target, angle);
1225}
1226
1227void applyRotateZ(Qureg qureg, int target, qreal angle) {
1228 validate_quregFields(qureg, __func__);
1229 validate_target(qureg, target, __func__);
1230
1231 // harmlessly re-validates
1232 applyMultiStateControlledRotateZ(qureg, nullptr, nullptr, 0, target, angle);
1233}
1234
1235void applyControlledRotateX(Qureg qureg, int control, int target, qreal angle) {
1236 validate_quregFields(qureg, __func__);
1237 validate_controlAndTarget(qureg, control, target, __func__);
1238
1239 // harmlessly re-validates
1240 applyMultiStateControlledRotateX(qureg, &control, nullptr, 1, target, angle);
1241}
1242
1243void applyControlledRotateY(Qureg qureg, int control, int target, qreal angle) {
1244 validate_quregFields(qureg, __func__);
1245 validate_controlAndTarget(qureg, control, target, __func__);
1246
1247 // harmlessly re-validates
1248 applyMultiStateControlledRotateY(qureg, &control, nullptr, 1, target, angle);
1249}
1250
1251void applyControlledRotateZ(Qureg qureg, int control, int target, qreal angle) {
1252 validate_quregFields(qureg, __func__);
1253 validate_controlAndTarget(qureg, control, target, __func__);
1254
1255 // harmlessly re-validates
1256 applyMultiStateControlledRotateZ(qureg, &control, nullptr, 1, target, angle);
1257}
1258
1259void applyMultiControlledRotateX(Qureg qureg, int* controls, int numControls, int target, qreal angle) {
1260 validate_quregFields(qureg, __func__);
1261 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
1262
1263 // harmlessly re-validates
1264 applyMultiStateControlledRotateX(qureg, controls, nullptr, numControls, target, angle);
1265}
1266
1267void applyMultiControlledRotateY(Qureg qureg, int* controls, int numControls, int target, qreal angle) {
1268 validate_quregFields(qureg, __func__);
1269 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
1270
1271 // harmlessly re-validates
1272 applyMultiStateControlledRotateY(qureg, controls, nullptr, numControls, target, angle);
1273}
1274
1275void applyMultiControlledRotateZ(Qureg qureg, int* controls, int numControls, int target, qreal angle) {
1276 validate_quregFields(qureg, __func__);
1277 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
1278
1279 // harmlessly re-validates
1280 applyMultiStateControlledRotateZ(qureg, controls, nullptr, numControls, target, angle);
1281}
1282
1283void applyMultiStateControlledRotateX(Qureg qureg, int* controls, int* states, int numControls, int target, qreal angle) {
1284 validate_quregFields(qureg, __func__);
1285 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
1286 validate_controlStates(states, numControls, __func__); // permits states==nullptr
1287
1288 // harmlessly re-validates
1289 applyMultiStateControlledPauliGadget(qureg, controls, states, numControls, getPauliStr("X", {target}), angle);
1290}
1291
1292void applyMultiStateControlledRotateY(Qureg qureg, int* controls, int* states, int numControls, int target, qreal angle) {
1293 validate_quregFields(qureg, __func__);
1294 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
1295 validate_controlStates(states, numControls, __func__); // permits states==nullptr
1296
1297 // harmlessly re-validates
1298 applyMultiStateControlledPauliGadget(qureg, controls, states, numControls, getPauliStr("Y", {target}), angle);
1299}
1300
1301void applyMultiStateControlledRotateZ(Qureg qureg, int* controls, int* states, int numControls, int target, qreal angle) {
1302 validate_quregFields(qureg, __func__);
1303 validate_controlsAndTarget(qureg, controls, numControls, target, __func__);
1304 validate_controlStates(states, numControls, __func__); // permits states==nullptr
1305
1306 // harmlessly re-validates
1307 applyMultiStateControlledPauliGadget(qureg, controls, states, numControls, getPauliStr("Z", {target}), angle);
1308}
1309
1310} // end de-mangler
1311
1312void applyMultiControlledRotateX(Qureg qureg, vector<int> controls, int target, qreal angle) {
1313
1314 applyMultiControlledRotateX(qureg, controls.data(), controls.size(), target, angle);
1315}
1316
1317void applyMultiControlledRotateY(Qureg qureg, vector<int> controls, int target, qreal angle) {
1318
1319 applyMultiControlledRotateY(qureg, controls.data(), controls.size(), target, angle);
1320}
1321
1322void applyMultiControlledRotateZ(Qureg qureg, vector<int> controls, int target, qreal angle) {
1323
1324 applyMultiControlledRotateZ(qureg, controls.data(), controls.size(), target, angle);
1325}
1326
1327void applyMultiStateControlledRotateX(Qureg qureg, vector<int> controls, vector<int> states, int target, qreal angle) {
1328 validate_controlsMatchStates(controls.size(), states.size(), __func__);
1329
1330 applyMultiStateControlledRotateX(qureg, controls.data(), states.data(), controls.size(), target, angle);
1331}
1332
1333void applyMultiStateControlledRotateY(Qureg qureg, vector<int> controls, vector<int> states, int target, qreal angle) {
1334 validate_controlsMatchStates(controls.size(), states.size(), __func__);
1335
1336 applyMultiStateControlledRotateY(qureg, controls.data(), states.data(), controls.size(), target, angle);
1337}
1338
1339void applyMultiStateControlledRotateZ(Qureg qureg, vector<int> controls, vector<int> states, int target, qreal angle) {
1340 validate_controlsMatchStates(controls.size(), states.size(), __func__);
1341
1342 applyMultiStateControlledRotateZ(qureg, controls.data(), states.data(), controls.size(), target, angle);
1343}
1344
1345
1346
1347/*
1348 * arbitrary axis rotation
1349 */
1350
1351extern "C" {
1352
1353void applyRotateAroundAxis(Qureg qureg, int targ, qreal angle, qreal axisX, qreal axisY, qreal axisZ) {
1354 validate_quregFields(qureg, __func__);
1355 validate_target(qureg, targ, __func__);
1356 validate_rotationAxisNotZeroVector(axisX, axisY, axisZ, __func__);
1357
1358 applyMultiStateControlledRotateAroundAxis(qureg, nullptr, nullptr, 0, targ, angle, axisX, axisY, axisZ);
1359}
1360
1361void applyControlledRotateAroundAxis(Qureg qureg, int ctrl, int targ, qreal angle, qreal axisX, qreal axisY, qreal axisZ) {
1362 validate_quregFields(qureg, __func__);
1363 validate_controlAndTarget(qureg, ctrl, targ, __func__);
1364 validate_rotationAxisNotZeroVector(axisX, axisY, axisZ, __func__);
1365
1366 applyMultiStateControlledRotateAroundAxis(qureg, &ctrl, nullptr, 1, targ, angle, axisX, axisY, axisZ);
1367}
1368
1369void applyMultiControlledRotateAroundAxis(Qureg qureg, int* ctrls, int numCtrls, int targ, qreal angle, qreal axisX, qreal axisY, qreal axisZ) {
1370 validate_quregFields(qureg, __func__);
1371 validate_controlsAndTarget(qureg, ctrls, numCtrls, targ, __func__);
1372 validate_rotationAxisNotZeroVector(axisX, axisY, axisZ, __func__);
1373
1374 applyMultiStateControlledRotateAroundAxis(qureg, ctrls, nullptr, numCtrls, targ, angle, axisX, axisY, axisZ);
1375}
1376
1377void applyMultiStateControlledRotateAroundAxis(Qureg qureg, int* ctrls, int* states, int numCtrls, int targ, qreal angle, qreal axisX, qreal axisY, qreal axisZ) {
1378 validate_quregFields(qureg, __func__);
1379 validate_controlsAndTarget(qureg, ctrls, numCtrls, targ, __func__);
1380 validate_controlStates(states, numCtrls, __func__); // permits states==nullptr
1381 validate_rotationAxisNotZeroVector(axisX, axisY, axisZ, __func__);
1382
1383 // defer division of vector norm to improve numerical accuracy
1384 qreal norm = std::sqrt(std::pow(axisX,2) + std::pow(axisY,2) + std::pow(axisZ,2)); // != 0
1385
1386 // treat as generic 1-qubit matrix
1387 qreal c = std::cos(angle/2);
1388 qreal s = std::sin(angle/2);
1389 qcomp u11 = c - (s * axisZ * 1_i) / norm;
1390 qcomp u12 = - (s * (axisY + axisX * 1_i)) / norm;
1391 qcomp u21 = (s * (axisY - axisX * 1_i)) / norm;
1392 qcomp u22 = c + (s * axisZ * 1_i) / norm;
1393 auto matr = getCompMatr1({{u11,u12},{u21,u22}});
1394
1395 // harmlessly re-validates, and checks unitarity of matr
1396 applyMultiStateControlledCompMatr1(qureg, ctrls, states, numCtrls, targ, matr);
1397}
1398
1399} // end de-mangler
1400
1401void applyMultiControlledRotateAroundAxis(Qureg qureg, vector<int> ctrls, int targ, qreal angle, qreal axisX, qreal axisY, qreal axisZ) {
1402
1403 applyMultiControlledRotateAroundAxis(qureg, ctrls.data(), ctrls.size(), targ, angle, axisX, axisY, axisZ);
1404}
1405
1406void applyMultiStateControlledRotateAroundAxis(Qureg qureg, vector<int> ctrls, vector<int> states, int targ, qreal angle, qreal axisX, qreal axisY, qreal axisZ) {
1407 validate_controlsMatchStates(ctrls.size(), states.size(), __func__);
1408
1409 applyMultiStateControlledRotateAroundAxis(qureg, ctrls.data(), states.data(), ctrls.size(), targ, angle, axisX, axisY, axisZ);
1410}
1411
1412
1413
1414/*
1415 * Pauli gadgets
1416 */
1417
1418extern "C" {
1419
1420void multiplyPauliGadget(Qureg qureg, PauliStr str, qreal angle) {
1421 validate_quregFields(qureg, __func__);
1422 validate_pauliStrTargets(qureg, str, __func__);
1423
1424 qreal phase = util_getPhaseFromGateAngle(angle);
1425 localiser_statevec_anyCtrlPauliGadget(qureg, {}, {}, str, phase);
1426}
1427
1428void applyPauliGadget(Qureg qureg, PauliStr str, qreal angle) {
1429 validate_quregFields(qureg, __func__);
1430 validate_pauliStrTargets(qureg, str, __func__);
1431
1432 applyMultiStateControlledPauliGadget(qureg, nullptr, nullptr, 0, str, angle);
1433}
1434
1435void applyControlledPauliGadget(Qureg qureg, int control, PauliStr str, qreal angle) {
1436 validate_quregFields(qureg, __func__);
1437 validate_controlAndPauliStrTargets(qureg, control, str, __func__);
1438
1439 applyMultiStateControlledPauliGadget(qureg, &control, nullptr, 1, str, angle);
1440}
1441
1442void applyMultiControlledPauliGadget(Qureg qureg, int* controls, int numControls, PauliStr str, qreal angle) {
1443 validate_quregFields(qureg, __func__);
1444 validate_controlsAndPauliStrTargets(qureg, controls, numControls, str, __func__);
1445
1446 applyMultiStateControlledPauliGadget(qureg, controls, nullptr, numControls, str, angle);
1447}
1448
1449void applyMultiStateControlledPauliGadget(Qureg qureg, int* controls, int* states, int numControls, PauliStr str, qreal angle) {
1450 validate_quregFields(qureg, __func__);
1451 validate_controlsAndPauliStrTargets(qureg, controls, numControls, str, __func__);
1452 validate_controlStates(states, numControls, __func__); // permits states==nullptr
1453
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
1463
1464 qreal phase = util_getPhaseFromGateAngle(angle);
1465 auto ctrlVec = util_getVector(controls, numControls);
1466 auto stateVec = util_getVector(states, numControls); // empty if states==nullptr
1467 localiser_statevec_anyCtrlPauliGadget(qureg, ctrlVec, stateVec, str, phase);
1468
1469 if (!qureg.isDensityMatrix)
1470 return;
1471
1472 // conj(e^iXZ) = e^(-iXZ), but conj(Y)=-Y, so odd-Y undoes phase negation
1473 phase *= paulis_hasOddNumY(str) ? 1 : -1;
1474 ctrlVec = util_getBraQubits(ctrlVec, qureg);
1475 str = paulis_getShiftedPauliStr(str, qureg.numQubits);
1476 localiser_statevec_anyCtrlPauliGadget(qureg, ctrlVec, stateVec, str, phase);
1477}
1478
1479} // end de-mangler
1480
1481void applyMultiControlledPauliGadget(Qureg qureg, vector<int> controls, PauliStr str, qreal angle) {
1482
1483 applyMultiControlledPauliGadget(qureg, controls.data(), controls.size(), str, angle);
1484}
1485
1486void applyMultiStateControlledPauliGadget(Qureg qureg, vector<int> controls, vector<int> states, PauliStr str, qreal angle) {
1487 validate_controlsMatchStates(controls.size(), states.size(), __func__);
1488
1489 applyMultiStateControlledPauliGadget(qureg, controls.data(), states.data(), controls.size(), str, angle);
1490}
1491
1492
1493
1494/*
1495 * phase gadgets
1496 */
1497
1498extern "C" {
1499
1500void multiplyPhaseGadget(Qureg qureg, int* targets, int numTargets, qreal angle) {
1501 validate_quregFields(qureg, __func__);
1502 validate_targets(qureg, targets, numTargets, __func__);
1503
1504 qreal phase = util_getPhaseFromGateAngle(angle);
1505 localiser_statevec_anyCtrlPhaseGadget(qureg, {}, {}, util_getVector(targets,numTargets), phase);
1506}
1507
1508void applyPhaseGadget(Qureg qureg, int* targets, int numTargets, qreal angle) {
1509 validate_quregFields(qureg, __func__);
1510 validate_targets(qureg, targets, numTargets, __func__);
1511
1512 // harmlessly re-validates
1513 applyMultiStateControlledPhaseGadget(qureg, nullptr, nullptr, 0, targets, numTargets, angle);
1514}
1515
1516void applyControlledPhaseGadget(Qureg qureg, int control, int* targets, int numTargets, qreal angle) {
1517 validate_quregFields(qureg, __func__);
1518 validate_controlAndTargets(qureg, control, targets, numTargets, __func__);
1519
1520 // harmlessly re-validates
1521 applyMultiStateControlledPhaseGadget(qureg, &control, nullptr, 1, targets, numTargets, angle);
1522}
1523
1524void applyMultiControlledPhaseGadget(Qureg qureg, int* controls, int numControls, int* targets, int numTargets, qreal angle) {
1525 validate_quregFields(qureg, __func__);
1526 validate_controlsAndTargets(qureg, controls, numControls, targets, numTargets, __func__);
1527
1528 // harmlessly re-validates
1529 applyMultiStateControlledPhaseGadget(qureg, controls, nullptr, numControls, targets, numTargets, angle);
1530}
1531
1532void applyMultiStateControlledPhaseGadget(Qureg qureg, int* controls, int* states, int numControls, int* targets, int numTargets, qreal angle) {
1533 validate_quregFields(qureg, __func__);
1534 validate_controlsAndTargets(qureg, controls, numControls, targets, numTargets, __func__);
1535 validate_controlStates(states, numControls, __func__);
1536
1537 qreal phase = util_getPhaseFromGateAngle(angle);
1538 auto ctrlVec = util_getVector(controls, numControls);
1539 auto targVec = util_getVector(targets, numTargets);
1540 auto stateVec = util_getVector(states, numControls); // empty if states==nullptr
1541 localiser_statevec_anyCtrlPhaseGadget(qureg, ctrlVec, stateVec, targVec, phase);
1542
1543 if (!qureg.isDensityMatrix)
1544 return;
1545
1546 phase *= -1;
1547 ctrlVec = util_getBraQubits(ctrlVec, qureg);
1548 targVec = util_getBraQubits(targVec, qureg);
1549 localiser_statevec_anyCtrlPhaseGadget(qureg, ctrlVec, stateVec, targVec, phase);
1550}
1551
1552} // end de-mangler
1553
1554void multiplyPhaseGadget(Qureg qureg, vector<int> targets, qreal angle) {
1555
1556 multiplyPhaseGadget(qureg, targets.data(), targets.size(), angle);
1557}
1558
1559void applyPhaseGadget(Qureg qureg, vector<int> targets, qreal angle) {
1560
1561 applyPhaseGadget(qureg, targets.data(), targets.size(), angle);
1562}
1563
1564void applyControlledPhaseGadget(Qureg qureg, int control, vector<int> targets, qreal angle) {
1565
1566 applyControlledPhaseGadget(qureg, control, targets.data(), targets.size(), angle);
1567}
1568
1569void applyMultiControlledPhaseGadget(Qureg qureg, vector<int> controls, vector<int> targets, qreal angle) {
1570
1571 applyMultiControlledPhaseGadget(qureg, controls.data(), controls.size(), targets.data(), targets.size(), angle);
1572}
1573
1574void applyMultiStateControlledPhaseGadget(Qureg qureg, vector<int> controls, vector<int> states, vector<int> targets, qreal angle) {
1575 validate_controlsMatchStates(controls.size(), states.size(), __func__);
1576
1577 applyMultiStateControlledPhaseGadget(qureg, controls.data(), states.data(), controls.size(), targets.data(), targets.size(), angle);
1578}
1579
1580
1581
1582/*
1583 * phase shift
1584 */
1585
1586extern "C" {
1587
1588void applyPhaseShift(Qureg qureg, int target, qreal angle) {
1589 validate_quregFields(qureg, __func__);
1590 validate_target(qureg, target, __func__);
1591
1592 // harmlessly re-validates
1593 applyMultiQubitPhaseShift(qureg, &target, 1, angle);
1594}
1595
1596void applyTwoQubitPhaseShift(Qureg qureg, int target1, int target2, qreal angle) {
1597 validate_quregFields(qureg, __func__);
1598 validate_twoTargets(qureg, target1, target2, __func__);
1599
1600 // harmlessly re-validates
1601 int targets[] = {target1, target2};
1602 applyMultiQubitPhaseShift(qureg, targets, 2, angle);
1603}
1604
1605void applyMultiQubitPhaseShift(Qureg qureg, int* targets, int numTargets, qreal angle) {
1606 validate_quregFields(qureg, __func__);
1607 validate_targets(qureg, targets, numTargets, __func__);
1608
1609 // treat as a (numTargets-1)-controlled 1-target diagonal matrix
1610 DiagMatr1 matr = getDiagMatr1({1, std::exp(1_i * angle)});
1611
1612 // harmlessly re-validates
1613 applyMultiStateControlledDiagMatr1(qureg, &targets[1], nullptr, numTargets-1, targets[0], matr);
1614}
1615
1616} // end de-mangler
1617
1618void applyMultiQubitPhaseShift(Qureg qureg, vector<int> targets, qreal angle) {
1619
1620 applyMultiQubitPhaseShift(qureg, targets.data(), targets.size(), angle);
1621}
1622
1623
1624
1625/*
1626 * phase flips
1627 */
1628
1629extern "C" {
1630
1631void applyPhaseFlip(Qureg qureg, int target) {
1632 validate_quregFields(qureg, __func__);
1633 validate_target(qureg, target, __func__);
1634
1635 // harmlessly re-validates
1636 applyMultiQubitPhaseFlip(qureg, &target, 1);
1637}
1638
1639void applyTwoQubitPhaseFlip(Qureg qureg, int target1, int target2) {
1640 validate_quregFields(qureg, __func__);
1641 validate_twoTargets(qureg, target1, target2, __func__);
1642
1643 // harmlessly re-validates
1644 int targets[] = {target1, target2};
1645 applyMultiQubitPhaseFlip(qureg, targets, 2);
1646}
1647
1648void applyMultiQubitPhaseFlip(Qureg qureg, int* targets, int numTargets) {
1649 validate_quregFields(qureg, __func__);
1650 validate_targets(qureg, targets, numTargets, __func__);
1651
1652 // treat as a (numTargets-1)-controlled 1-target Pauli Z
1653 DiagMatr1 matr = getDiagMatr1({1, -1});
1654
1655 // harmlessly re-validates
1656 applyMultiStateControlledDiagMatr1(qureg, &targets[1], nullptr, numTargets-1, targets[0], matr);
1657}
1658
1659} // end de-mangler
1660
1661void applyMultiQubitPhaseFlip(Qureg qureg, vector<int> targets) {
1662
1663 applyMultiQubitPhaseFlip(qureg, targets.data(), targets.size());
1664}
1665
1666
1667
1668/*
1669 * many-qubit CNOTs
1670 */
1671
1672extern "C" {
1673
1674void multiplyMultiQubitNot(Qureg qureg, int* targets, int numTargets) {
1675 validate_quregFields(qureg, __func__);
1676 validate_targets(qureg, targets, numTargets, __func__);
1677
1678 // harmlessly re-validates
1679 multiplyPauliStr(qureg, getPauliStr(std::string(numTargets, 'X'), targets, numTargets));
1680}
1681
1682void applyMultiQubitNot(Qureg qureg, int* targets, int numTargets) {
1683 validate_quregFields(qureg, __func__);
1684 validate_targets(qureg, targets, numTargets, __func__);
1685
1686 // harmlessly re-validates
1687 applyMultiStateControlledMultiQubitNot(qureg, nullptr, nullptr, 0, targets, numTargets);
1688}
1689
1690void applyControlledMultiQubitNot(Qureg qureg, int control, int* targets, int numTargets) {
1691 validate_quregFields(qureg, __func__);
1692 validate_controlAndTargets(qureg, control, targets, numTargets, __func__);
1693
1694 // harmlessly re-validates
1695 applyMultiStateControlledMultiQubitNot(qureg, &control, nullptr, 1, targets, numTargets);
1696}
1697
1698void applyMultiControlledMultiQubitNot(Qureg qureg, int* controls, int numControls, int* targets, int numTargets) {
1699 validate_quregFields(qureg, __func__);
1700 validate_controlsAndTargets(qureg, controls, numControls, targets, numTargets, __func__);
1701
1702 // harmlessly re-validates
1703 applyMultiStateControlledMultiQubitNot(qureg, controls, nullptr, numControls, targets, numTargets);
1704}
1705
1706void applyMultiStateControlledMultiQubitNot(Qureg qureg, int* controls, int* states, int numControls, int* targets, int numTargets) {
1707 validate_quregFields(qureg, __func__);
1708 validate_controlsAndTargets(qureg, controls, numControls, targets, numTargets, __func__);
1709 validate_controlStates(states, numControls, __func__);
1710
1711 // treat as an all-X PauliStr
1712 PauliStr str = getPauliStr(std::string(numTargets, 'X'), targets, numTargets);
1713
1714 // harmlessly re-validates
1715 applyMultiStateControlledPauliStr(qureg, controls, states, numControls, str);
1716}
1717
1718} // end de-mangler
1719
1720void multiplyMultiQubitNot(Qureg qureg, vector<int> targets) {
1721
1722 multiplyMultiQubitNot(qureg, targets.data(), targets.size());
1723}
1724
1725void applyMultiQubitNot(Qureg qureg, vector<int> targets) {
1726
1727 applyMultiQubitNot(qureg, targets.data(), targets.size());
1728}
1729
1730void applyControlledMultiQubitNot(Qureg qureg, int control, vector<int> targets) {
1731
1732 applyControlledMultiQubitNot(qureg, control, targets.data(), targets.size());
1733}
1734
1735void applyMultiControlledMultiQubitNot(Qureg qureg, vector<int> controls, vector<int> targets) {
1736
1737 applyMultiControlledMultiQubitNot(qureg, controls.data(), controls.size(), targets.data(), targets.size());
1738}
1739
1740void applyMultiStateControlledMultiQubitNot(Qureg qureg, vector<int> controls, vector<int> states, vector<int> targets) {
1741 validate_controlsMatchStates(controls.size(), states.size(), __func__);
1742
1743 applyMultiStateControlledMultiQubitNot(qureg, controls.data(), states.data(), controls.size(), targets.data(), targets.size());
1744}
1745
1746
1747
1748/*
1749 * projectors
1750 */
1751
1752extern "C" {
1753
1754void applyQubitProjector(Qureg qureg, int target, int outcome) {
1755 validate_quregFields(qureg, __func__);
1756 validate_target(qureg, target, __func__);
1757 validate_measurementOutcomeIsValid(outcome, __func__);
1758
1759 // we permit the outcome to be negligibly likely, leaving state = null
1760 qreal prob = 1;
1761 (qureg.isDensityMatrix)?
1762 localiser_densmatr_multiQubitProjector(qureg, {target}, {outcome}, prob):
1763 localiser_statevec_multiQubitProjector(qureg, {target}, {outcome}, prob);
1764}
1765
1766void applyMultiQubitProjector(Qureg qureg, int* qubits, int* outcomes, int numQubits) {
1767 validate_quregFields(qureg, __func__);
1768 validate_targets(qureg, qubits, numQubits, __func__);
1769 validate_measurementOutcomesAreValid(outcomes, numQubits, __func__);
1770
1771 qreal prob = 1;
1772 auto qubitVec = util_getVector(qubits, numQubits);
1773 auto outcomeVec = util_getVector(outcomes, numQubits);
1774
1775 (qureg.isDensityMatrix)?
1776 localiser_densmatr_multiQubitProjector(qureg, qubitVec, outcomeVec, prob):
1777 localiser_statevec_multiQubitProjector(qureg, qubitVec, outcomeVec, prob);
1778}
1779
1780} // end de-mangler
1781
1782void applyMultiQubitProjector(Qureg qureg, vector<int> qubits, vector<int> outcomes) {
1783 validate_measurementOutcomesMatchTargets(qubits.size(), outcomes.size(), __func__);
1784
1785 applyMultiQubitProjector(qureg, qubits.data(), outcomes.data(), outcomes.size());
1786}
1787
1788
1789
1790/*
1791 * measurement
1792 */
1793
1794extern "C" {
1795
1796int applyQubitMeasurement(Qureg qureg, int target) {
1797 validate_quregFields(qureg, __func__);
1798 validate_target(qureg, target, __func__);
1799
1800 qreal prob = 0; // ignored
1801 return applyQubitMeasurementAndGetProb(qureg, target, &prob); // harmlessly re-validates
1802}
1803
1804int applyQubitMeasurementAndGetProb(Qureg qureg, int target, qreal* probability) {
1805 validate_quregFields(qureg, __func__);
1806 validate_target(qureg, target, __func__);
1807
1808 // we do not assume state normalisation (that is posteriori checked),
1809 // so we must perform two reductions; one for each outcome. We choose
1810 // to re-enumerate the state (potentially doubling caching costs) to
1811 // avoid the nuisances/race-cons of parallel adding to two scalars.
1812 vector<qreal> probs(2);
1813 probs[0] = calcProbOfQubitOutcome(qureg, target, 0); // harmlessly re-validates
1814 probs[1] = calcProbOfQubitOutcome(qureg, target, 1); // " "
1815 validate_measurementProbsAreNormalised(probs, __func__);
1816
1817 // randomly choose the outcome
1818 int outcome = rand_getRandomSingleQubitOutcome(probs[0]);
1819 *probability = probs[outcome];
1820
1821 // collapse to the outcome
1822 (qureg.isDensityMatrix)?
1823 localiser_densmatr_multiQubitProjector(qureg, {target}, {outcome}, *probability):
1824 localiser_statevec_multiQubitProjector(qureg, {target}, {outcome}, *probability);
1825
1826 return outcome;
1827}
1828
1829qreal applyForcedQubitMeasurement(Qureg qureg, int target, int outcome) {
1830 validate_quregFields(qureg, __func__);
1831 validate_target(qureg, target, __func__);
1832 validate_measurementOutcomeIsValid(outcome, __func__);
1833
1834 // note that we do not merely invoke applyForcedMultiQubitMeasurement()
1835 // because we must validate the renormalising probability and
1836 // report this function's name during the error message
1837 qreal prob = calcProbOfQubitOutcome(qureg, target, outcome); // harmlessly re-validates
1838 validate_measurementOutcomeProbNotZero(outcome, prob, __func__);
1839
1840 // project to the outcome, renormalising the surviving states
1841 (qureg.isDensityMatrix)?
1842 localiser_densmatr_multiQubitProjector(qureg, {target}, {outcome}, prob):
1843 localiser_statevec_multiQubitProjector(qureg, {target}, {outcome}, prob);
1844
1845 return prob;
1846}
1847
1848qindex applyMultiQubitMeasurement(Qureg qureg, int* qubits, int numQubits) {
1849 validate_quregFields(qureg, __func__);
1850 validate_targets(qureg, qubits, numQubits, __func__);
1851
1852 qreal prob = 0; // ignored
1853
1854 // below validates post-measurement and would report 'AndGetProb' function suffix. Eh!
1855 return applyMultiQubitMeasurementAndGetProb(qureg, qubits, numQubits, &prob);
1856}
1857
1858qindex applyMultiQubitMeasurementAndGetProb(Qureg qureg, int* qubits, int numQubits, qreal* probability) {
1859 validate_quregFields(qureg, __func__);
1860 validate_targets(qureg, qubits, numQubits, __func__);
1861
1862 // find the probability of all possible outcomes...
1863 qindex numProbs = powerOf2(numQubits);
1864
1865 // by allocating a temp vector, and validating successful (since exponentially big!)
1866 vector<qreal> probs;
1867 auto callback = [&]() { validate_tempAllocSucceeded(false, numProbs, sizeof(qreal), __func__); };
1868 util_tryAllocVector(probs, numProbs, callback);
1869
1870 // populate probs
1871 calcProbsOfAllMultiQubitOutcomes(probs.data(), qureg, qubits, numQubits); // harmlessly re-validates
1872
1873 // we cannot meaningfully sample these probs if not normalised
1874 validate_measurementProbsAreNormalised(probs, __func__);
1875
1876 // randomly choose an outcome
1877 qindex outcome = rand_getRandomMultiQubitOutcome(probs);
1878 *probability = probs[outcome];
1879
1880 // map outcome to individual qubit outcomes
1881 auto qubitVec = util_getVector(qubits, numQubits);
1882 auto outcomeVec = vector<int>(numQubits);
1883 getBitsFromInteger(outcomeVec.data(), outcome, numQubits);
1884
1885 // project to the outcomes, renormalising the surviving states
1886 (qureg.isDensityMatrix)?
1887 localiser_densmatr_multiQubitProjector(qureg, qubitVec, outcomeVec, *probability):
1888 localiser_statevec_multiQubitProjector(qureg, qubitVec, outcomeVec, *probability);
1889
1890 return outcome;
1891}
1892
1893qreal applyForcedMultiQubitMeasurement(Qureg qureg, int* qubits, int* outcomes, int numQubits) {
1894 validate_quregFields(qureg, __func__);
1895 validate_targets(qureg, qubits, numQubits, __func__);
1896 validate_measurementOutcomesAreValid(outcomes, numQubits, __func__);
1897
1898 auto qubitVec = util_getVector(qubits, numQubits);
1899 auto outcomeVec = util_getVector(outcomes, numQubits);
1900
1901 // ensure probability of the forced measurement outcome is not negligible
1902 qreal prob = calcProbOfMultiQubitOutcome(qureg, qubits, outcomes, numQubits); // harmlessly re-validates
1903 validate_measurementOutcomesProbNotZero(outcomes, numQubits, prob, __func__);
1904
1905 // project to the outcome, renormalising the surviving states
1906 (qureg.isDensityMatrix)?
1907 localiser_densmatr_multiQubitProjector(qureg, qubitVec, outcomeVec, prob):
1908 localiser_statevec_multiQubitProjector(qureg, qubitVec, outcomeVec, prob);
1909
1910 return prob;
1911}
1912
1913} // end de-mangler
1914
1915qindex applyMultiQubitMeasurementAndGetProb(Qureg qureg, vector<int> qubits, qreal* probability) {
1916
1917 return applyMultiQubitMeasurementAndGetProb(qureg, qubits.data(), qubits.size(), probability);
1918}
1919
1920qreal applyForcedMultiQubitMeasurement(Qureg qureg, vector<int> qubits, vector<int> outcomes) {
1921 validate_measurementOutcomesMatchTargets(qubits.size(), outcomes.size(), __func__);
1922
1923 return applyForcedMultiQubitMeasurement(qureg, qubits.data(), outcomes.data(), outcomes.size());
1924}
1925
1926
1927
1928/*
1929 * QFT
1930 */
1931
1932extern "C" {
1933
1934void applyQuantumFourierTransform(Qureg qureg, int* targets, int numTargets) {
1935 validate_quregFields(qureg, __func__);
1936 validate_targets(qureg, targets, numTargets, __func__);
1937
1938 /// @todo
1939 /// change this placeholder implementation to the bespoke, optimised routine,
1940 /// wherein each contiguous controlled-phase gate is merged
1941
1942 for (int n=numTargets-1; n>=0; n--) {
1943 applyHadamard(qureg, targets[n]);
1944 for (int m=0; m<n; m++) {
1945 qreal arg = const_PI / powerOf2(m+1);
1946 applyTwoQubitPhaseShift(qureg, targets[n], targets[n-m-1], arg);
1947 }
1948 }
1949
1950 int mid = numTargets/2; // floors
1951 for (int n=0; n<mid; n++)
1952 applySwap(qureg, targets[n], targets[numTargets-1-n]);
1953}
1954
1956 validate_quregFields(qureg, __func__);
1957
1958 // tiny; no need to validate alloc
1959 vector<int> targets(qureg.numQubits);
1960 for (size_t i=0; i<targets.size(); i++)
1961 targets[i] = i;
1962
1963 applyQuantumFourierTransform(qureg, targets.data(), targets.size());
1964}
1965
1966} // end de-mangler
1967
1968void applyQuantumFourierTransform(Qureg qureg, vector<int> targets) {
1969
1970 applyQuantumFourierTransform(qureg, targets.data(), targets.size());
1971}
qreal calcProbOfQubitOutcome(Qureg qureg, int qubit, int outcome)
void calcProbsOfAllMultiQubitOutcomes(qreal *outcomeProbs, Qureg qureg, int *qubits, int numQubits)
qreal calcProbOfMultiQubitOutcome(Qureg qureg, int *qubits, int *outcomes, int numQubits)
static CompMatr2 getCompMatr2(qcomp **in)
Definition matrices.h:351
static CompMatr1 getCompMatr1(qcomp **in)
Definition matrices.h:325
static DiagMatr1 getDiagMatr1(qcomp *in)
Definition matrices.h:378
void applyCompMatr1(Qureg qureg, int target, CompMatr1 matrix)
void multiplyCompMatr1(Qureg qureg, int target, CompMatr1 matrix)
void applyMultiControlledCompMatr1(Qureg qureg, int *controls, int numControls, int target, CompMatr1 matrix)
void applyControlledCompMatr1(Qureg qureg, int control, int target, CompMatr1 matrix)
void applyMultiStateControlledCompMatr1(Qureg qureg, int *controls, int *states, int numControls, int target, CompMatr1 matrix)
void applyMultiStateControlledCompMatr2(Qureg qureg, int *controls, int *states, int numControls, int target1, int target2, CompMatr2 matrix)
void multiplyCompMatr2(Qureg qureg, int target1, int target2, CompMatr2 matrix)
void applyMultiControlledCompMatr2(Qureg qureg, int *controls, int numControls, int target1, int target2, CompMatr2 matrix)
void applyCompMatr2(Qureg qureg, int target1, int target2, CompMatr2 matrix)
void applyControlledCompMatr2(Qureg qureg, int control, int target1, int target2, CompMatr2 matrix)
void applyMultiStateControlledCompMatr(Qureg qureg, int *controls, int *states, int numControls, int *targets, int numTargets, CompMatr matrix)
void multiplyCompMatr(Qureg qureg, int *targets, int numTargets, CompMatr matrix)
void applyMultiControlledCompMatr(Qureg qureg, int *controls, int numControls, int *targets, int numTargets, CompMatr matrix)
void applyControlledCompMatr(Qureg qureg, int control, int *targets, int numTargets, CompMatr matrix)
void applyCompMatr(Qureg qureg, int *targets, int numTargets, CompMatr matrix)
void applyControlledDiagMatr1(Qureg qureg, int control, int target, DiagMatr1 matrix)
void multiplyDiagMatr1(Qureg qureg, int target, DiagMatr1 matrix)
void applyDiagMatr1(Qureg qureg, int target, DiagMatr1 matrix)
void applyMultiStateControlledDiagMatr1(Qureg qureg, int *controls, int *states, int numControls, int target, DiagMatr1 matrix)
void applyMultiControlledDiagMatr1(Qureg qureg, int *controls, int numControls, int target, DiagMatr1 matrix)
void applyMultiStateControlledDiagMatr2(Qureg qureg, int *controls, int *states, int numControls, int target1, int target2, DiagMatr2 matrix)
void applyMultiControlledDiagMatr2(Qureg qureg, int *controls, int numControls, int target1, int target2, DiagMatr2 matrix)
void applyDiagMatr2(Qureg qureg, int target1, int target2, DiagMatr2 matrix)
void applyControlledDiagMatr2(Qureg qureg, int control, int target1, int target2, DiagMatr2 matrix)
void multiplyDiagMatr2(Qureg qureg, int target1, int target2, DiagMatr2 matrix)
void multiplyDiagMatr(Qureg qureg, int *targets, int numTargets, DiagMatr matrix)
void multiplyDiagMatrPower(Qureg qureg, int *targets, int numTargets, DiagMatr matrix, qcomp exponent)
void applyDiagMatr(Qureg qureg, int *targets, int numTargets, DiagMatr matrix)
void applyMultiControlledDiagMatrPower(Qureg qureg, int *controls, int numControls, int *targets, int numTargets, DiagMatr matrix, qcomp exponent)
void applyMultiStateControlledDiagMatrPower(Qureg qureg, int *controls, int *states, int numControls, int *targets, int numTargets, DiagMatr matrix, qcomp exponent)
void applyDiagMatrPower(Qureg qureg, int *targets, int numTargets, DiagMatr matrix, qcomp exponent)
void applyControlledDiagMatr(Qureg qureg, int control, int *targets, int numTargets, DiagMatr matrix)
void applyMultiControlledDiagMatr(Qureg qureg, int *controls, int numControls, int *targets, int numTargets, DiagMatr matrix)
void applyControlledDiagMatrPower(Qureg qureg, int control, int *targets, int numTargets, DiagMatr matrix, qcomp exponent)
void applyMultiStateControlledDiagMatr(Qureg qureg, int *controls, int *states, int numControls, int *targets, int numTargets, DiagMatr matrix)
void applyControlledT(Qureg qureg, int control, int target)
void applyControlledS(Qureg qureg, int control, int target)
void applyMultiStateControlledHadamard(Qureg qureg, int *controls, int *states, int numControls, int target)
void applyMultiControlledHadamard(Qureg qureg, int *controls, int numControls, int target)
void applyS(Qureg qureg, int target)
void applyMultiControlledT(Qureg qureg, int *controls, int numControls, int target)
void applyMultiControlledS(Qureg qureg, int *controls, int numControls, int target)
void applyT(Qureg qureg, int target)
void applyMultiStateControlledS(Qureg qureg, int *controls, int *states, int numControls, int target)
void applyHadamard(Qureg qureg, int target)
void applyControlledHadamard(Qureg qureg, int control, int target)
void applyMultiStateControlledT(Qureg qureg, int *controls, int *states, int numControls, int target)
void applyFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matrix)
void multiplyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent)
void applyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent)
void multiplyFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matrix)
qreal applyForcedQubitMeasurement(Qureg qureg, int target, int outcome)
qindex applyMultiQubitMeasurement(Qureg qureg, int *qubits, int numQubits)
int applyQubitMeasurement(Qureg qureg, int target)
qreal applyForcedMultiQubitMeasurement(Qureg qureg, int *qubits, int *outcomes, int numQubits)
qindex applyMultiQubitMeasurementAndGetProb(Qureg qureg, int *qubits, int numQubits, qreal *probability)
int applyQubitMeasurementAndGetProb(Qureg qureg, int target, qreal *probability)
void applyMultiStateControlledMultiQubitNot(Qureg qureg, int *controls, int *states, int numControls, int *targets, int numTargets)
void multiplyMultiQubitNot(Qureg qureg, int *targets, int numTargets)
void applyMultiControlledMultiQubitNot(Qureg qureg, int *controls, int numControls, int *targets, int numTargets)
void applyMultiQubitNot(Qureg qureg, int *targets, int numTargets)
void applyControlledMultiQubitNot(Qureg qureg, int control, int *targets, int numTargets)
void applyMultiControlledPauliZ(Qureg qureg, int *controls, int numControls, int target)
void applyPauliX(Qureg qureg, int target)
void applyControlledPauliX(Qureg qureg, int control, int target)
void applyMultiStateControlledPauliY(Qureg qureg, int *controls, int *states, int numControls, int target)
void applyMultiControlledPauliY(Qureg qureg, int *controls, int numControls, int target)
void applyControlledPauliZ(Qureg qureg, int control, int target)
void applyMultiControlledPauliX(Qureg qureg, int *controls, int numControls, int target)
void applyPauliZ(Qureg qureg, int target)
void applyMultiStateControlledPauliZ(Qureg qureg, int *controls, int *states, int numControls, int target)
void applyPauliY(Qureg qureg, int target)
void applyControlledPauliY(Qureg qureg, int control, int target)
void applyMultiStateControlledPauliX(Qureg qureg, int *controls, int *states, int numControls, int target)
void applyMultiControlledPauliGadget(Qureg qureg, int *controls, int numControls, PauliStr str, qreal angle)
void multiplyPauliGadget(Qureg qureg, PauliStr str, qreal angle)
void applyControlledPauliGadget(Qureg qureg, int control, PauliStr str, qreal angle)
void applyMultiStateControlledPauliGadget(Qureg qureg, int *controls, int *states, int numControls, PauliStr str, qreal angle)
void applyPauliGadget(Qureg qureg, PauliStr str, qreal angle)
void applyMultiControlledPauliStr(Qureg qureg, int *controls, int numControls, PauliStr str)
void multiplyPauliStr(Qureg qureg, PauliStr str)
void applyPauliStr(Qureg qureg, PauliStr str)
void applyMultiStateControlledPauliStr(Qureg qureg, int *controls, int *states, int numControls, PauliStr str)
void applyControlledPauliStr(Qureg qureg, int control, PauliStr str)
void multiplyPauliStrSum(Qureg qureg, PauliStrSum sum, Qureg workspace)
void applyTrotterizedPauliStrSumGadget(Qureg qureg, PauliStrSum sum, qreal angle, int order, int reps)
void applyControlledPhaseGadget(Qureg qureg, int control, int *targets, int numTargets, qreal angle)
void applyMultiControlledPhaseGadget(Qureg qureg, int *controls, int numControls, int *targets, int numTargets, qreal angle)
void applyMultiQubitPhaseShift(Qureg qureg, int *targets, int numTargets, qreal angle)
void applyTwoQubitPhaseShift(Qureg qureg, int target1, int target2, qreal angle)
void applyTwoQubitPhaseFlip(Qureg qureg, int target1, int target2)
void applyMultiStateControlledPhaseGadget(Qureg qureg, int *controls, int *states, int numControls, int *targets, int numTargets, qreal angle)
void applyPhaseShift(Qureg qureg, int target, qreal angle)
void applyPhaseFlip(Qureg qureg, int target)
void multiplyPhaseGadget(Qureg qureg, int *targets, int numTargets, qreal angle)
void applyMultiQubitPhaseFlip(Qureg qureg, int *targets, int numTargets)
void applyPhaseGadget(Qureg qureg, int *targets, int numTargets, qreal angle)
void applyMultiQubitProjector(Qureg qureg, int *qubits, int *outcomes, int numQubits)
void applyQubitProjector(Qureg qureg, int target, int outcome)
void applyFullQuantumFourierTransform(Qureg qureg)
void applyQuantumFourierTransform(Qureg qureg, int *targets, int numTargets)
void applyMultiStateControlledRotateY(Qureg qureg, int *controls, int *states, int numControls, int target, qreal angle)
void applyControlledRotateZ(Qureg qureg, int control, int target, qreal angle)
void applyMultiControlledRotateX(Qureg qureg, int *controls, int numControls, int target, qreal angle)
void applyMultiStateControlledRotateX(Qureg qureg, int *controls, int *states, int numControls, int target, qreal angle)
void applyMultiControlledRotateZ(Qureg qureg, int *controls, int numControls, int target, qreal angle)
void applyMultiStateControlledRotateZ(Qureg qureg, int *controls, int *states, int numControls, int target, qreal angle)
void applyRotateZ(Qureg qureg, int target, qreal angle)
void applyMultiStateControlledRotateAroundAxis(Qureg qureg, int *ctrls, int *states, int numCtrls, int targ, qreal angle, qreal axisX, qreal axisY, qreal axisZ)
void applyControlledRotateX(Qureg qureg, int control, int target, qreal angle)
void applyRotateY(Qureg qureg, int target, qreal angle)
void applyRotateX(Qureg qureg, int target, qreal angle)
void applyRotateAroundAxis(Qureg qureg, int targ, qreal angle, qreal axisX, qreal axisY, qreal axisZ)
void applyMultiControlledRotateAroundAxis(Qureg qureg, int *ctrls, int numCtrls, int targ, qreal angle, qreal axisX, qreal axisY, qreal axisZ)
void applyMultiControlledRotateY(Qureg qureg, int *controls, int numControls, int target, qreal angle)
void applyControlledRotateAroundAxis(Qureg qureg, int ctrl, int targ, qreal angle, qreal axisX, qreal axisY, qreal axisZ)
void applyControlledRotateY(Qureg qureg, int control, int target, qreal angle)
void applyMultiControlledSwap(Qureg qureg, int *controls, int numControls, int qubit1, int qubit2)
void applyControlledSwap(Qureg qureg, int control, int qubit1, int qubit2)
void applyMultiStateControlledSwap(Qureg qureg, int *controls, int *states, int numControls, int qubit1, int qubit2)
void applySwap(Qureg qureg, int qubit1, int qubit2)
void applyControlledSqrtSwap(Qureg qureg, int control, int target1, int target2)
void multiplySwap(Qureg qureg, int qubit1, int qubit2)
void applySqrtSwap(Qureg qureg, int target1, int target2)
void applyMultiControlledSqrtSwap(Qureg qureg, int *controls, int numControls, int target1, int target2)
void applyMultiStateControlledSqrtSwap(Qureg qureg, int *controls, int *states, int numControls, int target1, int target2)
PauliStr getPauliStr(const char *paulis, int *indices, int numPaulis)
Definition paulis.cpp:306
Definition qureg.h:49