14#ifndef _GPU_PAULI_PROPAGATOR_H
15#define _GPU_PAULI_PROPAGATOR_H 1
21#define _USE_MATH_DEFINES
26class GpuPauliPropagator {
28 explicit GpuPauliPropagator(
const std::shared_ptr<GpuLibrary> &lib)
29 : lib(lib), obj(
nullptr) {}
31 GpuPauliPropagator() =
delete;
32 GpuPauliPropagator(
const GpuPauliPropagator &) =
delete;
33 GpuPauliPropagator &operator=(
const GpuPauliPropagator &) =
delete;
34 GpuPauliPropagator(GpuPauliPropagator &&) =
default;
35 GpuPauliPropagator &operator=(GpuPauliPropagator &&) =
default;
37 ~GpuPauliPropagator() {
38 if (lib && obj) lib->DestroyPauliPropSimulator(obj);
43 obj = lib->CreatePauliPropSimulator(numQubits);
45 return obj !=
nullptr;
52 return lib->PauliPropGetNrQubits(obj);
57 bool SetWillUseSampling(
bool willUseSampling) {
59 return lib->PauliPropSetWillUseSampling(obj, willUseSampling) == 1;
64 bool GetWillUseSampling() {
66 return lib->PauliPropGetWillUseSampling(obj) == 1;
71 double GetCoefficientTruncationCutoff() {
73 return lib->PauliPropGetCoefficientTruncationCutoff(obj);
78 void SetCoefficientTruncationCutoff(
double cutoff) {
80 lib->PauliPropSetCoefficientTruncationCutoff(obj, cutoff);
84 double GetWeightTruncationCutoff() {
86 return lib->PauliPropGetWeightTruncationCutoff(obj);
91 void SetWeightTruncationCutoff(
double cutoff) {
93 lib->PauliPropSetWeightTruncationCutoff(obj, cutoff);
97 int GetNumGatesBetweenTruncations()
100 return lib->PauliPropGetNumGatesBetweenTruncations(obj);
105 void SetNumGatesBetweenTruncations(
int numGates)
108 lib->PauliPropSetNumGatesBetweenTruncations(obj, numGates);
112 int GetNumGatesBetweenDeduplications()
115 return lib->PauliPropGetNumGatesBetweenDeduplications(obj);
120 void SetNumGatesBetweenDeduplications(
int numGates)
123 lib->PauliPropSetNumGatesBetweenDeduplications(obj, numGates);
127 bool ClearOperators()
130 return lib->PauliPropClearOperators(obj);
135 bool AllocateMemory(
double percentage)
138 return lib->PauliPropAllocateMemory(obj, percentage);
143 double GetExpectationValue()
146 return lib->PauliPropGetExpectationValue(obj);
154 return lib->PauliPropExecute(obj);
159 double ExpectationValue(
const std::string& pauliStr)
161 SetInPauliExpansionUnique(pauliStr);
163 return GetExpectationValue();
166 double ExpectationValueMultiple(
167 const std::vector<std::string> &pauliStrs,
168 const std::vector<double> &coefficients)
170 SetInPauliExpansionMultiple(pauliStrs, coefficients);
172 return GetExpectationValue();
175 bool SetInPauliExpansionUnique(
const std::string& pauliStr)
178 return lib->PauliPropSetInPauliExpansionUnique(obj, pauliStr.c_str());
183 bool SetInPauliExpansionMultiple(
const std::vector<std::string> &pauliStrs,
const std::vector<double> &coefficients)
185 if (lib && !pauliStrs.empty() && pauliStrs.size() == coefficients.size()) {
186 std::vector<char *> cStrs(pauliStrs.size());
187 for (
size_t i = 0; i < pauliStrs.size(); ++i) {
188 cStrs[i] =
const_cast<char *
>(pauliStrs[i].c_str());
190 return lib->PauliPropSetInPauliExpansionMultiple(
191 obj, (
const char **)cStrs.data(), coefficients.data(),
static_cast<int>(pauliStrs.size()));
199 return lib->PauliPropApplyX(obj, qubit);
207 return lib->PauliPropApplyY(obj, qubit);
215 return lib->PauliPropApplyZ(obj, qubit);
223 return lib->PauliPropApplyH(obj, qubit);
231 return lib->PauliPropApplyS(obj, qubit);
236 bool ApplySQRTX(
int qubit)
239 return lib->PauliPropApplySQRTX(obj, qubit);
244 bool ApplySQRTY(
int qubit)
247 return lib->PauliPropApplySQRTY(obj, qubit);
252 bool ApplySQRTZ(
int qubit)
255 return lib->PauliPropApplySQRTZ(obj, qubit);
260 bool ApplyCX(
int controlQubit,
int targetQubit)
263 return lib->PauliPropApplyCX(obj, controlQubit, targetQubit);
268 bool ApplyCY(
int controlQubit,
int targetQubit)
271 return lib->PauliPropApplyCY(obj, controlQubit, targetQubit);
276 bool ApplyCZ(
int controlQubit,
int targetQubit)
279 return lib->PauliPropApplyCZ(obj, controlQubit, targetQubit);
284 bool ApplySWAP(
int qubit1,
int qubit2)
287 return lib->PauliPropApplySWAP(obj, qubit1, qubit2);
292 bool ApplyISWAP(
int qubit1,
int qubit2) {
294 return lib->PauliPropApplyISWAP(obj, qubit1, qubit2);
299 bool ApplyRX(
int qubit,
double angle)
302 return lib->PauliPropApplyRX(obj, qubit, angle);
307 bool ApplyRY(
int qubit,
double angle)
310 return lib->PauliPropApplyRY(obj, qubit, angle);
315 bool ApplyRZ(
int qubit,
double angle)
318 return lib->PauliPropApplyRZ(obj, qubit, angle);
325 if (!
ApplyZ(qubit))
return false;
326 if (!
ApplyS(qubit))
return false;
333 if (!
ApplyZ(qubit))
return false;
334 if (!
ApplyS(qubit))
return false;
335 if (!
ApplyH(qubit))
return false;
336 if (!
ApplyS(qubit))
return false;
341 bool ApplySxDAG(
int qubit)
343 if (!
ApplyS(qubit))
return false;
344 if (!
ApplyH(qubit))
return false;
345 if (!
ApplyS(qubit))
return false;
349 bool ApplyP(
int qubit,
double lambda)
351 return ApplyRZ(qubit, lambda);
356 return ApplyRZ(qubit, M_PI_4);
361 return ApplyRZ(qubit, -M_PI_4);
364 bool ApplyU(
int qubit,
double theta,
double phi,
double lambda,
double gamma = 0.0)
366 if (!ApplyRZ(qubit, lambda))
return false;
367 if (!ApplyRY(qubit, theta))
return false;
368 if (!ApplyRZ(qubit, phi))
return false;
373 bool ApplyCH(
int controlQubit,
int targetQubit)
375 if (!
ApplyH(targetQubit))
return false;
376 if (!
ApplySDG(targetQubit))
return false;
377 if (!
ApplyCX(controlQubit, targetQubit))
return false;
378 if (!
ApplyH(targetQubit))
return false;
379 if (!
ApplyT(targetQubit))
return false;
380 if (!
ApplyCX(controlQubit, targetQubit))
return false;
381 if (!
ApplyT(targetQubit))
return false;
382 if (!
ApplyH(targetQubit))
return false;
383 if (!
ApplyS(targetQubit))
return false;
384 if (!
ApplyX(targetQubit))
return false;
385 if (!
ApplyS(controlQubit))
return false;
390 bool ApplyCU(
int controlQubit,
int targetQubit,
double theta,
double phi,
391 double lambda,
double gamma = 0.0)
394 if (!
ApplyP(controlQubit, gamma))
return false;
396 const double lambdaPlusPhiHalf = 0.5 * (lambda + phi);
397 const double halfTheta = 0.5 * theta;
398 if (!
ApplyP(targetQubit, 0.5 * (lambda - phi)))
return false;
399 if (!
ApplyP(controlQubit, lambdaPlusPhiHalf))
return false;
400 if (!
ApplyCX(controlQubit, targetQubit))
return false;
401 if (!
ApplyU(targetQubit, -halfTheta, 0, -lambdaPlusPhiHalf))
return false;
402 if (!
ApplyCX(controlQubit, targetQubit))
return false;
403 if (!
ApplyU(targetQubit, halfTheta, phi, 0))
return false;
407 bool ApplyCRX(
int controlQubit,
int targetQubit,
double angle)
409 const double halfAngle = angle * 0.5;
410 if (!
ApplyH(targetQubit))
return false;
411 if (!
ApplyCX(controlQubit, targetQubit))
return false;
412 if (!ApplyRZ(targetQubit, -halfAngle))
return false;
413 if (!
ApplyCX(controlQubit, targetQubit))
return false;
414 if (!ApplyRZ(targetQubit, halfAngle))
return false;
415 if (!
ApplyH(targetQubit))
return false;
419 bool ApplyCRY(
int controlQubit,
int targetQubit,
double angle)
421 const double halfAngle = angle * 0.5;
422 if (!ApplyRY(targetQubit, halfAngle))
return false;
423 if (!
ApplyCX(controlQubit, targetQubit))
return false;
424 if (!ApplyRY(targetQubit, -halfAngle))
return false;
425 if (!
ApplyCX(controlQubit, targetQubit))
return false;
429 bool ApplyCRZ(
int controlQubit,
int targetQubit,
double angle)
431 const double halfAngle = angle * 0.5;
432 if (!ApplyRZ(targetQubit, halfAngle))
return false;
433 if (!
ApplyCX(controlQubit, targetQubit))
return false;
434 if (!ApplyRZ(targetQubit, -halfAngle))
return false;
435 if (!
ApplyCX(controlQubit, targetQubit))
return false;
441 bool ApplyCP(
int controlQubit,
int targetQubit,
double lambda)
443 const double halfAngle = lambda * 0.5;
444 if (!
ApplyP(controlQubit, halfAngle))
return false;
445 if (!
ApplyCX(controlQubit, targetQubit))
return false;
446 if (!
ApplyP(targetQubit, -halfAngle))
return false;
447 if (!
ApplyCX(controlQubit, targetQubit))
return false;
448 if (!
ApplyP(targetQubit, halfAngle))
return false;
454 bool ApplyCS(
int controlQubit,
int targetQubit)
456 if (!
ApplyT(controlQubit))
return false;
457 if (!
ApplyT(targetQubit))
return false;
458 if (!
ApplyCX(controlQubit, targetQubit))
return false;
459 if (!
ApplyTDG(targetQubit))
return false;
460 if (!
ApplyCX(controlQubit, targetQubit))
return false;
465 bool ApplyCSDAG(
int controlQubit,
int targetQubit)
467 if (!
ApplyCX(controlQubit, targetQubit))
return false;
468 if (!
ApplyT(targetQubit))
return false;
469 if (!
ApplyCX(controlQubit, targetQubit))
return false;
470 if (!
ApplyTDG(controlQubit))
return false;
471 if (!
ApplyTDG(targetQubit))
return false;
476 bool ApplyCSX(
int controlQubit,
int targetQubit)
478 if (!
ApplyH(targetQubit))
return false;
479 if (!ApplyCS(controlQubit, targetQubit))
return false;
480 if (!
ApplyH(targetQubit))
return false;
485 bool ApplyCSXDAG(
int controlQubit,
int targetQubit)
487 if (!
ApplyH(targetQubit))
return false;
488 if (!ApplyCSDAG(controlQubit, targetQubit))
return false;
489 if (!
ApplyH(targetQubit))
return false;
494 bool ApplyCSwap(
int controlQubit,
int targetQubit1,
int targetQubit2)
496 const size_t q1 = controlQubit;
497 const size_t q2 = targetQubit1;
498 const size_t q3 = targetQubit2;
500 if (!
ApplyCX(q3, q2))
return false;
501 if (!
ApplyCSX(q2, q3))
return false;
502 if (!
ApplyCX(q1, q2))
return false;
504 if (!
ApplyP(q3, M_PI))
return false;
505 if (!
ApplyP(q2, -M_PI_2))
return false;
507 if (!
ApplyCSX(q2, q3))
return false;
508 if (!
ApplyCX(q1, q2))
return false;
510 if (!
ApplyP(q3, M_PI))
return false;
511 if (!
ApplyCSX(q1, q3))
return false;
512 if (!
ApplyCX(q3, q2))
return false;
517 bool ApplyCCX(
int controlQubit1,
int controlQubit2,
int targetQubit)
519 const size_t q1 = controlQubit1;
520 const size_t q2 = controlQubit2;
521 const size_t q3 = targetQubit;
523 if (!
ApplyCSX(q2, q3))
return false;
524 if (!
ApplyCX(q1, q2))
return false;
525 if (!ApplyCSXDAG(q2, q3))
return false;
526 if (!
ApplyCX(q1, q2))
return false;
527 if (!
ApplyCSX(q1, q3))
return false;
539 bool AddNoiseX(
int qubit,
double probability)
542 return lib->PauliPropAddNoiseX(obj, qubit, probability);
547 bool AddNoiseY(
int qubit,
double probability)
550 return lib->PauliPropAddNoiseY(obj, qubit, probability);
555 bool AddNoiseZ(
int qubit,
double probability)
558 return lib->PauliPropAddNoiseZ(obj, qubit, probability);
563 bool AddNoiseXYZ(
int qubit,
double px,
double py,
double pz)
566 return lib->PauliPropAddNoiseXYZ(obj, qubit, px, py, pz);
571 bool AddAmplitudeDamping(
int qubit,
double dampingProb,
double exciteProb)
574 return lib->PauliPropAddAmplitudeDamping(
575 obj, qubit, dampingProb, exciteProb);
580 double QubitProbability0(
int qubit)
583 return lib->PauliPropQubitProbability0(obj, qubit);
591 return lib->PauliPropProbability(obj, outcome);
596 bool MeasureQubit(
int qubit)
599 return lib->PauliPropMeasureQubit(obj, qubit);
604 std::vector<bool> SampleQubits(
const std::vector<int>& qubits)
606 std::vector<bool> results;
607 if (lib && !qubits.empty()) {
608 std::vector<int> cQubits = qubits;
609 unsigned char *res = lib->PauliPropSampleQubits(
610 obj, qubits.data(),
static_cast<int>(cQubits.size()));
614 results.reserve(cQubits.size());
615 for (
size_t i = 0; i < cQubits.size(); ++i)
618 const bool bit = ((res[i / 8] >> (i % 8)) & 1) == 1;
619 results.push_back(bit);
622 lib->PauliPropFreeSampledQubits(res);
630 lib->PauliPropSaveState(obj);
637 lib->PauliPropRestoreState(obj);
642 std::shared_ptr<GpuLibrary> 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)