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;
61 throw std::runtime_error(
"P gate not supported in stabilizer simulation");
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);
89 state->apply_x(qubit);
90 NotifyObservers(qubits);
101 state->apply_y(qubit);
102 NotifyObservers(qubits);
113 state->apply_z(qubit);
114 NotifyObservers(qubits);
125 state->apply_h(qubit);
126 NotifyObservers(qubits);
140 AER::Operations::Op op;
141 op.type = AER::Operations::OpType::gate;
143 op.qubits = AER::reg_t{qubit};
145 state->buffer_op(std::move(op));
147 const AER::cvector_t S = {{1, 0}, complex_t(0.0, 1)};
148 state->apply_diagonal_matrix(qubits, S);
151 NotifyObservers(qubits);
165 AER::Operations::Op op;
166 op.type = AER::Operations::OpType::gate;
168 op.qubits = AER::reg_t{qubit};
170 state->buffer_op(std::move(op));
172 const AER::cvector_t Sdg = {{1, 0}, complex_t(0.0, -1)};
173 state->apply_diagonal_matrix(qubits, Sdg);
176 NotifyObservers(qubits);
187 throw std::runtime_error(
"T gate not supported in stabilizer simulation");
193 AER::Operations::Op op;
194 op.type = AER::Operations::OpType::gate;
196 op.qubits = AER::reg_t{qubit};
197 state->buffer_op(std::move(op));
199 const AER::cvector_t T = {{1, 0}, std::polar<double>(1, M_PI / 4.)};
200 state->apply_diagonal_matrix(qubits, T);
203 NotifyObservers(qubits);
214 throw std::runtime_error(
215 "TDG gate not supported in stabilizer simulation");
221 AER::Operations::Op op;
222 op.type = AER::Operations::OpType::gate;
224 op.qubits = AER::reg_t{qubit};
225 state->buffer_op(std::move(op));
227 const AER::cvector_t Tdg = {{1, 0}, std::polar<double>(1, -M_PI / 4.)};
228 state->apply_diagonal_matrix(qubits, Tdg);
231 NotifyObservers(qubits);
245 AER::Operations::Op op;
246 op.type = AER::Operations::OpType::gate;
248 op.qubits = AER::reg_t{qubit};
250 state->buffer_op(std::move(op));
256 state->apply_unitary(qubits, AER::Linalg::Matrix::SX);
259 NotifyObservers(qubits);
273 AER::Operations::Op op;
274 op.type = AER::Operations::OpType::gate;
276 op.qubits = AER::reg_t{qubit};
278 state->buffer_op(std::move(op));
280 state->apply_unitary(qubits, AER::Linalg::Matrix::SXDG);
282 NotifyObservers(qubits);
301 static const cmatrix_t K = AER::Utils::make_matrix<complex_t>(
302 {{{1. / std::sqrt(2.), 0}, {0, -1. / std::sqrt(2.)}},
303 {{0, 1. / std::sqrt(2.)}, {-1. / std::sqrt(2.), 0}}});
305 state->apply_unitary(qubits, K);
308 NotifyObservers(qubits);
320 throw std::runtime_error(
321 "Rx gate not supported in stabilizer simulation");
330 const cmatrix_t rx = AER::Linalg::Matrix::rx(theta);
331 state->apply_unitary(qubits, rx);
334 NotifyObservers(qubits);
346 throw std::runtime_error(
347 "Ry gate not supported in stabilizer simulation");
356 const cmatrix_t ry = AER::Linalg::Matrix::ry(theta);
358 state->apply_unitary(qubits, ry);
361 NotifyObservers(qubits);
373 throw std::runtime_error(
374 "Rz gate not supported in stabilizer simulation");
397 const cmatrix_t rz = AER::Linalg::Matrix::rz(theta);
399 state->apply_unitary(qubits, rz);
402 NotifyObservers(qubits);
416 double gamma)
override {
418 throw std::runtime_error(
"U gate not supported in stabilizer simulation");
427 const cmatrix_t u = AER::Linalg::Matrix::u4(theta, phi, lambda, gamma);
429 state->apply_unitary(qubits, u);
432 NotifyObservers(qubits);
444 state->apply_cx(qubits);
445 NotifyObservers(qubits);
460 ApplyCX(ctrl_qubit, tgt_qubit);
463 state->apply_cy(qubits);
465 NotifyObservers(qubits);
477 state->apply_cz(qubits);
478 NotifyObservers(qubits);
490 double lambda)
override {
492 throw std::runtime_error(
493 "CP gate not supported in stabilizer simulation");
498 const double halfAngle = lambda * 0.5;
499 ApplyP(ctrl_qubit, halfAngle);
500 ApplyCX(ctrl_qubit, tgt_qubit);
501 ApplyP(tgt_qubit, -halfAngle);
502 ApplyCX(ctrl_qubit, tgt_qubit);
503 ApplyP(tgt_qubit, halfAngle);
505 const cmatrix_t CP = AER::Linalg::Matrix::cphase(lambda);
507 state->apply_unitary(qubits, CP);
510 NotifyObservers(qubits);
522 double theta)
override {
524 throw std::runtime_error(
525 "CRx gate not supported in stabilizer simulation");
530 const double halfAngle = theta * 0.5;
533 ApplyCX(ctrl_qubit, tgt_qubit);
534 ApplyRz(tgt_qubit, -halfAngle);
535 ApplyCX(ctrl_qubit, tgt_qubit);
543 const double t2 = theta * 0.5;
545 const complex_t i(0., 1.);
546 mat(1, 1) = std::cos(t2);
547 mat(1, 3) = -i * std::sin(t2);
548 mat(3, 1) = mat(1, 3);
549 mat(3, 3) = mat(1, 1);
552 state->apply_unitary(qubits, mat);
555 NotifyObservers(qubits);
567 double theta)
override {
569 throw std::runtime_error(
570 "CRy gate not supported in stabilizer simulation");
575 const double halfAngle = theta * 0.5;
578 ApplyCX(ctrl_qubit, tgt_qubit);
579 ApplyRy(tgt_qubit, -halfAngle);
580 ApplyCX(ctrl_qubit, tgt_qubit);
586 const double t2 = theta * 0.5;
588 mat(1, 1) = std::complex<double>(cos(t2), 0);
589 mat(1, 3) = std::complex<double>(-sin(t2), 0);
590 mat(3, 1) = std::complex<double>(sin(t2), 0);
591 mat(3, 3) = mat(1, 1);
594 state->apply_unitary(qubits, mat);
597 NotifyObservers(qubits);
609 double theta)
override {
611 throw std::runtime_error(
612 "CRz gate not supported in stabilizer simulation");
617 const double halfAngle = theta * 0.5;
619 ApplyCX(ctrl_qubit, tgt_qubit);
620 ApplyRz(tgt_qubit, -halfAngle);
621 ApplyCX(ctrl_qubit, tgt_qubit);
623 const double t2 = theta * 0.5;
625 {1, 0}, std::polar(1., -t2), {1, 0}, std::polar(1., t2)};
628 state->apply_diagonal_matrix(qubits, v);
631 NotifyObservers(qubits);
643 throw std::runtime_error(
644 "CH gate not supported in stabilizer simulation");
651 ApplyCX(ctrl_qubit, tgt_qubit);
654 ApplyCX(ctrl_qubit, tgt_qubit);
661 const cmatrix_t CU = AER::Linalg::Matrix::cu(M_PI_2, 0, M_PI, 0);
662 state->apply_unitary(qubits, CU);
665 NotifyObservers(qubits);
677 throw std::runtime_error(
678 "CSx gate not supported in stabilizer simulation");
686 ApplyCX(ctrl_qubit, tgt_qubit);
688 ApplyCX(ctrl_qubit, tgt_qubit);
691 static const cmatrix_t CSX = AER::Utils::make_matrix<complex_t>(
692 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}},
693 {{0, 0}, {0.5, 0.5}, {0, 0}, {0.5, -0.5}},
694 {{0, 0}, {0, 0}, {1, 0}, {0, 0}},
695 {{0, 0}, {0.5, -0.5}, {0, 0}, {0.5, 0.5}}});
697 state->apply_unitary(qubits, CSX);
699 NotifyObservers(qubits);
712 throw std::runtime_error(
713 "CSxDAG gate not supported in stabilizer simulation");
719 ApplyCX(ctrl_qubit, tgt_qubit);
721 ApplyCX(ctrl_qubit, tgt_qubit);
726 static const cmatrix_t CSXDG = AER::Utils::make_matrix<complex_t>(
727 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}},
728 {{0, 0}, {0.5, -0.5}, {0, 0}, {0.5, 0.5}},
729 {{0, 0}, {0, 0}, {1, 0}, {0, 0}},
730 {{0, 0}, {0.5, 0.5}, {0, 0}, {0.5, -0.5}}});
732 state->apply_unitary(qubits, CSXDG);
735 NotifyObservers(qubits);
750 AER::Operations::Op op;
751 op.type = AER::Operations::OpType::gate;
753 op.qubits = AER::reg_t{qubit0, qubit1};
755 state->buffer_op(std::move(op));
758 state->apply_unitary(qubits, AER::Linalg::Matrix::SWAP);
760 NotifyObservers(qubits);
774 throw std::runtime_error(
775 "CCX gate not supported in stabilizer simulation");
780 AER::Operations::Op op;
781 op.type = AER::Operations::OpType::gate;
783 op.qubits = AER::reg_t{qubit0, qubit1, qubit2};
785 state->buffer_op(std::move(op));
787 static const cmatrix_t mat = AER::Utils::make_matrix<complex_t>(
788 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
789 {{0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
790 {{0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
791 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}},
792 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}},
793 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}},
794 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}},
795 {{0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}});
798 state->apply_unitary(qubits, mat);
801 NotifyObservers(qubits);
815 throw std::runtime_error(
816 "CSwap gate not supported in stabilizer simulation");
821 const int q1 = ctrl_qubit;
822 const int q2 = qubit0;
823 const int q3 = qubit1;
839 static const cmatrix_t mat = AER::Utils::make_matrix<complex_t>(
840 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
841 {{0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
842 {{0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
843 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}},
844 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}},
845 {{0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
846 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}},
847 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}}});
850 state->apply_unitary(qubits, mat);
853 NotifyObservers(qubits);
868 double theta,
double phi,
double lambda,
double gamma)
override {
870 throw std::runtime_error(
871 "CU gate not supported in stabilizer simulation");
876 if (gamma != 0.0)
ApplyP(ctrl_qubit, gamma);
878 const double lambdaPlusPhiHalf = 0.5 * (lambda + phi);
879 const double halfTheta = 0.5 * theta;
880 ApplyP(tgt_qubit, 0.5 * (lambda - phi));
881 ApplyP(ctrl_qubit, lambdaPlusPhiHalf);
882 ApplyCX(ctrl_qubit, tgt_qubit);
883 ApplyU(tgt_qubit, -halfTheta, 0, -lambdaPlusPhiHalf, 0);
884 ApplyCX(ctrl_qubit, tgt_qubit);
885 ApplyU(tgt_qubit, halfTheta, phi, 0, 0);
887 const cmatrix_t CU = AER::Linalg::Matrix::cu(theta, phi, lambda, gamma);
889 state->apply_unitary(qubits, CU);
892 NotifyObservers(qubits);
902 void ApplyNop()
override {
903 AER::Operations::Op op;
905 AER::Operations::OpType::barrier;
907 state->buffer_op(std::move(op));
920 std::unique_ptr<ISimulator> Clone()
override {
921 auto sim = std::make_unique<AerSimulator>();
924 if (simulationType == SimulationType::kMatrixProductState)
925 sim->Configure(
"method",
"matrix_product_state");
926 else if (simulationType == SimulationType::kStabilizer)
927 sim->Configure(
"method",
"stabilizer");
928 else if (simulationType == SimulationType::kTensorNetwork)
929 sim->Configure(
"method",
"tensor_network");
930 else if (simulationType == SimulationType::kExtendedStabilizer)
931 sim->Configure(
"method",
"extended_stabilizer");
933 sim->Configure(
"method",
"statevector");
935 if (simulationType == SimulationType::kMatrixProductState) {
937 sim->Configure(
"matrix_product_state_max_bond_dimension",
938 std::to_string(chi).c_str());
939 if (limitEntanglement)
940 sim->Configure(
"matrix_product_state_truncation_threshold",
941 std::to_string(singularValueThreshold).c_str());
942 sim->Configure(
"mps_sample_measure_algorithm", useMPSMeasureNoCollapse
943 ?
"mps_probabilities"
944 :
"mps_apply_measure");
947 sim->SetMultithreading(
948 enableMultithreading);
950 AER::Vector<complex_t> localSavedAmplitudes =
952 AER::Data localSavedState =
957 if (state && state->is_initialized()) {
962 sim->savedAmplitudes = std::move(savedAmplitudes);
963 sim->savedState = std::move(savedState);
969 sim->savedAmplitudes = localSavedAmplitudes;
970 sim->savedState = localSavedState;
973 savedAmplitudes = std::move(localSavedAmplitudes);
974 savedState = std::move(localSavedState);
977 sim->savedAmplitudes = std::move(localSavedAmplitudes);
978 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)
uint_fast64_t qubit_t
The type of a qubit.
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.