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 (useDoublePrecision) mps->SetDataType(
true);
64 if (limitEntanglement && singularValueThreshold > 0.)
65 mps->SetCutoff(singularValueThreshold);
66 if (limitSize && chi > 0) mps->SetMaxExtent(chi);
67 const bool res = mps->Create(nrQubits);
69 throw std::runtime_error(
70 "GpuState::Initialize: Failed to create "
71 "and initialize the MPS state.");
73 throw std::runtime_error(
74 "GpuState::Initialize: Failed to create the MPS state.");
75 }
else if (simulationType == SimulationType::kTensorNetwork) {
76 tn = SimulatorsFactory::CreateGpuLibTensorNetSim();
78 const bool res = tn->Create(nrQubits);
80 throw std::runtime_error(
81 "GpuState::Initialize: Failed to create "
82 "and initialize the tensor network state.");
84 throw std::runtime_error(
85 "GpuState::Initialize: Failed to create the tensor network "
87 }
else if (simulationType == SimulationType::kPauliPropagator) {
88 pp = SimulatorsFactory::CreateGpuPauliPropagatorSimulatorUnique();
90 const bool res = pp->CreateSimulator(nrQubits);
92 throw std::runtime_error(
93 "GpuState::Initialize: Failed to create "
94 "and initialize the Pauli propagator state.");
96 pp->SetWillUseSampling(
true);
97 if (!pp->AllocateMemory(0.9))
98 throw std::runtime_error(
99 "GpuState::Initialize: Failed to allocate memory for the "
100 "Pauli propagator state.");
102 throw std::runtime_error(
103 "GpuState::Initialize: Failed to create the Pauli propagator "
106 throw std::runtime_error(
107 "GpuState::Initialize: Invalid simulation "
108 "type for initializing the state.");
123 void InitializeState(
size_t num_qubits,
124 std::vector<std::complex<double>> &litudes)
override {
125 if (num_qubits == 0)
return;
127 nrQubits = num_qubits;
130 if (simulationType != SimulationType::kStatevector)
131 throw std::runtime_error(
132 "GpuState::InitializeState: Invalid simulation "
133 "type for initializing the state.");
136 if (simulationType == SimulationType::kStatevector) {
137 state = SimulatorsFactory::CreateGpuLibStateVectorSim();
139 state->CreateWithState(
140 nrQubits,
reinterpret_cast<const double *
>(amplitudes.data()));
157 void InitializeState(
size_t num_qubits,
158 AER::Vector<std::complex<double>> &litudes)
override {
159 if (num_qubits == 0)
return;
161 nrQubits = num_qubits;
164 if (simulationType != SimulationType::kStatevector)
165 throw std::runtime_error(
166 "GpuState::InitializeState: Invalid simulation "
167 "type for initializing the state.");
170 if (simulationType == SimulationType::kStatevector) {
171 state = SimulatorsFactory::CreateGpuLibStateVectorSim();
173 state->CreateWithState(
174 nrQubits,
reinterpret_cast<const double *
>(amplitudes.data()));
191 void InitializeState(
size_t num_qubits,
192 Eigen::VectorXcd &litudes)
override {
193 if (num_qubits == 0)
return;
195 nrQubits = num_qubits;
198 if (simulationType != SimulationType::kStatevector)
199 throw std::runtime_error(
200 "GpuState::InitializeState: Invalid simulation "
201 "type for initializing the state.");
204 if (simulationType == SimulationType::kStatevector) {
205 state = SimulatorsFactory::CreateGpuLibStateVectorSim();
207 state->CreateWithState(
208 nrQubits,
reinterpret_cast<const double *
>(amplitudes.data()));
219 void Reset()
override {
227 pp->ClearOperators();
238 void SetInitialQubitsMap(
239 const std::vector<long long int> &initialMap)
override {
240 if (mps) mps->SetInitialQubitsMap(initialMap);
251 void Configure(
const char *key,
const char *value)
override {
252 if (std::string(
"method") == key) {
253 if (std::string(
"statevector") == value)
254 simulationType = SimulationType::kStatevector;
255 else if (std::string(
"matrix_product_state") == value)
256 simulationType = SimulationType::kMatrixProductState;
257 else if (std::string(
"tensor_network") == value)
258 simulationType = SimulationType::kTensorNetwork;
259 else if (std::string(
"pauli_propagator") == value)
260 simulationType = SimulationType::kPauliPropagator;
261 }
else if (std::string(
"matrix_product_state_truncation_threshold") ==
263 singularValueThreshold = std::stod(value);
264 if (singularValueThreshold > 0.) {
265 limitEntanglement =
true;
266 if (mps) mps->SetCutoff(singularValueThreshold);
267 if (tn) tn->SetCutoff(singularValueThreshold);
269 limitEntanglement =
false;
270 }
else if (std::string(
"matrix_product_state_max_bond_dimension") == key) {
271 chi = std::stoi(value);
274 if (mps) mps->SetMaxExtent(chi);
275 if (tn) tn->SetMaxExtent(chi);
278 }
else if (std::string(
"use_double_precision") == key) {
280 (std::string(
"1") == value || std::string(
"true") == value);
293 if (std::string(
"method") == key) {
294 switch (simulationType) {
295 case SimulationType::kStatevector:
296 return "statevector";
297 case SimulationType::kMatrixProductState:
298 return "matrix_product_state";
299 case SimulationType::kTensorNetwork:
300 return "tensor_network";
301 case SimulationType::kPauliPropagator:
302 return "pauli_propagator";
306 }
else if (std::string(
"matrix_product_state_truncation_threshold") ==
308 if (limitEntanglement && singularValueThreshold > 0.)
309 return std::to_string(singularValueThreshold);
310 }
else if (std::string(
"matrix_product_state_max_bond_dimension") == key) {
311 if (limitSize && limitSize > 0)
return std::to_string(chi);
326 if ((simulationType == SimulationType::kStatevector && state) ||
327 (simulationType == SimulationType::kMatrixProductState && mps) ||
328 (simulationType == SimulationType::kPauliPropagator && pp))
331 const size_t oldNrQubits = nrQubits;
332 nrQubits += num_qubits;
352 void Clear()
override {
374 if (qubits.size() >
sizeof(
size_t) * 8)
376 <<
"Warning: The number of qubits to measure is larger than the "
377 "number of bits in the size_t type, the outcome will be undefined"
384 if (simulationType == SimulationType::kStatevector) {
386 for (
size_t qubit : qubits) {
387 if (state->MeasureQubitCollapse(
static_cast<int>(qubit))) res |= mask;
390 }
else if (simulationType == SimulationType::kMatrixProductState) {
392 for (
size_t qubit : qubits) {
393 if (mps->Measure(
static_cast<unsigned int>(qubit))) res |= mask;
396 }
else if (simulationType == SimulationType::kTensorNetwork) {
398 for (
size_t qubit : qubits) {
399 if (tn->Measure(
static_cast<unsigned int>(qubit))) res |= mask;
402 }
else if (simulationType == SimulationType::kPauliPropagator) {
404 for (
size_t qubit : qubits) {
405 if (pp->MeasureQubit(
static_cast<int>(qubit))) res |= mask;
411 NotifyObservers(qubits);
423 std::vector<bool> res(qubits.size(),
false);
426 if (simulationType == SimulationType::kStatevector) {
427 for (
size_t i = 0; i < qubits.size(); ++i)
428 res[i] = state->MeasureQubitCollapse(
static_cast<int>(qubits[i]));
429 }
else if (simulationType == SimulationType::kMatrixProductState) {
430 for (
size_t i = 0; i < qubits.size(); ++i)
431 res[i] = mps->Measure(
static_cast<unsigned int>(qubits[i]));
432 }
else if (simulationType == SimulationType::kTensorNetwork) {
433 for (
size_t i = 0; i < qubits.size(); ++i)
434 res[i] = tn->Measure(
static_cast<unsigned int>(qubits[i]));
435 }
else if (simulationType == SimulationType::kPauliPropagator) {
436 for (
size_t i = 0; i < qubits.size(); ++i)
437 res[i] = pp->MeasureQubit(
static_cast<int>(qubits[i]));
440 NotifyObservers(qubits);
453 if (simulationType == SimulationType::kStatevector) {
454 for (
size_t qubit : qubits)
455 if (state->MeasureQubitCollapse(
static_cast<int>(qubit)))
456 state->ApplyX(
static_cast<int>(qubit));
457 }
else if (simulationType == SimulationType::kMatrixProductState) {
458 for (
size_t qubit : qubits)
459 if (mps->Measure(
static_cast<unsigned int>(qubit)))
460 mps->ApplyX(
static_cast<unsigned int>(qubit));
461 }
else if (simulationType == SimulationType::kTensorNetwork) {
462 for (
size_t qubit : qubits)
463 if (tn->Measure(
static_cast<unsigned int>(qubit)))
464 tn->ApplyX(
static_cast<unsigned int>(qubit));
465 }
else if (simulationType == SimulationType::kPauliPropagator) {
466 for (
size_t qubit : qubits)
467 if (pp->MeasureQubit(
static_cast<int>(qubit)))
468 pp->ApplyX(
static_cast<int>(qubit));
472 NotifyObservers(qubits);
487 if (simulationType == SimulationType::kStatevector)
488 return state->BasisStateProbability(outcome);
489 else if (simulationType == SimulationType::kMatrixProductState ||
490 simulationType == SimulationType::kTensorNetwork) {
492 return std::norm(ampl);
493 }
else if (simulationType == SimulationType::kPauliPropagator) {
494 return pp->Probability(outcome);
514 if (simulationType == SimulationType::kStatevector)
515 state->Amplitude(outcome, &real, &imag);
516 else if (simulationType == SimulationType::kMatrixProductState ||
517 simulationType == SimulationType::kTensorNetwork) {
518 std::vector<long int> fixedValues(nrQubits);
519 for (
size_t i = 0; i < nrQubits; ++i)
520 fixedValues[i] = (outcome & (1ULL << i)) ? 1 : 0;
521 if (simulationType == SimulationType::kMatrixProductState)
522 mps->Amplitude(nrQubits, fixedValues.data(), &real, &imag);
523 else if (simulationType == SimulationType::kTensorNetwork)
524 tn->Amplitude(nrQubits, fixedValues.data(), &real, &imag);
525 }
else if (simulationType == SimulationType::kPauliPropagator) {
527 throw std::runtime_error(
528 "GpuState::Amplitude: Invalid simulation type for amplitude "
532 return std::complex<double>(real, imag);
548 std::complex<double> ProjectOnZero()
override {
549 if (simulationType == SimulationType::kMatrixProductState)
550 return mps->ProjectOnZero();
566 if (nrQubits == 0)
return {};
567 const size_t numStates = 1ULL << nrQubits;
568 std::vector<double> result(numStates);
570 if (simulationType == SimulationType::kStatevector)
571 state->AllProbabilities(result.data());
572 else if (simulationType == SimulationType::kMatrixProductState ||
573 simulationType == SimulationType::kTensorNetwork) {
577 result[i] = std::norm(std::complex<double>(val.real(), val.imag()));
579 }
else if (simulationType == SimulationType::kPauliPropagator) {
582 result[i] = pp->Probability(i);
602 std::vector<double> result(qubits.size());
604 if (simulationType == SimulationType::kStatevector) {
605 for (
size_t i = 0; i < qubits.size(); ++i)
606 result[i] = state->BasisStateProbability(qubits[i]);
607 }
else if (simulationType == SimulationType::kMatrixProductState ||
608 simulationType == SimulationType::kTensorNetwork) {
609 for (
size_t i = 0; i < qubits.size(); ++i) {
611 result[i] = std::norm(ampl);
613 }
else if (simulationType == SimulationType::kPauliPropagator) {
614 for (
size_t i = 0; i < qubits.size(); ++i)
615 result[i] = pp->Probability(qubits[i]);
637 std::unordered_map<Types::qubit_t, Types::qubit_t>
SampleCounts(
639 if (qubits.empty() || shots == 0)
return {};
643 <<
"Warning: The number of qubits to measure is larger than the "
644 "number of bits in the Types::qubit_t type, the outcome will be "
648 std::unordered_map<Types::qubit_t, Types::qubit_t> result;
652 if (simulationType == SimulationType::kStatevector) {
653 std::vector<long int> samples(shots);
654 state->SampleAll(shots, samples.data());
656 for (
auto outcome : samples) {
661 for (
size_t i = 0; i < qubits.size(); ++i) {
662 if (outcome & (1ULL << qubits[i])) translatedOutcome |= mask;
665 ++result[translatedOutcome];
667 }
else if (simulationType == SimulationType::kMatrixProductState) {
668 std::unordered_map<std::vector<bool>, int64_t> *map =
669 mps->GetMapForSample();
671 std::vector<unsigned int> qubitsIndices(qubits.begin(), qubits.end());
673 mps->Sample(shots, qubitsIndices.size(), qubitsIndices.data(), map);
676 for (
const auto &[meas, cnt] : *map) {
680 if (meas[q]) outcome |= mask;
684 result[outcome] += cnt;
687 mps->FreeMapForSample(map);
688 }
else if (simulationType == SimulationType::kTensorNetwork) {
689 std::unordered_map<std::vector<bool>, int64_t> *map =
690 tn->GetMapForSample();
691 std::vector<unsigned int> qubitsIndices(qubits.begin(), qubits.end());
692 tn->Sample(shots, qubitsIndices.size(), qubitsIndices.data(), map);
694 for (
const auto &[meas, cnt] : *map) {
698 if (meas[q]) outcome |= mask;
701 result[outcome] += cnt;
703 tn->FreeMapForSample(map);
704 }
else if (simulationType == SimulationType::kPauliPropagator) {
705 std::vector<int> qb(qubits.begin(), qubits.end());
706 for (
size_t shot = 0; shot < shots; ++shot) {
708 auto res = pp->SampleQubits(qb);
709 for (
size_t i = 0; i < qubits.size(); ++i) {
710 if (res[i]) meas |= (1ULL << i);
717 NotifyObservers(qubits);
735 std::unordered_map<std::vector<bool>,
Types::qubit_t> SampleCountsMany(
737 if (qubits.empty() || shots == 0)
return {};
743 if (simulationType == SimulationType::kStatevector) {
744 std::vector<long int> samples(shots);
745 state->SampleAll(shots, samples.data());
747 std::vector<bool> outcomeVec(qubits.size());
748 for (
auto outcome : samples) {
749 for (
size_t i = 0; i < qubits.size(); ++i)
750 outcomeVec[i] = ((outcome >> qubits[i]) & 1) == 1;
751 ++result[outcomeVec];
753 }
else if (simulationType == SimulationType::kMatrixProductState) {
754 std::unordered_map<std::vector<bool>, int64_t> *map =
755 mps->GetMapForSample();
757 std::vector<unsigned int> qubitsIndices(qubits.begin(), qubits.end());
758 mps->Sample(shots, qubitsIndices.size(), qubitsIndices.data(), map);
761 for (
const auto &[meas, cnt] : *map) result[meas] += cnt;
763 mps->FreeMapForSample(map);
764 }
else if (simulationType == SimulationType::kTensorNetwork) {
765 std::unordered_map<std::vector<bool>, int64_t> *map =
766 tn->GetMapForSample();
767 std::vector<unsigned int> qubitsIndices(qubits.begin(), qubits.end());
768 tn->Sample(shots, qubitsIndices.size(), qubitsIndices.data(), map);
770 for (
const auto &[meas, cnt] : *map) result[meas] += cnt;
771 tn->FreeMapForSample(map);
772 }
else if (simulationType == SimulationType::kPauliPropagator) {
773 std::vector<int> qb(qubits.begin(), qubits.end());
774 for (
size_t shot = 0; shot < shots; ++shot) {
775 const auto res = pp->SampleQubits(qb);
781 NotifyObservers(qubits);
797 double ExpectationValue(
const std::string &pauliString)
override {
800 if (simulationType == SimulationType::kStatevector)
801 result = state->ExpectationValue(pauliString);
802 else if (simulationType == SimulationType::kMatrixProductState)
803 result = mps->ExpectationValue(pauliString);
804 else if (simulationType == SimulationType::kTensorNetwork)
805 result = tn->ExpectationValue(pauliString);
806 else if (simulationType == SimulationType::kPauliPropagator)
807 result = pp->ExpectationValue(pauliString);
809 throw std::runtime_error(
810 "GpuState::ExpectationValue: Invalid simulation type for expectation "
811 "value calculation.");
823 SimulatorType GetType()
const override {
return SimulatorType::kGpuSim; }
843 void Flush()
override {}
856 if (simulationType == SimulationType::kStatevector)
857 state->SaveStateDestructive();
859 throw std::runtime_error(
860 "GpuState::SaveStateToInternalDestructive: Invalid simulation type "
861 "for saving the state destructively.");
871 if (simulationType == SimulationType::kStatevector)
872 state->RestoreStateFreeSaved();
874 throw std::runtime_error(
875 "GpuState::RestoreInternalDestructiveSavedState: Invalid simulation "
876 "type for restoring the state destructively.");
888 if (simulationType == SimulationType::kStatevector)
890 else if (simulationType == SimulationType::kMatrixProductState)
892 else if (simulationType == SimulationType::kTensorNetwork)
894 else if (simulationType == SimulationType::kPauliPropagator)
906 if (simulationType == SimulationType::kStatevector)
907 state->RestoreStateNoFreeSaved();
908 else if (simulationType == SimulationType::kMatrixProductState)
910 else if (simulationType == SimulationType::kTensorNetwork)
912 else if (simulationType == SimulationType::kPauliPropagator)
923 std::complex<double> AmplitudeRaw(
Types::qubit_t outcome)
override {
958 bool IsQcsim()
const override {
return false; }
977 if (simulationType == SimulationType::kStatevector)
978 return state->MeasureAllQubitsNoCollapse();
979 else if (simulationType == SimulationType::kMatrixProductState ||
980 simulationType == SimulationType::kTensorNetwork ||
981 simulationType == SimulationType::kPauliPropagator) {
984 <<
"Warning: The number of qubits to measure is larger than the "
985 "number of bits in the Types::qubit_t type, the outcome will be "
990 std::iota(fixedValues.begin(), fixedValues.end(), 0);
992 if (res.empty())
return 0;
997 throw std::runtime_error(
998 "QCSimState::MeasureNoCollapse: Invalid simulation type for measuring "
999 "all the qubits without collapsing the state.");
1018 std::vector<bool> MeasureNoCollapseMany()
override {
1019 if (simulationType == SimulationType::kStatevector) {
1020 const auto meas = state->MeasureAllQubitsNoCollapse();
1021 std::vector<bool> result(nrQubits,
false);
1022 for (
size_t i = 0; i < nrQubits; ++i) result[i] = ((meas >> i) & 1) == 1;
1024 }
else if (simulationType == SimulationType::kMatrixProductState ||
1025 simulationType == SimulationType::kTensorNetwork ||
1026 simulationType == SimulationType::kPauliPropagator) {
1028 std::iota(fixedValues.begin(), fixedValues.end(), 0);
1029 const auto res = SampleCountsMany(fixedValues, 1);
1030 if (res.empty())
return std::vector<bool>(nrQubits,
false);
1035 throw std::runtime_error(
1036 "QCSimState::MeasureNoCollapseMany: Invalid simulation type for "
1038 "all the qubits without collapsing the state.");
1040 return std::vector<bool>(nrQubits,
false);
1044 SimulationType simulationType =
1045 SimulationType::kStatevector;
1047 std::unique_ptr<GpuLibStateVectorSim>
1049 std::unique_ptr<GpuLibMPSSim> mps;
1050 std::unique_ptr<GpuLibTNSim> tn;
1051 std::unique_ptr<GpuPauliPropagator>
1054 size_t nrQubits = 0;
1055 bool limitSize =
false;
1056 bool limitEntanglement =
false;
1057 Eigen::Index chi = 10;
1058 double singularValueThreshold = 0.;
1059 bool useDoublePrecision =
false;
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)
uint_fast64_t qubit_t
The type of a qubit.
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.