15#ifndef _GPUSIMULATOR_H
16#define _GPUSIMULATOR_H
18#ifdef INCLUDED_BY_FACTORY
41class GpuSimulator :
public GpuState {
43 GpuSimulator() =
default;
45 GpuSimulator(
const GpuSimulator &) =
delete;
46 GpuSimulator &operator=(
const GpuSimulator &) =
delete;
49 GpuSimulator(GpuSimulator &&other) =
default;
50 GpuSimulator &operator=(GpuSimulator &&other) =
default;
59 const Eigen::Matrix2cd& gate)
override {
65 if (!mpo->ApplyOneQubitMatrix(
66 static_cast<int>(qubit),
67 reinterpret_cast<const double*
>(gate.data())))
68 throw std::runtime_error(
69 "GpuSimulator::ApplyGenericOneQubitGate: Failed to apply the "
70 "generic one-qubit gate on the matrix product operator "
72 NotifyObservers({qubit});
76 if (!mps->ApplyOneQubitMatrix(
77 static_cast<unsigned int>(qubit),
78 reinterpret_cast<const double*
>(gate.data())))
79 throw std::runtime_error(
80 "GpuSimulator::ApplyGenericOneQubitGate: Failed to apply the "
81 "generic one-qubit gate on the matrix product state simulator.");
82 NotifyObservers({qubit});
86 ApplyQuantumChannel({qubit}, QuantumChannel({gate}));
89 throw std::runtime_error(
90 "GpuSimulator::ApplyGenericOneQubitGate: Not supported for GPU "
101 const Eigen::Matrix4cd& gate)
override {
103 if (!mpo->ApplyTwoQubitMatrix(
104 static_cast<int>(qubit0),
static_cast<int>(qubit1),
105 reinterpret_cast<const double*
>(gate.data())))
106 throw std::runtime_error(
107 "GpuSimulator::ApplyGenericTwoQubitGate: Failed to apply the "
108 "generic two-qubit gate on the matrix product operator "
110 NotifyObservers({qubit0, qubit1});
114 if (!mps->ApplyTwoQubitMatrix(
115 static_cast<unsigned int>(qubit0),
116 static_cast<unsigned int>(qubit1),
117 reinterpret_cast<const double*
>(gate.data())))
118 throw std::runtime_error(
119 "GpuSimulator::ApplyGenericTwoQubitGate: Failed to apply the "
120 "generic two-qubit gate on the matrix product state simulator.");
121 NotifyObservers({qubit0, qubit1});
125 ApplyQuantumChannel({qubit0, qubit1}, QuantumChannel({gate}));
128 throw std::runtime_error(
129 "GpuSimulator::ApplyGenericTwoQubitGate: Not supported for GPU "
142 state->ApplyP(qubit, lambda);
144 densityMatrix->ApplyP(qubit, lambda);
146 mpo->ApplyP(qubit, lambda);
148 mps->ApplyP(qubit, lambda);
150 tn->ApplyP(qubit, lambda);
152 pp->ApplyP(qubit, lambda);
154 NotifyObservers({qubit});
165 state->ApplyX(qubit);
167 densityMatrix->ApplyX(qubit);
177 NotifyObservers({qubit});
188 state->ApplyY(qubit);
190 densityMatrix->ApplyY(qubit);
200 NotifyObservers({qubit});
211 state->ApplyZ(qubit);
213 densityMatrix->ApplyZ(qubit);
223 NotifyObservers({qubit});
234 state->ApplyH(qubit);
236 densityMatrix->ApplyH(qubit);
246 NotifyObservers({qubit});
257 state->ApplyS(qubit);
259 densityMatrix->ApplyS(qubit);
269 NotifyObservers({qubit});
280 state->ApplySDG(qubit);
282 densityMatrix->ApplySDG(qubit);
284 mpo->ApplySDG(qubit);
286 mps->ApplySDG(qubit);
292 NotifyObservers({qubit});
303 state->ApplyT(qubit);
305 densityMatrix->ApplyT(qubit);
315 NotifyObservers({qubit});
326 state->ApplyTDG(qubit);
328 densityMatrix->ApplyTDG(qubit);
330 mpo->ApplyTDG(qubit);
332 mps->ApplyTDG(qubit);
338 NotifyObservers({qubit});
349 state->ApplySX(qubit);
351 densityMatrix->ApplySX(qubit);
359 pp->ApplySQRTX(qubit);
361 NotifyObservers({qubit});
372 state->ApplySXDG(qubit);
374 densityMatrix->ApplySXDG(qubit);
376 mpo->ApplySXDG(qubit);
378 mps->ApplySXDG(qubit);
380 tn->ApplySXDG(qubit);
382 pp->ApplySxDAG(qubit);
384 NotifyObservers({qubit});
395 state->ApplyK(qubit);
397 densityMatrix->ApplyK(qubit);
407 NotifyObservers({qubit});
419 state->ApplyRx(qubit, theta);
421 densityMatrix->ApplyRx(qubit, theta);
423 mpo->ApplyRx(qubit, theta);
425 mps->ApplyRx(qubit, theta);
427 tn->ApplyRx(qubit, theta);
429 pp->ApplyRX(qubit, theta);
431 NotifyObservers({qubit});
443 state->ApplyRy(qubit, theta);
445 densityMatrix->ApplyRy(qubit, theta);
447 mpo->ApplyRy(qubit, theta);
449 mps->ApplyRy(qubit, theta);
451 tn->ApplyRy(qubit, theta);
453 pp->ApplyRY(qubit, theta);
455 NotifyObservers({qubit});
467 state->ApplyRz(qubit, theta);
469 densityMatrix->ApplyRz(qubit, theta);
471 mpo->ApplyRz(qubit, theta);
473 mps->ApplyRz(qubit, theta);
475 tn->ApplyRz(qubit, theta);
477 pp->ApplyRZ(qubit, theta);
479 NotifyObservers({qubit});
490 double gamma)
override {
492 state->ApplyU(qubit, theta, phi, lambda, gamma);
494 densityMatrix->ApplyU(qubit, theta, phi, lambda, gamma);
496 mpo->ApplyU(qubit, theta, phi, lambda, gamma);
498 mps->ApplyU(qubit, theta, phi, lambda, gamma);
500 tn->ApplyU(qubit, theta, phi, lambda, gamma);
502 pp->ApplyU(qubit, theta, phi, lambda, gamma);
504 NotifyObservers({qubit});
516 state->ApplyCX(ctrl_qubit, tgt_qubit);
518 densityMatrix->ApplyCX(ctrl_qubit, tgt_qubit);
520 mpo->ApplyCX(ctrl_qubit, tgt_qubit);
522 mps->ApplyCX(ctrl_qubit, tgt_qubit);
524 tn->ApplyCX(ctrl_qubit, tgt_qubit);
526 pp->ApplyCX(ctrl_qubit, tgt_qubit);
528 NotifyObservers({tgt_qubit, ctrl_qubit});
540 state->ApplyCY(ctrl_qubit, tgt_qubit);
542 densityMatrix->ApplyCY(ctrl_qubit, tgt_qubit);
544 mpo->ApplyCY(ctrl_qubit, tgt_qubit);
546 mps->ApplyCY(ctrl_qubit, tgt_qubit);
548 tn->ApplyCY(ctrl_qubit, tgt_qubit);
550 pp->ApplyCY(ctrl_qubit, tgt_qubit);
552 NotifyObservers({tgt_qubit, ctrl_qubit});
564 state->ApplyCZ(ctrl_qubit, tgt_qubit);
566 densityMatrix->ApplyCZ(ctrl_qubit, tgt_qubit);
568 mpo->ApplyCZ(ctrl_qubit, tgt_qubit);
570 mps->ApplyCZ(ctrl_qubit, tgt_qubit);
572 tn->ApplyCZ(ctrl_qubit, tgt_qubit);
574 pp->ApplyCZ(ctrl_qubit, tgt_qubit);
576 NotifyObservers({tgt_qubit, ctrl_qubit});
588 double lambda)
override {
590 state->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
592 densityMatrix->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
594 mpo->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
596 mps->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
598 tn->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
600 pp->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
602 NotifyObservers({tgt_qubit, ctrl_qubit});
614 double theta)
override {
616 state->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
618 densityMatrix->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
620 mpo->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
622 mps->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
624 tn->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
626 pp->ApplyCRX(ctrl_qubit, tgt_qubit, theta);
628 NotifyObservers({tgt_qubit, ctrl_qubit});
640 double theta)
override {
642 state->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
644 densityMatrix->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
646 mpo->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
648 mps->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
650 tn->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
652 pp->ApplyCRY(ctrl_qubit, tgt_qubit, theta);
654 NotifyObservers({tgt_qubit, ctrl_qubit});
666 double theta)
override {
668 state->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
670 densityMatrix->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
672 mpo->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
674 mps->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
676 tn->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
678 pp->ApplyCRZ(ctrl_qubit, tgt_qubit, theta);
680 NotifyObservers({tgt_qubit, ctrl_qubit});
692 state->ApplyCH(ctrl_qubit, tgt_qubit);
694 densityMatrix->ApplyCH(ctrl_qubit, tgt_qubit);
696 mpo->ApplyCH(ctrl_qubit, tgt_qubit);
698 mps->ApplyCH(ctrl_qubit, tgt_qubit);
700 tn->ApplyCH(ctrl_qubit, tgt_qubit);
702 pp->ApplyCH(ctrl_qubit, tgt_qubit);
704 NotifyObservers({tgt_qubit, ctrl_qubit});
716 state->ApplyCSX(ctrl_qubit, tgt_qubit);
718 densityMatrix->ApplyCSX(ctrl_qubit, tgt_qubit);
720 mpo->ApplyCSX(ctrl_qubit, tgt_qubit);
722 mps->ApplyCSX(ctrl_qubit, tgt_qubit);
724 tn->ApplyCSX(ctrl_qubit, tgt_qubit);
726 pp->ApplyCSX(ctrl_qubit, tgt_qubit);
728 NotifyObservers({tgt_qubit, ctrl_qubit});
741 state->ApplyCSXDG(ctrl_qubit, tgt_qubit);
743 densityMatrix->ApplyCSXDG(ctrl_qubit, tgt_qubit);
745 mpo->ApplyCSXDG(ctrl_qubit, tgt_qubit);
747 mps->ApplyCSXDG(ctrl_qubit, tgt_qubit);
749 tn->ApplyCSXDG(ctrl_qubit, tgt_qubit);
751 pp->ApplyCSXDAG(ctrl_qubit, tgt_qubit);
753 NotifyObservers({tgt_qubit, ctrl_qubit});
765 state->ApplySwap(qubit0, qubit1);
767 densityMatrix->ApplySwap(qubit0, qubit1);
769 mpo->ApplySwap(qubit0, qubit1);
771 mps->ApplySwap(qubit0, qubit1);
773 tn->ApplySwap(qubit0, qubit1);
775 pp->ApplySWAP(qubit0, qubit1);
777 NotifyObservers({qubit1, qubit0});
791 state->ApplyCCX(qubit0, qubit1, qubit2);
792 NotifyObservers({qubit0, qubit1, qubit2});
794 densityMatrix->ApplyCCX(qubit0, qubit1, qubit2);
795 NotifyObservers({qubit0, qubit1, qubit2});
797 const size_t q1 = qubit0;
798 const size_t q2 = qubit1;
799 const size_t q3 = qubit2;
803 mpo->ApplyCSX(
static_cast<int>(q2),
static_cast<int>(q3));
804 NotifyObservers({qubit1, qubit2});
806 mpo->ApplyCX(
static_cast<int>(q1),
static_cast<int>(q2));
807 NotifyObservers({qubit0, qubit1});
809 mpo->ApplyCSXDG(
static_cast<int>(q2),
static_cast<int>(q3));
810 NotifyObservers({qubit1, qubit2});
812 mpo->ApplyCX(
static_cast<int>(q1),
static_cast<int>(q2));
813 NotifyObservers({qubit0, qubit1});
815 mpo->ApplyCSX(
static_cast<int>(q1),
static_cast<int>(q3));
816 NotifyObservers({qubit0, qubit2});
818 const size_t q1 = qubit0;
819 const size_t q2 = qubit1;
820 const size_t q3 = qubit2;
823 mps->ApplyCSX(
static_cast<unsigned int>(q2),
824 static_cast<unsigned int>(q3));
825 NotifyObservers({qubit1, qubit2});
827 mps->ApplyCX(
static_cast<unsigned int>(q1),
828 static_cast<unsigned int>(q2));
829 NotifyObservers({qubit0, qubit1});
831 mps->ApplyCSXDG(
static_cast<unsigned int>(q2),
832 static_cast<unsigned int>(q3));
833 NotifyObservers({qubit1, qubit2});
835 mps->ApplyCX(
static_cast<unsigned int>(q1),
836 static_cast<unsigned int>(q2));
837 NotifyObservers({qubit0, qubit1});
839 mps->ApplyCSX(
static_cast<unsigned int>(q1),
840 static_cast<unsigned int>(q3));
841 NotifyObservers({qubit0, qubit2});
843 tn->ApplyCCX(qubit0, qubit1, qubit2);
844 NotifyObservers({qubit0, qubit1, qubit2});
846 pp->ApplyCCX(qubit0, qubit1, qubit2);
847 NotifyObservers({qubit0, qubit1, qubit2});
862 state->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
863 NotifyObservers({qubit1, qubit0, ctrl_qubit});
865 densityMatrix->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
866 NotifyObservers({qubit1, qubit0, ctrl_qubit});
868 const size_t q1 = ctrl_qubit;
869 const size_t q2 = qubit0;
870 const size_t q3 = qubit1;
874 mpo->ApplyCX(
static_cast<int>(q3),
static_cast<int>(q2));
875 NotifyObservers({qubit1, qubit0});
877 mpo->ApplyCSX(
static_cast<int>(q2),
static_cast<int>(q3));
878 NotifyObservers({qubit0, qubit1});
880 mpo->ApplyCX(
static_cast<int>(q1),
static_cast<int>(q2));
881 NotifyObservers({ctrl_qubit, qubit0});
883 mpo->ApplyP(
static_cast<int>(q3), M_PI);
884 NotifyObservers({qubit1});
885 mpo->ApplyP(
static_cast<int>(q2), -M_PI_2);
886 NotifyObservers({qubit0});
888 mpo->ApplyCSX(
static_cast<int>(q2),
static_cast<int>(q3));
889 NotifyObservers({qubit0, qubit1});
891 mpo->ApplyCX(
static_cast<int>(q1),
static_cast<int>(q2));
892 NotifyObservers({ctrl_qubit, qubit0});
894 mpo->ApplyP(
static_cast<int>(q3), M_PI);
895 NotifyObservers({qubit1});
897 mpo->ApplyCSX(
static_cast<int>(q1),
static_cast<int>(q3));
898 NotifyObservers({ctrl_qubit, qubit1});
900 mpo->ApplyCX(
static_cast<int>(q3),
static_cast<int>(q2));
901 NotifyObservers({qubit1, qubit0});
903 const size_t q1 = ctrl_qubit;
904 const size_t q2 = qubit0;
905 const size_t q3 = qubit1;
909 mps->ApplyCX(
static_cast<unsigned int>(q3),
910 static_cast<unsigned int>(q2));
911 NotifyObservers({qubit1, qubit0});
913 mps->ApplyCSX(
static_cast<unsigned int>(q2),
914 static_cast<unsigned int>(q3));
915 NotifyObservers({qubit0, qubit1});
917 mps->ApplyCX(
static_cast<unsigned int>(q1),
918 static_cast<unsigned int>(q2));
919 NotifyObservers({ctrl_qubit, qubit0});
921 mps->ApplyP(
static_cast<unsigned int>(q3), M_PI);
922 NotifyObservers({qubit1});
923 mps->ApplyP(
static_cast<unsigned int>(q2), -M_PI_2);
924 NotifyObservers({qubit0});
926 mps->ApplyCSX(
static_cast<unsigned int>(q2),
927 static_cast<unsigned int>(q3));
928 NotifyObservers({qubit0, qubit1});
930 mps->ApplyCX(
static_cast<unsigned int>(q1),
931 static_cast<unsigned int>(q2));
932 NotifyObservers({ctrl_qubit, qubit0});
934 mps->ApplyP(
static_cast<unsigned int>(q3), M_PI);
935 NotifyObservers({qubit1});
937 mps->ApplyCSX(
static_cast<unsigned int>(q1),
938 static_cast<unsigned int>(q3));
939 NotifyObservers({ctrl_qubit, qubit1});
941 mps->ApplyCX(
static_cast<unsigned int>(q3),
942 static_cast<unsigned int>(q2));
943 NotifyObservers({qubit1, qubit0});
945 tn->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
946 NotifyObservers({qubit1, qubit0, ctrl_qubit});
948 pp->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
949 NotifyObservers({qubit1, qubit0, ctrl_qubit});
965 double theta,
double phi,
double lambda,
double gamma)
override {
967 state->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
969 densityMatrix->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
971 mpo->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
973 mps->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
975 tn->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
977 pp->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
979 NotifyObservers({tgt_qubit, ctrl_qubit});
989 void ApplyNop()
override {
1003 std::unique_ptr<ISimulator> Clone()
override {
1006 throw std::runtime_error(
1007 "GpuSimulator::Clone: Cloning Tensor Network or Pauli Propagator "
1008 "simulation is not "
1012 auto cloned = std::make_unique<GpuSimulator>();
1014 cloned->simulationType = simulationType;
1015 cloned->nrQubits = nrQubits;
1017 cloned->lookaheadDepth = lookaheadDepth;
1018 cloned->lookaheadDepthWithHeuristic = lookaheadDepthWithHeuristic;
1019 cloned->useOptimalMeetingPosition = useOptimalMeetingPosition;
1020 cloned->upcomingGates = upcomingGates;
1021 cloned->upcomingGateIndex = upcomingGateIndex;
1022 cloned->growthFactorGate = growthFactorGate;
1023 cloned->growthFactorSwap = growthFactorSwap;
1024 cloned->configuration = configuration;
1027 cloned->state = state->Clone();
1028 else if (densityMatrix) {
1029 cloned->densityMatrix = densityMatrix->Clone();
1030 if (!cloned->densityMatrix)
1031 throw std::runtime_error(
1032 "GpuSimulator::Clone: Failed to clone density matrix state.");
1034 cloned->mpo = mpo->Clone();
1036 throw std::runtime_error(
1037 "GpuSimulator::Clone: Failed to clone matrix product operator "
1040 cloned->gateCounterObserver =
1041 std::make_shared<GateCounterObserver>(upcomingGateIndex);
1042 cloned->RegisterObserver(cloned->gateCounterObserver);
1044 cloned->dummySim = dummySim ? dummySim->Clone() :
nullptr;
1046 cloned->curMaxBondDim = curMaxBondDim;
1047 cloned->mpo->SetCallbackContext(cloned.get());
1049 cloned->mps = mps->Clone();
1051 cloned->gateCounterObserver =
1052 std::make_shared<GateCounterObserver>(upcomingGateIndex);
1053 cloned->RegisterObserver(cloned->gateCounterObserver);
1055 cloned->dummySim = dummySim ? dummySim->Clone() :
nullptr;
1057 cloned->curMaxBondDim = curMaxBondDim;
1058 cloned->mps->SetCallbackContext(cloned.get());
1059 }
else if (tn || pp) {
1060 throw std::runtime_error(
1061 "GpuSimulator::Clone: Cloning Tensor Network or Pauli Propagator "
1062 "simulation is not "
1066 if (configuration.IsSet(
"seed"))
1067 cloned->SetSeed(DeriveSeed(
1068 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)
uint_fast64_t qubit_t
The type of a qubit.