15#ifndef _AER_SIMULATOR_H_
16#define _AER_SIMULATOR_H_
20#ifdef INCLUDED_BY_FACTORY
41class AerSimulator :
public AerState {
43 AerSimulator() =
default;
45 AerSimulator(
const AerSimulator &) =
delete;
46 AerSimulator &operator=(
const AerSimulator &) =
delete;
49 AerSimulator(AerSimulator &&other) =
default;
50 AerSimulator &operator=(AerSimulator &&other) =
default;
59 void ApplyP(Types::qubit_t qubit,
double lambda)
override {
61 throw std::runtime_error(
"P gate not supported in stabilizer simulation");
63 const Types::qubits_vector qubits = {qubit};
66 AER::Operations::Op op;
67 op.type = AER::Operations::OpType::gate;
69 op.qubits = AER::reg_t{qubit};
72 state->buffer_op(std::move(op));
74 const AER::cvector_t P = {{1, 0}, std::polar(1., lambda)};
75 state->apply_diagonal_matrix(qubits, P);
78 NotifyObservers(qubits);
87 void ApplyX(Types::qubit_t qubit)
override {
88 const Types::qubits_vector qubits = {qubit};
89 state->apply_x(qubit);
90 NotifyObservers(qubits);
99 void ApplyY(Types::qubit_t qubit)
override {
100 const Types::qubits_vector qubits = {qubit};
101 state->apply_y(qubit);
102 NotifyObservers(qubits);
111 void ApplyZ(Types::qubit_t qubit)
override {
112 const Types::qubits_vector qubits = {qubit};
113 state->apply_z(qubit);
114 NotifyObservers(qubits);
123 void ApplyH(Types::qubit_t qubit)
override {
124 const Types::qubits_vector qubits = {qubit};
125 state->apply_h(qubit);
126 NotifyObservers(qubits);
135 void ApplyS(Types::qubit_t qubit)
override {
136 const Types::qubits_vector qubits = {qubit};
139 AER::Operations::Op op;
140 op.type = AER::Operations::OpType::gate;
142 op.qubits = AER::reg_t{qubit};
144 state->buffer_op(std::move(op));
146 const AER::cvector_t S = {{1, 0}, complex_t(0.0, 1)};
147 state->apply_diagonal_matrix(qubits, S);
150 NotifyObservers(qubits);
159 void ApplySDG(Types::qubit_t qubit)
override {
160 const Types::qubits_vector qubits = {qubit};
164 AER::Operations::Op op;
165 op.type = AER::Operations::OpType::gate;
167 op.qubits = AER::reg_t{qubit};
169 state->buffer_op(std::move(op));
171 const AER::cvector_t Sdg = {{1, 0}, complex_t(0.0, -1)};
172 state->apply_diagonal_matrix(qubits, Sdg);
175 NotifyObservers(qubits);
184 void ApplyT(Types::qubit_t qubit)
override {
186 throw std::runtime_error(
"T gate not supported in stabilizer simulation");
188 const Types::qubits_vector qubits = {qubit};
192 AER::Operations::Op op;
193 op.type = AER::Operations::OpType::gate;
195 op.qubits = AER::reg_t{qubit};
196 state->buffer_op(std::move(op));
198 const AER::cvector_t T = {{1, 0}, std::polar<double>(1, M_PI / 4.)};
199 state->apply_diagonal_matrix(qubits, T);
202 NotifyObservers(qubits);
211 void ApplyTDG(Types::qubit_t qubit)
override {
213 throw std::runtime_error(
214 "TDG gate not supported in stabilizer simulation");
216 const Types::qubits_vector qubits = {qubit};
220 AER::Operations::Op op;
221 op.type = AER::Operations::OpType::gate;
223 op.qubits = AER::reg_t{qubit};
224 state->buffer_op(std::move(op));
226 const AER::cvector_t Tdg = {{1, 0}, std::polar<double>(1, -M_PI / 4.)};
227 state->apply_diagonal_matrix(qubits, Tdg);
230 NotifyObservers(qubits);
239 void ApplySx(Types::qubit_t qubit)
override {
240 const Types::qubits_vector qubits = {qubit};
243 AER::Operations::Op op;
244 op.type = AER::Operations::OpType::gate;
246 op.qubits = AER::reg_t{qubit};
248 state->buffer_op(std::move(op));
254 state->apply_unitary(qubits, AER::Linalg::Matrix::SX);
257 NotifyObservers(qubits);
266 void ApplySxDAG(Types::qubit_t qubit)
override {
267 const Types::qubits_vector qubits = {qubit};
271 AER::Operations::Op op;
272 op.type = AER::Operations::OpType::gate;
274 op.qubits = AER::reg_t{qubit};
276 state->buffer_op(std::move(op));
278 state->apply_unitary(qubits, AER::Linalg::Matrix::SXDG);
280 NotifyObservers(qubits);
289 void ApplyK(Types::qubit_t qubit)
override {
290 const Types::qubits_vector qubits = {qubit};
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}}});
303 state->apply_unitary(qubits, K);
306 NotifyObservers(qubits);
316 void ApplyRx(Types::qubit_t qubit,
double theta)
override {
318 throw std::runtime_error(
319 "Rx gate not supported in stabilizer simulation");
321 const Types::qubits_vector qubits = {qubit};
328 const cmatrix_t rx = AER::Linalg::Matrix::rx(theta);
329 state->apply_unitary(qubits, rx);
332 NotifyObservers(qubits);
342 void ApplyRy(Types::qubit_t qubit,
double theta)
override {
344 throw std::runtime_error(
345 "Ry gate not supported in stabilizer simulation");
347 const Types::qubits_vector qubits = {qubit};
354 const cmatrix_t ry = AER::Linalg::Matrix::ry(theta);
356 state->apply_unitary(qubits, ry);
359 NotifyObservers(qubits);
369 void ApplyRz(Types::qubit_t qubit,
double theta)
override {
371 throw std::runtime_error(
372 "Rz gate not supported in stabilizer simulation");
374 const Types::qubits_vector qubits = {qubit};
394 const cmatrix_t rz = AER::Linalg::Matrix::rz(theta);
396 state->apply_unitary(qubits, rz);
399 NotifyObservers(qubits);
412 void ApplyU(Types::qubit_t qubit,
double theta,
double phi,
double lambda,
413 double gamma)
override {
415 throw std::runtime_error(
"U gate not supported in stabilizer simulation");
417 const Types::qubits_vector qubits = {qubit};
424 const cmatrix_t u = AER::Linalg::Matrix::u4(theta, phi, lambda, gamma);
426 state->apply_unitary(qubits, u);
429 NotifyObservers(qubits);
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);
452 void ApplyCY(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)
override {
453 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
457 ApplyCX(ctrl_qubit, tgt_qubit);
460 state->apply_cy(qubits);
462 NotifyObservers(qubits);
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);
486 void ApplyCP(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
487 double lambda)
override {
489 throw std::runtime_error(
490 "CP gate not supported in stabilizer simulation");
492 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
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);
502 const cmatrix_t CP = AER::Linalg::Matrix::cphase(lambda);
504 state->apply_unitary(qubits, CP);
507 NotifyObservers(qubits);
518 void ApplyCRx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
519 double theta)
override {
521 throw std::runtime_error(
522 "CRx gate not supported in stabilizer simulation");
524 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
527 const double halfAngle = theta * 0.5;
530 ApplyCX(ctrl_qubit, tgt_qubit);
531 ApplyRz(tgt_qubit, -halfAngle);
532 ApplyCX(ctrl_qubit, tgt_qubit);
540 const double t2 = theta * 0.5;
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);
549 state->apply_unitary(qubits, mat);
552 NotifyObservers(qubits);
563 void ApplyCRy(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
564 double theta)
override {
566 throw std::runtime_error(
567 "CRy gate not supported in stabilizer simulation");
569 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
572 const double halfAngle = theta * 0.5;
575 ApplyCX(ctrl_qubit, tgt_qubit);
576 ApplyRy(tgt_qubit, -halfAngle);
577 ApplyCX(ctrl_qubit, tgt_qubit);
583 const double t2 = theta * 0.5;
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);
591 state->apply_unitary(qubits, mat);
594 NotifyObservers(qubits);
605 void ApplyCRz(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
606 double theta)
override {
608 throw std::runtime_error(
609 "CRz gate not supported in stabilizer simulation");
611 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
614 const double halfAngle = theta * 0.5;
616 ApplyCX(ctrl_qubit, tgt_qubit);
617 ApplyRz(tgt_qubit, -halfAngle);
618 ApplyCX(ctrl_qubit, tgt_qubit);
620 const double t2 = theta * 0.5;
622 {1, 0}, std::polar(1., -t2), {1, 0}, std::polar(1., t2)};
625 state->apply_diagonal_matrix(qubits, v);
628 NotifyObservers(qubits);
638 void ApplyCH(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)
override {
640 throw std::runtime_error(
641 "CH gate not supported in stabilizer simulation");
643 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
648 ApplyCX(ctrl_qubit, tgt_qubit);
651 ApplyCX(ctrl_qubit, tgt_qubit);
658 const cmatrix_t CU = AER::Linalg::Matrix::cu(M_PI_2, 0, M_PI, 0);
659 state->apply_unitary(qubits, CU);
662 NotifyObservers(qubits);
672 void ApplyCSx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)
override {
674 throw std::runtime_error(
675 "CSx gate not supported in stabilizer simulation");
677 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
683 ApplyCX(ctrl_qubit, tgt_qubit);
685 ApplyCX(ctrl_qubit, tgt_qubit);
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}}});
695 state->apply_unitary(qubits, CSX);
697 NotifyObservers(qubits);
707 void ApplyCSxDAG(Types::qubit_t ctrl_qubit,
708 Types::qubit_t tgt_qubit)
override {
710 throw std::runtime_error(
711 "CSxDAG gate not supported in stabilizer simulation");
713 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
717 ApplyCX(ctrl_qubit, tgt_qubit);
719 ApplyCX(ctrl_qubit, tgt_qubit);
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}}});
730 state->apply_unitary(qubits, CSXDG);
733 NotifyObservers(qubits);
743 void ApplySwap(Types::qubit_t qubit0, Types::qubit_t qubit1)
override {
744 const Types::qubits_vector qubits = {qubit0, qubit1};
747 AER::Operations::Op op;
748 op.type = AER::Operations::OpType::gate;
750 op.qubits = AER::reg_t{qubit0, qubit1};
752 state->buffer_op(std::move(op));
755 state->apply_unitary(qubits, AER::Linalg::Matrix::SWAP);
757 NotifyObservers(qubits);
768 void ApplyCCX(Types::qubit_t qubit0, Types::qubit_t qubit1,
769 Types::qubit_t qubit2)
override {
771 throw std::runtime_error(
772 "CCX gate not supported in stabilizer simulation");
774 const Types::qubits_vector qubits = {qubit0, qubit1, qubit2};
777 AER::Operations::Op op;
778 op.type = AER::Operations::OpType::gate;
780 op.qubits = AER::reg_t{qubit0, qubit1, qubit2};
782 state->buffer_op(std::move(op));
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}}});
795 state->apply_unitary(qubits, mat);
798 NotifyObservers(qubits);
809 void ApplyCSwap(Types::qubit_t ctrl_qubit, Types::qubit_t qubit0,
810 Types::qubit_t qubit1)
override {
812 throw std::runtime_error(
813 "CSwap gate not supported in stabilizer simulation");
815 const Types::qubits_vector qubits = {ctrl_qubit, qubit0, qubit1};
818 const int q1 = ctrl_qubit;
819 const int q2 = qubit0;
820 const int q3 = qubit1;
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}}});
847 state->apply_unitary(qubits, mat);
850 NotifyObservers(qubits);
864 void ApplyCU(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
865 double theta,
double phi,
double lambda,
double gamma)
override {
867 throw std::runtime_error(
868 "CU gate not supported in stabilizer simulation");
870 const Types::qubits_vector qubits = {ctrl_qubit, tgt_qubit};
873 if (gamma != 0.0)
ApplyP(ctrl_qubit, gamma);
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);
884 const cmatrix_t CU = AER::Linalg::Matrix::cu(theta, phi, lambda, gamma);
886 state->apply_unitary(qubits, CU);
889 NotifyObservers(qubits);
899 void ApplyNop()
override {
900 AER::Operations::Op op;
902 AER::Operations::OpType::barrier;
904 state->buffer_op(std::move(op));
917 std::unique_ptr<ISimulator> Clone()
override {
918 auto sim = std::make_unique<AerSimulator>();
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");
930 sim->Configure(
"method",
"statevector");
932 if (simulationType == SimulationType::kMatrixProductState) {
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");
944 sim->SetMultithreading(
945 enableMultithreading);
947 AER::Vector<complex_t> localSavedAmplitudes =
949 AER::Data localSavedState =
954 if (state && state->is_initialized()) {
959 sim->savedAmplitudes = std::move(savedAmplitudes);
960 sim->savedState = std::move(savedState);
966 sim->savedAmplitudes = localSavedAmplitudes;
967 sim->savedState = localSavedState;
970 savedAmplitudes = std::move(localSavedAmplitudes);
971 savedState = std::move(localSavedState);
974 sim->savedAmplitudes = std::move(localSavedAmplitudes);
975 sim->savedState = std::move(localSavedState);
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)