20#ifdef INCLUDED_BY_FACTORY
38class GpuState :
public ISimulator {
47 void Initialize()
override {
49 if (simulationType == SimulationType::kStatevector) {
50 state = SimulatorsFactory::CreateGpuLibStateVectorSim();
52 const bool res = state->Create(nrQubits);
54 throw std::runtime_error(
55 "GpuState::Initialize: Failed to create "
56 "and initialize the statevector state.");
58 throw std::runtime_error(
59 "GpuState::Initialize: Failed to create the statevector state.");
60 }
else if (simulationType == SimulationType::kMatrixProductState) {
61 mps = SimulatorsFactory::CreateGpuLibMPSSim();
63 if (limitEntanglement && singularValueThreshold > 0.)
64 mps->SetCutoff(singularValueThreshold);
65 if (limitSize && chi > 0) mps->SetMaxExtent(chi);
66 const bool res = mps->Create(nrQubits);
68 throw std::runtime_error(
69 "GpuState::Initialize: Failed to create "
70 "and initialize the MPS state.");
72 throw std::runtime_error(
73 "GpuState::Initialize: Failed to create the MPS state.");
74 }
else if (simulationType == SimulationType::kTensorNetwork) {
75 tn = SimulatorsFactory::CreateGpuLibTensorNetSim();
77 const bool res = tn->Create(nrQubits);
79 throw std::runtime_error(
80 "GpuState::Initialize: Failed to create "
81 "and initialize the tensor network state.");
83 throw std::runtime_error(
84 "GpuState::Initialize: Failed to create the tensor network "
86 }
else if (simulationType == SimulationType::kPauliPropagator) {
87 pp = SimulatorsFactory::CreateGpuPauliPropagatorSimulatorUnique();
89 const bool res = pp->CreateSimulator(nrQubits);
91 throw std::runtime_error(
92 "GpuState::Initialize: Failed to create "
93 "and initialize the Pauli propagator state.");
95 pp->SetWillUseSampling(
true);
96 if (!pp->AllocateMemory(0.9))
97 throw std::runtime_error(
98 "GpuState::Initialize: Failed to allocate memory for the "
99 "Pauli propagator state.");
101 throw std::runtime_error(
102 "GpuState::Initialize: Failed to create the Pauli propagator "
105 throw std::runtime_error(
106 "GpuState::Initialize: Invalid simulation "
107 "type for initializing the state.");
122 void InitializeState(
size_t num_qubits,
123 std::vector<std::complex<double>> &litudes)
override {
124 if (num_qubits == 0)
return;
126 nrQubits = num_qubits;
129 if (simulationType != SimulationType::kStatevector)
130 throw std::runtime_error(
131 "GpuState::InitializeState: Invalid simulation "
132 "type for initializing the state.");
135 if (simulationType == SimulationType::kStatevector) {
136 state = SimulatorsFactory::CreateGpuLibStateVectorSim();
138 state->CreateWithState(
139 nrQubits,
reinterpret_cast<const double *
>(amplitudes.data()));
156 void InitializeState(
size_t num_qubits,
157 AER::Vector<std::complex<double>> &litudes)
override {
158 if (num_qubits == 0)
return;
160 nrQubits = num_qubits;
163 if (simulationType != SimulationType::kStatevector)
164 throw std::runtime_error(
165 "GpuState::InitializeState: Invalid simulation "
166 "type for initializing the state.");
169 if (simulationType == SimulationType::kStatevector) {
170 state = SimulatorsFactory::CreateGpuLibStateVectorSim();
172 state->CreateWithState(
173 nrQubits,
reinterpret_cast<const double *
>(amplitudes.data()));
190 void InitializeState(
size_t num_qubits,
191 Eigen::VectorXcd &litudes)
override {
192 if (num_qubits == 0)
return;
194 nrQubits = num_qubits;
197 if (simulationType != SimulationType::kStatevector)
198 throw std::runtime_error(
199 "GpuState::InitializeState: Invalid simulation "
200 "type for initializing the state.");
203 if (simulationType == SimulationType::kStatevector) {
204 state = SimulatorsFactory::CreateGpuLibStateVectorSim();
206 state->CreateWithState(
207 nrQubits,
reinterpret_cast<const double *
>(amplitudes.data()));
218 void Reset()
override {
226 pp->ClearOperators();
237 void Configure(
const char *key,
const char *value)
override {
238 if (std::string(
"method") == key) {
239 if (std::string(
"statevector") == value)
240 simulationType = SimulationType::kStatevector;
241 else if (std::string(
"matrix_product_state") == value)
242 simulationType = SimulationType::kMatrixProductState;
243 else if (std::string(
"tensor_network") == value)
244 simulationType = SimulationType::kTensorNetwork;
245 else if (std::string(
"pauli_propagator") == value)
246 simulationType = SimulationType::kPauliPropagator;
247 }
else if (std::string(
"matrix_product_state_truncation_threshold") ==
249 singularValueThreshold = std::stod(value);
250 if (singularValueThreshold > 0.) {
251 limitEntanglement =
true;
252 if (mps) mps->SetCutoff(singularValueThreshold);
253 if (tn) tn->SetCutoff(singularValueThreshold);
255 limitEntanglement =
false;
256 }
else if (std::string(
"matrix_product_state_max_bond_dimension") == key) {
257 chi = std::stoi(value);
260 if (mps) mps->SetMaxExtent(chi);
261 if (tn) tn->SetMaxExtent(chi);
276 if (std::string(
"method") == key) {
277 switch (simulationType) {
278 case SimulationType::kStatevector:
279 return "statevector";
280 case SimulationType::kMatrixProductState:
281 return "matrix_product_state";
282 case SimulationType::kTensorNetwork:
283 return "tensor_network";
284 case SimulationType::kPauliPropagator:
285 return "pauli_propagator";
289 }
else if (std::string(
"matrix_product_state_truncation_threshold") ==
291 if (limitEntanglement && singularValueThreshold > 0.)
292 return std::to_string(singularValueThreshold);
293 }
else if (std::string(
"matrix_product_state_max_bond_dimension") == key) {
294 if (limitSize && limitSize > 0)
return std::to_string(chi);
309 if ((simulationType == SimulationType::kStatevector && state) ||
310 (simulationType == SimulationType::kMatrixProductState && mps) ||
311 (simulationType == SimulationType::kPauliPropagator && pp))
314 const size_t oldNrQubits = nrQubits;
315 nrQubits += num_qubits;
335 void Clear()
override {
350 size_t Measure(
const Types::qubits_vector &qubits)
override {
359 if (simulationType == SimulationType::kStatevector) {
361 for (
size_t qubit : qubits) {
362 if (state->MeasureQubitCollapse(
static_cast<int>(qubit))) res |= mask;
365 }
else if (simulationType == SimulationType::kMatrixProductState) {
367 for (
size_t qubit : qubits) {
368 if (mps->Measure(
static_cast<unsigned int>(qubit))) res |= mask;
371 }
else if (simulationType == SimulationType::kTensorNetwork) {
373 for (
size_t qubit : qubits) {
374 if (tn->Measure(
static_cast<unsigned int>(qubit))) res |= mask;
377 }
else if (simulationType == SimulationType::kPauliPropagator) {
379 for (
size_t qubit : qubits) {
380 if (pp->MeasureQubit(
static_cast<int>(qubit))) res |= mask;
386 NotifyObservers(qubits);
397 void ApplyReset(
const Types::qubits_vector &qubits)
override {
399 if (simulationType == SimulationType::kStatevector) {
400 for (
size_t qubit : qubits)
401 if (state->MeasureQubitCollapse(
static_cast<int>(qubit)))
402 state->ApplyX(
static_cast<int>(qubit));
403 }
else if (simulationType == SimulationType::kMatrixProductState) {
404 for (
size_t qubit : qubits)
405 if (mps->Measure(
static_cast<unsigned int>(qubit)))
406 mps->ApplyX(
static_cast<unsigned int>(qubit));
407 }
else if (simulationType == SimulationType::kTensorNetwork) {
408 for (
size_t qubit : qubits)
409 if (tn->Measure(
static_cast<unsigned int>(qubit)))
410 tn->ApplyX(
static_cast<unsigned int>(qubit));
411 }
else if (simulationType == SimulationType::kPauliPropagator) {
412 for (
size_t qubit : qubits)
413 if (pp->MeasureQubit(
static_cast<int>(qubit)))
414 pp->ApplyX(
static_cast<int>(qubit));
418 NotifyObservers(qubits);
432 double Probability(Types::qubit_t outcome)
override {
433 if (simulationType == SimulationType::kStatevector)
434 return state->BasisStateProbability(outcome);
435 else if (simulationType == SimulationType::kMatrixProductState ||
436 simulationType == SimulationType::kTensorNetwork) {
438 return std::norm(ampl);
439 }
else if (simulationType == SimulationType::kPauliPropagator) {
440 return pp->Probability(outcome);
456 std::complex<double>
Amplitude(Types::qubit_t outcome)
override {
460 if (simulationType == SimulationType::kStatevector)
461 state->Amplitude(outcome, &real, &imag);
462 else if (simulationType == SimulationType::kMatrixProductState ||
463 simulationType == SimulationType::kTensorNetwork) {
464 std::vector<long int> fixedValues(nrQubits);
465 for (
size_t i = 0; i < nrQubits; ++i)
466 fixedValues[i] = (outcome & (1ULL << i)) ? 1 : 0;
467 if (simulationType == SimulationType::kMatrixProductState)
468 mps->Amplitude(nrQubits, fixedValues.data(), &real, &imag);
469 else if (simulationType == SimulationType::kTensorNetwork)
470 tn->Amplitude(nrQubits, fixedValues.data(), &real, &imag);
471 }
else if (simulationType == SimulationType::kPauliPropagator) {
473 throw std::runtime_error(
474 "GpuState::Amplitude: Invalid simulation type for amplitude calculation.");
477 return std::complex<double>(real, imag);
491 if (nrQubits == 0)
return {};
492 const size_t numStates = 1ULL << nrQubits;
493 std::vector<double> result(numStates);
495 if (simulationType == SimulationType::kStatevector)
496 state->AllProbabilities(result.data());
497 else if (simulationType == SimulationType::kMatrixProductState ||
498 simulationType == SimulationType::kTensorNetwork) {
500 for (Types::qubit_t i = 0; i < (Types::qubit_t)numStates; ++i) {
502 result[i] = std::norm(std::complex<double>(val.real(), val.imag()));
504 }
else if (simulationType == SimulationType::kPauliPropagator) {
506 for (Types::qubit_t i = 0; i < (Types::qubit_t)numStates; ++i) {
507 result[i] = pp->Probability(i);
526 const Types::qubits_vector &qubits)
override {
527 std::vector<double> result(qubits.size());
529 if (simulationType == SimulationType::kStatevector) {
530 for (
size_t i = 0; i < qubits.size(); ++i)
531 result[i] = state->BasisStateProbability(qubits[i]);
532 }
else if (simulationType == SimulationType::kMatrixProductState ||
533 simulationType == SimulationType::kTensorNetwork) {
534 for (
size_t i = 0; i < qubits.size(); ++i) {
536 result[i] = std::norm(ampl);
538 }
else if (simulationType == SimulationType::kPauliPropagator) {
539 for (
size_t i = 0; i < qubits.size(); ++i)
540 result[i] = pp->Probability(qubits[i]);
559 std::unordered_map<Types::qubit_t, Types::qubit_t>
SampleCounts(
560 const Types::qubits_vector &qubits,
size_t shots = 1000)
override {
561 if (qubits.empty() || shots == 0)
return {};
563 std::unordered_map<Types::qubit_t, Types::qubit_t> result;
567 if (simulationType == SimulationType::kStatevector) {
568 std::vector<long int> samples(shots);
569 state->SampleAll(shots, samples.data());
571 for (
auto outcome : samples) ++result[outcome];
572 }
else if (simulationType == SimulationType::kMatrixProductState) {
573 std::unordered_map<std::vector<bool>, int64_t> *map =
574 mps->GetMapForSample();
576 std::vector<unsigned int> qubitsIndices(qubits.begin(), qubits.end());
578 mps->Sample(shots, qubitsIndices.size(), qubitsIndices.data(), map);
581 for (
const auto &[meas, cnt] : *map) {
582 Types::qubit_t outcome = 0;
583 Types::qubit_t mask = 1ULL;
584 for (Types::qubit_t q = 0; q < qubits.size(); ++q) {
585 if (meas[q]) outcome |= mask;
589 result[outcome] += cnt;
592 mps->FreeMapForSample(map);
593 }
else if (simulationType == SimulationType::kTensorNetwork) {
594 std::unordered_map<std::vector<bool>, int64_t> *map =
595 tn->GetMapForSample();
596 std::vector<unsigned int> qubitsIndices(qubits.begin(), qubits.end());
597 tn->Sample(shots, qubitsIndices.size(), qubitsIndices.data(), map);
599 for (
const auto &[meas, cnt] : *map) {
600 Types::qubit_t outcome = 0;
601 Types::qubit_t mask = 1ULL;
602 for (Types::qubit_t q = 0; q < qubits.size(); ++q) {
603 if (meas[q]) outcome |= mask;
606 result[outcome] += cnt;
608 tn->FreeMapForSample(map);
609 }
else if (simulationType == SimulationType::kPauliPropagator) {
610 std::vector<int> qb(qubits.begin(), qubits.end());
611 for (
size_t shot = 0; shot < shots; ++shot) {
613 auto res = pp->SampleQubits(qb);
614 for (
size_t i = 0; i < qubits.size(); ++i) {
615 if (res[i]) meas |= (1ULL << i);
623 NotifyObservers(qubits);
639 double ExpectationValue(
const std::string &pauliString)
override {
642 if (simulationType == SimulationType::kStatevector)
643 result = state->ExpectationValue(pauliString);
644 else if (simulationType == SimulationType::kMatrixProductState)
645 result = mps->ExpectationValue(pauliString);
646 else if (simulationType == SimulationType::kTensorNetwork)
647 result = tn->ExpectationValue(pauliString);
648 else if (simulationType == SimulationType::kPauliPropagator)
649 result = pp->ExpectationValue(pauliString);
651 throw std::runtime_error(
652 "GpuState::ExpectationValue: Invalid simulation type for expectation "
653 "value calculation.");
665 SimulatorType GetType()
const override {
return SimulatorType::kGpuSim; }
685 void Flush()
override {}
698 if (simulationType == SimulationType::kStatevector)
699 state->SaveStateDestructive();
701 throw std::runtime_error(
702 "GpuState::SaveStateToInternalDestructive: Invalid simulation type "
703 "for saving the state destructively.");
713 if (simulationType == SimulationType::kStatevector)
714 state->RestoreStateFreeSaved();
716 throw std::runtime_error(
717 "GpuState::RestoreInternalDestructiveSavedState: Invalid simulation "
718 "type for restoring the state destructively.");
730 if (simulationType == SimulationType::kStatevector)
732 else if (simulationType == SimulationType::kMatrixProductState)
734 else if (simulationType == SimulationType::kTensorNetwork)
736 else if (simulationType == SimulationType::kPauliPropagator)
748 if (simulationType == SimulationType::kStatevector)
749 state->RestoreStateNoFreeSaved();
750 else if (simulationType == SimulationType::kMatrixProductState)
752 else if (simulationType == SimulationType::kTensorNetwork)
754 else if (simulationType == SimulationType::kPauliPropagator)
765 std::complex<double> AmplitudeRaw(Types::qubit_t outcome)
override {
800 bool IsQcsim()
const override {
return false; }
816 if (simulationType == SimulationType::kStatevector)
817 return state->MeasureAllQubitsNoCollapse();
818 else if (simulationType == SimulationType::kMatrixProductState ||
819 simulationType == SimulationType::kTensorNetwork ||
820 simulationType == SimulationType::kPauliPropagator) {
821 Types::qubits_vector fixedValues(nrQubits);
822 std::iota(fixedValues.begin(), fixedValues.end(), 0);
824 if (res.empty())
return 0;
829 throw std::runtime_error(
830 "QCSimState::MeasureNoCollapse: Invalid simulation type for measuring "
831 "all the qubits without collapsing the state.");
837 SimulationType simulationType =
838 SimulationType::kStatevector;
840 std::unique_ptr<GpuLibStateVectorSim>
842 std::unique_ptr<GpuLibMPSSim> mps;
843 std::unique_ptr<GpuLibTNSim> tn;
844 std::unique_ptr<GpuPauliPropagator> pp;
847 bool limitSize =
false;
848 bool limitEntanglement =
false;
849 Eigen::Index chi = 10;
850 double singularValueThreshold = 0.;
double Probability(void *sim, unsigned long long int outcome)
char * GetConfiguration(void *sim, const char *key)
int RestoreState(void *sim)
int ApplyReset(void *sim, const unsigned long int *qubits, unsigned long int nrQubits)
unsigned long int AllocateQubits(void *sim, unsigned long int nrQubits)
unsigned long int GetNumberOfQubits(void *sim)
double * AllProbabilities(void *sim)
unsigned long long int MeasureNoCollapse(void *sim)
int GetMultithreading(void *sim)
unsigned long long int Measure(void *sim, const unsigned long int *qubits, unsigned long int nrQubits)
double * Amplitude(void *sim, unsigned long long int outcome)
double * Probabilities(void *sim, const unsigned long long int *qubits, unsigned long int nrQubits)
int SetMultithreading(void *sim, int multithreading)
int SaveStateToInternalDestructive(void *sim)
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 RestoreInternalDestructiveSavedState(void *sim)