14#ifndef _GPU_PAULI_PROPAGATOR_H
15#define _GPU_PAULI_PROPAGATOR_H 1
21#define _USE_MATH_DEFINES
27class GpuPauliPropagator
30 explicit GpuPauliPropagator(
const std::shared_ptr<GpuLibrary> &lib,
int device = -1)
31 : device(device == -1 && lib ? lib->GetCreationDevice() : device), lib(lib), obj(
nullptr)
35 int GetGpuDevice()
const
37 return lib ? lib->PauliPropGetGpuId(obj) : -1;
40 GpuPauliPropagator() =
delete;
41 GpuPauliPropagator(
const GpuPauliPropagator &) =
delete;
42 GpuPauliPropagator &operator=(
const GpuPauliPropagator &) =
delete;
43 GpuPauliPropagator(GpuPauliPropagator &&) =
default;
44 GpuPauliPropagator &operator=(GpuPauliPropagator &&) =
default;
49 lib->DestroyPauliPropSimulator(obj);
56 auto lock = lib->LockInitialization();
57 if (!lib->SetGpuDevice(device))
60 lib->DestroyPauliPropSimulator(obj);
62 obj = lib->CreatePauliPropSimulator(numQubits);
64 return obj !=
nullptr;
73 return lib->PauliPropGetNrQubits(obj);
78 bool SetSeed(uint64_t seed)
80 return lib && obj && lib->PauliPropSetSeed(obj, seed);
83 bool SetWillUseSampling(
bool willUseSampling)
87 return lib->PauliPropSetWillUseSampling(obj, willUseSampling) == 1;
92 bool GetWillUseSampling()
96 return lib->PauliPropGetWillUseSampling(obj) == 1;
101 double GetCoefficientTruncationCutoff()
105 return lib->PauliPropGetCoefficientTruncationCutoff(obj);
110 void SetCoefficientTruncationCutoff(
double cutoff)
114 lib->PauliPropSetCoefficientTruncationCutoff(obj, cutoff);
118 double GetWeightTruncationCutoff()
122 return lib->PauliPropGetWeightTruncationCutoff(obj);
127 void SetWeightTruncationCutoff(
double cutoff)
131 lib->PauliPropSetWeightTruncationCutoff(obj, cutoff);
135 int GetNumGatesBetweenTruncations()
139 return lib->PauliPropGetNumGatesBetweenTruncations(obj);
144 void SetNumGatesBetweenTruncations(
int numGates)
148 lib->PauliPropSetNumGatesBetweenTruncations(obj, numGates);
152 int GetNumGatesBetweenDeduplications()
156 return lib->PauliPropGetNumGatesBetweenDeduplications(obj);
161 void SetNumGatesBetweenDeduplications(
int numGates)
165 lib->PauliPropSetNumGatesBetweenDeduplications(obj, numGates);
169 bool ClearOperators()
173 return lib->PauliPropClearOperators(obj);
178 bool AllocateMemory(
double percentage)
182 return lib->PauliPropAllocateMemory(obj, percentage);
187 double GetExpectationValue()
191 return lib->PauliPropGetExpectationValue(obj);
200 return lib->PauliPropExecute(obj);
205 double ExpectationValue(
const std::string &pauliStr)
207 SetInPauliExpansionUnique(pauliStr);
209 return GetExpectationValue();
212 double ExpectationValueMultiple(
const std::vector<std::string> &pauliStrs,
const std::vector<double> &coefficients)
214 SetInPauliExpansionMultiple(pauliStrs, coefficients);
216 return GetExpectationValue();
219 bool SetInPauliExpansionUnique(
const std::string &pauliStr)
223 return lib->PauliPropSetInPauliExpansionUnique(obj, pauliStr.c_str());
228 bool SetInPauliExpansionMultiple(
const std::vector<std::string> &pauliStrs,
const std::vector<double> &coefficients)
230 if (lib && !pauliStrs.empty() && pauliStrs.size() == coefficients.size())
232 std::vector<char *> cStrs(pauliStrs.size());
233 for (
size_t i = 0; i < pauliStrs.size(); ++i)
235 cStrs[i] =
const_cast<char *
>(pauliStrs[i].c_str());
237 return lib->PauliPropSetInPauliExpansionMultiple(obj, (
const char **)cStrs.data(), coefficients.data(),
static_cast<int>(pauliStrs.size()));
246 return lib->PauliPropApplyX(obj, qubit);
255 return lib->PauliPropApplyY(obj, qubit);
264 return lib->PauliPropApplyZ(obj, qubit);
273 return lib->PauliPropApplyH(obj, qubit);
282 return lib->PauliPropApplyS(obj, qubit);
287 bool ApplySQRTX(
int qubit)
291 return lib->PauliPropApplySQRTX(obj, qubit);
296 bool ApplySQRTY(
int qubit)
300 return lib->PauliPropApplySQRTY(obj, qubit);
305 bool ApplySQRTZ(
int qubit)
309 return lib->PauliPropApplySQRTZ(obj, qubit);
314 bool ApplyCX(
int controlQubit,
int targetQubit)
318 return lib->PauliPropApplyCX(obj, controlQubit, targetQubit);
323 bool ApplyCY(
int controlQubit,
int targetQubit)
327 return lib->PauliPropApplyCY(obj, controlQubit, targetQubit);
332 bool ApplyCZ(
int controlQubit,
int targetQubit)
336 return lib->PauliPropApplyCZ(obj, controlQubit, targetQubit);
341 bool ApplySWAP(
int qubit1,
int qubit2)
345 return lib->PauliPropApplySWAP(obj, qubit1, qubit2);
350 bool ApplyISWAP(
int qubit1,
int qubit2)
354 return lib->PauliPropApplyISWAP(obj, qubit1, qubit2);
359 bool ApplyRX(
int qubit,
double angle)
363 return lib->PauliPropApplyRX(obj, qubit, angle);
368 bool ApplyRY(
int qubit,
double angle)
372 return lib->PauliPropApplyRY(obj, qubit, angle);
377 bool ApplyRZ(
int qubit,
double angle)
381 return lib->PauliPropApplyRZ(obj, qubit, angle);
410 bool ApplySxDAG(
int qubit)
421 bool ApplyP(
int qubit,
double lambda)
423 return ApplyRZ(qubit, lambda);
428 return ApplyRZ(qubit, M_PI_4);
433 return ApplyRZ(qubit, -M_PI_4);
436 bool ApplyU(
int qubit,
double theta,
double phi,
double lambda,
double gamma = 0.0)
438 if (!ApplyRZ(qubit, lambda))
440 if (!ApplyRY(qubit, theta))
442 if (!ApplyRZ(qubit, phi))
448 bool ApplyCH(
int controlQubit,
int targetQubit)
454 if (!
ApplyCX(controlQubit, targetQubit))
460 if (!
ApplyCX(controlQubit, targetQubit))
470 if (!
ApplyS(controlQubit))
476 bool ApplyCU(
int controlQubit,
int targetQubit,
double theta,
double phi,
double lambda,
double gamma = 0.0)
480 if (!
ApplyP(controlQubit, gamma))
483 const double lambdaPlusPhiHalf = 0.5 * (lambda + phi);
484 const double halfTheta = 0.5 * theta;
485 if (!
ApplyP(targetQubit, 0.5 * (lambda - phi)))
487 if (!
ApplyP(controlQubit, lambdaPlusPhiHalf))
489 if (!
ApplyCX(controlQubit, targetQubit))
491 if (!
ApplyU(targetQubit, -halfTheta, 0, -lambdaPlusPhiHalf))
493 if (!
ApplyCX(controlQubit, targetQubit))
495 if (!
ApplyU(targetQubit, halfTheta, phi, 0))
500 bool ApplyCRX(
int controlQubit,
int targetQubit,
double angle)
502 const double halfAngle = angle * 0.5;
505 if (!
ApplyCX(controlQubit, targetQubit))
507 if (!ApplyRZ(targetQubit, -halfAngle))
509 if (!
ApplyCX(controlQubit, targetQubit))
511 if (!ApplyRZ(targetQubit, halfAngle))
518 bool ApplyCRY(
int controlQubit,
int targetQubit,
double angle)
520 const double halfAngle = angle * 0.5;
521 if (!ApplyRY(targetQubit, halfAngle))
523 if (!
ApplyCX(controlQubit, targetQubit))
525 if (!ApplyRY(targetQubit, -halfAngle))
527 if (!
ApplyCX(controlQubit, targetQubit))
532 bool ApplyCRZ(
int controlQubit,
int targetQubit,
double angle)
534 const double halfAngle = angle * 0.5;
535 if (!ApplyRZ(targetQubit, halfAngle))
537 if (!
ApplyCX(controlQubit, targetQubit))
539 if (!ApplyRZ(targetQubit, -halfAngle))
541 if (!
ApplyCX(controlQubit, targetQubit))
546 bool ApplyCP(
int controlQubit,
int targetQubit,
double lambda)
548 const double halfAngle = lambda * 0.5;
549 if (!
ApplyP(controlQubit, halfAngle))
551 if (!
ApplyCX(controlQubit, targetQubit))
553 if (!
ApplyP(targetQubit, -halfAngle))
555 if (!
ApplyCX(controlQubit, targetQubit))
557 if (!
ApplyP(targetQubit, halfAngle))
563 bool ApplyCS(
int controlQubit,
int targetQubit)
565 if (!
ApplyT(controlQubit))
569 if (!
ApplyCX(controlQubit, targetQubit))
573 if (!
ApplyCX(controlQubit, targetQubit))
579 bool ApplyCSDAG(
int controlQubit,
int targetQubit)
581 if (!
ApplyCX(controlQubit, targetQubit))
585 if (!
ApplyCX(controlQubit, targetQubit))
595 bool ApplyCSX(
int controlQubit,
int targetQubit)
599 if (!ApplyCS(controlQubit, targetQubit))
607 bool ApplyCSXDAG(
int controlQubit,
int targetQubit)
611 if (!ApplyCSDAG(controlQubit, targetQubit))
619 bool ApplyCSwap(
int controlQubit,
int targetQubit1,
int targetQubit2)
621 const size_t q1 = controlQubit;
622 const size_t q2 = targetQubit1;
623 const size_t q3 = targetQubit2;
652 bool ApplyCCX(
int controlQubit1,
int controlQubit2,
int targetQubit)
654 const size_t q1 = controlQubit1;
655 const size_t q2 = controlQubit2;
656 const size_t q3 = targetQubit;
662 if (!ApplyCSXDAG(q2, q3))
680 bool AddNoiseX(
int qubit,
double probability)
684 return lib->PauliPropAddNoiseX(obj, qubit, probability);
689 bool AddNoiseY(
int qubit,
double probability)
693 return lib->PauliPropAddNoiseY(obj, qubit, probability);
698 bool AddNoiseZ(
int qubit,
double probability)
702 return lib->PauliPropAddNoiseZ(obj, qubit, probability);
707 bool AddNoiseXYZ(
int qubit,
double px,
double py,
double pz)
711 return lib->PauliPropAddNoiseXYZ(obj, qubit, px, py, pz);
716 bool AddAmplitudeDamping(
int qubit,
double dampingProb,
double exciteProb)
720 return lib->PauliPropAddAmplitudeDamping(obj, qubit, dampingProb, exciteProb);
725 double QubitProbability0(
int qubit)
729 return lib->PauliPropQubitProbability0(obj, qubit);
738 return lib->PauliPropProbability(obj, outcome);
743 bool MeasureQubit(
int qubit)
747 return lib->PauliPropMeasureQubit(obj, qubit);
752 std::vector<bool> SampleQubits(
const std::vector<int> &qubits)
754 std::vector<bool> results;
755 if (lib && !qubits.empty())
757 std::vector<int> cQubits = qubits;
758 unsigned char *res = lib->PauliPropSampleQubits(obj, qubits.data(),
static_cast<int>(cQubits.size()));
762 results.reserve(cQubits.size());
763 for (
size_t i = 0; i < cQubits.size(); ++i)
766 const bool bit = ((res[i / 8] >> (i % 8)) & 1) == 1;
767 results.push_back(bit);
770 lib->PauliPropFreeSampledQubits(res);
779 lib->PauliPropSaveState(obj);
787 lib->PauliPropRestoreState(obj);
793 GpuDeviceContext lib;
int ApplyK(void *sim, int qubit)
double Probability(void *sim, unsigned long long int outcome)
int RestoreState(void *sim)
int ApplyX(void *sim, int qubit)
int ApplyU(void *sim, int qubit, double theta, double phi, double lambda, double gamma)
unsigned long int CreateSimulator(int simType, int simExecType)
int ApplyTDG(void *sim, int qubit)
int ApplyS(void *sim, int qubit)
int ApplyCX(void *sim, int controlQubit, int targetQubit)
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 ApplyP(void *sim, int qubit, double theta)
int ApplyCH(void *sim, int controlQubit, int targetQubit)
int ApplyCZ(void *sim, int controlQubit, int targetQubit)
int ApplyT(void *sim, int qubit)
int ApplyCSX(void *sim, int controlQubit, int targetQubit)
Bounded online routing based on current physical bond dimensions.