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