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
82 const AER::reg_t qubits = {qubit0, qubit1};
83 AER::cmatrix_t gate_matrix(4, 4);
84 for (
size_t i = 0; i < 4; ++i)
85 for (
size_t j = 0; j < 4; ++j)
86 gate_matrix(i, j) = gate(i, j);
88 state->apply_unitary(qubits, gate_matrix);
89 NotifyObservers(qubits);
101 throw std::runtime_error(
"P gate not supported in stabilizer simulation");
106 AER::Operations::Op op;
107 op.type = AER::Operations::OpType::gate;
109 op.qubits = AER::reg_t{qubit};
110 op.params = {lambda};
112 state->buffer_op(std::move(op));
114 const AER::cvector_t P = {{1, 0}, std::polar(1., lambda)};
115 state->apply_diagonal_matrix(qubits, P);
118 NotifyObservers(qubits);
129 state->apply_x(qubit);
130 NotifyObservers(qubits);
141 state->apply_y(qubit);
142 NotifyObservers(qubits);
153 state->apply_z(qubit);
154 NotifyObservers(qubits);
165 state->apply_h(qubit);
166 NotifyObservers(qubits);
180 AER::Operations::Op op;
181 op.type = AER::Operations::OpType::gate;
183 op.qubits = AER::reg_t{qubit};
185 state->buffer_op(std::move(op));
187 const AER::cvector_t S = {{1, 0}, complex_t(0.0, 1)};
188 state->apply_diagonal_matrix(qubits, S);
191 NotifyObservers(qubits);
205 AER::Operations::Op op;
206 op.type = AER::Operations::OpType::gate;
208 op.qubits = AER::reg_t{qubit};
210 state->buffer_op(std::move(op));
212 const AER::cvector_t Sdg = {{1, 0}, complex_t(0.0, -1)};
213 state->apply_diagonal_matrix(qubits, Sdg);
216 NotifyObservers(qubits);
227 throw std::runtime_error(
"T gate not supported in stabilizer simulation");
233 AER::Operations::Op op;
234 op.type = AER::Operations::OpType::gate;
236 op.qubits = AER::reg_t{qubit};
237 state->buffer_op(std::move(op));
239 const AER::cvector_t T = {{1, 0}, std::polar<double>(1, M_PI / 4.)};
240 state->apply_diagonal_matrix(qubits, T);
243 NotifyObservers(qubits);
254 throw std::runtime_error(
255 "TDG gate not supported in stabilizer simulation");
261 AER::Operations::Op op;
262 op.type = AER::Operations::OpType::gate;
264 op.qubits = AER::reg_t{qubit};
265 state->buffer_op(std::move(op));
267 const AER::cvector_t Tdg = {{1, 0}, std::polar<double>(1, -M_PI / 4.)};
268 state->apply_diagonal_matrix(qubits, Tdg);
271 NotifyObservers(qubits);
285 AER::Operations::Op op;
286 op.type = AER::Operations::OpType::gate;
288 op.qubits = AER::reg_t{qubit};
290 state->buffer_op(std::move(op));
296 state->apply_unitary(qubits, AER::Linalg::Matrix::SX);
299 NotifyObservers(qubits);
313 AER::Operations::Op op;
314 op.type = AER::Operations::OpType::gate;
316 op.qubits = AER::reg_t{qubit};
318 state->buffer_op(std::move(op));
320 state->apply_unitary(qubits, AER::Linalg::Matrix::SXDG);
322 NotifyObservers(qubits);
341 static const cmatrix_t K = AER::Utils::make_matrix<complex_t>(
342 {{{1. / std::sqrt(2.), 0}, {0, -1. / std::sqrt(2.)}},
343 {{0, 1. / std::sqrt(2.)}, {-1. / std::sqrt(2.), 0}}});
345 state->apply_unitary(qubits, K);
348 NotifyObservers(qubits);
360 throw std::runtime_error(
361 "Rx gate not supported in stabilizer simulation");
370 const cmatrix_t rx = AER::Linalg::Matrix::rx(theta);
371 state->apply_unitary(qubits, rx);
374 NotifyObservers(qubits);
386 throw std::runtime_error(
387 "Ry gate not supported in stabilizer simulation");
396 const cmatrix_t ry = AER::Linalg::Matrix::ry(theta);
398 state->apply_unitary(qubits, ry);
401 NotifyObservers(qubits);
413 throw std::runtime_error(
414 "Rz gate not supported in stabilizer simulation");
418 AER::Operations::Op op;
419 op.type = AER::Operations::OpType::gate;
421 op.qubits = AER::reg_t{qubit};
424 state->buffer_op(std::move(op));
426 const cmatrix_t rz = AER::Linalg::Matrix::rz(theta);
428 state->apply_unitary(qubits, rz);
431 NotifyObservers(qubits);
445 double gamma)
override {
447 throw std::runtime_error(
"U gate not supported in stabilizer simulation");
456 const cmatrix_t u = AER::Linalg::Matrix::u4(theta, phi, lambda, gamma);
458 state->apply_unitary(qubits, u);
461 NotifyObservers(qubits);
473 state->apply_cx(qubits);
474 NotifyObservers(qubits);
489 ApplyCX(ctrl_qubit, tgt_qubit);
492 state->apply_cy(qubits);
494 NotifyObservers(qubits);
506 state->apply_cz(qubits);
507 NotifyObservers(qubits);
519 double lambda)
override {
521 throw std::runtime_error(
522 "CP gate not supported in stabilizer simulation");
527 const double halfAngle = lambda * 0.5;
528 ApplyP(ctrl_qubit, halfAngle);
529 ApplyCX(ctrl_qubit, tgt_qubit);
530 ApplyP(tgt_qubit, -halfAngle);
531 ApplyCX(ctrl_qubit, tgt_qubit);
532 ApplyP(tgt_qubit, halfAngle);
534 const cmatrix_t CP = AER::Linalg::Matrix::cphase(lambda);
536 state->apply_unitary(qubits, CP);
539 NotifyObservers(qubits);
551 double theta)
override {
553 throw std::runtime_error(
554 "CRx gate not supported in stabilizer simulation");
559 const double halfAngle = theta * 0.5;
562 ApplyCX(ctrl_qubit, tgt_qubit);
563 ApplyRz(tgt_qubit, -halfAngle);
564 ApplyCX(ctrl_qubit, tgt_qubit);
572 const double t2 = theta * 0.5;
574 const complex_t i(0., 1.);
575 mat(1, 1) = std::cos(t2);
576 mat(1, 3) = -i * std::sin(t2);
577 mat(3, 1) = mat(1, 3);
578 mat(3, 3) = mat(1, 1);
581 state->apply_unitary(qubits, mat);
584 NotifyObservers(qubits);
596 double theta)
override {
598 throw std::runtime_error(
599 "CRy gate not supported in stabilizer simulation");
604 const double halfAngle = theta * 0.5;
607 ApplyCX(ctrl_qubit, tgt_qubit);
608 ApplyRy(tgt_qubit, -halfAngle);
609 ApplyCX(ctrl_qubit, tgt_qubit);
615 const double t2 = theta * 0.5;
617 mat(1, 1) = std::complex<double>(cos(t2), 0);
618 mat(1, 3) = std::complex<double>(-sin(t2), 0);
619 mat(3, 1) = std::complex<double>(sin(t2), 0);
620 mat(3, 3) = mat(1, 1);
623 state->apply_unitary(qubits, mat);
626 NotifyObservers(qubits);
638 double theta)
override {
640 throw std::runtime_error(
641 "CRz gate not supported in stabilizer simulation");
646 const double halfAngle = theta * 0.5;
648 ApplyCX(ctrl_qubit, tgt_qubit);
649 ApplyRz(tgt_qubit, -halfAngle);
650 ApplyCX(ctrl_qubit, tgt_qubit);
652 const double t2 = theta * 0.5;
654 {1, 0}, std::polar(1., -t2), {1, 0}, std::polar(1., t2)};
657 state->apply_diagonal_matrix(qubits, v);
660 NotifyObservers(qubits);
672 throw std::runtime_error(
673 "CH gate not supported in stabilizer simulation");
680 ApplyCX(ctrl_qubit, tgt_qubit);
683 ApplyCX(ctrl_qubit, tgt_qubit);
690 const cmatrix_t CU = AER::Linalg::Matrix::cu(M_PI_2, 0, M_PI, 0);
691 state->apply_unitary(qubits, CU);
694 NotifyObservers(qubits);
706 throw std::runtime_error(
707 "CSx gate not supported in stabilizer simulation");
715 ApplyCX(ctrl_qubit, tgt_qubit);
717 ApplyCX(ctrl_qubit, tgt_qubit);
720 static const cmatrix_t CSX = AER::Utils::make_matrix<complex_t>(
721 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}},
722 {{0, 0}, {0.5, 0.5}, {0, 0}, {0.5, -0.5}},
723 {{0, 0}, {0, 0}, {1, 0}, {0, 0}},
724 {{0, 0}, {0.5, -0.5}, {0, 0}, {0.5, 0.5}}});
726 state->apply_unitary(qubits, CSX);
728 NotifyObservers(qubits);
741 throw std::runtime_error(
742 "CSxDAG gate not supported in stabilizer simulation");
748 ApplyCX(ctrl_qubit, tgt_qubit);
750 ApplyCX(ctrl_qubit, tgt_qubit);
755 static const cmatrix_t CSXDG = AER::Utils::make_matrix<complex_t>(
756 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}},
757 {{0, 0}, {0.5, -0.5}, {0, 0}, {0.5, 0.5}},
758 {{0, 0}, {0, 0}, {1, 0}, {0, 0}},
759 {{0, 0}, {0.5, 0.5}, {0, 0}, {0.5, -0.5}}});
761 state->apply_unitary(qubits, CSXDG);
764 NotifyObservers(qubits);
779 AER::Operations::Op op;
780 op.type = AER::Operations::OpType::gate;
782 op.qubits = AER::reg_t{qubit0, qubit1};
784 state->buffer_op(std::move(op));
787 state->apply_unitary(qubits, AER::Linalg::Matrix::SWAP);
789 NotifyObservers(qubits);
803 throw std::runtime_error(
804 "CCX gate not supported in stabilizer simulation");
809 AER::Operations::Op op;
810 op.type = AER::Operations::OpType::gate;
812 op.qubits = AER::reg_t{qubit0, qubit1, qubit2};
814 state->buffer_op(std::move(op));
816 static const cmatrix_t mat = AER::Utils::make_matrix<complex_t>(
817 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
818 {{0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
819 {{0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
820 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}},
821 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}},
822 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}},
823 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}},
824 {{0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}});
827 state->apply_unitary(qubits, mat);
830 NotifyObservers(qubits);
844 throw std::runtime_error(
845 "CSwap gate not supported in stabilizer simulation");
850 const int q1 =
static_cast<int>(ctrl_qubit);
851 const int q2 =
static_cast<int>(qubit0);
852 const int q3 =
static_cast<int>(qubit1);
868 static const cmatrix_t mat = AER::Utils::make_matrix<complex_t>(
869 {{{1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
870 {{0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
871 {{0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
872 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}},
873 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}},
874 {{0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
875 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}},
876 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}}});
879 state->apply_unitary(qubits, mat);
882 NotifyObservers(qubits);
897 double theta,
double phi,
double lambda,
double gamma)
override {
899 throw std::runtime_error(
900 "CU gate not supported in stabilizer simulation");
905 if (gamma != 0.0)
ApplyP(ctrl_qubit, gamma);
907 const double lambdaPlusPhiHalf = 0.5 * (lambda + phi);
908 const double halfTheta = 0.5 * theta;
909 ApplyP(tgt_qubit, 0.5 * (lambda - phi));
910 ApplyP(ctrl_qubit, lambdaPlusPhiHalf);
911 ApplyCX(ctrl_qubit, tgt_qubit);
912 ApplyU(tgt_qubit, -halfTheta, 0, -lambdaPlusPhiHalf, 0);
913 ApplyCX(ctrl_qubit, tgt_qubit);
914 ApplyU(tgt_qubit, halfTheta, phi, 0, 0);
916 const cmatrix_t CU = AER::Linalg::Matrix::cu(theta, phi, lambda, gamma);
918 state->apply_unitary(qubits, CU);
921 NotifyObservers(qubits);
931 void ApplyNop()
override {
932 AER::Operations::Op op;
934 AER::Operations::OpType::barrier;
936 state->buffer_op(std::move(op));
949 std::unique_ptr<ISimulator> Clone()
override {
950 auto sim = std::make_unique<AerSimulator>();
952 sim->configuration = configuration;
953 for (
const auto& [key, value] : configuration.GetConfigMap())
954 sim->Configure(key.c_str(), value.c_str());
957 if (simulationType == SimulationType::kMatrixProductState)
958 sim->Configure(
"method",
"matrix_product_state");
959 else if (simulationType == SimulationType::kStabilizer)
960 sim->Configure(
"method",
"stabilizer");
961 else if (simulationType == SimulationType::kTensorNetwork)
962 sim->Configure(
"method",
"tensor_network");
963 else if (simulationType == SimulationType::kExtendedStabilizer)
964 sim->Configure(
"method",
"extended_stabilizer");
965 else if (simulationType == SimulationType::kDensityMatrix)
966 sim->Configure(
"method",
"density_matrix");
968 sim->Configure(
"method",
"statevector");
970 if (simulationType == SimulationType::kMatrixProductState) {
971 std::string key =
"matrix_product_state_max_bond_dimension";
972 if (configuration.IsSet(key))
973 sim->Configure(key.c_str(), configuration.GetConfiguration(key).c_str());
975 key =
"matrix_product_state_truncation_threshold";
976 if (configuration.IsSet(key))
977 sim->Configure(key.c_str(), configuration.GetConfiguration(key).c_str());
979 key =
"mps_sample_measure_algorithm";
980 if (configuration.IsSet(key))
981 sim->Configure(key.c_str(),
982 configuration.GetConfiguration(key).c_str());
985 sim->SetMultithreading(
986 enableMultithreading);
988 AER::Vector<complex_t> localSavedAmplitudes =
990 AER::Data localSavedState =
993 AER::cmatrix_t localSavedDensityMatrix =
995 auto localSavedExtendedStabilizerState = savedExtendedStabilizerState;
998 if (state && state->is_initialized()) {
1003 sim->savedAmplitudes = std::move(savedAmplitudes);
1004 sim->savedState = std::move(savedState);
1005 sim->savedDensityMatrix = std::move(savedDensityMatrix);
1006 sim->savedExtendedStabilizerState = savedExtendedStabilizerState;
1008 sim->RestoreState();
1012 sim->savedAmplitudes = localSavedAmplitudes;
1013 sim->savedState = localSavedState;
1014 sim->savedDensityMatrix = localSavedDensityMatrix;
1015 sim->savedExtendedStabilizerState = localSavedExtendedStabilizerState;
1018 savedAmplitudes = std::move(localSavedAmplitudes);
1019 savedState = std::move(localSavedState);
1020 savedDensityMatrix = std::move(localSavedDensityMatrix);
1021 savedExtendedStabilizerState =
1022 std::move(localSavedExtendedStabilizerState);
1025 sim->savedAmplitudes = std::move(localSavedAmplitudes);
1026 sim->savedState = std::move(localSavedState);
1027 sim->savedDensityMatrix = std::move(localSavedDensityMatrix);
1028 sim->savedExtendedStabilizerState =
1029 std::move(localSavedExtendedStabilizerState);
1031 sim->RestoreState();
1037 if (configuration.IsSet(
"seed"))
1038 sim->SetSeed(DeriveSeed(
1039 std::stoull(configuration.GetConfiguration(
"seed")),
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.