The Quantum Exact Simulation Toolkit v4.3.0
Loading...
Searching...
No Matches
multiplication.cpp
1/** @file
2 * API definitions for directly pre- and post-multiplying
3 * operators upon density matrices, likely constituting
4 * non-physical operations which break state normalisation.
5 *
6 * @author Tyson Jones
7 */
8
9#include "quest/include/qureg.h"
10#include "quest/include/paulis.h"
11#include "quest/include/matrices.h"
12#include "quest/include/multiplication.h"
13
14#include "quest/src/core/validation.hpp"
15#include "quest/src/core/lists.hpp"
16#include "quest/src/core/utilities.hpp"
17#include "quest/src/core/localiser.hpp"
18#include "quest/src/core/paulilogic.hpp"
19
20#include <vector>
21
22using std::vector;
23
24
25
26// The multiplication API doesn't accept control qubits
27// (which don't have much relevance to non-unitaries),
28// so passes ctrls={} to most internal functions; we
29// spare ourselves some keystrokes by this shortcut
30List64 none = lists_getEmptyList64();
31
32
33
34/*
35 * CompMatr1
36 */
37
38extern "C" {
39
40void leftapplyCompMatr1(Qureg qureg, int target, CompMatr1 matrix) {
41 validate_quregFields(qureg, __func__);
42 validate_target(qureg, target, __func__);
43 validate_matrixFields(matrix, __func__);
44
45 bool conj = false;
46 bool transp = false;
47 localiser_statevec_anyCtrlOneTargDenseMatr(qureg, none, none, target, matrix, conj, transp);
48}
49
50void rightapplyCompMatr1(Qureg qureg, int target, CompMatr1 matrix) {
51 validate_quregFields(qureg, __func__);
52 validate_quregIsDensityMatrix(qureg, __func__);
53 validate_target(qureg, target, __func__);
54 validate_matrixFields(matrix, __func__);
55
56 // rho matrix ~ transpose(rho) (x) I ||rho>>
57 bool conj = false;
58 bool transp = true;
59 int qubit = util_getBraQubit(target, qureg);
60 localiser_statevec_anyCtrlOneTargDenseMatr(qureg, none, none, qubit, matrix, conj, transp);
61}
62
63} // end de-mangler
64
65
66
67/*
68 * CompMatr2
69 */
70
71extern "C" {
72
73void leftapplyCompMatr2(Qureg qureg, int target1, int target2, CompMatr2 matrix) {
74 validate_quregFields(qureg, __func__);
75 validate_twoTargets(qureg, target1, target2, __func__);
76 validate_matrixFields(matrix, __func__);
77 validate_mixedAmpsFitInNode(qureg, 2, __func__);
78
79 bool conj = false;
80 bool transp = false;
81 localiser_statevec_anyCtrlTwoTargDenseMatr(qureg, none, none, target1, target2, matrix, conj, transp);
82}
83
84void rightapplyCompMatr2(Qureg qureg, int target1, int target2, CompMatr2 matrix) {
85 validate_quregFields(qureg, __func__);
86 validate_quregIsDensityMatrix(qureg, __func__);
87 validate_twoTargets(qureg, target1, target2, __func__);
88 validate_matrixFields(matrix, __func__);
89 validate_mixedAmpsFitInNode(qureg, 2, __func__);
90
91 // rho matrix ~ transpose(rho) (x) I ||rho>>
92 bool conj = false;
93 bool transp = true;
94 int qubit1 = util_getBraQubit(target1, qureg);
95 int qubit2 = util_getBraQubit(target2, qureg);
96 localiser_statevec_anyCtrlTwoTargDenseMatr(qureg, none, none, qubit1, qubit2, matrix, conj, transp);
97}
98
99} // end de-mangler
100
101
102
103/*
104 * CompMatr
105 */
106
107extern "C" {
108
109void leftapplyCompMatr(Qureg qureg, int* targets, int numTargets, CompMatr matrix) {
110 validate_quregFields(qureg, __func__);
111 validate_targets(qureg, targets, numTargets, __func__);
112 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also validates fields and is-sync
113 validate_mixedAmpsFitInNode(qureg, numTargets, __func__);
114
115 bool conj = false;
116 bool transp = false;
117 localiser_statevec_anyCtrlAnyTargDenseMatr(qureg, none, none, lists_getList64(targets, numTargets), matrix, conj, transp);
118}
119
120void rightapplyCompMatr(Qureg qureg, int* targets, int numTargets, CompMatr matrix) {
121 validate_quregFields(qureg, __func__);
122 validate_quregIsDensityMatrix(qureg, __func__);
123 validate_targets(qureg, targets, numTargets, __func__);
124 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also validates fields and is-sync
125 validate_mixedAmpsFitInNode(qureg, numTargets, __func__);
126
127 // rho matrix ~ transpose(rho) (x) I ||rho>>
128 bool conj = false;
129 bool transp = true;
130 auto qubits = util_getBraQubits(lists_getList64(targets, numTargets), qureg);
131 localiser_statevec_anyCtrlAnyTargDenseMatr(qureg, none, none, qubits, matrix, conj, transp);
132}
133
134} // end de-mangler
135
136void leftapplyCompMatr(Qureg qureg, vector<int> targets, CompMatr matr) {
137
138 leftapplyCompMatr(qureg, targets.data(), targets.size(), matr);
139}
140
141void rightapplyCompMatr(Qureg qureg, vector<int> targets, CompMatr matr) {
142
143 rightapplyCompMatr(qureg, targets.data(), targets.size(), matr);
144}
145
146
147
148/*
149 * DiagMatr1
150 */
151
152extern "C" {
153
154void leftapplyDiagMatr1(Qureg qureg, int target, DiagMatr1 matrix) {
155 validate_quregFields(qureg, __func__);
156 validate_target(qureg, target, __func__);
157 validate_matrixFields(matrix, __func__);
158
159 bool conj = false;
160 localiser_statevec_anyCtrlOneTargDiagMatr(qureg, none, none, target, matrix, conj);
161}
162
163void rightapplyDiagMatr1(Qureg qureg, int target, DiagMatr1 matrix) {
164 validate_quregFields(qureg, __func__);
165 validate_quregIsDensityMatrix(qureg, __func__);
166 validate_target(qureg, target, __func__);
167 validate_matrixFields(matrix, __func__);
168
169 bool conj = false;
170 int qubit = util_getBraQubit(target, qureg);
171 localiser_statevec_anyCtrlOneTargDiagMatr(qureg, none, none, qubit, matrix, conj);
172}
173
174} // end de-mangler
175
176
177
178/*
179 * DiagMatr2
180 */
181
182extern "C" {
183
184void leftapplyDiagMatr2(Qureg qureg, int target1, int target2, DiagMatr2 matrix) {
185 validate_quregFields(qureg, __func__);
186 validate_twoTargets(qureg, target1, target2, __func__);
187 validate_matrixFields(matrix, __func__);
188
189 bool conj = false;
190 localiser_statevec_anyCtrlTwoTargDiagMatr(qureg, none, none, target1, target2, matrix, conj);
191}
192
193void rightapplyDiagMatr2(Qureg qureg, int target1, int target2, DiagMatr2 matrix) {
194 validate_quregFields(qureg, __func__);
195 validate_quregIsDensityMatrix(qureg, __func__);
196 validate_twoTargets(qureg, target1, target2, __func__);
197 validate_matrixFields(matrix, __func__);
198
199 bool conj = false;
200 int qubit1 = util_getBraQubit(target1, qureg);
201 int qubit2 = util_getBraQubit(target2, qureg);
202 localiser_statevec_anyCtrlTwoTargDiagMatr(qureg, none, none, qubit1, qubit2, matrix, conj);
203}
204
205} // end de-mangler
206
207
208
209/*
210 * DiagMatr
211 */
212
213extern "C" {
214
215void leftapplyDiagMatr(Qureg qureg, int* targets, int numTargets, DiagMatr matrix) {
216 validate_quregFields(qureg, __func__);
217 validate_targets(qureg, targets, numTargets, __func__);
218 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also validates fields and is-sync
219
220 bool conj = false;
221 qcomp exponent = 1;
222 auto qubits = lists_getList64(targets, numTargets);
223 localiser_statevec_anyCtrlAnyTargDiagMatr(qureg, none, none, qubits, matrix, exponent, conj);
224}
225
226void rightapplyDiagMatr(Qureg qureg, int* targets, int numTargets, DiagMatr matrix) {
227 validate_quregFields(qureg, __func__);
228 validate_quregIsDensityMatrix(qureg, __func__);
229 validate_targets(qureg, targets, numTargets, __func__);
230 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also validates fields and is-sync
231
232 bool conj = false;
233 qcomp exponent = 1;
234 auto qubits = util_getBraQubits(lists_getList64(targets, numTargets), qureg);
235 localiser_statevec_anyCtrlAnyTargDiagMatr(qureg, none, none, qubits, matrix, exponent, conj);
236}
237
238} // end de-mangler
239
240void leftapplyDiagMatr(Qureg qureg, vector<int> targets, DiagMatr matrix) {
241
242 leftapplyDiagMatr(qureg, targets.data(), targets.size(), matrix);
243}
244
245void rightapplyDiagMatr(Qureg qureg, vector<int> targets, DiagMatr matrix) {
246
247 rightapplyDiagMatr(qureg, targets.data(), targets.size(), matrix);
248}
249
250
251
252/*
253 * DiagMatrPower
254 */
255
256extern "C" {
257
258void leftapplyDiagMatrPower(Qureg qureg, int* targets, int numTargets, DiagMatr matrix, qcomp exponent) {
259 validate_quregFields(qureg, __func__);
260 validate_targets(qureg, targets, numTargets, __func__);
261 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also validates fields and is-sync, but not unitarity
262 validate_matrixExpIsNonDiverging(matrix, exponent, __func__); // harmlessly re-validates fields and is-sync
263
264 bool conj = false;
265 auto qubits = lists_getList64(targets, numTargets);
266 localiser_statevec_anyCtrlAnyTargDiagMatr(qureg, none, none, qubits, matrix, exponent, conj);
267}
268
269void rightapplyDiagMatrPower(Qureg qureg, int* targets, int numTargets, DiagMatr matrix, qcomp exponent) {
270 validate_quregFields(qureg, __func__);
271 validate_quregIsDensityMatrix(qureg, __func__);
272 validate_targets(qureg, targets, numTargets, __func__);
273 validate_matrixDimMatchesTargets(matrix, numTargets, __func__); // also validates fields and is-sync, but not unitarity
274 validate_matrixExpIsNonDiverging(matrix, exponent, __func__); // harmlessly re-validates fields and is-sync
275
276 bool conj = false;
277 auto qubits = util_getBraQubits(lists_getList64(targets, numTargets), qureg);
278 localiser_statevec_anyCtrlAnyTargDiagMatr(qureg, none, none, qubits, matrix, exponent, conj);
279}
280
281} // end de-mangler
282
283void leftapplyDiagMatrPower(Qureg qureg, vector<int> targets, DiagMatr matrix, qcomp exponent) {
284
285 leftapplyDiagMatrPower(qureg, targets.data(), targets.size(), matrix, exponent);
286}
287
288void rightapplyDiagMatrPower(Qureg qureg, vector<int> targets, DiagMatr matrix, qcomp exponent) {
289
290 rightapplyDiagMatrPower(qureg, targets.data(), targets.size(), matrix, exponent);
291}
292
293
294
295/*
296 * FullStateDiagMatr (and power)
297 */
298
299extern "C" {
300
302 validate_quregFields(qureg, __func__);
303 validate_matrixFields(matrix, __func__);
304 validate_matrixAndQuregAreCompatible(matrix, qureg, false, __func__); // matrix can be non-unitary
305
306 leftapplyFullStateDiagMatrPower(qureg, matrix, 1); // harmlessly re-validates
307}
308
309void leftapplyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent) {
310 validate_quregFields(qureg, __func__);
311 validate_matrixFields(matrix, __func__);
312 validate_matrixAndQuregAreCompatible(matrix, qureg, false, __func__); // matrix can be non-unitary
313 validate_matrixExpIsNonDiverging(matrix, exponent, __func__);
314
315 // rho -> matrix^exponent rho
316 bool leftMultiply = true;
317 bool rightMultiply = false;
318 bool rightConj = false;
319
320 (qureg.isDensityMatrix)?
321 localiser_densmatr_allTargDiagMatr(qureg, matrix, exponent, leftMultiply, rightMultiply, rightConj):
322 localiser_statevec_allTargDiagMatr(qureg, matrix, exponent);
323}
324
326 validate_quregFields(qureg, __func__);
327 validate_quregIsDensityMatrix(qureg, __func__);
328 validate_matrixFields(matrix, __func__);
329 validate_matrixAndQuregAreCompatible(matrix, qureg, false, __func__); // matrix can be non-unitary
330
331 rightapplyFullStateDiagMatrPower(qureg, matrix, 1); // harmlessly re-validates
332}
333
334void rightapplyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent) {
335 validate_quregFields(qureg, __func__);
336 validate_quregIsDensityMatrix(qureg, __func__);
337 validate_matrixFields(matrix, __func__);
338 validate_matrixAndQuregAreCompatible(matrix, qureg, false, __func__); // matrix can be non-unitary
339 validate_matrixExpIsNonDiverging(matrix, exponent, __func__);
340
341 // rho -> rho matrix^exponent
342 bool leftMultiply = false;
343 bool rightMultiply = true;
344 bool rightConj = false;
345 localiser_densmatr_allTargDiagMatr(qureg, matrix, exponent, leftMultiply, rightMultiply, rightConj);
346}
347
348} // end de-mangler
349
350
351
352/*
353 * swap
354 */
355
356extern "C" {
357
358void leftapplySwap(Qureg qureg, int qubit1, int qubit2) {
359 validate_quregFields(qureg, __func__);
360 validate_twoTargets(qureg, qubit1, qubit2, __func__);
361
362 localiser_statevec_anyCtrlSwap(qureg, none, none, qubit1, qubit2);
363}
364
365void rightapplySwap(Qureg qureg, int qubit1, int qubit2) {
366 validate_quregFields(qureg, __func__);
367 validate_quregIsDensityMatrix(qureg, __func__);
368 validate_twoTargets(qureg, qubit1, qubit2, __func__);
369
370 qubit1 = util_getBraQubit(qubit1, qureg);
371 qubit2 = util_getBraQubit(qubit2, qureg);
372 localiser_statevec_anyCtrlSwap(qureg, none, none, qubit1, qubit2);
373}
374
375} // end de-mangler
376
377
378
379/*
380 * individual Paulis
381 */
382
383extern "C" {
384
385void leftapplyPauliX(Qureg qureg, int target) {
386 validate_quregFields(qureg, __func__);
387 validate_target(qureg, target, __func__);
388
389 PauliStr str = getPauliStr("X", {target});
390 localiser_statevec_anyCtrlPauliTensor(qureg, none, none, str);
391}
392
393void leftapplyPauliY(Qureg qureg, int target) {
394 validate_quregFields(qureg, __func__);
395 validate_target(qureg, target, __func__);
396
397 PauliStr str = getPauliStr("Y", {target});
398 localiser_statevec_anyCtrlPauliTensor(qureg, none, none, str);
399}
400
401void leftapplyPauliZ(Qureg qureg, int target) {
402 validate_quregFields(qureg, __func__);
403 validate_target(qureg, target, __func__);
404
405 PauliStr str = getPauliStr("Z", {target});
406 localiser_statevec_anyCtrlPauliTensor(qureg, none, none, str);
407}
408
409void rightapplyPauliX(Qureg qureg, int target) {
410 validate_quregFields(qureg, __func__);
411 validate_quregIsDensityMatrix(qureg, __func__);
412 validate_target(qureg, target, __func__);
413
414 PauliStr str = getPauliStr("X", {target});
415 str = paulis_getShiftedPauliStr(str, qureg.numQubits);
416 localiser_statevec_anyCtrlPauliTensor(qureg, none, none, str);
417}
418
419void rightapplyPauliY(Qureg qureg, int target) {
420 validate_quregFields(qureg, __func__);
421 validate_quregIsDensityMatrix(qureg, __func__);
422 validate_target(qureg, target, __func__);
423
424 qcomp factor = -1; // undo transpose
425 PauliStr str = getPauliStr("Y", {target});
426 str = paulis_getShiftedPauliStr(str, qureg.numQubits);
427 localiser_statevec_anyCtrlPauliTensor(qureg, none, none, str, factor);
428}
429
430void rightapplyPauliZ(Qureg qureg, int target) {
431 validate_quregFields(qureg, __func__);
432 validate_quregIsDensityMatrix(qureg, __func__);
433 validate_target(qureg, target, __func__);
434
435 PauliStr str = getPauliStr("Z", {target});
436 str = paulis_getShiftedPauliStr(str, qureg.numQubits);
437 localiser_statevec_anyCtrlPauliTensor(qureg, none, none, str);
438}
439
440} // end de-mangler
441
442
443
444/*
445 * Pauli strings
446 */
447
448extern "C" {
449
451 validate_quregFields(qureg, __func__);
452 validate_pauliStrTargets(qureg, str, __func__);
453
454 localiser_statevec_anyCtrlPauliTensor(qureg, none, none, str);
455}
456
458 validate_quregFields(qureg, __func__);
459 validate_quregIsDensityMatrix(qureg, __func__);
460 validate_pauliStrTargets(qureg, str, __func__);
461
462 qcomp factor = paulis_getSignOfPauliStrConj(str); // undo transpose
463 str = paulis_getShiftedPauliStr(str, qureg.numQubits);
464 localiser_statevec_anyCtrlPauliTensor(qureg, none, none, str, factor);
465}
466
467} // end de-mangler
468
469
470
471/*
472 * Pauli gadgets
473 */
474
475extern "C" {
476
477void leftapplyPauliGadget(Qureg qureg, PauliStr str, qreal angle) {
478 validate_quregFields(qureg, __func__);
479 validate_pauliStrTargets(qureg, str, __func__);
480
481 qreal phase = util_getPhaseFromGateAngle(angle);
482 localiser_statevec_anyCtrlPauliGadget(qureg, none, none, str, phase);
483}
484
485void rightapplyPauliGadget(Qureg qureg, PauliStr str, qreal angle) {
486 validate_quregFields(qureg, __func__);
487 validate_quregIsDensityMatrix(qureg, __func__);
488 validate_pauliStrTargets(qureg, str, __func__);
489
490 qreal factor = paulis_getSignOfPauliStrConj(str);
491 qreal phase = factor * util_getPhaseFromGateAngle(angle);
492 str = paulis_getShiftedPauliStr(str, qureg.numQubits);
493 localiser_statevec_anyCtrlPauliGadget(qureg, none, none, str, phase);
494}
495
496} // end de-mangler
497
498
499
500/*
501 * phase gadgets
502 */
503
504extern "C" {
505
506void leftapplyPhaseGadget(Qureg qureg, int* targets, int numTargets, qreal angle) {
507 validate_quregFields(qureg, __func__);
508 validate_targets(qureg, targets, numTargets, __func__);
509
510 qreal phase = util_getPhaseFromGateAngle(angle);
511 auto qubits = lists_getList64(targets, numTargets);
512 localiser_statevec_anyCtrlPhaseGadget(qureg, none, none, qubits, phase);
513}
514
515void rightapplyPhaseGadget(Qureg qureg, int* targets, int numTargets, qreal angle) {
516 validate_quregFields(qureg, __func__);
517 validate_quregIsDensityMatrix(qureg, __func__);
518 validate_targets(qureg, targets, numTargets, __func__);
519
520 qreal phase = util_getPhaseFromGateAngle(angle);
521 auto qubits = util_getBraQubits(lists_getList64(targets, numTargets), qureg);
522 localiser_statevec_anyCtrlPhaseGadget(qureg, none, none, qubits, phase);
523}
524
525} // end de-mangler
526
527void leftapplyPhaseGadget(Qureg qureg, vector<int> targets, qreal angle) {
528
529 leftapplyPhaseGadget(qureg, targets.data(), targets.size(), angle);
530}
531
532void rightapplyPhaseGadget(Qureg qureg, vector<int> targets, qreal angle) {
533
534 rightapplyPhaseGadget(qureg, targets.data(), targets.size(), angle);
535}
536
537
538
539/*
540 * many-qubit NOTs
541 */
542
543extern "C" {
544
545void leftapplyMultiQubitNot(Qureg qureg, int* targets, int numTargets) {
546 validate_quregFields(qureg, __func__);
547 validate_targets(qureg, targets, numTargets, __func__);
548
549 // harmlessly re-validates
550 PauliStr str = getPauliStr(std::string(numTargets, 'X'), targets, numTargets);
551 leftapplyPauliStr(qureg, str);
552}
553
554void rightapplyMultiQubitNot(Qureg qureg, int* targets, int numTargets) {
555 validate_quregFields(qureg, __func__);
556 validate_quregIsDensityMatrix(qureg, __func__);
557 validate_targets(qureg, targets, numTargets, __func__);
558
559 // harmlessly re-validates
560 PauliStr str = getPauliStr(std::string(numTargets, 'X'), targets, numTargets);
561 rightapplyPauliStr(qureg, str);
562}
563
564} // end de-mangler
565
566void leftapplyMultiQubitNot(Qureg qureg, vector<int> targets) {
567
568 leftapplyMultiQubitNot(qureg, targets.data(), targets.size());
569}
570
571void rightapplyMultiQubitNot(Qureg qureg, vector<int> targets) {
572
573 rightapplyMultiQubitNot(qureg, targets.data(), targets.size());
574}
575
576
577
578/*
579 * projectors
580 */
581
582extern "C" {
583
584void leftapplyQubitProjector(Qureg qureg, int qubit, int outcome) {
585 validate_quregFields(qureg, __func__);
586 validate_target(qureg, qubit, __func__);
587 validate_measurementOutcomeIsValid(outcome, __func__);
588
589 qreal prob = 1;
590 localiser_statevec_multiQubitProjector(qureg, lists_getList64({qubit}), lists_getList64({outcome}), prob);
591}
592
593void leftapplyMultiQubitProjector(Qureg qureg, int* qubits, int* outcomes, int numQubits) {
594 validate_quregFields(qureg, __func__);
595 validate_targets(qureg, qubits, numQubits, __func__);
596 validate_measurementOutcomesAreValid(outcomes, numQubits, __func__);
597
598 qreal prob = 1;
599 auto qubitVec = lists_getList64(qubits, numQubits);
600 auto outcomeVec = lists_getList64(outcomes, numQubits);
601 localiser_statevec_multiQubitProjector(qureg, qubitVec, outcomeVec, prob);
602}
603
604void rightapplyQubitProjector(Qureg qureg, int qubit, int outcome) {
605 validate_quregFields(qureg, __func__);
606 validate_quregIsDensityMatrix(qureg, __func__);
607 validate_target(qureg, qubit, __func__);
608 validate_measurementOutcomeIsValid(outcome, __func__);
609
610 qreal prob = 1;
611 auto qubitList = lists_getList64({util_getBraQubit(qubit,qureg)});
612 localiser_statevec_multiQubitProjector(qureg, qubitList, lists_getList64({outcome}), prob);
613}
614
615void rightapplyMultiQubitProjector(Qureg qureg, int* qubits, int* outcomes, int numQubits) {
616 validate_quregFields(qureg, __func__);
617 validate_quregIsDensityMatrix(qureg, __func__);
618 validate_targets(qureg, qubits, numQubits, __func__);
619 validate_measurementOutcomesAreValid(outcomes, numQubits, __func__);
620
621 qreal prob = 1;
622 auto qubitVec = util_getBraQubits(lists_getList64(qubits, numQubits), qureg);
623 auto outcomeVec = lists_getList64(outcomes, numQubits);
624 localiser_statevec_multiQubitProjector(qureg, qubitVec, outcomeVec, prob);
625}
626
627} // end de-mangler
628
629void leftapplyMultiQubitProjector(Qureg qureg, vector<int> qubits, vector<int> outcomes) {
630 validate_measurementOutcomesMatchTargets(qubits.size(), outcomes.size(), __func__);
631
632 leftapplyMultiQubitProjector(qureg, qubits.data(), outcomes.data(), outcomes.size());
633}
634
635void rightapplyMultiQubitProjector(Qureg qureg, vector<int> qubits, vector<int> outcomes) {
636 validate_measurementOutcomesMatchTargets(qubits.size(), outcomes.size(), __func__);
637
638 rightapplyMultiQubitProjector(qureg, qubits.data(), outcomes.data(), outcomes.size());
639}
640
641
642
643/*
644 * Pauli string sums
645 */
646
647extern "C" {
648
649void leftapplyPauliStrSum(Qureg qureg, PauliStrSum sum, Qureg workspace) {
650 validate_quregFields(qureg, __func__);
651 validate_quregFields(workspace, __func__);
652 validate_quregCanBeWorkspace(qureg, workspace, __func__);
653 validate_pauliStrSumFields(sum, __func__);
654 validate_pauliStrSumTargets(sum, qureg, __func__);
655
656 // clone qureg to workspace, set qureg to blank
657 localiser_statevec_setQuregToClone(workspace, qureg);
658 localiser_statevec_initUniformState(qureg, 0);
659
660 // left-multiply each term in-turn, mixing into output qureg, then undo using idempotency
661 for (qindex i=0; i<sum.numTerms; i++) {
662 localiser_statevec_anyCtrlPauliTensor(workspace, none, none, sum.strings[i]);
663 localiser_statevec_setQuregToWeightedSum(qureg, {1, sum.coeffs[i]}, {qureg, workspace});
664 localiser_statevec_anyCtrlPauliTensor(workspace, none, none, sum.strings[i]);
665 }
666
667 // workspace -> qureg, and qureg -> sum * qureg
668}
669
670void rightapplyPauliStrSum(Qureg qureg, PauliStrSum sum, Qureg workspace) {
671 validate_quregFields(qureg, __func__);
672 validate_quregFields(workspace, __func__);
673 validate_quregIsDensityMatrix(qureg, __func__);
674 validate_quregCanBeWorkspace(qureg, workspace, __func__);
675 validate_pauliStrSumFields(sum, __func__);
676 validate_pauliStrSumTargets(sum, qureg, __func__);
677
678 // clone qureg to workspace, set qureg to blank
679 localiser_statevec_setQuregToClone(workspace, qureg);
680 localiser_statevec_initUniformState(qureg, 0);
681
682 // post-multiply each term in-turn, mixing into output qureg, then undo using idempotency
683 for (qindex i=0; i<sum.numTerms; i++) {
684 PauliStr str = paulis_getShiftedPauliStr(sum.strings[i], qureg.numQubits);
685 qcomp factor = paulis_getSignOfPauliStrConj(str); // undoes transpose
686
687 localiser_statevec_anyCtrlPauliTensor(workspace, none, none, str, factor);
688 localiser_statevec_setQuregToWeightedSum(qureg, {1, sum.coeffs[i]}, {qureg, workspace});
689 localiser_statevec_anyCtrlPauliTensor(workspace, none, none, str, factor);
690 }
691
692 // workspace -> qureg, and qureg -> sum * qureg
693}
694
695} // end de-mangler
void rightapplyCompMatr1(Qureg qureg, int target, CompMatr1 matrix)
void leftapplyCompMatr1(Qureg qureg, int target, CompMatr1 matrix)
void rightapplyCompMatr2(Qureg qureg, int target1, int target2, CompMatr2 matrix)
void leftapplyCompMatr2(Qureg qureg, int target1, int target2, CompMatr2 matrix)
void leftapplyCompMatr(Qureg qureg, int *targets, int numTargets, CompMatr matrix)
void rightapplyCompMatr(Qureg qureg, int *targets, int numTargets, CompMatr matrix)
void leftapplyDiagMatr1(Qureg qureg, int target, DiagMatr1 matrix)
void rightapplyDiagMatr1(Qureg qureg, int target, DiagMatr1 matrix)
void leftapplyDiagMatr2(Qureg qureg, int target1, int target2, DiagMatr2 matrix)
void rightapplyDiagMatr2(Qureg qureg, int target1, int target2, DiagMatr2 matrix)
void rightapplyDiagMatr(Qureg qureg, int *targets, int numTargets, DiagMatr matrix)
void leftapplyDiagMatrPower(Qureg qureg, int *targets, int numTargets, DiagMatr matrix, qcomp exponent)
void rightapplyDiagMatrPower(Qureg qureg, int *targets, int numTargets, DiagMatr matrix, qcomp exponent)
void leftapplyDiagMatr(Qureg qureg, int *targets, int numTargets, DiagMatr matrix)
void rightapplyFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matrix)
void leftapplyFullStateDiagMatr(Qureg qureg, FullStateDiagMatr matrix)
void rightapplyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent)
void leftapplyFullStateDiagMatrPower(Qureg qureg, FullStateDiagMatr matrix, qcomp exponent)
void leftapplyMultiQubitNot(Qureg qureg, int *targets, int numTargets)
void rightapplyMultiQubitNot(Qureg qureg, int *targets, int numTargets)
void leftapplyPauliX(Qureg qureg, int target)
void rightapplyPauliY(Qureg qureg, int target)
void leftapplyPauliY(Qureg qureg, int target)
void leftapplyPauliZ(Qureg qureg, int target)
void rightapplyPauliX(Qureg qureg, int target)
void rightapplyPauliZ(Qureg qureg, int target)
void leftapplyPauliGadget(Qureg qureg, PauliStr str, qreal angle)
void rightapplyPauliGadget(Qureg qureg, PauliStr str, qreal angle)
void rightapplyPauliStr(Qureg qureg, PauliStr str)
void leftapplyPauliStr(Qureg qureg, PauliStr str)
void rightapplyPauliStrSum(Qureg qureg, PauliStrSum sum, Qureg workspace)
void leftapplyPauliStrSum(Qureg qureg, PauliStrSum sum, Qureg workspace)
void rightapplyPhaseGadget(Qureg qureg, int *targets, int numTargets, qreal angle)
void leftapplyPhaseGadget(Qureg qureg, int *targets, int numTargets, qreal angle)
void leftapplyMultiQubitProjector(Qureg qureg, int *qubits, int *outcomes, int numQubits)
void rightapplyQubitProjector(Qureg qureg, int qubit, int outcome)
void rightapplyMultiQubitProjector(Qureg qureg, int *qubits, int *outcomes, int numQubits)
void leftapplyQubitProjector(Qureg qureg, int qubit, int outcome)
void leftapplySwap(Qureg qureg, int qubit1, int qubit2)
void rightapplySwap(Qureg qureg, int qubit1, int qubit2)
PauliStr getPauliStr(const char *paulis, int *indices, int numPaulis)
Definition paulis.cpp:76
Definition qureg.h:49