Maestro 0.1.0
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
AerSimulator.h
Go to the documentation of this file.
1
13#pragma once
14
15#ifndef _AER_SIMULATOR_H_
16#define _AER_SIMULATOR_H_
17
18#ifndef NO_QISKIT_AER
19
20#ifdef INCLUDED_BY_FACTORY
21
22#include "AerState.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 AerSimulator : public AerState {
42 public:
43 AerSimulator() = default;
44 // allow no copy or assignment
45 AerSimulator(const AerSimulator &) = delete;
46 AerSimulator &operator=(const AerSimulator &) = delete;
47
48 // but allow moving
49 AerSimulator(AerSimulator &&other) = default;
50 AerSimulator &operator=(AerSimulator &&other) = default;
51
59 void ApplyP(Types::qubit_t qubit, double lambda) override {
60 if (GetSimulationType() == SimulationType::kStabilizer)
61 throw std::runtime_error("P gate not supported in stabilizer simulation");
62
63 const Types::qubits_vector qubits = {qubit};
64
65 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
66 AER::Operations::Op op;
67 op.type = AER::Operations::OpType::gate;
68 op.name = "p";
69 op.qubits = AER::reg_t{qubit};
70 op.params = {lambda};
71
72 state->buffer_op(std::move(op));
73 } else {
74 const AER::cvector_t P = {{1, 0}, std::polar(1., lambda)};
75 state->apply_diagonal_matrix(qubits, P);
76 }
77
78 NotifyObservers(qubits);
79 }
80
87 void ApplyX(Types::qubit_t qubit) override {
88 const Types::qubits_vector qubits = {qubit};
89 state->apply_x(qubit);
90 NotifyObservers(qubits);
91 }
92
99 void ApplyY(Types::qubit_t qubit) override {
100 const Types::qubits_vector qubits = {qubit};
101 state->apply_y(qubit);
102 NotifyObservers(qubits);
103 }
104
111 void ApplyZ(Types::qubit_t qubit) override {
112 const Types::qubits_vector qubits = {qubit};
113 state->apply_z(qubit);
114 NotifyObservers(qubits);
115 }
116
123 void ApplyH(Types::qubit_t qubit) override {
124 const Types::qubits_vector qubits = {qubit};
125 state->apply_h(qubit);
126 NotifyObservers(qubits);
127 }
128
135 void ApplyS(Types::qubit_t qubit) override {
136 const Types::qubits_vector qubits = {qubit};
137
138 if (GetSimulationType() == SimulationType::kStabilizer || GetSimulationType() == SimulationType::kExtendedStabilizer) {
139 AER::Operations::Op op;
140 op.type = AER::Operations::OpType::gate;
141 op.name = "s";
142 op.qubits = AER::reg_t{qubit};
143
144 state->buffer_op(std::move(op));
145 } else {
146 const AER::cvector_t S = {{1, 0}, complex_t(0.0, 1)};
147 state->apply_diagonal_matrix(qubits, S);
148 }
149
150 NotifyObservers(qubits);
151 }
152
159 void ApplySDG(Types::qubit_t qubit) override {
160 const Types::qubits_vector qubits = {qubit};
161
162 if (GetSimulationType() == SimulationType::kStabilizer ||
163 GetSimulationType() == SimulationType::kExtendedStabilizer) {
164 AER::Operations::Op op;
165 op.type = AER::Operations::OpType::gate;
166 op.name = "sdg";
167 op.qubits = AER::reg_t{qubit};
168
169 state->buffer_op(std::move(op));
170 } else {
171 const AER::cvector_t Sdg = {{1, 0}, complex_t(0.0, -1)};
172 state->apply_diagonal_matrix(qubits, Sdg);
173 }
174
175 NotifyObservers(qubits);
176 }
177
184 void ApplyT(Types::qubit_t qubit) override {
185 if (GetSimulationType() == SimulationType::kStabilizer)
186 throw std::runtime_error("T gate not supported in stabilizer simulation");
187
188 const Types::qubits_vector qubits = {qubit};
189 // state->apply_u(qubit, 0, 0, M_PI / 4.0);
190
191 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
192 AER::Operations::Op op;
193 op.type = AER::Operations::OpType::gate;
194 op.name = "t";
195 op.qubits = AER::reg_t{qubit};
196 state->buffer_op(std::move(op));
197 } else {
198 const AER::cvector_t T = {{1, 0}, std::polar<double>(1, M_PI / 4.)};
199 state->apply_diagonal_matrix(qubits, T);
200 }
201
202 NotifyObservers(qubits);
203 }
204
211 void ApplyTDG(Types::qubit_t qubit) override {
212 if (GetSimulationType() == SimulationType::kStabilizer)
213 throw std::runtime_error(
214 "TDG gate not supported in stabilizer simulation");
215
216 const Types::qubits_vector qubits = {qubit};
217 // state->apply_u(qubit, 0, 0, -M_PI / 4.0);
218
219 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
220 AER::Operations::Op op;
221 op.type = AER::Operations::OpType::gate;
222 op.name = "tdg";
223 op.qubits = AER::reg_t{qubit};
224 state->buffer_op(std::move(op));
225 } else {
226 const AER::cvector_t Tdg = {{1, 0}, std::polar<double>(1, -M_PI / 4.)};
227 state->apply_diagonal_matrix(qubits, Tdg);
228 }
229
230 NotifyObservers(qubits);
231 }
232
239 void ApplySx(Types::qubit_t qubit) override {
240 const Types::qubits_vector qubits = {qubit};
241
242 if (GetSimulationType() == SimulationType::kStabilizer || GetSimulationType() == SimulationType::kExtendedStabilizer) {
243 AER::Operations::Op op;
244 op.type = AER::Operations::OpType::gate;
245 op.name = "sx";
246 op.qubits = AER::reg_t{qubit};
247
248 state->buffer_op(std::move(op));
249 } else {
250 // there is a difference in the global phase for this
251 // changed to match qcsim behavior (and also the qiskit docs and
252 // implementation - not the one exposed in 'contrib', though)
253 // state->apply_mcrx({ qubit }, -M_PI / 4.0);
254 state->apply_unitary(qubits, AER::Linalg::Matrix::SX);
255 }
256
257 NotifyObservers(qubits);
258 }
259
266 void ApplySxDAG(Types::qubit_t qubit) override {
267 const Types::qubits_vector qubits = {qubit};
268
269 if (GetSimulationType() == SimulationType::kStabilizer ||
270 GetSimulationType() == SimulationType::kExtendedStabilizer) {
271 AER::Operations::Op op;
272 op.type = AER::Operations::OpType::gate;
273 op.name = "sxdg";
274 op.qubits = AER::reg_t{qubit};
275
276 state->buffer_op(std::move(op));
277 } else
278 state->apply_unitary(qubits, AER::Linalg::Matrix::SXDG);
279
280 NotifyObservers(qubits);
281 }
282
289 void ApplyK(Types::qubit_t qubit) override {
290 const Types::qubits_vector qubits = {qubit};
291
292 if (GetSimulationType() == SimulationType::kStabilizer ||
293 GetSimulationType() == SimulationType::kExtendedStabilizer) {
294 ApplyZ(qubit);
295 ApplyS(qubit);
296 ApplyH(qubit);
297 ApplyS(qubit);
298 } else {
299 static const cmatrix_t K = AER::Utils::make_matrix<complex_t>(
300 {{{1. / std::sqrt(2.), 0}, {0, -1. / std::sqrt(2.)}},
301 {{0, 1. / std::sqrt(2.)}, {-1. / std::sqrt(2.), 0}}});
302
303 state->apply_unitary(qubits, K);
304 }
305
306 NotifyObservers(qubits);
307 }
308
316 void ApplyRx(Types::qubit_t qubit, double theta) override {
317 if (GetSimulationType() == SimulationType::kStabilizer)
318 throw std::runtime_error(
319 "Rx gate not supported in stabilizer simulation");
320
321 const Types::qubits_vector qubits = {qubit};
322
323 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
324 ApplyH(qubit);
325 ApplyRz(qubit, theta);
326 ApplyH(qubit);
327 } else {
328 const cmatrix_t rx = AER::Linalg::Matrix::rx(theta);
329 state->apply_unitary(qubits, rx);
330 }
331
332 NotifyObservers(qubits);
333 }
334
342 void ApplyRy(Types::qubit_t qubit, double theta) override {
343 if (GetSimulationType() == SimulationType::kStabilizer)
344 throw std::runtime_error(
345 "Ry gate not supported in stabilizer simulation");
346
347 const Types::qubits_vector qubits = {qubit};
348
349 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
350 ApplySDG(qubit);
351 ApplyRx(qubit, theta);
352 ApplyS(qubit);
353 } else {
354 const cmatrix_t ry = AER::Linalg::Matrix::ry(theta);
355
356 state->apply_unitary(qubits, ry);
357 }
358
359 NotifyObservers(qubits);
360 }
361
369 void ApplyRz(Types::qubit_t qubit, double theta) override {
370 if (GetSimulationType() == SimulationType::kStabilizer)
371 throw std::runtime_error(
372 "Rz gate not supported in stabilizer simulation");
373
374 const Types::qubits_vector qubits = {qubit};
375 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
376 // this does not suffice, as it is implemented only for pi/4 multiples by
377 // qiskit aer... use p instead, which is implemented for any angle...
378 // there is a phase difference, but it is not important for the stabilizer
379 // simulation
380
381 // it's very important as many other non-clifford gates are implemented based on rotations!
382
383 /*
384 AER::Operations::Op op;
385 op.type = AER::Operations::OpType::gate;
386 op.name = "rz";
387 op.qubits = AER::reg_t{qubit};
388 op.params = {theta};
389
390 state->buffer_op(std::move(op));
391 */
392 ApplyP(qubit, theta);
393 } else {
394 const cmatrix_t rz = AER::Linalg::Matrix::rz(theta);
395
396 state->apply_unitary(qubits, rz);
397 }
398
399 NotifyObservers(qubits);
400 }
401
412 void ApplyU(Types::qubit_t qubit, double theta, double phi, double lambda,
413 double gamma) override {
414 if (GetSimulationType() == SimulationType::kStabilizer)
415 throw std::runtime_error("U gate not supported in stabilizer simulation");
416
417 const Types::qubits_vector qubits = {qubit};
418
419 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
420 ApplyRz(qubit, lambda);
421 ApplyRy(qubit, theta);
422 ApplyRz(qubit, phi);
423 } else {
424 const cmatrix_t u = AER::Linalg::Matrix::u4(theta, phi, lambda, gamma);
425
426 state->apply_unitary(qubits, u);
427 }
428
429 NotifyObservers(qubits);
430 }
431
439 void ApplyCX(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
440 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
441 state->apply_cx(qubits);
442 NotifyObservers(qubits);
443 }
444
452 void ApplyCY(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
453 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
454
455 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
456 ApplySDG(tgt_qubit);
457 ApplyCX(ctrl_qubit, tgt_qubit);
458 ApplyS(tgt_qubit);
459 } else {
460 state->apply_cy(qubits);
461 }
462 NotifyObservers(qubits);
463 }
464
472 void ApplyCZ(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
473 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
474 state->apply_cz(qubits);
475 NotifyObservers(qubits);
476 }
477
486 void ApplyCP(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
487 double lambda) override {
488 if (GetSimulationType() == SimulationType::kStabilizer)
489 throw std::runtime_error(
490 "CP gate not supported in stabilizer simulation");
491
492 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
493
494 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
495 const double halfAngle = lambda * 0.5;
496 ApplyP(ctrl_qubit, halfAngle);
497 ApplyCX(ctrl_qubit, tgt_qubit);
498 ApplyP(tgt_qubit, -halfAngle);
499 ApplyCX(ctrl_qubit, tgt_qubit);
500 ApplyP(tgt_qubit, halfAngle);
501 } else {
502 const cmatrix_t CP = AER::Linalg::Matrix::cphase(lambda);
503 // state->apply_mcphase(qubits, lambda);
504 state->apply_unitary(qubits, CP);
505 }
506
507 NotifyObservers(qubits);
508 }
509
518 void ApplyCRx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
519 double theta) override {
520 if (GetSimulationType() == SimulationType::kStabilizer)
521 throw std::runtime_error(
522 "CRx gate not supported in stabilizer simulation");
523
524 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
525
526 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
527 const double halfAngle = theta * 0.5;
528
529 ApplyH(tgt_qubit);
530 ApplyCX(ctrl_qubit, tgt_qubit);
531 ApplyRz(tgt_qubit, -halfAngle);
532 ApplyCX(ctrl_qubit, tgt_qubit);
533 ApplyRz(tgt_qubit, halfAngle);
534 ApplyH(tgt_qubit);
535 } else {
536 cmatrix_t mat(4, 4);
537 mat(0, 0) = 1;
538 mat(2, 2) = 1;
539
540 const double t2 = theta * 0.5;
541
542 const complex_t i(0., 1.);
543 mat(1, 1) = std::cos(t2);
544 mat(1, 3) = -i * std::sin(t2);
545 mat(3, 1) = mat(1, 3);
546 mat(3, 3) = mat(1, 1);
547
548 // state->apply_mcrx(qubits, theta);
549 state->apply_unitary(qubits, mat);
550 }
551
552 NotifyObservers(qubits);
553 }
554
563 void ApplyCRy(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
564 double theta) override {
565 if (GetSimulationType() == SimulationType::kStabilizer)
566 throw std::runtime_error(
567 "CRy gate not supported in stabilizer simulation");
568
569 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
570
571 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
572 const double halfAngle = theta * 0.5;
573
574 ApplyRy(tgt_qubit, halfAngle);
575 ApplyCX(ctrl_qubit, tgt_qubit);
576 ApplyRy(tgt_qubit, -halfAngle);
577 ApplyCX(ctrl_qubit, tgt_qubit);
578 } else {
579 cmatrix_t mat(4, 4);
580 mat(0, 0) = 1;
581 mat(2, 2) = 1;
582
583 const double t2 = theta * 0.5;
584
585 mat(1, 1) = std::complex<double>(cos(t2), 0);
586 mat(1, 3) = std::complex<double>(-sin(t2), 0);
587 mat(3, 1) = std::complex<double>(sin(t2), 0);
588 mat(3, 3) = mat(1, 1);
589
590 // state->apply_mcry(qubits, theta);
591 state->apply_unitary(qubits, mat);
592 }
593
594 NotifyObservers(qubits);
595 }
596
605 void ApplyCRz(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
606 double theta) override {
607 if (GetSimulationType() == SimulationType::kStabilizer)
608 throw std::runtime_error(
609 "CRz gate not supported in stabilizer simulation");
610
611 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
612
613 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
614 const double halfAngle = theta * 0.5;
615 ApplyRz(tgt_qubit, halfAngle);
616 ApplyCX(ctrl_qubit, tgt_qubit);
617 ApplyRz(tgt_qubit, -halfAngle);
618 ApplyCX(ctrl_qubit, tgt_qubit);
619 } else {
620 const double t2 = theta * 0.5;
621 AER::cvector_t v = {
622 {1, 0}, std::polar(1., -t2), {1, 0}, std::polar(1., t2)};
623
624 // state->apply_mcrz(qubits, theta);
625 state->apply_diagonal_matrix(qubits, v);
626 }
627
628 NotifyObservers(qubits);
629 }
630
638 void ApplyCH(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
639 if (GetSimulationType() == SimulationType::kStabilizer)
640 throw std::runtime_error(
641 "CH gate not supported in stabilizer simulation");
642
643 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
644
645 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
646 ApplyH(tgt_qubit);
647 ApplySDG(tgt_qubit);
648 ApplyCX(ctrl_qubit, tgt_qubit);
649 ApplyH(tgt_qubit);
650 ApplyT(tgt_qubit);
651 ApplyCX(ctrl_qubit, tgt_qubit);
652 ApplyT(tgt_qubit);
653 ApplyH(tgt_qubit);
654 ApplyS(tgt_qubit);
655 ApplyX(tgt_qubit);
656 ApplyS(ctrl_qubit);
657 } else {
658 const cmatrix_t CU = AER::Linalg::Matrix::cu(M_PI_2, 0, M_PI, 0);
659 state->apply_unitary(qubits, CU);
660 // state->apply_cu(qubits, M_PI_2, 0, M_PI, 0);
661 }
662 NotifyObservers(qubits);
663 }
664
672 void ApplyCSx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
673 if (GetSimulationType() == SimulationType::kStabilizer)
674 throw std::runtime_error(
675 "CSx gate not supported in stabilizer simulation");
676
677 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
678
679 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
680 ApplyH(tgt_qubit);
681 ApplyT(ctrl_qubit);
682 ApplyT(tgt_qubit);
683 ApplyCX(ctrl_qubit, tgt_qubit);
684 ApplyTDG(tgt_qubit);
685 ApplyCX(ctrl_qubit, tgt_qubit);
686 ApplyH(tgt_qubit);
687 } else {
688 static const cmatrix_t CSX = AER::Utils::make_matrix<complex_t>(
689 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}},
690 {{0, 0}, {0.5, 0.5}, {0, 0}, {0.5, -0.5}},
691 {{0, 0}, {0, 0}, {1, 0}, {0, 0}},
692 {{0, 0}, {0.5, -0.5}, {0, 0}, {0.5, 0.5}}});
693
694
695 state->apply_unitary(qubits, CSX);
696 }
697 NotifyObservers(qubits);
698 }
699
707 void ApplyCSxDAG(Types::qubit_t ctrl_qubit,
708 Types::qubit_t tgt_qubit) override {
709 if (GetSimulationType() == SimulationType::kStabilizer)
710 throw std::runtime_error(
711 "CSxDAG gate not supported in stabilizer simulation");
712
713 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
714
715 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
716 ApplyH(tgt_qubit);
717 ApplyCX(ctrl_qubit, tgt_qubit);
718 ApplyT(tgt_qubit);
719 ApplyCX(ctrl_qubit, tgt_qubit);
720 ApplyTDG(ctrl_qubit);
721 ApplyTDG(tgt_qubit);
722 ApplyH(tgt_qubit);
723 } else {
724 static const cmatrix_t CSXDG = AER::Utils::make_matrix<complex_t>(
725 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}},
726 {{0, 0}, {0.5, -0.5}, {0, 0}, {0.5, 0.5}},
727 {{0, 0}, {0, 0}, {1, 0}, {0, 0}},
728 {{0, 0}, {0.5, 0.5}, {0, 0}, {0.5, -0.5}}});
729
730 state->apply_unitary(qubits, CSXDG);
731 }
732
733 NotifyObservers(qubits);
734 }
735
743 void ApplySwap(Types::qubit_t qubit0, Types::qubit_t qubit1) override {
744 const Types::qubits_vector qubits = {qubit0, qubit1};
745
746 if (GetSimulationType() == SimulationType::kStabilizer || GetSimulationType() == SimulationType::kExtendedStabilizer) {
747 AER::Operations::Op op;
748 op.type = AER::Operations::OpType::gate;
749 op.name = "swap";
750 op.qubits = AER::reg_t{qubit0, qubit1};
751
752 state->buffer_op(std::move(op));
753 } else
754 // state->apply_mcswap(qubits);
755 state->apply_unitary(qubits, AER::Linalg::Matrix::SWAP);
756
757 NotifyObservers(qubits);
758 }
759
768 void ApplyCCX(Types::qubit_t qubit0, Types::qubit_t qubit1,
769 Types::qubit_t qubit2) override {
770 if (GetSimulationType() == SimulationType::kStabilizer)
771 throw std::runtime_error(
772 "CCX gate not supported in stabilizer simulation");
773
774 const Types::qubits_vector qubits = {qubit0, qubit1, qubit2};
775
776 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
777 AER::Operations::Op op;
778 op.type = AER::Operations::OpType::gate;
779 op.name = "ccx";
780 op.qubits = AER::reg_t{qubit0, qubit1, qubit2};
781
782 state->buffer_op(std::move(op));
783 } else {
784 static const cmatrix_t mat = AER::Utils::make_matrix<complex_t>(
785 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
786 {{0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
787 {{0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
788 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}},
789 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}},
790 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}},
791 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}},
792 {{0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}});
793
794 // state->apply_mcx(qubits);
795 state->apply_unitary(qubits, mat);
796 }
797
798 NotifyObservers(qubits);
799 }
800
809 void ApplyCSwap(Types::qubit_t ctrl_qubit, Types::qubit_t qubit0,
810 Types::qubit_t qubit1) override {
811 if (GetSimulationType() == SimulationType::kStabilizer)
812 throw std::runtime_error(
813 "CSwap gate not supported in stabilizer simulation");
814
815 const Types::qubits_vector qubits = {ctrl_qubit, qubit0, qubit1};
816
817 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
818 const int q1 = ctrl_qubit; // control
819 const int q2 = qubit0;
820 const int q3 = qubit1;
821
822 ApplyCX(q3, q2);
823 ApplyCSx(q2, q3);
824 ApplyCX(q1, q2);
825
826 ApplyP(q3, M_PI);
827 ApplyP(q2, -M_PI_2);
828
829 ApplyCSx(q2, q3);
830 ApplyCX(q1, q2);
831
832 ApplyP(q3, M_PI);
833 ApplyCSx(q1, q3);
834 ApplyCX(q3, q2);
835 } else {
836 static const cmatrix_t mat = AER::Utils::make_matrix<complex_t>(
837 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
838 {{0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
839 {{0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
840 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}},
841 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}},
842 {{0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
843 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}},
844 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}}});
845
846 // state->apply_mcswap(qubits);
847 state->apply_unitary(qubits, mat);
848 }
849
850 NotifyObservers(qubits);
851 }
852
864 void ApplyCU(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
865 double theta, double phi, double lambda, double gamma) override {
866 if (GetSimulationType() == SimulationType::kStabilizer)
867 throw std::runtime_error(
868 "CU gate not supported in stabilizer simulation");
869
870 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
871
872 if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
873 if (gamma != 0.0) ApplyP(ctrl_qubit, gamma);
874
875 const double lambdaPlusPhiHalf = 0.5 * (lambda + phi);
876 const double halfTheta = 0.5 * theta;
877 ApplyP(tgt_qubit, 0.5 * (lambda - phi));
878 ApplyP(ctrl_qubit, lambdaPlusPhiHalf);
879 ApplyCX(ctrl_qubit, tgt_qubit);
880 ApplyU(tgt_qubit, -halfTheta, 0, -lambdaPlusPhiHalf, 0);
881 ApplyCX(ctrl_qubit, tgt_qubit);
882 ApplyU(tgt_qubit, halfTheta, phi, 0, 0);
883 } else {
884 const cmatrix_t CU = AER::Linalg::Matrix::cu(theta, phi, lambda, gamma);
885 // state->apply_mcu(qubits, theta, phi, lambda, gamma);
886 state->apply_unitary(qubits, CU);
887 }
888
889 NotifyObservers(qubits);
890 }
891
899 void ApplyNop() override {
900 AER::Operations::Op op;
901 op.type =
902 AER::Operations::OpType::barrier; // there is also 'nop' but that one
903 // doesn't work with stabilizer
904 state->buffer_op(std::move(op));
905 }
906
917 std::unique_ptr<ISimulator> Clone() override {
918 auto sim = std::make_unique<AerSimulator>();
919
920 // the tricky part is cloning the state
921 if (simulationType == SimulationType::kMatrixProductState)
922 sim->Configure("method", "matrix_product_state");
923 else if (simulationType == SimulationType::kStabilizer)
924 sim->Configure("method", "stabilizer");
925 else if (simulationType == SimulationType::kTensorNetwork)
926 sim->Configure("method", "tensor_network");
927 else if (simulationType == SimulationType::kExtendedStabilizer)
928 sim->Configure("method", "extended_stabilizer");
929 else
930 sim->Configure("method", "statevector");
931
932 if (simulationType == SimulationType::kMatrixProductState) {
933 if (limitSize)
934 sim->Configure("matrix_product_state_max_bond_dimension",
935 std::to_string(chi).c_str());
936 if (limitEntanglement)
937 sim->Configure("matrix_product_state_truncation_threshold",
938 std::to_string(singularValueThreshold).c_str());
939 sim->Configure("mps_sample_measure_algorithm", useMPSMeasureNoCollapse
940 ? "mps_probabilities"
941 : "mps_apply_measure");
942 }
943
944 sim->SetMultithreading(
945 enableMultithreading);
947 AER::Vector<complex_t> localSavedAmplitudes =
948 savedAmplitudes;
949 AER::Data localSavedState =
950 savedState;
953 // now the tricky part
954 if (state && state->is_initialized()) {
955 SaveState(); // this also restores the state if it's destroyed in the
956 // saving process!
957 // now the current state is saved in savedAmplitudes or savedState, so use
958 // it to initialize the cloned state, like this
959 sim->savedAmplitudes = std::move(savedAmplitudes);
960 sim->savedState = std::move(savedState);
961
962 sim->RestoreState(); // now the state is loaded in the cloned simulator
963
964 // those saved previously can be an older state, so put them in the clone,
965 // too
966 sim->savedAmplitudes = localSavedAmplitudes;
967 sim->savedState = localSavedState;
968
969 // those saved previously can be an older state, so put them back
970 savedAmplitudes = std::move(localSavedAmplitudes);
971 savedState = std::move(localSavedState);
972 } else {
973 // std::cout << "Restored from non initialized state" << std::endl;
974 sim->savedAmplitudes = std::move(localSavedAmplitudes);
975 sim->savedState = std::move(localSavedState);
976
977 sim->RestoreState(); // this might not be necessary, but sometimes, not
978 // very often, an exception is thrown about the
979 // state not being initialized, this might prevent
980 // that
981 }
982
983 return sim;
984 }
985};
986
987} // namespace Private
988} // namespace Simulators
989
990#endif
991
992#endif
993
994#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)
int SaveState(void *sim)