2#if defined(INCLUDED_BY_FACTORY) && defined(__linux__)
9class GpuPauliPropagatorSimulator :
public ImmediateGpuSimulator
12 GpuPauliPropagatorSimulator()
14 configuration.SetConfiguration(
"method",
"pauli_propagator");
17 const char *MethodName()
const override
19 return "pauli_propagator";
22 void Initialize()
override
26 auto initializationLock = GpuLibrary::GetInstance()->LockInitialization();
27 const int gpuDevice = configuration.IsSet(
"gpu_device") ? Configuration::ParseGpuDevice(configuration.GetConfiguration(
"gpu_device"))
28 : SimulatorsFactory::ResolveGpuDevice();
29 configuration.SetConfiguration(
"gpu_device", std::to_string(gpuDevice));
30 if (!SimulatorsFactory::GetGpuLibrary(gpuDevice))
31 throw std::runtime_error(
"GpuState::Initialize: Unable to initialize GPU device " + std::to_string(gpuDevice));
33 pp = SimulatorsFactory::CreateGpuPauliPropagatorSimulatorUnique(gpuDevice);
36 const bool res = pp->CreateSimulator(nrQubits);
38 throw std::runtime_error(
"GpuState::Initialize: Failed to create "
39 "and initialize the Pauli propagator state.");
40 for (
const auto &[key, value] : configuration.GetConfigMap())
42 Configure(key.c_str(), value.c_str());
43 pp->SetWillUseSampling(
true);
44 if (!pp->AllocateMemory(0.9))
45 throw std::runtime_error(
"GpuState::Initialize: Failed to allocate memory for the "
46 "Pauli propagator state.");
49 throw std::runtime_error(
"GpuState::Initialize: Failed to create the Pauli propagator "
52 if (GetGpuDevice() != gpuDevice)
53 throw std::runtime_error(
"GpuState::Initialize: GPU plugin did not confirm the requested "
54 "device; update the GPU library");
62 upcomingGateIndex = 0;
65 void Configure(
const char *key,
const char *value)
override
69 if (std::string(
"gpu_device") == key)
71 const int device = Configuration::ParseGpuDevice(value);
72 if ((pp) && device != Configuration::ParseGpuDevice(configuration.GetConfiguration(key)))
73 throw std::invalid_argument(
"gpu_device cannot change after initialization; clear the "
75 configuration.SetConfiguration(key, std::to_string(device));
78 const auto svdGroup = Configuration::GpuSvdSettingGroup(key);
79 if (!svdGroup.empty())
81 Configuration::ParseGpuSvdFlag(value);
82 configuration.SetConfiguration(key, value);
85 if (std::string(
"method") == key)
87 ValidateMethod(value);
88 configuration.SetConfiguration(key, value);
91 if (std::string(key) ==
"precision" || std::string(key) ==
"use_double_precision")
93 Configuration::ParsePrecision(key, value);
94 configuration.SetConfiguration(key, value);
97 if (!configuration.WasApplied(key, value))
98 configuration.SetConfiguration(key, value);
99 if (std::string(
"seed") == key)
101 const uint64_t seed = std::stoull(value);
102 SeedAuxiliaryRng(seed);
110 if (std::string(
"matrix_product_state_truncation_threshold") == key || std::string(
"matrix_product_operator_truncation_threshold") == key)
112 else if (std::string(
"matrix_product_state_max_bond_dimension") == key || std::string(
"matrix_product_operator_max_bond_dimension") == key)
117 if (std::string(
"pauli_propagator_coefficient_threshold") == key)
119 const double coefficientThreshold = std::stod(value);
120 pp->SetCoefficientTruncationCutoff(coefficientThreshold);
122 else if (std::string(
"pauli_propagator_pauli_weight_threshold") == key)
124 const double pauliWeightThreshold = std::stod(value);
125 pp->SetWeightTruncationCutoff(pauliWeightThreshold);
127 else if (std::string(
"pauli_propagator_steps_between_trims") == key)
129 const int stepsBetweenTrims = std::stoi(value);
130 pp->SetNumGatesBetweenTruncations(stepsBetweenTrims);
132 else if (std::string(
"pauli_propagator_num_gates_between_deduplications") == key)
134 const int numGatesBetweenDeduplications = std::stoi(value);
135 pp->SetNumGatesBetweenDeduplications(numGatesBetweenDeduplications);
136 if (!configuration.IsSet(
"pauli_propagator_steps_between_trims"))
137 pp->SetNumGatesBetweenTruncations(numGatesBetweenDeduplications);
146 if (std::string(key) ==
"precision" || std::string(key) ==
"use_double_precision")
148 const bool useDouble = configuration.GetConfiguration(
"precision") ==
"double";
149 return std::string(key) ==
"precision" ? (useDouble ?
"double" :
"single") : (useDouble ?
"1" :
"0");
153 if (std::string(
"method") == key)
155 return configuration.GetConfiguration(key);
162 const size_t oldNrQubits = nrQubits;
163 nrQubits += num_qubits;
167 void Clear()
override
171 upcomingGateIndex = 0;
172 upcomingGates.clear();
177 if (qubits.size() >
sizeof(
size_t) * 8)
178 std::cerr <<
"Warning: The number of qubits to measure is larger than the "
179 "number of bits in the size_t type, the outcome will be undefined"
185 for (
size_t qubit : qubits)
187 if (pp->MeasureQubit(
static_cast<int>(qubit)))
193 NotifyObservers(qubits);
199 std::vector<bool> res(qubits.size(),
false);
202 for (
size_t i = 0; i < qubits.size(); ++i)
203 res[i] = pp->MeasureQubit(
static_cast<int>(qubits[i]));
206 NotifyObservers(qubits);
214 for (
size_t qubit : qubits)
215 if (pp->MeasureQubit(
static_cast<int>(qubit)))
216 pp->ApplyX(
static_cast<int>(qubit));
219 NotifyObservers(qubits);
224 return pp->Probability(outcome);
230 throw std::runtime_error(
"GpuState::Amplitude: Invalid simulation type for amplitude "
239 if (nrQubits >= std::numeric_limits<size_t>::digits)
240 throw std::length_error(
"Full probability enumeration exceeds the basis-index API; query "
241 "selected bit vectors");
242 const size_t numStates =
size_t{1} << nrQubits;
243 std::vector<double> result(numStates);
247 result[i] = pp->Probability(i);
255 std::vector<double> result(qubits.size());
257 for (
size_t i = 0; i < qubits.size(); ++i)
258 result[i] = pp->Probability(qubits[i]);
265 if (qubits.empty() || shots == 0)
268 std::cerr <<
"Warning: The number of qubits to measure is larger than the "
269 "number of bits in the Types::qubit_t type, the outcome will be "
272 std::unordered_map<Types::qubit_t, Types::qubit_t> result;
275 std::vector<int> qb(qubits.begin(), qubits.end());
276 for (
size_t shot = 0; shot < shots; ++shot)
279 auto res = pp->SampleQubits(qb);
280 for (
size_t i = 0; i < qubits.size(); ++i)
289 NotifyObservers(qubits);
295 if (qubits.empty() || shots == 0)
300 std::vector<int> qb(qubits.begin(), qubits.end());
301 for (
size_t shot = 0; shot < shots; ++shot)
303 const auto res = pp->SampleQubits(qb);
308 NotifyObservers(qubits);
312 double ExpectationValue(
const std::string &pauliString)
override
315 result = pp->ExpectationValue(pauliString);
319 int GetGpuDevice()
const override
322 return pp->GetGpuDevice();
328 return SimulationType::kPauliPropagator;
353 pp->ApplyP(qubit, lambda);
354 NotifyObservers({qubit});
360 NotifyObservers({qubit});
366 NotifyObservers({qubit});
372 NotifyObservers({qubit});
378 NotifyObservers({qubit});
384 NotifyObservers({qubit});
390 NotifyObservers({qubit});
396 NotifyObservers({qubit});
402 NotifyObservers({qubit});
407 pp->ApplySQRTX(qubit);
408 NotifyObservers({qubit});
413 pp->ApplySxDAG(qubit);
414 NotifyObservers({qubit});
420 NotifyObservers({qubit});
425 pp->ApplyRX(qubit, theta);
426 NotifyObservers({qubit});
431 pp->ApplyRY(qubit, theta);
432 NotifyObservers({qubit});
437 pp->ApplyRZ(qubit, theta);
438 NotifyObservers({qubit});
441 void ApplyU(
Types::qubit_t qubit,
double theta,
double phi,
double lambda,
double gamma)
override
443 pp->ApplyU(qubit, theta, phi, lambda, gamma);
444 NotifyObservers({qubit});
449 pp->ApplyCX(ctrl_qubit, tgt_qubit);
450 NotifyObservers({tgt_qubit, ctrl_qubit});
455 pp->ApplyCY(ctrl_qubit, tgt_qubit);
456 NotifyObservers({tgt_qubit, ctrl_qubit});
461 pp->ApplyCZ(ctrl_qubit, tgt_qubit);
462 NotifyObservers({tgt_qubit, ctrl_qubit});
467 pp->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
468 NotifyObservers({tgt_qubit, ctrl_qubit});
473 pp->ApplyCRX(ctrl_qubit, tgt_qubit, theta);
474 NotifyObservers({tgt_qubit, ctrl_qubit});
479 pp->ApplyCRY(ctrl_qubit, tgt_qubit, theta);
480 NotifyObservers({tgt_qubit, ctrl_qubit});
485 pp->ApplyCRZ(ctrl_qubit, tgt_qubit, theta);
486 NotifyObservers({tgt_qubit, ctrl_qubit});
491 pp->ApplyCH(ctrl_qubit, tgt_qubit);
492 NotifyObservers({tgt_qubit, ctrl_qubit});
497 pp->ApplyCSX(ctrl_qubit, tgt_qubit);
498 NotifyObservers({tgt_qubit, ctrl_qubit});
503 pp->ApplyCSXDAG(ctrl_qubit, tgt_qubit);
504 NotifyObservers({tgt_qubit, ctrl_qubit});
509 pp->ApplySWAP(qubit0, qubit1);
510 NotifyObservers({qubit1, qubit0});
515 pp->ApplyCCX(qubit0, qubit1, qubit2);
516 NotifyObservers({qubit0, qubit1, qubit2});
521 pp->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
522 NotifyObservers({qubit1, qubit0, ctrl_qubit});
527 pp->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
528 NotifyObservers({tgt_qubit, ctrl_qubit});
531 std::unique_ptr<ISimulator> Clone()
override
533 throw std::runtime_error(
"GpuSimulator::Clone: Cloning Tensor Network or Pauli Propagator "
539 std::unique_ptr<GpuPauliPropagator> pp;
int ApplyK(void *sim, int qubit)
double Probability(void *sim, unsigned long long int outcome)
char * GetConfiguration(void *sim, const char *key)
int RestoreState(void *sim)
int ApplyRx(void *sim, int qubit, double theta)
int ApplyReset(void *sim, const unsigned long int *qubits, unsigned long int nrQubits)
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)
unsigned long int AllocateQubits(void *sim, unsigned long int nrQubits)
int ApplyCRz(void *sim, int controlQubit, int targetQubit, double theta)
double * AllProbabilities(void *sim)
int ApplyCP(void *sim, int controlQubit, int targetQubit, double theta)
int ApplySDG(void *sim, int qubit)
unsigned long long int Measure(void *sim, const unsigned long int *qubits, unsigned long int nrQubits)
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)
double * Amplitude(void *sim, unsigned long long int outcome)
int ApplyZ(void *sim, int qubit)
int ApplyH(void *sim, int qubit)
int ApplyCY(void *sim, int controlQubit, int targetQubit)
double * Probabilities(void *sim, const unsigned long long int *qubits, unsigned long int nrQubits)
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 SaveStateToInternalDestructive(void *sim)
int ApplyCH(void *sim, int controlQubit, int targetQubit)
int GetSimulationType(void *sim)
unsigned long long int * SampleCounts(void *sim, const unsigned long long int *qubits, unsigned long int nrQubits, unsigned long int shots)
int ApplyCZ(void *sim, int controlQubit, int targetQubit)
int ApplyRz(void *sim, int qubit, double theta)
int RestoreInternalDestructiveSavedState(void *sim)
int ApplyT(void *sim, int qubit)
int ApplyCRx(void *sim, int controlQubit, int targetQubit, double theta)
SimulationType
The type of simulation.
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
uint_fast64_t qubit_t
The type of a qubit.