15#ifndef _AER_SIMULATOR_H_
16#define _AER_SIMULATOR_H_
20#ifdef INCLUDED_BY_FACTORY
43class AerSimulator :
public AerState
46 AerSimulator() =
default;
48 AerSimulator(
const AerSimulator &) =
delete;
49 AerSimulator &operator=(
const AerSimulator &) =
delete;
52 AerSimulator(AerSimulator &&other) =
default;
53 AerSimulator &operator=(AerSimulator &&other) =
default;
62 const AER::reg_t qubits = {qubit};
63 AER::cmatrix_t gate_matrix(2, 2);
64 gate_matrix(0, 0) = gate(0, 0);
65 gate_matrix(0, 1) = gate(0, 1);
66 gate_matrix(1, 0) = gate(1, 0);
67 gate_matrix(1, 1) = gate(1, 1);
69 state->apply_unitary(qubits, gate_matrix);
70 NotifyObservers(qubits);
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);
102 throw std::runtime_error(
"P gate not supported in stabilizer simulation");
108 AER::Operations::Op op;
109 op.type = AER::Operations::OpType::gate;
111 op.qubits = AER::reg_t{qubit};
112 op.params = {lambda};
114 state->buffer_op(std::move(op));
118 const AER::cvector_t P = {{1, 0}, std::polar(1., lambda)};
119 state->apply_diagonal_matrix(qubits, P);
122 NotifyObservers(qubits);
134 state->apply_x(qubit);
135 NotifyObservers(qubits);
147 state->apply_y(qubit);
148 NotifyObservers(qubits);
160 state->apply_z(qubit);
161 NotifyObservers(qubits);
173 state->apply_h(qubit);
174 NotifyObservers(qubits);
189 AER::Operations::Op op;
190 op.type = AER::Operations::OpType::gate;
192 op.qubits = AER::reg_t{qubit};
194 state->buffer_op(std::move(op));
198 const AER::cvector_t S = {{1, 0}, complex_t(0.0, 1)};
199 state->apply_diagonal_matrix(qubits, S);
202 NotifyObservers(qubits);
217 AER::Operations::Op op;
218 op.type = AER::Operations::OpType::gate;
220 op.qubits = AER::reg_t{qubit};
222 state->buffer_op(std::move(op));
226 const AER::cvector_t Sdg = {{1, 0}, complex_t(0.0, -1)};
227 state->apply_diagonal_matrix(qubits, Sdg);
230 NotifyObservers(qubits);
242 throw std::runtime_error(
"T gate not supported in stabilizer simulation");
249 AER::Operations::Op op;
250 op.type = AER::Operations::OpType::gate;
252 op.qubits = AER::reg_t{qubit};
253 state->buffer_op(std::move(op));
257 const AER::cvector_t T = {{1, 0}, std::polar<double>(1, M_PI / 4.)};
258 state->apply_diagonal_matrix(qubits, T);
261 NotifyObservers(qubits);
273 throw std::runtime_error(
"TDG gate not supported in stabilizer simulation");
280 AER::Operations::Op op;
281 op.type = AER::Operations::OpType::gate;
283 op.qubits = AER::reg_t{qubit};
284 state->buffer_op(std::move(op));
288 const AER::cvector_t Tdg = {{1, 0}, std::polar<double>(1, -M_PI / 4.)};
289 state->apply_diagonal_matrix(qubits, Tdg);
292 NotifyObservers(qubits);
307 AER::Operations::Op op;
308 op.type = AER::Operations::OpType::gate;
310 op.qubits = AER::reg_t{qubit};
312 state->buffer_op(std::move(op));
320 state->apply_unitary(qubits, AER::Linalg::Matrix::SX);
323 NotifyObservers(qubits);
338 AER::Operations::Op op;
339 op.type = AER::Operations::OpType::gate;
341 op.qubits = AER::reg_t{qubit};
343 state->buffer_op(std::move(op));
346 state->apply_unitary(qubits, AER::Linalg::Matrix::SXDG);
348 NotifyObservers(qubits);
370 static const cmatrix_t K =
371 AER::Utils::make_matrix<complex_t>({{{1. / std::sqrt(2.), 0}, {0, -1. / std::sqrt(2.)}}, {{0, 1. / std::sqrt(2.)}, {-1. / std::sqrt(2.), 0}}});
373 state->apply_unitary(qubits, K);
376 NotifyObservers(qubits);
389 throw std::runtime_error(
"Rx gate not supported in stabilizer simulation");
401 const cmatrix_t rx = AER::Linalg::Matrix::rx(theta);
402 state->apply_unitary(qubits, rx);
405 NotifyObservers(qubits);
418 throw std::runtime_error(
"Ry gate not supported in stabilizer simulation");
430 const cmatrix_t ry = AER::Linalg::Matrix::ry(theta);
432 state->apply_unitary(qubits, ry);
435 NotifyObservers(qubits);
448 throw std::runtime_error(
"Rz gate not supported in stabilizer simulation");
453 AER::Operations::Op op;
454 op.type = AER::Operations::OpType::gate;
456 op.qubits = AER::reg_t{qubit};
459 state->buffer_op(std::move(op));
463 const cmatrix_t rz = AER::Linalg::Matrix::rz(theta);
465 state->apply_unitary(qubits, rz);
468 NotifyObservers(qubits);
481 void ApplyU(
Types::qubit_t qubit,
double theta,
double phi,
double lambda,
double gamma)
override
484 throw std::runtime_error(
"U gate not supported in stabilizer simulation");
496 const cmatrix_t u = AER::Linalg::Matrix::u4(theta, phi, lambda, gamma);
498 state->apply_unitary(qubits, u);
501 NotifyObservers(qubits);
514 state->apply_cx(qubits);
515 NotifyObservers(qubits);
532 ApplyCX(ctrl_qubit, tgt_qubit);
537 state->apply_cy(qubits);
539 NotifyObservers(qubits);
552 state->apply_cz(qubits);
553 NotifyObservers(qubits);
567 throw std::runtime_error(
"CP gate not supported in stabilizer simulation");
573 const double halfAngle = lambda * 0.5;
574 ApplyP(ctrl_qubit, halfAngle);
575 ApplyCX(ctrl_qubit, tgt_qubit);
576 ApplyP(tgt_qubit, -halfAngle);
577 ApplyCX(ctrl_qubit, tgt_qubit);
578 ApplyP(tgt_qubit, halfAngle);
582 const cmatrix_t CP = AER::Linalg::Matrix::cphase(lambda);
584 state->apply_unitary(qubits, CP);
587 NotifyObservers(qubits);
601 throw std::runtime_error(
"CRx gate not supported in stabilizer simulation");
607 const double halfAngle = theta * 0.5;
610 ApplyCX(ctrl_qubit, tgt_qubit);
611 ApplyRz(tgt_qubit, -halfAngle);
612 ApplyCX(ctrl_qubit, tgt_qubit);
622 const double t2 = theta * 0.5;
624 const complex_t i(0., 1.);
625 mat(1, 1) = std::cos(t2);
626 mat(1, 3) = -i * std::sin(t2);
627 mat(3, 1) = mat(1, 3);
628 mat(3, 3) = mat(1, 1);
631 state->apply_unitary(qubits, mat);
634 NotifyObservers(qubits);
648 throw std::runtime_error(
"CRy gate not supported in stabilizer simulation");
654 const double halfAngle = theta * 0.5;
657 ApplyCX(ctrl_qubit, tgt_qubit);
658 ApplyRy(tgt_qubit, -halfAngle);
659 ApplyCX(ctrl_qubit, tgt_qubit);
667 const double t2 = theta * 0.5;
669 mat(1, 1) = std::complex<double>(cos(t2), 0);
670 mat(1, 3) = std::complex<double>(-sin(t2), 0);
671 mat(3, 1) = std::complex<double>(sin(t2), 0);
672 mat(3, 3) = mat(1, 1);
675 state->apply_unitary(qubits, mat);
678 NotifyObservers(qubits);
692 throw std::runtime_error(
"CRz gate not supported in stabilizer simulation");
698 const double halfAngle = theta * 0.5;
700 ApplyCX(ctrl_qubit, tgt_qubit);
701 ApplyRz(tgt_qubit, -halfAngle);
702 ApplyCX(ctrl_qubit, tgt_qubit);
706 const double t2 = theta * 0.5;
707 AER::cvector_t v = {{1, 0}, std::polar(1., -t2), {1, 0}, std::polar(1., t2)};
710 state->apply_diagonal_matrix(qubits, v);
713 NotifyObservers(qubits);
726 throw std::runtime_error(
"CH gate not supported in stabilizer simulation");
734 ApplyCX(ctrl_qubit, tgt_qubit);
737 ApplyCX(ctrl_qubit, tgt_qubit);
746 const cmatrix_t CU = AER::Linalg::Matrix::cu(M_PI_2, 0, M_PI, 0);
747 state->apply_unitary(qubits, CU);
750 NotifyObservers(qubits);
763 throw std::runtime_error(
"CSx gate not supported in stabilizer simulation");
772 ApplyCX(ctrl_qubit, tgt_qubit);
774 ApplyCX(ctrl_qubit, tgt_qubit);
779 static const cmatrix_t CSX = AER::Utils::make_matrix<complex_t>({{{1, 0}, {0, 0}, {0, 0}, {0, 0}},
780 {{0, 0}, {0.5, 0.5}, {0, 0}, {0.5, -0.5}},
781 {{0, 0}, {0, 0}, {1, 0}, {0, 0}},
782 {{0, 0}, {0.5, -0.5}, {0, 0}, {0.5, 0.5}}});
784 state->apply_unitary(qubits, CSX);
786 NotifyObservers(qubits);
799 throw std::runtime_error(
"CSxDAG gate not supported in stabilizer simulation");
806 ApplyCX(ctrl_qubit, tgt_qubit);
808 ApplyCX(ctrl_qubit, tgt_qubit);
815 static const cmatrix_t CSXDG = AER::Utils::make_matrix<complex_t>({{{1, 0}, {0, 0}, {0, 0}, {0, 0}},
816 {{0, 0}, {0.5, -0.5}, {0, 0}, {0.5, 0.5}},
817 {{0, 0}, {0, 0}, {1, 0}, {0, 0}},
818 {{0, 0}, {0.5, 0.5}, {0, 0}, {0.5, -0.5}}});
820 state->apply_unitary(qubits, CSXDG);
823 NotifyObservers(qubits);
839 AER::Operations::Op op;
840 op.type = AER::Operations::OpType::gate;
842 op.qubits = AER::reg_t{qubit0, qubit1};
844 state->buffer_op(std::move(op));
848 state->apply_unitary(qubits, AER::Linalg::Matrix::SWAP);
850 NotifyObservers(qubits);
864 throw std::runtime_error(
"CCX gate not supported in stabilizer simulation");
870 AER::Operations::Op op;
871 op.type = AER::Operations::OpType::gate;
873 op.qubits = AER::reg_t{qubit0, qubit1, qubit2};
875 state->buffer_op(std::move(op));
879 static const cmatrix_t mat = AER::Utils::make_matrix<complex_t>({{{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}, {0, 0}, {0, 0}, {1, 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}, {0, 0}, {0, 0}, {1, 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}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}});
889 state->apply_unitary(qubits, mat);
892 NotifyObservers(qubits);
906 throw std::runtime_error(
"CSwap gate not supported in stabilizer simulation");
912 const int q1 =
static_cast<int>(ctrl_qubit);
913 const int q2 =
static_cast<int>(qubit0);
914 const int q3 =
static_cast<int>(qubit1);
932 static const cmatrix_t mat = AER::Utils::make_matrix<complex_t>({{{1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
933 {{0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
934 {{0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
935 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}},
936 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}},
937 {{0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
938 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}, {0, 0}},
939 {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {1, 0}}});
942 state->apply_unitary(qubits, mat);
945 NotifyObservers(qubits);
962 throw std::runtime_error(
"CU gate not supported in stabilizer simulation");
969 ApplyP(ctrl_qubit, gamma);
971 const double lambdaPlusPhiHalf = 0.5 * (lambda + phi);
972 const double halfTheta = 0.5 * theta;
973 ApplyP(tgt_qubit, 0.5 * (lambda - phi));
974 ApplyP(ctrl_qubit, lambdaPlusPhiHalf);
975 ApplyCX(ctrl_qubit, tgt_qubit);
976 ApplyU(tgt_qubit, -halfTheta, 0, -lambdaPlusPhiHalf, 0);
977 ApplyCX(ctrl_qubit, tgt_qubit);
978 ApplyU(tgt_qubit, halfTheta, phi, 0, 0);
982 const cmatrix_t CU = AER::Linalg::Matrix::cu(theta, phi, lambda, gamma);
984 state->apply_unitary(qubits, CU);
987 NotifyObservers(qubits);
997 void ApplyNop()
override
999 AER::Operations::Op op;
1000 op.type = AER::Operations::OpType::barrier;
1002 state->buffer_op(std::move(op));
1015 std::unique_ptr<ISimulator> Clone()
override
1017 auto sim = std::make_unique<AerSimulator>();
1019 sim->configuration = configuration;
1020 for (
const auto &[key, value] : configuration.GetConfigMap())
1021 sim->Configure(key.c_str(), value.c_str());
1024 if (simulationType == SimulationType::kMatrixProductState)
1025 sim->Configure(
"method",
"matrix_product_state");
1026 else if (simulationType == SimulationType::kStabilizer)
1027 sim->Configure(
"method",
"stabilizer");
1028 else if (simulationType == SimulationType::kTensorNetwork)
1029 sim->Configure(
"method",
"tensor_network");
1030 else if (simulationType == SimulationType::kExtendedStabilizer)
1031 sim->Configure(
"method",
"extended_stabilizer");
1032 else if (simulationType == SimulationType::kDensityMatrix)
1033 sim->Configure(
"method",
"density_matrix");
1035 sim->Configure(
"method",
"statevector");
1037 if (simulationType == SimulationType::kMatrixProductState)
1039 std::string key =
"matrix_product_state_max_bond_dimension";
1040 if (configuration.IsSet(key))
1041 sim->Configure(key.c_str(), configuration.GetConfiguration(key).c_str());
1043 key =
"matrix_product_state_truncation_threshold";
1044 if (configuration.IsSet(key))
1045 sim->Configure(key.c_str(), configuration.GetConfiguration(key).c_str());
1047 key =
"mps_sample_measure_algorithm";
1048 if (configuration.IsSet(key))
1049 sim->Configure(key.c_str(), configuration.GetConfiguration(key).c_str());
1052 sim->SetMultithreading(enableMultithreading);
1054 AER::Vector<complex_t> localSavedAmplitudes = savedAmplitudes;
1055 AER::Data localSavedState = savedState;
1057 AER::cmatrix_t localSavedDensityMatrix = savedDensityMatrix;
1058 auto localSavedExtendedStabilizerState = savedExtendedStabilizerState;
1061 if (state && state->is_initialized())
1067 sim->savedAmplitudes = std::move(savedAmplitudes);
1068 sim->savedState = std::move(savedState);
1069 sim->savedDensityMatrix = std::move(savedDensityMatrix);
1070 sim->savedExtendedStabilizerState = savedExtendedStabilizerState;
1072 sim->RestoreState();
1076 sim->savedAmplitudes = localSavedAmplitudes;
1077 sim->savedState = localSavedState;
1078 sim->savedDensityMatrix = localSavedDensityMatrix;
1079 sim->savedExtendedStabilizerState = localSavedExtendedStabilizerState;
1082 savedAmplitudes = std::move(localSavedAmplitudes);
1083 savedState = std::move(localSavedState);
1084 savedDensityMatrix = std::move(localSavedDensityMatrix);
1085 savedExtendedStabilizerState = std::move(localSavedExtendedStabilizerState);
1090 sim->savedAmplitudes = std::move(localSavedAmplitudes);
1091 sim->savedState = std::move(localSavedState);
1092 sim->savedDensityMatrix = std::move(localSavedDensityMatrix);
1093 sim->savedExtendedStabilizerState = std::move(localSavedExtendedStabilizerState);
1095 sim->RestoreState();
1101 if (configuration.IsSet(
"seed"))
1102 sim->SetSeed(DeriveSeed(std::stoull(configuration.GetConfiguration(
"seed")), nextSeedStream++));
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 ApplyGenericOneQubitGate(void *sim, unsigned long q0, const double *buffer)
int ApplyGenericTwoQubitGate(void *sim, unsigned long q0, unsigned long q1, const double *buffer)
Bounded online routing based on current physical bond dimensions.
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
uint_fast64_t qubit_t
The type of a qubit.