Maestro 0.3.1
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
GpuSimulator.h
Go to the documentation of this file.
1
12
13#pragma once
14
15#ifndef _GPUSIMULATOR_H
16#define _GPUSIMULATOR_H
17
18#ifdef INCLUDED_BY_FACTORY
19
20#ifdef __linux__
21
22#include "GpuState.h"
23
24namespace Simulators {
25// TODO: Maybe use the pimpl idiom
26// https://en.cppreference.com/w/cpp/language/pimpl to hide the implementation
27// for good but during development this should be good enough
28namespace Private {
29
41class GpuSimulator : public GpuState {
42 public:
43 GpuSimulator() = default;
44 // allow no copy or assignment
45 GpuSimulator(const GpuSimulator &) = delete;
46 GpuSimulator &operator=(const GpuSimulator &) = delete;
47
48 // but allow moving
49 GpuSimulator(GpuSimulator &&other) = default;
50 GpuSimulator &operator=(GpuSimulator &&other) = default;
51
52
58 void ApplyGenericOneQubitGate(Types::qubit_t qubit,
59 const Eigen::Matrix2cd& gate) override {
60 // The MPS and MPO backends expose a direct unitary-matrix-application
61 // primitive; use it instead of routing through the Kraus/quantum-channel
62 // path (which is still what the density matrix backend needs, since it
63 // has no such primitive).
64 if (GetSimulationType() == SimulationType::kMatrixProductOperator) {
65 if (!mpo->ApplyOneQubitMatrix(
66 static_cast<int>(qubit),
67 reinterpret_cast<const double*>(gate.data())))
68 throw std::runtime_error(
69 "GpuSimulator::ApplyGenericOneQubitGate: Failed to apply the "
70 "generic one-qubit gate on the matrix product operator "
71 "simulator.");
72 NotifyObservers({qubit});
73 return;
74 }
75 if (GetSimulationType() == SimulationType::kMatrixProductState) {
76 if (!mps->ApplyOneQubitMatrix(
77 static_cast<unsigned int>(qubit),
78 reinterpret_cast<const double*>(gate.data())))
79 throw std::runtime_error(
80 "GpuSimulator::ApplyGenericOneQubitGate: Failed to apply the "
81 "generic one-qubit gate on the matrix product state simulator.");
82 NotifyObservers({qubit});
83 return;
84 }
85 if (GetSimulationType() == SimulationType::kDensityMatrix) {
86 ApplyQuantumChannel({qubit}, QuantumChannel({gate}));
87 return;
88 }
89 throw std::runtime_error(
90 "GpuSimulator::ApplyGenericOneQubitGate: Not supported for GPU "
91 "simulator yet.");
92 }
93
100 void ApplyGenericTwoQubitGate(Types::qubit_t qubit0, Types::qubit_t qubit1,
101 const Eigen::Matrix4cd& gate) override {
102 if (GetSimulationType() == SimulationType::kMatrixProductOperator) {
103 if (!mpo->ApplyTwoQubitMatrix(
104 static_cast<int>(qubit0), static_cast<int>(qubit1),
105 reinterpret_cast<const double*>(gate.data())))
106 throw std::runtime_error(
107 "GpuSimulator::ApplyGenericTwoQubitGate: Failed to apply the "
108 "generic two-qubit gate on the matrix product operator "
109 "simulator.");
110 NotifyObservers({qubit0, qubit1});
111 return;
112 }
113 if (GetSimulationType() == SimulationType::kMatrixProductState) {
114 if (!mps->ApplyTwoQubitMatrix(
115 static_cast<unsigned int>(qubit0),
116 static_cast<unsigned int>(qubit1),
117 reinterpret_cast<const double*>(gate.data())))
118 throw std::runtime_error(
119 "GpuSimulator::ApplyGenericTwoQubitGate: Failed to apply the "
120 "generic two-qubit gate on the matrix product state simulator.");
121 NotifyObservers({qubit0, qubit1});
122 return;
123 }
124 if (GetSimulationType() == SimulationType::kDensityMatrix) {
125 ApplyQuantumChannel({qubit0, qubit1}, QuantumChannel({gate}));
126 return;
127 }
128 throw std::runtime_error(
129 "GpuSimulator::ApplyGenericTwoQubitGate: Not supported for GPU "
130 "simulator yet.");
131 }
132
140 void ApplyP(Types::qubit_t qubit, double lambda) override {
141 if (GetSimulationType() == SimulationType::kStatevector)
142 state->ApplyP(qubit, lambda);
143 else if (GetSimulationType() == SimulationType::kDensityMatrix)
144 densityMatrix->ApplyP(qubit, lambda);
145 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
146 mpo->ApplyP(qubit, lambda);
147 else if (GetSimulationType() == SimulationType::kMatrixProductState)
148 mps->ApplyP(qubit, lambda);
149 else if (GetSimulationType() == SimulationType::kTensorNetwork)
150 tn->ApplyP(qubit, lambda);
151 else if (GetSimulationType() == SimulationType::kPauliPropagator)
152 pp->ApplyP(qubit, lambda);
153
154 NotifyObservers({qubit});
155 }
156
163 void ApplyX(Types::qubit_t qubit) override {
164 if (GetSimulationType() == SimulationType::kStatevector)
165 state->ApplyX(qubit);
166 else if (GetSimulationType() == SimulationType::kDensityMatrix)
167 densityMatrix->ApplyX(qubit);
168 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
169 mpo->ApplyX(qubit);
170 else if (GetSimulationType() == SimulationType::kMatrixProductState)
171 mps->ApplyX(qubit);
172 else if (GetSimulationType() == SimulationType::kTensorNetwork)
173 tn->ApplyX(qubit);
174 else if (GetSimulationType() == SimulationType::kPauliPropagator)
175 pp->ApplyX(qubit);
176
177 NotifyObservers({qubit});
178 }
179
186 void ApplyY(Types::qubit_t qubit) override {
187 if (GetSimulationType() == SimulationType::kStatevector)
188 state->ApplyY(qubit);
189 else if (GetSimulationType() == SimulationType::kDensityMatrix)
190 densityMatrix->ApplyY(qubit);
191 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
192 mpo->ApplyY(qubit);
193 else if (GetSimulationType() == SimulationType::kMatrixProductState)
194 mps->ApplyY(qubit);
195 else if (GetSimulationType() == SimulationType::kTensorNetwork)
196 tn->ApplyY(qubit);
197 else if (GetSimulationType() == SimulationType::kPauliPropagator)
198 pp->ApplyY(qubit);
199
200 NotifyObservers({qubit});
201 }
202
209 void ApplyZ(Types::qubit_t qubit) override {
210 if (GetSimulationType() == SimulationType::kStatevector)
211 state->ApplyZ(qubit);
212 else if (GetSimulationType() == SimulationType::kDensityMatrix)
213 densityMatrix->ApplyZ(qubit);
214 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
215 mpo->ApplyZ(qubit);
216 else if (GetSimulationType() == SimulationType::kMatrixProductState)
217 mps->ApplyZ(qubit);
218 else if (GetSimulationType() == SimulationType::kTensorNetwork)
219 tn->ApplyZ(qubit);
220 else if (GetSimulationType() == SimulationType::kPauliPropagator)
221 pp->ApplyZ(qubit);
222
223 NotifyObservers({qubit});
224 }
225
232 void ApplyH(Types::qubit_t qubit) override {
233 if (GetSimulationType() == SimulationType::kStatevector)
234 state->ApplyH(qubit);
235 else if (GetSimulationType() == SimulationType::kDensityMatrix)
236 densityMatrix->ApplyH(qubit);
237 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
238 mpo->ApplyH(qubit);
239 else if (GetSimulationType() == SimulationType::kMatrixProductState)
240 mps->ApplyH(qubit);
241 else if (GetSimulationType() == SimulationType::kTensorNetwork)
242 tn->ApplyH(qubit);
243 else if (GetSimulationType() == SimulationType::kPauliPropagator)
244 pp->ApplyH(qubit);
245
246 NotifyObservers({qubit});
247 }
248
255 void ApplyS(Types::qubit_t qubit) override {
256 if (GetSimulationType() == SimulationType::kStatevector)
257 state->ApplyS(qubit);
258 else if (GetSimulationType() == SimulationType::kDensityMatrix)
259 densityMatrix->ApplyS(qubit);
260 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
261 mpo->ApplyS(qubit);
262 else if (GetSimulationType() == SimulationType::kMatrixProductState)
263 mps->ApplyS(qubit);
264 else if (GetSimulationType() == SimulationType::kTensorNetwork)
265 tn->ApplyS(qubit);
266 else if (GetSimulationType() == SimulationType::kPauliPropagator)
267 pp->ApplyS(qubit);
268
269 NotifyObservers({qubit});
270 }
271
278 void ApplySDG(Types::qubit_t qubit) override {
279 if (GetSimulationType() == SimulationType::kStatevector)
280 state->ApplySDG(qubit);
281 else if (GetSimulationType() == SimulationType::kDensityMatrix)
282 densityMatrix->ApplySDG(qubit);
283 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
284 mpo->ApplySDG(qubit);
285 else if (GetSimulationType() == SimulationType::kMatrixProductState)
286 mps->ApplySDG(qubit);
287 else if (GetSimulationType() == SimulationType::kTensorNetwork)
288 tn->ApplySDG(qubit);
289 else if (GetSimulationType() == SimulationType::kPauliPropagator)
290 pp->ApplySDG(qubit);
291
292 NotifyObservers({qubit});
293 }
294
301 void ApplyT(Types::qubit_t qubit) override {
302 if (GetSimulationType() == SimulationType::kStatevector)
303 state->ApplyT(qubit);
304 else if (GetSimulationType() == SimulationType::kDensityMatrix)
305 densityMatrix->ApplyT(qubit);
306 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
307 mpo->ApplyT(qubit);
308 else if (GetSimulationType() == SimulationType::kMatrixProductState)
309 mps->ApplyT(qubit);
310 else if (GetSimulationType() == SimulationType::kTensorNetwork)
311 tn->ApplyT(qubit);
312 else if (GetSimulationType() == SimulationType::kPauliPropagator)
313 pp->ApplyT(qubit);
314
315 NotifyObservers({qubit});
316 }
317
324 void ApplyTDG(Types::qubit_t qubit) override {
325 if (GetSimulationType() == SimulationType::kStatevector)
326 state->ApplyTDG(qubit);
327 else if (GetSimulationType() == SimulationType::kDensityMatrix)
328 densityMatrix->ApplyTDG(qubit);
329 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
330 mpo->ApplyTDG(qubit);
331 else if (GetSimulationType() == SimulationType::kMatrixProductState)
332 mps->ApplyTDG(qubit);
333 else if (GetSimulationType() == SimulationType::kTensorNetwork)
334 tn->ApplyTDG(qubit);
335 else if (GetSimulationType() == SimulationType::kPauliPropagator)
336 pp->ApplyTDG(qubit);
337
338 NotifyObservers({qubit});
339 }
340
347 void ApplySx(Types::qubit_t qubit) override {
348 if (GetSimulationType() == SimulationType::kStatevector)
349 state->ApplySX(qubit);
350 else if (GetSimulationType() == SimulationType::kDensityMatrix)
351 densityMatrix->ApplySX(qubit);
352 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
353 mpo->ApplySX(qubit);
354 else if (GetSimulationType() == SimulationType::kMatrixProductState)
355 mps->ApplySX(qubit);
356 else if (GetSimulationType() == SimulationType::kTensorNetwork)
357 tn->ApplySX(qubit);
358 else if (GetSimulationType() == SimulationType::kPauliPropagator)
359 pp->ApplySQRTX(qubit);
360
361 NotifyObservers({qubit});
362 }
363
370 void ApplySxDAG(Types::qubit_t qubit) override {
371 if (GetSimulationType() == SimulationType::kStatevector)
372 state->ApplySXDG(qubit);
373 else if (GetSimulationType() == SimulationType::kDensityMatrix)
374 densityMatrix->ApplySXDG(qubit);
375 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
376 mpo->ApplySXDG(qubit);
377 else if (GetSimulationType() == SimulationType::kMatrixProductState)
378 mps->ApplySXDG(qubit);
379 else if (GetSimulationType() == SimulationType::kTensorNetwork)
380 tn->ApplySXDG(qubit);
381 else if (GetSimulationType() == SimulationType::kPauliPropagator)
382 pp->ApplySxDAG(qubit);
383
384 NotifyObservers({qubit});
385 }
386
393 void ApplyK(Types::qubit_t qubit) override {
394 if (GetSimulationType() == SimulationType::kStatevector)
395 state->ApplyK(qubit);
396 else if (GetSimulationType() == SimulationType::kDensityMatrix)
397 densityMatrix->ApplyK(qubit);
398 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
399 mpo->ApplyK(qubit);
400 else if (GetSimulationType() == SimulationType::kMatrixProductState)
401 mps->ApplyK(qubit);
402 else if (GetSimulationType() == SimulationType::kTensorNetwork)
403 tn->ApplyK(qubit);
404 else if (GetSimulationType() == SimulationType::kPauliPropagator)
405 pp->ApplyK(qubit);
406
407 NotifyObservers({qubit});
408 }
409
417 void ApplyRx(Types::qubit_t qubit, double theta) override {
418 if (GetSimulationType() == SimulationType::kStatevector)
419 state->ApplyRx(qubit, theta);
420 else if (GetSimulationType() == SimulationType::kDensityMatrix)
421 densityMatrix->ApplyRx(qubit, theta);
422 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
423 mpo->ApplyRx(qubit, theta);
424 else if (GetSimulationType() == SimulationType::kMatrixProductState)
425 mps->ApplyRx(qubit, theta);
426 else if (GetSimulationType() == SimulationType::kTensorNetwork)
427 tn->ApplyRx(qubit, theta);
428 else if (GetSimulationType() == SimulationType::kPauliPropagator)
429 pp->ApplyRX(qubit, theta);
430
431 NotifyObservers({qubit});
432 }
433
441 void ApplyRy(Types::qubit_t qubit, double theta) override {
442 if (GetSimulationType() == SimulationType::kStatevector)
443 state->ApplyRy(qubit, theta);
444 else if (GetSimulationType() == SimulationType::kDensityMatrix)
445 densityMatrix->ApplyRy(qubit, theta);
446 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
447 mpo->ApplyRy(qubit, theta);
448 else if (GetSimulationType() == SimulationType::kMatrixProductState)
449 mps->ApplyRy(qubit, theta);
450 else if (GetSimulationType() == SimulationType::kTensorNetwork)
451 tn->ApplyRy(qubit, theta);
452 else if (GetSimulationType() == SimulationType::kPauliPropagator)
453 pp->ApplyRY(qubit, theta);
454
455 NotifyObservers({qubit});
456 }
457
465 void ApplyRz(Types::qubit_t qubit, double theta) override {
466 if (GetSimulationType() == SimulationType::kStatevector)
467 state->ApplyRz(qubit, theta);
468 else if (GetSimulationType() == SimulationType::kDensityMatrix)
469 densityMatrix->ApplyRz(qubit, theta);
470 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
471 mpo->ApplyRz(qubit, theta);
472 else if (GetSimulationType() == SimulationType::kMatrixProductState)
473 mps->ApplyRz(qubit, theta);
474 else if (GetSimulationType() == SimulationType::kTensorNetwork)
475 tn->ApplyRz(qubit, theta);
476 else if (GetSimulationType() == SimulationType::kPauliPropagator)
477 pp->ApplyRZ(qubit, theta);
478
479 NotifyObservers({qubit});
480 }
481
489 void ApplyU(Types::qubit_t qubit, double theta, double phi, double lambda,
490 double gamma) override {
491 if (GetSimulationType() == SimulationType::kStatevector)
492 state->ApplyU(qubit, theta, phi, lambda, gamma);
493 else if (GetSimulationType() == SimulationType::kDensityMatrix)
494 densityMatrix->ApplyU(qubit, theta, phi, lambda, gamma);
495 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
496 mpo->ApplyU(qubit, theta, phi, lambda, gamma);
497 else if (GetSimulationType() == SimulationType::kMatrixProductState)
498 mps->ApplyU(qubit, theta, phi, lambda, gamma);
499 else if (GetSimulationType() == SimulationType::kTensorNetwork)
500 tn->ApplyU(qubit, theta, phi, lambda, gamma);
501 else if (GetSimulationType() == SimulationType::kPauliPropagator)
502 pp->ApplyU(qubit, theta, phi, lambda, gamma);
503
504 NotifyObservers({qubit});
505 }
506
514 void ApplyCX(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
515 if (GetSimulationType() == SimulationType::kStatevector)
516 state->ApplyCX(ctrl_qubit, tgt_qubit);
517 else if (GetSimulationType() == SimulationType::kDensityMatrix)
518 densityMatrix->ApplyCX(ctrl_qubit, tgt_qubit);
519 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
520 mpo->ApplyCX(ctrl_qubit, tgt_qubit);
521 else if (GetSimulationType() == SimulationType::kMatrixProductState)
522 mps->ApplyCX(ctrl_qubit, tgt_qubit);
523 else if (GetSimulationType() == SimulationType::kTensorNetwork)
524 tn->ApplyCX(ctrl_qubit, tgt_qubit);
525 else if (GetSimulationType() == SimulationType::kPauliPropagator)
526 pp->ApplyCX(ctrl_qubit, tgt_qubit);
527
528 NotifyObservers({tgt_qubit, ctrl_qubit});
529 }
530
538 void ApplyCY(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
539 if (GetSimulationType() == SimulationType::kStatevector)
540 state->ApplyCY(ctrl_qubit, tgt_qubit);
541 else if (GetSimulationType() == SimulationType::kDensityMatrix)
542 densityMatrix->ApplyCY(ctrl_qubit, tgt_qubit);
543 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
544 mpo->ApplyCY(ctrl_qubit, tgt_qubit);
545 else if (GetSimulationType() == SimulationType::kMatrixProductState)
546 mps->ApplyCY(ctrl_qubit, tgt_qubit);
547 else if (GetSimulationType() == SimulationType::kTensorNetwork)
548 tn->ApplyCY(ctrl_qubit, tgt_qubit);
549 else if (GetSimulationType() == SimulationType::kPauliPropagator)
550 pp->ApplyCY(ctrl_qubit, tgt_qubit);
551
552 NotifyObservers({tgt_qubit, ctrl_qubit});
553 }
554
562 void ApplyCZ(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
563 if (GetSimulationType() == SimulationType::kStatevector)
564 state->ApplyCZ(ctrl_qubit, tgt_qubit);
565 else if (GetSimulationType() == SimulationType::kDensityMatrix)
566 densityMatrix->ApplyCZ(ctrl_qubit, tgt_qubit);
567 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
568 mpo->ApplyCZ(ctrl_qubit, tgt_qubit);
569 else if (GetSimulationType() == SimulationType::kMatrixProductState)
570 mps->ApplyCZ(ctrl_qubit, tgt_qubit);
571 else if (GetSimulationType() == SimulationType::kTensorNetwork)
572 tn->ApplyCZ(ctrl_qubit, tgt_qubit);
573 else if (GetSimulationType() == SimulationType::kPauliPropagator)
574 pp->ApplyCZ(ctrl_qubit, tgt_qubit);
575
576 NotifyObservers({tgt_qubit, ctrl_qubit});
577 }
578
587 void ApplyCP(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
588 double lambda) override {
589 if (GetSimulationType() == SimulationType::kStatevector)
590 state->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
591 else if (GetSimulationType() == SimulationType::kDensityMatrix)
592 densityMatrix->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
593 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
594 mpo->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
595 else if (GetSimulationType() == SimulationType::kMatrixProductState)
596 mps->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
597 else if (GetSimulationType() == SimulationType::kTensorNetwork)
598 tn->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
599 else if (GetSimulationType() == SimulationType::kPauliPropagator)
600 pp->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
601
602 NotifyObservers({tgt_qubit, ctrl_qubit});
603 }
604
613 void ApplyCRx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
614 double theta) override {
615 if (GetSimulationType() == SimulationType::kStatevector)
616 state->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
617 else if (GetSimulationType() == SimulationType::kDensityMatrix)
618 densityMatrix->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
619 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
620 mpo->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
621 else if (GetSimulationType() == SimulationType::kMatrixProductState)
622 mps->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
623 else if (GetSimulationType() == SimulationType::kTensorNetwork)
624 tn->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
625 else if (GetSimulationType() == SimulationType::kPauliPropagator)
626 pp->ApplyCRX(ctrl_qubit, tgt_qubit, theta);
627
628 NotifyObservers({tgt_qubit, ctrl_qubit});
629 }
630
639 void ApplyCRy(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
640 double theta) override {
641 if (GetSimulationType() == SimulationType::kStatevector)
642 state->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
643 else if (GetSimulationType() == SimulationType::kDensityMatrix)
644 densityMatrix->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
645 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
646 mpo->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
647 else if (GetSimulationType() == SimulationType::kMatrixProductState)
648 mps->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
649 else if (GetSimulationType() == SimulationType::kTensorNetwork)
650 tn->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
651 else if (GetSimulationType() == SimulationType::kPauliPropagator)
652 pp->ApplyCRY(ctrl_qubit, tgt_qubit, theta);
653
654 NotifyObservers({tgt_qubit, ctrl_qubit});
655 }
656
665 void ApplyCRz(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
666 double theta) override {
667 if (GetSimulationType() == SimulationType::kStatevector)
668 state->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
669 else if (GetSimulationType() == SimulationType::kDensityMatrix)
670 densityMatrix->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
671 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
672 mpo->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
673 else if (GetSimulationType() == SimulationType::kMatrixProductState)
674 mps->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
675 else if (GetSimulationType() == SimulationType::kTensorNetwork)
676 tn->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
677 else if (GetSimulationType() == SimulationType::kPauliPropagator)
678 pp->ApplyCRZ(ctrl_qubit, tgt_qubit, theta);
679
680 NotifyObservers({tgt_qubit, ctrl_qubit});
681 }
682
690 void ApplyCH(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
691 if (GetSimulationType() == SimulationType::kStatevector)
692 state->ApplyCH(ctrl_qubit, tgt_qubit);
693 else if (GetSimulationType() == SimulationType::kDensityMatrix)
694 densityMatrix->ApplyCH(ctrl_qubit, tgt_qubit);
695 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
696 mpo->ApplyCH(ctrl_qubit, tgt_qubit);
697 else if (GetSimulationType() == SimulationType::kMatrixProductState)
698 mps->ApplyCH(ctrl_qubit, tgt_qubit);
699 else if (GetSimulationType() == SimulationType::kTensorNetwork)
700 tn->ApplyCH(ctrl_qubit, tgt_qubit);
701 else if (GetSimulationType() == SimulationType::kPauliPropagator)
702 pp->ApplyCH(ctrl_qubit, tgt_qubit);
703
704 NotifyObservers({tgt_qubit, ctrl_qubit});
705 }
706
714 void ApplyCSx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
715 if (GetSimulationType() == SimulationType::kStatevector)
716 state->ApplyCSX(ctrl_qubit, tgt_qubit);
717 else if (GetSimulationType() == SimulationType::kDensityMatrix)
718 densityMatrix->ApplyCSX(ctrl_qubit, tgt_qubit);
719 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
720 mpo->ApplyCSX(ctrl_qubit, tgt_qubit);
721 else if (GetSimulationType() == SimulationType::kMatrixProductState)
722 mps->ApplyCSX(ctrl_qubit, tgt_qubit);
723 else if (GetSimulationType() == SimulationType::kTensorNetwork)
724 tn->ApplyCSX(ctrl_qubit, tgt_qubit);
725 else if (GetSimulationType() == SimulationType::kPauliPropagator)
726 pp->ApplyCSX(ctrl_qubit, tgt_qubit);
727
728 NotifyObservers({tgt_qubit, ctrl_qubit});
729 }
730
738 void ApplyCSxDAG(Types::qubit_t ctrl_qubit,
739 Types::qubit_t tgt_qubit) override {
740 if (GetSimulationType() == SimulationType::kStatevector)
741 state->ApplyCSXDG(ctrl_qubit, tgt_qubit);
742 else if (GetSimulationType() == SimulationType::kDensityMatrix)
743 densityMatrix->ApplyCSXDG(ctrl_qubit, tgt_qubit);
744 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
745 mpo->ApplyCSXDG(ctrl_qubit, tgt_qubit);
746 else if (GetSimulationType() == SimulationType::kMatrixProductState)
747 mps->ApplyCSXDG(ctrl_qubit, tgt_qubit);
748 else if (GetSimulationType() == SimulationType::kTensorNetwork)
749 tn->ApplyCSXDG(ctrl_qubit, tgt_qubit);
750 else if (GetSimulationType() == SimulationType::kPauliPropagator)
751 pp->ApplyCSXDAG(ctrl_qubit, tgt_qubit);
752
753 NotifyObservers({tgt_qubit, ctrl_qubit});
754 }
755
763 void ApplySwap(Types::qubit_t qubit0, Types::qubit_t qubit1) override {
764 if (GetSimulationType() == SimulationType::kStatevector)
765 state->ApplySwap(qubit0, qubit1);
766 else if (GetSimulationType() == SimulationType::kDensityMatrix)
767 densityMatrix->ApplySwap(qubit0, qubit1);
768 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
769 mpo->ApplySwap(qubit0, qubit1);
770 else if (GetSimulationType() == SimulationType::kMatrixProductState)
771 mps->ApplySwap(qubit0, qubit1);
772 else if (GetSimulationType() == SimulationType::kTensorNetwork)
773 tn->ApplySwap(qubit0, qubit1);
774 else if (GetSimulationType() == SimulationType::kPauliPropagator)
775 pp->ApplySWAP(qubit0, qubit1);
776
777 NotifyObservers({qubit1, qubit0});
778 }
779
788 void ApplyCCX(Types::qubit_t qubit0, Types::qubit_t qubit1,
789 Types::qubit_t qubit2) override {
790 if (GetSimulationType() == SimulationType::kStatevector) {
791 state->ApplyCCX(qubit0, qubit1, qubit2);
792 NotifyObservers({qubit0, qubit1, qubit2});
793 } else if (GetSimulationType() == SimulationType::kDensityMatrix) {
794 densityMatrix->ApplyCCX(qubit0, qubit1, qubit2);
795 NotifyObservers({qubit0, qubit1, qubit2});
796 } else if (GetSimulationType() == SimulationType::kMatrixProductOperator) {
797 const size_t q1 = qubit0; // control 1
798 const size_t q2 = qubit1; // control 2
799 const size_t q3 = qubit2; // target
800
801 // The gpu MPO backend does not expose a native CCX gate; decompose it
802 // with the same Sleator-Weinfurter decomposition used for MPS.
803 mpo->ApplyCSX(static_cast<int>(q2), static_cast<int>(q3));
804 NotifyObservers({qubit1, qubit2});
805
806 mpo->ApplyCX(static_cast<int>(q1), static_cast<int>(q2));
807 NotifyObservers({qubit0, qubit1});
808
809 mpo->ApplyCSXDG(static_cast<int>(q2), static_cast<int>(q3));
810 NotifyObservers({qubit1, qubit2});
811
812 mpo->ApplyCX(static_cast<int>(q1), static_cast<int>(q2));
813 NotifyObservers({qubit0, qubit1});
814
815 mpo->ApplyCSX(static_cast<int>(q1), static_cast<int>(q3));
816 NotifyObservers({qubit0, qubit2});
817 } else if (GetSimulationType() == SimulationType::kMatrixProductState) {
818 const size_t q1 = qubit0; // control 1
819 const size_t q2 = qubit1; // control 2
820 const size_t q3 = qubit2; // target
821
822 // Sleator-Weinfurter decomposition
823 mps->ApplyCSX(static_cast<unsigned int>(q2),
824 static_cast<unsigned int>(q3));
825 NotifyObservers({qubit1, qubit2});
826
827 mps->ApplyCX(static_cast<unsigned int>(q1),
828 static_cast<unsigned int>(q2));
829 NotifyObservers({qubit0, qubit1});
830
831 mps->ApplyCSXDG(static_cast<unsigned int>(q2),
832 static_cast<unsigned int>(q3));
833 NotifyObservers({qubit1, qubit2});
834
835 mps->ApplyCX(static_cast<unsigned int>(q1),
836 static_cast<unsigned int>(q2));
837 NotifyObservers({qubit0, qubit1});
838
839 mps->ApplyCSX(static_cast<unsigned int>(q1),
840 static_cast<unsigned int>(q3));
841 NotifyObservers({qubit0, qubit2});
842 } else if (GetSimulationType() == SimulationType::kTensorNetwork) {
843 tn->ApplyCCX(qubit0, qubit1, qubit2);
844 NotifyObservers({qubit0, qubit1, qubit2});
845 } else if (GetSimulationType() == SimulationType::kPauliPropagator) {
846 pp->ApplyCCX(qubit0, qubit1, qubit2);
847 NotifyObservers({qubit0, qubit1, qubit2});
848 }
849 }
850
859 void ApplyCSwap(Types::qubit_t ctrl_qubit, Types::qubit_t qubit0,
860 Types::qubit_t qubit1) override {
861 if (GetSimulationType() == SimulationType::kStatevector) {
862 state->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
863 NotifyObservers({qubit1, qubit0, ctrl_qubit});
864 } else if (GetSimulationType() == SimulationType::kDensityMatrix) {
865 densityMatrix->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
866 NotifyObservers({qubit1, qubit0, ctrl_qubit});
867 } else if (GetSimulationType() == SimulationType::kMatrixProductOperator) {
868 const size_t q1 = ctrl_qubit; // control
869 const size_t q2 = qubit0;
870 const size_t q3 = qubit1;
871
872 // The gpu MPO backend does not expose a native CSwap gate; decompose it
873 // with the same decomposition used for MPS.
874 mpo->ApplyCX(static_cast<int>(q3), static_cast<int>(q2));
875 NotifyObservers({qubit1, qubit0});
876
877 mpo->ApplyCSX(static_cast<int>(q2), static_cast<int>(q3));
878 NotifyObservers({qubit0, qubit1});
879
880 mpo->ApplyCX(static_cast<int>(q1), static_cast<int>(q2));
881 NotifyObservers({ctrl_qubit, qubit0});
882
883 mpo->ApplyP(static_cast<int>(q3), M_PI);
884 NotifyObservers({qubit1});
885 mpo->ApplyP(static_cast<int>(q2), -M_PI_2);
886 NotifyObservers({qubit0});
887
888 mpo->ApplyCSX(static_cast<int>(q2), static_cast<int>(q3));
889 NotifyObservers({qubit0, qubit1});
890
891 mpo->ApplyCX(static_cast<int>(q1), static_cast<int>(q2));
892 NotifyObservers({ctrl_qubit, qubit0});
893
894 mpo->ApplyP(static_cast<int>(q3), M_PI);
895 NotifyObservers({qubit1});
896
897 mpo->ApplyCSX(static_cast<int>(q1), static_cast<int>(q3));
898 NotifyObservers({ctrl_qubit, qubit1});
899
900 mpo->ApplyCX(static_cast<int>(q3), static_cast<int>(q2));
901 NotifyObservers({qubit1, qubit0});
902 } else if (GetSimulationType() == SimulationType::kMatrixProductState) {
903 const size_t q1 = ctrl_qubit; // control
904 const size_t q2 = qubit0;
905 const size_t q3 = qubit1;
906
907 // TODO: find a better decomposition
908 // this one I've got with the qiskit transpiler
909 mps->ApplyCX(static_cast<unsigned int>(q3),
910 static_cast<unsigned int>(q2));
911 NotifyObservers({qubit1, qubit0});
912
913 mps->ApplyCSX(static_cast<unsigned int>(q2),
914 static_cast<unsigned int>(q3));
915 NotifyObservers({qubit0, qubit1});
916
917 mps->ApplyCX(static_cast<unsigned int>(q1),
918 static_cast<unsigned int>(q2));
919 NotifyObservers({ctrl_qubit, qubit0});
920
921 mps->ApplyP(static_cast<unsigned int>(q3), M_PI);
922 NotifyObservers({qubit1});
923 mps->ApplyP(static_cast<unsigned int>(q2), -M_PI_2);
924 NotifyObservers({qubit0});
925
926 mps->ApplyCSX(static_cast<unsigned int>(q2),
927 static_cast<unsigned int>(q3));
928 NotifyObservers({qubit0, qubit1});
929
930 mps->ApplyCX(static_cast<unsigned int>(q1),
931 static_cast<unsigned int>(q2));
932 NotifyObservers({ctrl_qubit, qubit0});
933
934 mps->ApplyP(static_cast<unsigned int>(q3), M_PI);
935 NotifyObservers({qubit1});
936
937 mps->ApplyCSX(static_cast<unsigned int>(q1),
938 static_cast<unsigned int>(q3));
939 NotifyObservers({ctrl_qubit, qubit1});
940
941 mps->ApplyCX(static_cast<unsigned int>(q3),
942 static_cast<unsigned int>(q2));
943 NotifyObservers({qubit1, qubit0});
944 } else if (GetSimulationType() == SimulationType::kTensorNetwork) {
945 tn->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
946 NotifyObservers({qubit1, qubit0, ctrl_qubit});
947 } else if (GetSimulationType() == SimulationType::kPauliPropagator) {
948 pp->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
949 NotifyObservers({qubit1, qubit0, ctrl_qubit});
950 }
951 }
952
964 void ApplyCU(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
965 double theta, double phi, double lambda, double gamma) override {
966 if (GetSimulationType() == SimulationType::kStatevector)
967 state->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
968 else if (GetSimulationType() == SimulationType::kDensityMatrix)
969 densityMatrix->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
970 else if (GetSimulationType() == SimulationType::kMatrixProductOperator)
971 mpo->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
972 else if (GetSimulationType() == SimulationType::kMatrixProductState)
973 mps->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
974 else if (GetSimulationType() == SimulationType::kTensorNetwork)
975 tn->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
976 else if (GetSimulationType() == SimulationType::kPauliPropagator)
977 pp->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
978
979 NotifyObservers({tgt_qubit, ctrl_qubit});
980 }
981
989 void ApplyNop() override {
990 // do nothing
991 }
992
1003 std::unique_ptr<ISimulator> Clone() override {
1004 if (GetSimulationType() == SimulationType::kTensorNetwork ||
1005 GetSimulationType() == SimulationType::kPauliPropagator) {
1006 throw std::runtime_error(
1007 "GpuSimulator::Clone: Cloning Tensor Network or Pauli Propagator "
1008 "simulation is not "
1009 "supported.");
1010 }
1011
1012 auto cloned = std::make_unique<GpuSimulator>();
1013
1014 cloned->simulationType = simulationType;
1015 cloned->nrQubits = nrQubits;
1016
1017 cloned->lookaheadDepth = lookaheadDepth;
1018 cloned->lookaheadDepthWithHeuristic = lookaheadDepthWithHeuristic;
1019 cloned->useOptimalMeetingPosition = useOptimalMeetingPosition;
1020 cloned->upcomingGates = upcomingGates;
1021 cloned->upcomingGateIndex = upcomingGateIndex;
1022 cloned->growthFactorGate = growthFactorGate;
1023 cloned->growthFactorSwap = growthFactorSwap;
1024 cloned->configuration = configuration;
1025
1026 if (state)
1027 cloned->state = state->Clone();
1028 else if (densityMatrix) {
1029 cloned->densityMatrix = densityMatrix->Clone();
1030 if (!cloned->densityMatrix)
1031 throw std::runtime_error(
1032 "GpuSimulator::Clone: Failed to clone density matrix state.");
1033 } else if (mpo) {
1034 cloned->mpo = mpo->Clone();
1035 if (!cloned->mpo)
1036 throw std::runtime_error(
1037 "GpuSimulator::Clone: Failed to clone matrix product operator "
1038 "state.");
1039
1040 cloned->gateCounterObserver =
1041 std::make_shared<GateCounterObserver>(upcomingGateIndex);
1042 cloned->RegisterObserver(cloned->gateCounterObserver);
1043
1044 cloned->dummySim = dummySim ? dummySim->Clone() : nullptr;
1045
1046 cloned->curMaxBondDim = curMaxBondDim;
1047 cloned->mpo->SetCallbackContext(cloned.get());
1048 } else if (mps) {
1049 cloned->mps = mps->Clone();
1050
1051 cloned->gateCounterObserver =
1052 std::make_shared<GateCounterObserver>(upcomingGateIndex);
1053 cloned->RegisterObserver(cloned->gateCounterObserver);
1054
1055 cloned->dummySim = dummySim ? dummySim->Clone() : nullptr;
1056
1057 cloned->curMaxBondDim = curMaxBondDim;
1058 cloned->mps->SetCallbackContext(cloned.get());
1059 } else if (tn || pp) {
1060 throw std::runtime_error(
1061 "GpuSimulator::Clone: Cloning Tensor Network or Pauli Propagator "
1062 "simulation is not "
1063 "supported.");
1064 }
1065
1066 if (configuration.IsSet("seed"))
1067 cloned->SetSeed(DeriveSeed(
1068 std::stoull(configuration.GetConfiguration("seed")),
1069 nextSeedStream++));
1070
1071 return cloned;
1072 }
1073};
1074
1075} // namespace Private
1076} // namespace Simulators
1077
1078#endif
1079#endif
1080#endif
int ApplyK(void *sim, int qubit)
int ApplyRx(void *sim, int qubit, double theta)
int ApplyX(void *sim, int qubit)
int ApplyU(void *sim, int qubit, double theta, double phi, double lambda, double gamma)
int ApplyCRy(void *sim, int controlQubit, int targetQubit, double theta)
int ApplyTDG(void *sim, int qubit)
int ApplyS(void *sim, int qubit)
int ApplyCX(void *sim, int controlQubit, int targetQubit)
int ApplyCRz(void *sim, int controlQubit, int targetQubit, double theta)
int ApplyCP(void *sim, int controlQubit, int targetQubit, double theta)
int ApplySDG(void *sim, int qubit)
int ApplyCSwap(void *sim, int controlQubit, int qubit1, int qubit2)
int ApplyCCX(void *sim, int controlQubit1, int controlQubit2, int targetQubit)
int ApplyY(void *sim, int qubit)
int ApplyZ(void *sim, int qubit)
int ApplyH(void *sim, int qubit)
int ApplyCY(void *sim, int controlQubit, int targetQubit)
int ApplyCU(void *sim, int controlQubit, int targetQubit, double theta, double phi, double lambda, double gamma)
int ApplySwap(void *sim, int qubit1, int qubit2)
int ApplyRy(void *sim, int qubit, double theta)
int ApplyP(void *sim, int qubit, double theta)
int ApplyCH(void *sim, int controlQubit, int targetQubit)
int GetSimulationType(void *sim)
int ApplyCZ(void *sim, int controlQubit, int targetQubit)
int ApplyRz(void *sim, int qubit, double theta)
int ApplyT(void *sim, int qubit)
int ApplyCRx(void *sim, int controlQubit, int targetQubit, double theta)
uint_fast64_t qubit_t
The type of a qubit.
Definition Types.h:21