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;
58 const Eigen::Matrix2cd& gate)
override
60 const AER::reg_t qubits = {qubit};
61 AER::cmatrix_t gate_matrix(2, 2);
62 gate_matrix(0, 0) = gate(0, 0);
63 gate_matrix(0, 1) = gate(0, 1);
64 gate_matrix(1, 0) = gate(1, 0);
65 gate_matrix(1, 1) = gate(1, 1);
67 state->apply_unitary(qubits, gate_matrix);
68 NotifyObservers(qubits);
79 const Eigen::Matrix4cd& gate)
override
81 const AER::reg_t qubits = {qubit1, qubit0};
82 AER::cmatrix_t gate_matrix(4, 4);
83 for (
size_t i = 0; i < 4; ++i)
84 for (
size_t j = 0; j < 4; ++j)
85 gate_matrix(i, j) = gate(i, j);
87 state->apply_unitary(qubits, gate_matrix);
88 NotifyObservers(qubits);
100 throw std::runtime_error(
"P gate not supported in stabilizer simulation");
105 AER::Operations::Op op;
106 op.type = AER::Operations::OpType::gate;
108 op.qubits = AER::reg_t{qubit};
109 op.params = {lambda};
111 state->buffer_op(std::move(op));
113 const AER::cvector_t P = {{1, 0}, std::polar(1., lambda)};
114 state->apply_diagonal_matrix(qubits, P);
117 NotifyObservers(qubits);
128 state->apply_x(qubit);
129 NotifyObservers(qubits);
140 state->apply_y(qubit);
141 NotifyObservers(qubits);
152 state->apply_z(qubit);
153 NotifyObservers(qubits);
164 state->apply_h(qubit);
165 NotifyObservers(qubits);
179 AER::Operations::Op op;
180 op.type = AER::Operations::OpType::gate;
182 op.qubits = AER::reg_t{qubit};
184 state->buffer_op(std::move(op));
186 const AER::cvector_t S = {{1, 0}, complex_t(0.0, 1)};
187 state->apply_diagonal_matrix(qubits, S);
190 NotifyObservers(qubits);
204 AER::Operations::Op op;
205 op.type = AER::Operations::OpType::gate;
207 op.qubits = AER::reg_t{qubit};
209 state->buffer_op(std::move(op));
211 const AER::cvector_t Sdg = {{1, 0}, complex_t(0.0, -1)};
212 state->apply_diagonal_matrix(qubits, Sdg);
215 NotifyObservers(qubits);
226 throw std::runtime_error(
"T gate not supported in stabilizer simulation");
232 AER::Operations::Op op;
233 op.type = AER::Operations::OpType::gate;
235 op.qubits = AER::reg_t{qubit};
236 state->buffer_op(std::move(op));
238 const AER::cvector_t T = {{1, 0}, std::polar<double>(1, M_PI / 4.)};
239 state->apply_diagonal_matrix(qubits, T);
242 NotifyObservers(qubits);
253 throw std::runtime_error(
254 "TDG gate not supported in stabilizer simulation");
260 AER::Operations::Op op;
261 op.type = AER::Operations::OpType::gate;
263 op.qubits = AER::reg_t{qubit};
264 state->buffer_op(std::move(op));
266 const AER::cvector_t Tdg = {{1, 0}, std::polar<double>(1, -M_PI / 4.)};
267 state->apply_diagonal_matrix(qubits, Tdg);
270 NotifyObservers(qubits);
284 AER::Operations::Op op;
285 op.type = AER::Operations::OpType::gate;
287 op.qubits = AER::reg_t{qubit};
289 state->buffer_op(std::move(op));
295 state->apply_unitary(qubits, AER::Linalg::Matrix::SX);
298 NotifyObservers(qubits);
312 AER::Operations::Op op;
313 op.type = AER::Operations::OpType::gate;
315 op.qubits = AER::reg_t{qubit};
317 state->buffer_op(std::move(op));
319 state->apply_unitary(qubits, AER::Linalg::Matrix::SXDG);
321 NotifyObservers(qubits);
340 static const cmatrix_t K = AER::Utils::make_matrix<complex_t>(
341 {{{1. / std::sqrt(2.), 0}, {0, -1. / std::sqrt(2.)}},
342 {{0, 1. / std::sqrt(2.)}, {-1. / std::sqrt(2.), 0}}});
344 state->apply_unitary(qubits, K);
347 NotifyObservers(qubits);
359 throw std::runtime_error(
360 "Rx gate not supported in stabilizer simulation");
369 const cmatrix_t rx = AER::Linalg::Matrix::rx(theta);
370 state->apply_unitary(qubits, rx);
373 NotifyObservers(qubits);
385 throw std::runtime_error(
386 "Ry gate not supported in stabilizer simulation");
395 const cmatrix_t ry = AER::Linalg::Matrix::ry(theta);
397 state->apply_unitary(qubits, ry);
400 NotifyObservers(qubits);
412 throw std::runtime_error(
413 "Rz gate not supported in stabilizer simulation");
436 const cmatrix_t rz = AER::Linalg::Matrix::rz(theta);
438 state->apply_unitary(qubits, rz);
441 NotifyObservers(qubits);
455 double gamma)
override {
457 throw std::runtime_error(
"U gate not supported in stabilizer simulation");
466 const cmatrix_t u = AER::Linalg::Matrix::u4(theta, phi, lambda, gamma);
468 state->apply_unitary(qubits, u);
471 NotifyObservers(qubits);
483 state->apply_cx(qubits);
484 NotifyObservers(qubits);
499 ApplyCX(ctrl_qubit, tgt_qubit);
502 state->apply_cy(qubits);
504 NotifyObservers(qubits);
516 state->apply_cz(qubits);
517 NotifyObservers(qubits);
529 double lambda)
override {
531 throw std::runtime_error(
532 "CP gate not supported in stabilizer simulation");
537 const double halfAngle = lambda * 0.5;
538 ApplyP(ctrl_qubit, halfAngle);
539 ApplyCX(ctrl_qubit, tgt_qubit);
540 ApplyP(tgt_qubit, -halfAngle);
541 ApplyCX(ctrl_qubit, tgt_qubit);
542 ApplyP(tgt_qubit, halfAngle);
544 const cmatrix_t CP = AER::Linalg::Matrix::cphase(lambda);
546 state->apply_unitary(qubits, CP);
549 NotifyObservers(qubits);
561 double theta)
override {
563 throw std::runtime_error(
564 "CRx gate not supported in stabilizer simulation");
569 const double halfAngle = theta * 0.5;
572 ApplyCX(ctrl_qubit, tgt_qubit);
573 ApplyRz(tgt_qubit, -halfAngle);
574 ApplyCX(ctrl_qubit, tgt_qubit);
582 const double t2 = theta * 0.5;
584 const complex_t i(0., 1.);
585 mat(1, 1) = std::cos(t2);
586 mat(1, 3) = -i * std::sin(t2);
587 mat(3, 1) = mat(1, 3);
588 mat(3, 3) = mat(1, 1);
591 state->apply_unitary(qubits, mat);
594 NotifyObservers(qubits);
606 double theta)
override {
608 throw std::runtime_error(
609 "CRy gate not supported in stabilizer simulation");
614 const double halfAngle = theta * 0.5;
617 ApplyCX(ctrl_qubit, tgt_qubit);
618 ApplyRy(tgt_qubit, -halfAngle);
619 ApplyCX(ctrl_qubit, tgt_qubit);
625 const double t2 = theta * 0.5;
627 mat(1, 1) = std::complex<double>(cos(t2), 0);
628 mat(1, 3) = std::complex<double>(-sin(t2), 0);
629 mat(3, 1) = std::complex<double>(sin(t2), 0);
630 mat(3, 3) = mat(1, 1);
633 state->apply_unitary(qubits, mat);
636 NotifyObservers(qubits);
648 double theta)
override {
650 throw std::runtime_error(
651 "CRz gate not supported in stabilizer simulation");
656 const double halfAngle = theta * 0.5;
658 ApplyCX(ctrl_qubit, tgt_qubit);
659 ApplyRz(tgt_qubit, -halfAngle);
660 ApplyCX(ctrl_qubit, tgt_qubit);
662 const double t2 = theta * 0.5;
664 {1, 0}, std::polar(1., -t2), {1, 0}, std::polar(1., t2)};
667 state->apply_diagonal_matrix(qubits, v);
670 NotifyObservers(qubits);
682 throw std::runtime_error(
683 "CH gate not supported in stabilizer simulation");
690 ApplyCX(ctrl_qubit, tgt_qubit);
693 ApplyCX(ctrl_qubit, tgt_qubit);
700 const cmatrix_t CU = AER::Linalg::Matrix::cu(M_PI_2, 0, M_PI, 0);
701 state->apply_unitary(qubits, CU);
704 NotifyObservers(qubits);
716 throw std::runtime_error(
717 "CSx gate not supported in stabilizer simulation");
725 ApplyCX(ctrl_qubit, tgt_qubit);
727 ApplyCX(ctrl_qubit, tgt_qubit);
730 static const cmatrix_t CSX = AER::Utils::make_matrix<complex_t>(
731 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}},
732 {{0, 0}, {0.5, 0.5}, {0, 0}, {0.5, -0.5}},
733 {{0, 0}, {0, 0}, {1, 0}, {0, 0}},
734 {{0, 0}, {0.5, -0.5}, {0, 0}, {0.5, 0.5}}});
736 state->apply_unitary(qubits, CSX);
738 NotifyObservers(qubits);
751 throw std::runtime_error(
752 "CSxDAG gate not supported in stabilizer simulation");
758 ApplyCX(ctrl_qubit, tgt_qubit);
760 ApplyCX(ctrl_qubit, tgt_qubit);
765 static const cmatrix_t CSXDG = AER::Utils::make_matrix<complex_t>(
766 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}},
767 {{0, 0}, {0.5, -0.5}, {0, 0}, {0.5, 0.5}},
768 {{0, 0}, {0, 0}, {1, 0}, {0, 0}},
769 {{0, 0}, {0.5, 0.5}, {0, 0}, {0.5, -0.5}}});
771 state->apply_unitary(qubits, CSXDG);
774 NotifyObservers(qubits);
789 AER::Operations::Op op;
790 op.type = AER::Operations::OpType::gate;
792 op.qubits = AER::reg_t{qubit0, qubit1};
794 state->buffer_op(std::move(op));
797 state->apply_unitary(qubits, AER::Linalg::Matrix::SWAP);
799 NotifyObservers(qubits);
813 throw std::runtime_error(
814 "CCX gate not supported in stabilizer simulation");
819 AER::Operations::Op op;
820 op.type = AER::Operations::OpType::gate;
822 op.qubits = AER::reg_t{qubit0, qubit1, qubit2};
824 state->buffer_op(std::move(op));
826 static const cmatrix_t mat = AER::Utils::make_matrix<complex_t>(
827 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
828 {{0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
829 {{0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
830 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}},
831 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}},
832 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}},
833 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}},
834 {{0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}});
837 state->apply_unitary(qubits, mat);
840 NotifyObservers(qubits);
854 throw std::runtime_error(
855 "CSwap gate not supported in stabilizer simulation");
860 const int q1 =
static_cast<int>(ctrl_qubit);
861 const int q2 =
static_cast<int>(qubit0);
862 const int q3 =
static_cast<int>(qubit1);
878 static const cmatrix_t mat = AER::Utils::make_matrix<complex_t>(
879 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
880 {{0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
881 {{0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
882 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}},
883 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}},
884 {{0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
885 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}},
886 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}}});
889 state->apply_unitary(qubits, mat);
892 NotifyObservers(qubits);
907 double theta,
double phi,
double lambda,
double gamma)
override {
909 throw std::runtime_error(
910 "CU gate not supported in stabilizer simulation");
915 if (gamma != 0.0)
ApplyP(ctrl_qubit, gamma);
917 const double lambdaPlusPhiHalf = 0.5 * (lambda + phi);
918 const double halfTheta = 0.5 * theta;
919 ApplyP(tgt_qubit, 0.5 * (lambda - phi));
920 ApplyP(ctrl_qubit, lambdaPlusPhiHalf);
921 ApplyCX(ctrl_qubit, tgt_qubit);
922 ApplyU(tgt_qubit, -halfTheta, 0, -lambdaPlusPhiHalf, 0);
923 ApplyCX(ctrl_qubit, tgt_qubit);
924 ApplyU(tgt_qubit, halfTheta, phi, 0, 0);
926 const cmatrix_t CU = AER::Linalg::Matrix::cu(theta, phi, lambda, gamma);
928 state->apply_unitary(qubits, CU);
931 NotifyObservers(qubits);
941 void ApplyNop()
override {
942 AER::Operations::Op op;
944 AER::Operations::OpType::barrier;
946 state->buffer_op(std::move(op));
959 std::unique_ptr<ISimulator> Clone()
override {
960 auto sim = std::make_unique<AerSimulator>();
963 if (simulationType == SimulationType::kMatrixProductState)
964 sim->Configure(
"method",
"matrix_product_state");
965 else if (simulationType == SimulationType::kStabilizer)
966 sim->Configure(
"method",
"stabilizer");
967 else if (simulationType == SimulationType::kTensorNetwork)
968 sim->Configure(
"method",
"tensor_network");
969 else if (simulationType == SimulationType::kExtendedStabilizer)
970 sim->Configure(
"method",
"extended_stabilizer");
972 sim->Configure(
"method",
"statevector");
974 if (simulationType == SimulationType::kMatrixProductState) {
976 sim->Configure(
"matrix_product_state_max_bond_dimension",
977 std::to_string(chi).c_str());
978 if (limitEntanglement) {
979 std::ostringstream oss;
980 oss << std::setprecision(std::numeric_limits<double>::max_digits10)
981 << singularValueThreshold;
982 sim->Configure(
"matrix_product_state_truncation_threshold",
985 sim->Configure(
"mps_sample_measure_algorithm", useMPSMeasureNoCollapse
986 ?
"mps_probabilities"
987 :
"mps_apply_measure");
990 sim->SetMultithreading(
991 enableMultithreading);
993 AER::Vector<complex_t> localSavedAmplitudes =
995 AER::Data localSavedState =
1000 if (state && state->is_initialized()) {
1005 sim->savedAmplitudes = std::move(savedAmplitudes);
1006 sim->savedState = std::move(savedState);
1008 sim->RestoreState();
1012 sim->savedAmplitudes = localSavedAmplitudes;
1013 sim->savedState = localSavedState;
1016 savedAmplitudes = std::move(localSavedAmplitudes);
1017 savedState = std::move(localSavedState);
1020 sim->savedAmplitudes = std::move(localSavedAmplitudes);
1021 sim->savedState = std::move(localSavedState);
1023 sim->RestoreState();
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)
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
uint_fast64_t qubit_t
The type of a qubit.