18#ifdef INCLUDED_BY_FACTORY
25#include "MPSSimulator.h"
26#include "QubitRegister.h"
29#include "../TensorNetworks/ForestContractor.h"
30#include "../TensorNetworks/TensorNetwork.h"
32#include "../Utils/Alias.h"
52class QCSimState :
public ISimulator {
54 QCSimState() : rng(std::random_device{}()), uniformZeroOne(0, 1) {}
63 void Initialize()
override {
65 if (simulationType == SimulationType::kMatrixProductState) {
67 std::make_unique<QC::TensorNetworks::MPSSimulator>(nrQubits);
68 if (limitEntanglement && singularValueThreshold > 0.)
69 mpsSimulator->setLimitEntanglement(singularValueThreshold);
70 if (limitSize && chi > 0) mpsSimulator->setLimitBondDimension(chi);
71 }
else if (simulationType == SimulationType::kStabilizer)
73 std::make_unique<QC::Clifford::StabilizerSimulator>(nrQubits);
74 else if (simulationType == SimulationType::kTensorNetwork) {
76 std::make_unique<TensorNetworks::TensorNetwork>(nrQubits);
79 const auto tensorContractor =
80 std::make_shared<TensorNetworks::ForestContractor>();
81 tensorNetwork->SetContractor(tensorContractor);
82 }
else if (simulationType == SimulationType::kPauliPropagator) {
83 pp = std::make_unique<Simulators::QcsimPauliPropagator>();
84 pp->SetNrQubits(
static_cast<int>(nrQubits));
86 state = std::make_unique<QC::QubitRegister<>>(nrQubits);
103 void InitializeState(
size_t num_qubits,
104 std::vector<std::complex<double>> &litudes)
override {
105 if (num_qubits == 0)
return;
107 nrQubits = num_qubits;
109 if (simulationType != SimulationType::kStatevector)
110 throw std::runtime_error(
111 "QCSimState::InitializeState: Invalid "
112 "simulation type for initializing the state.");
114 Eigen::VectorXcd amplitudesEigen(
115 Eigen::Map<Eigen::VectorXcd, Eigen::Unaligned>(amplitudes.data(),
117 state->setRegisterStorageFastNoNormalize(amplitudesEigen);
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;
162 if (simulationType != SimulationType::kStatevector)
163 throw std::runtime_error(
164 "QCSimState::InitializeState: Invalid "
165 "simulation type for initializing the state.");
167 Eigen::VectorXcd amplitudesEigen(
168 Eigen::Map<Eigen::VectorXcd, Eigen::Unaligned>(amplitudes.data(),
170 state->setRegisterStorageFastNoNormalize(amplitudesEigen);
185 void InitializeState(
size_t num_qubits,
186 Eigen::VectorXcd &litudes)
override {
187 if (num_qubits == 0)
return;
189 nrQubits = num_qubits;
192 if (simulationType != SimulationType::kStatevector)
193 throw std::runtime_error(
194 "QCSimState::InitializeState: Invalid "
195 "simulation type for initializing the state.");
197 state = std::make_unique<QC::QubitRegister<>>(nrQubits, amplitudes);
198 state->SetMultithreading(enableMultithreading);
207 void Reset()
override {
209 mpsSimulator->Clear();
210 else if (cliffordSimulator)
211 cliffordSimulator->Reset();
212 else if (tensorNetwork)
213 tensorNetwork->Clear();
217 pp->ClearOperations();
227 bool SupportsMPSSwapOptimization()
const override {
return true; }
237 void SetInitialQubitsMap(
238 const std::vector<long long int> &initialMap)
override {
240 mpsSimulator->SetInitialQubitsMap(initialMap);
241 if (!dummySim || dummySim->getNrQubits() != initialMap.size()) {
242 dummySim = std::make_unique<Simulators::MPSDummySimulator>(initialMap.size());
243 dummySim->SetMaxBondDimension(
244 limitSize ?
static_cast<long long int>(chi) : 0);
246 dummySim->SetInitialQubitsMap(initialMap);
250 void SetUseOptimalMeetingPosition(
bool enable)
override {
251 useOptimalMeetingPositionOnly = enable;
253 mpsSimulator->SetUseOptimalMeetingPosition(enable);
256 void SetLookaheadDepth(
int depth)
override {
257 lookaheadDepth = depth;
258 if (mpsSimulator && depth > 0 && !useOptimalMeetingPositionOnly)
259 mpsSimulator->SetUseOptimalMeetingPosition(
true);
262 void SetLookaheadDepthWithHeuristic(
int depth)
override
264 lookaheadDepthWithHeuristic = depth;
265 if (lookaheadDepth < depth) SetLookaheadDepth(depth);
268 void SetUpcomingGates(
270 upcomingGates = gates;
271 upcomingGateIndex = 0;
273 if (!mpsSimulator || lookaheadDepth <= 0)
return;
277 gateCounterObserver = std::make_shared<GateCounterObserver>(upcomingGateIndex);
278 RegisterObserver(gateCounterObserver);
283 mpsSimulator->SetMeetingPositionCallback(
284 [
this](
const auto &bondDims)
285 -> QC::TensorNetworks::MPSSimulatorInterface::IndexType {
286 const size_t nQ = bondDims.size() + 1;
288 if (!dummySim || dummySim->getNrQubits() != nQ) {
289 dummySim = std::make_unique<Simulators::MPSDummySimulator>(nQ);
290 dummySim->SetMaxBondDimension(limitSize ? static_cast<long long int>(chi) : 0);
296 dummySim->setTotalSwappingCost(0);
316 std::vector<double> bondDimsD(bondDims.begin(), bondDims.end());
317 dummySim->SetCurrentBondDimensions(bondDimsD);
328 const auto &op = upcomingGates[upcomingGateIndex];
329 const auto qbits = op->AffectedQubits();
358 double bestCost = std::numeric_limits<double>::infinity();
359 auto res = dummySim->FindBestMeetingPosition(upcomingGates, upcomingGateIndex, lookaheadDepth, lookaheadDepthWithHeuristic, 0, bestCost);
363 dummySim->SwapQubitsToPosition(qbits[0], qbits[1], res);
364 dummySim->ApplyGate(op);
394 long long int GetGatesCounter()
const override {
return upcomingGateIndex; }
405 void SetGatesCounter(
long long int counter)
override {
406 upcomingGateIndex = counter;
417 void IncrementGatesCounter()
override {
429 void Configure(
const char *key,
const char *value)
override {
430 if (std::string(
"method") == key) {
431 if (std::string(
"statevector") == value)
432 simulationType = SimulationType::kStatevector;
433 else if (std::string(
"matrix_product_state") == value)
434 simulationType = SimulationType::kMatrixProductState;
435 else if (std::string(
"stabilizer") == value)
436 simulationType = SimulationType::kStabilizer;
437 else if (std::string(
"tensor_network") == value)
438 simulationType = SimulationType::kTensorNetwork;
439 else if (std::string(
"pauli_propagator") == value)
440 simulationType = SimulationType::kPauliPropagator;
441 }
else if (std::string(
"matrix_product_state_truncation_threshold") ==
443 singularValueThreshold = std::stod(value);
444 if (singularValueThreshold > 0.) {
445 limitEntanglement =
true;
447 mpsSimulator->setLimitEntanglement(singularValueThreshold);
449 limitEntanglement =
false;
450 }
else if (std::string(
"matrix_product_state_max_bond_dimension") == key) {
451 chi = std::stoi(value);
454 if (mpsSimulator) mpsSimulator->setLimitBondDimension(chi);
455 if (dummySim) dummySim->SetMaxBondDimension(
static_cast<long long int>(chi));
458 if (mpsSimulator) mpsSimulator->setLimitBondDimension(0);
459 if (dummySim) dummySim->SetMaxBondDimension(0);
461 }
else if (std::string(
"mps_sample_measure_algorithm") == key)
462 useMPSMeasureNoCollapse = std::string(
"mps_probabilities") == value;
473 if (std::string(
"method") == key) {
474 switch (simulationType) {
475 case SimulationType::kStatevector:
476 return "statevector";
477 case SimulationType::kMatrixProductState:
478 return "matrix_product_state";
479 case SimulationType::kStabilizer:
481 case SimulationType::kTensorNetwork:
482 return "tensor_network";
483 case SimulationType::kPauliPropagator:
484 return "pauli_propagator";
488 }
else if (std::string(
"matrix_product_state_truncation_threshold") ==
490 if (limitEntanglement && singularValueThreshold > 0.)
491 return std::to_string(singularValueThreshold);
492 }
else if (std::string(
"matrix_product_state_max_bond_dimension") == key) {
493 if (limitSize && chi > 0)
return std::to_string(chi);
494 }
else if (std::string(
"mps_sample_measure_algorithm") == key) {
495 return useMPSMeasureNoCollapse ?
"mps_probabilities"
496 :
"mps_apply_measure";
510 if ((simulationType == SimulationType::kStatevector && state) ||
511 (simulationType == SimulationType::kMatrixProductState &&
513 (simulationType == SimulationType::kStabilizer && cliffordSimulator) ||
514 (simulationType == SimulationType::kTensorNetwork && tensorNetwork))
517 const size_t oldNrQubits = nrQubits;
518 nrQubits += num_qubits;
519 if (simulationType == SimulationType::kPauliPropagator)
520 if (pp) pp->SetNrQubits(
static_cast<int>(nrQubits));
540 void Clear()
override {
542 mpsSimulator =
nullptr;
543 cliffordSimulator =
nullptr;
544 tensorNetwork =
nullptr;
563 if (qubits.size() >
sizeof(
size_t) * 8)
565 <<
"Warning: The number of qubits to measure is larger than the "
566 "number of bits in the size_t type, the outcome will be undefined"
573 if (simulationType == SimulationType::kStatevector) {
574 for (
size_t qubit : qubits) {
575 if (state->MeasureQubit(
static_cast<unsigned int>(qubit))) res |= mask;
578 }
else if (simulationType == SimulationType::kStabilizer) {
579 for (
size_t qubit : qubits) {
580 if (cliffordSimulator->MeasureQubit(
static_cast<unsigned int>(qubit)))
584 }
else if (simulationType == SimulationType::kTensorNetwork) {
585 for (
size_t qubit : qubits) {
586 if (tensorNetwork->Measure(
static_cast<unsigned int>(qubit)))
590 }
else if (simulationType == SimulationType::kPauliPropagator) {
591 std::vector<int> qubitsInt(qubits.begin(), qubits.end());
592 const auto res = pp->Measure(qubitsInt);
594 for (
size_t i = 0; i < res.size(); ++i) {
595 if (res[i]) result |= mask;
608 const std::set<Eigen::Index> qubitsSet(qubits.begin(), qubits.end());
609 auto measured = mpsSimulator->MeasureQubits(qubitsSet);
611 if (measured[qubit]) res |= mask;
617 NotifyObservers(qubits);
629 std::vector<bool> res(qubits.size(),
false);
632 if (simulationType == SimulationType::kStatevector) {
633 for (
size_t q = 0; q < qubits.size(); ++q)
634 if (state->MeasureQubit(
static_cast<unsigned int>(qubits[q])))
636 }
else if (simulationType == SimulationType::kStabilizer) {
637 for (
size_t q = 0; q < qubits.size(); ++q)
638 if (cliffordSimulator->MeasureQubit(
639 static_cast<unsigned int>(qubits[q])))
641 }
else if (simulationType == SimulationType::kTensorNetwork) {
642 for (
size_t q = 0; q < qubits.size(); ++q)
643 if (tensorNetwork->Measure(
static_cast<unsigned int>(qubits[q])))
645 }
else if (simulationType == SimulationType::kPauliPropagator) {
646 std::vector<int> qubitsInt(qubits.begin(), qubits.end());
647 res = pp->Measure(qubitsInt);
649 const std::set<Eigen::Index> qubitsSet(qubits.begin(), qubits.end());
650 auto measured = mpsSimulator->MeasureQubits(qubitsSet);
651 for (
size_t q = 0; q < qubits.size(); ++q)
652 if (measured[qubits[q]]) res[q] =
true;
655 NotifyObservers(qubits);
667 QC::Gates::PauliXGate xGate;
670 if (simulationType == SimulationType::kStatevector) {
671 for (
size_t qubit : qubits)
672 if (state->MeasureQubit(
static_cast<unsigned int>(qubit)))
673 state->ApplyGate(xGate,
static_cast<unsigned int>(qubit));
674 }
else if (simulationType == SimulationType::kStabilizer) {
675 for (
size_t qubit : qubits)
676 if (cliffordSimulator->MeasureQubit(
static_cast<unsigned int>(qubit)))
677 cliffordSimulator->ApplyX(
static_cast<unsigned int>(qubit));
678 }
else if (simulationType == SimulationType::kTensorNetwork) {
679 for (
size_t qubit : qubits)
680 if (tensorNetwork->Measure(
static_cast<unsigned int>(qubit)))
681 tensorNetwork->AddGate(xGate,
static_cast<unsigned int>(qubit));
682 }
else if (simulationType == SimulationType::kPauliPropagator) {
683 std::vector<int> qubitsInt(qubits.begin(), qubits.end());
684 const auto res = pp->Measure(qubitsInt);
685 for (
size_t i = 0; i < res.size(); ++i) {
686 if (res[i]) pp->ApplyX(qubitsInt[i]);
689 for (
size_t qubit : qubits)
690 if (mpsSimulator->MeasureQubit(
static_cast<unsigned int>(qubit)))
691 mpsSimulator->ApplyGate(xGate,
static_cast<unsigned int>(qubit));
695 NotifyObservers(qubits);
710 if (simulationType == SimulationType::kMatrixProductState)
711 return mpsSimulator->getBasisStateProbability(
712 static_cast<unsigned int>(outcome));
713 else if (simulationType == SimulationType::kStabilizer)
714 return cliffordSimulator->getBasisStateProbability(
715 static_cast<unsigned int>(outcome));
716 else if (simulationType == SimulationType::kTensorNetwork)
717 return tensorNetwork->getBasisStateProbability(outcome);
718 else if (simulationType == SimulationType::kPauliPropagator)
719 return pp->Probability(outcome);
721 return state->getBasisStateProbability(
static_cast<unsigned int>(outcome));
735 if (simulationType == SimulationType::kMatrixProductState)
736 return mpsSimulator->getBasisStateAmplitude(
737 static_cast<unsigned int>(outcome));
738 else if (simulationType == SimulationType::kStabilizer)
739 throw std::runtime_error(
740 "QCSimState::Amplitude: Invalid simulation type for obtaining the "
741 "amplitude of the specified outcome.");
742 else if (simulationType == SimulationType::kTensorNetwork)
743 throw std::runtime_error(
744 "QCSimState::Amplitude: Not supported for the "
745 "tensor network simulator.");
746 else if (simulationType == SimulationType::kPauliPropagator)
747 throw std::runtime_error(
748 "QCSimState::Amplitude: Invalid simulation type for obtaining the "
749 "amplitude of the specified outcome.");
751 return state->getBasisStateAmplitude(
static_cast<unsigned int>(outcome));
767 std::complex<double> ProjectOnZero()
override {
768 if (simulationType == SimulationType::kMatrixProductState)
769 return mpsSimulator->ProjectOnZero();
785 if (simulationType == SimulationType::kTensorNetwork)
786 throw std::runtime_error(
787 "QCSimState::AllProbabilities: Invalid "
788 "simulation type for obtaining probabilities.");
789 else if (simulationType == SimulationType::kStabilizer)
790 return cliffordSimulator->AllProbabilities();
791 else if (simulationType == SimulationType::kPauliPropagator) {
793 std::vector<double> result(nrBasisStates);
794 for (
size_t i = 0; i < nrBasisStates; ++i) result[i] = pp->Probability(i);
798 const Eigen::VectorXcd probs =
799 simulationType == SimulationType::kMatrixProductState
800 ? mpsSimulator->getRegisterStorage().cwiseAbs2()
801 : state->getRegisterStorage().cwiseAbs2();
803 std::vector<double> result(probs.size());
805 for (
int i = 0; i < probs.size(); ++i) result[i] = probs[i].real();
823 if (simulationType == SimulationType::kStabilizer)
824 throw std::runtime_error(
825 "QCSimState::Probabilities: Invalid simulation "
826 "type for obtaining probabilities.");
827 else if (simulationType == SimulationType::kTensorNetwork) {
829 throw std::runtime_error(
830 "QCSimState::Probabilities: Not implemented yet "
831 "for the tensor network simulator.");
834 std::vector<double> result(qubits.size());
836 if (simulationType == SimulationType::kMatrixProductState) {
837 for (
int i = 0; i < static_cast<int>(qubits.size()); ++i)
838 result[i] = mpsSimulator->getBasisStateProbability(qubits[i]);
839 }
else if (simulationType == SimulationType::kPauliPropagator) {
840 for (
int i = 0; i < static_cast<int>(qubits.size()); ++i)
841 result[i] = pp->Probability(qubits[i]);
843 const Eigen::VectorXcd ® = state->getRegisterStorage();
845 for (
int i = 0; i < static_cast<int>(qubits.size()); ++i)
846 result[i] = std::norm(reg[qubits[i]]);
868 std::unordered_map<Types::qubit_t, Types::qubit_t>
SampleCounts(
870 if (qubits.empty() || shots == 0)
return {};
872 if (qubits.size() >
sizeof(
size_t) * 8)
874 <<
"Warning: The number of qubits to measure is larger than the "
875 "number of bits in the size_t type, the outcome will be undefined"
881 std::unordered_map<Types::qubit_t, Types::qubit_t> result;
885 if (simulationType == SimulationType::kMatrixProductState) {
887 if (useMPSMeasureNoCollapse) {
889 const std::set<Eigen::Index> qset(qubits.begin(), qubits.end());
893 for (
size_t shot = 0; shot < shots; ++shot) {
899 for (
auto q : qubits) {
900 const size_t qubitMask = 1ULL << q;
901 if (measRaw & qubitMask) meas |= mask;
907 }
else if (qset.size() > 1) {
908 mpsSimulator->MoveAtBeginningOfChain(qset);
911 for (
size_t shot = 0; shot < shots; ++shot) {
912 const auto measRaw = mpsSimulator->MeasureNoCollapse(qset);
918 for (
auto q : qubits) {
919 const size_t qubitMask = 1ULL << q;
920 if (measRaw.at(q)) meas |= mask;
927 }
else if (qset.size() == 1) {
930 const auto prob0 = mpsSimulator->GetProbability(qubits[0]);
931 for (
size_t shot = 0; shot < shots; ++shot) {
932 const size_t meas = uniformZeroOne(rng) < prob0 ? 0ULL : 1ULL;
935 for (
size_t i = 1; i < qubits.size(); ++i) {
945 auto savedState = mpsSimulator->getState();
946 for (
size_t shot = 0; shot < shots; ++shot) {
947 const size_t meas =
Measure(qubits);
949 mpsSimulator->setState(savedState);
952 }
else if (simulationType == SimulationType::kStabilizer) {
953 cliffordSimulator->SaveState();
954 for (
size_t shot = 0; shot < shots; ++shot) {
955 const size_t meas =
Measure(qubits);
957 cliffordSimulator->RestoreState();
959 cliffordSimulator->ClearSavedState();
960 }
else if (simulationType == SimulationType::kTensorNetwork) {
961 tensorNetwork->SaveState();
962 for (
size_t shot = 0; shot < shots; ++shot) {
963 const size_t meas =
Measure(qubits);
965 tensorNetwork->RestoreState();
967 tensorNetwork->ClearSavedState();
968 }
else if (simulationType == SimulationType::kPauliPropagator) {
969 std::vector<int> qubitsInt(qubits.begin(), qubits.end());
970 for (
size_t shot = 0; shot < shots; ++shot) {
971 const auto res = pp->Sample(qubitsInt);
974 for (
size_t i = 0; i < qubits.size(); ++i) {
975 if (res[i]) meas |= (1ULL << i);
982 const auto &statev = state->getRegisterStorage();
986 for (
size_t shot = 0; shot < shots; ++shot) {
987 const double prob = 1. - uniformZeroOne(rng);
988 const size_t measRaw = alias.
Sample(prob);
992 for (
auto q : qubits) {
993 const size_t qubitMask = 1ULL << q;
994 if ((measRaw & qubitMask) != 0) meas |= mask;
1001 for (
size_t shot = 0; shot < shots; ++shot) {
1006 for (
auto q : qubits) {
1007 const size_t qubitMask = 1ULL << q;
1008 if ((measRaw & qubitMask) != 0) meas |= mask;
1018 NotifyObservers(qubits);
1036 std::unordered_map<std::vector<bool>,
Types::qubit_t> SampleCountsMany(
1038 if (qubits.empty() || shots == 0)
return {};
1044 if (simulationType == SimulationType::kMatrixProductState) {
1046 if (useMPSMeasureNoCollapse) {
1048 const std::set<Eigen::Index> qset(qubits.begin(), qubits.end());
1052 for (
size_t shot = 0; shot < shots; ++shot) {
1053 const auto meas = MeasureNoCollapseMany();
1057 std::vector<bool> measVec(qubits.size());
1058 for (
size_t i = 0; i < qubits.size(); ++i)
1059 measVec[i] = meas[qubits[i]];
1063 }
else if (qset.size() > 1) {
1064 mpsSimulator->MoveAtBeginningOfChain(qset);
1067 for (
size_t shot = 0; shot < shots; ++shot) {
1068 const auto meas = mpsSimulator->MeasureNoCollapse(qset);
1072 std::vector<bool> measVec(qubits.size());
1073 for (
size_t i = 0; i < qubits.size(); ++i)
1074 measVec[i] = meas.at(qubits[i]);
1078 }
else if (qset.size() == 1) {
1081 const auto prob0 = mpsSimulator->GetProbability(qubits[0]);
1082 for (
size_t shot = 0; shot < shots; ++shot) {
1083 const size_t meas = uniformZeroOne(rng) < prob0 ? 0ULL : 1ULL;
1084 const std::vector<bool> m(qubits.size(), meas);
1091 auto savedState = mpsSimulator->getState();
1092 for (
size_t shot = 0; shot < shots; ++shot) {
1093 const auto meas = MeasureMany(qubits);
1096 mpsSimulator->setState(savedState);
1099 }
else if (simulationType == SimulationType::kStabilizer) {
1100 cliffordSimulator->SaveState();
1101 for (
size_t shot = 0; shot < shots; ++shot) {
1102 const auto meas = MeasureMany(qubits);
1104 cliffordSimulator->RestoreState();
1106 cliffordSimulator->ClearSavedState();
1107 }
else if (simulationType == SimulationType::kTensorNetwork) {
1108 tensorNetwork->SaveState();
1109 for (
size_t shot = 0; shot < shots; ++shot) {
1110 const auto meas = MeasureMany(qubits);
1112 tensorNetwork->RestoreState();
1114 tensorNetwork->ClearSavedState();
1115 }
else if (simulationType == SimulationType::kPauliPropagator) {
1116 std::vector<int> qubitsInt(qubits.begin(), qubits.end());
1117 for (
size_t shot = 0; shot < shots; ++shot) {
1118 const auto meas = pp->Sample(qubitsInt);
1123 const auto &statev = state->getRegisterStorage();
1127 for (
size_t shot = 0; shot < shots; ++shot) {
1128 const double prob = 1. - uniformZeroOne(rng);
1129 const size_t measRaw = alias.
Sample(prob);
1131 std::vector<bool> meas(qubits.size(),
false);
1133 for (
size_t i = 0; i < qubits.size(); ++i)
1134 if (((measRaw >> qubits[i]) & 1) == 1) meas[i] =
true;
1139 for (
size_t shot = 0; shot < shots; ++shot) {
1140 const auto measRaw = MeasureNoCollapseMany();
1141 std::vector<bool> meas(qubits.size(),
false);
1143 for (
size_t i = 0; i < qubits.size(); ++i)
1144 if (measRaw[qubits[i]]) meas[i] =
true;
1152 NotifyObservers(qubits);
1168 double ExpectationValue(
const std::string &pauliStringOrig)
override {
1169 if (pauliStringOrig.empty())
return 1.0;
1171 std::string pauliString = pauliStringOrig;
1174 const auto pauliOp = toupper(pauliString[i]);
1175 if (pauliOp !=
'I' && pauliOp !=
'Z')
return 0.0;
1181 if (simulationType == SimulationType::kStabilizer)
1182 return cliffordSimulator->ExpectationValue(pauliString);
1183 else if (simulationType == SimulationType::kTensorNetwork)
1184 return tensorNetwork->ExpectationValue(pauliString);
1185 else if (simulationType == SimulationType::kPauliPropagator)
1186 return pp->ExpectationValue(pauliString);
1189 static const QC::Gates::PauliXGate<> xgate;
1190 static const QC::Gates::PauliYGate<> ygate;
1191 static const QC::Gates::PauliZGate<> zgate;
1193 std::vector<QC::Gates::AppliedGate<Eigen::MatrixXcd>> pauliStringVec;
1194 pauliStringVec.reserve(pauliString.size());
1196 for (
size_t q = 0; q < pauliString.size(); ++q) {
1197 switch (toupper(pauliString[q])) {
1199 QC::Gates::AppliedGate<Eigen::MatrixXcd> ag(
1201 pauliStringVec.emplace_back(std::move(ag));
1204 QC::Gates::AppliedGate<Eigen::MatrixXcd> ag(
1206 pauliStringVec.emplace_back(std::move(ag));
1209 QC::Gates::AppliedGate<Eigen::MatrixXcd> ag(
1211 pauliStringVec.emplace_back(std::move(ag));
1220 if (pauliStringVec.empty())
return 1.0;
1222 if (simulationType == SimulationType::kMatrixProductState)
1223 return mpsSimulator->ExpectationValue(pauliStringVec).real();
1225 return state->ExpectationValue(pauliStringVec).real();
1235 SimulatorType GetType()
const override {
return SimulatorType::kQCSim; }
1255 void Flush()
override {}
1286 if (simulationType == SimulationType::kMatrixProductState)
1287 mpsSimulator->SaveState();
1288 else if (simulationType == SimulationType::kStabilizer)
1289 cliffordSimulator->SaveState();
1290 else if (simulationType == SimulationType::kTensorNetwork)
1291 tensorNetwork->SaveState();
1292 else if (simulationType == SimulationType::kPauliPropagator)
1307 if (simulationType == SimulationType::kMatrixProductState)
1308 mpsSimulator->RestoreState();
1309 else if (simulationType == SimulationType::kStabilizer)
1310 cliffordSimulator->RestoreState();
1311 else if (simulationType == SimulationType::kTensorNetwork)
1312 tensorNetwork->RestoreState();
1313 else if (simulationType == SimulationType::kPauliPropagator)
1316 state->RestoreState();
1326 std::complex<double> AmplitudeRaw(
Types::qubit_t outcome)
override {
1339 enableMultithreading = multithreading;
1340 if (state) state->SetMultithreading(multithreading);
1341 if (cliffordSimulator) cliffordSimulator->SetMultithreading(multithreading);
1342 if (tensorNetwork) tensorNetwork->SetMultithreading(multithreading);
1345 pp->EnableParallel();
1347 pp->DisableParallel();
1370 bool IsQcsim()
const override {
return true; }
1391 <<
"Warning: The number of qubits to measure is larger than the "
1392 "number of bits in the Types::qubit_t type, the outcome will be "
1396 if (simulationType == SimulationType::kStatevector)
1397 return state->MeasureNoCollapse();
1398 else if (simulationType == SimulationType::kMatrixProductState) {
1399 const auto measured = mpsSimulator->MeasureNoCollapse();
1403 if (measured.at(q)) result |= mask;
1407 }
else if (simulationType == SimulationType::kPauliPropagator) {
1409 std::iota(qubitsInt.begin(), qubitsInt.end(), 0);
1410 const auto res = pp->Sample(qubitsInt);
1412 for (
size_t i = 0; i < res.size(); ++i) {
1413 if (res[i]) result |= (1ULL << i);
1418 throw std::runtime_error(
1419 "QCSimState::MeasureNoCollapse: Invalid simulation type for measuring "
1420 "all the qubits without collapsing the state.");
1439 std::vector<bool> MeasureNoCollapseMany()
override {
1440 if (simulationType == SimulationType::kStatevector) {
1442 std::vector<bool> res(nrQubits);
1443 for (
size_t i = 0; i < nrQubits; ++i) res[i] = ((state >> i) & 1) == 1;
1445 }
else if (simulationType == SimulationType::kMatrixProductState) {
1446 const auto measured = mpsSimulator->MeasureNoCollapse();
1447 std::vector<bool> res(nrQubits);
1448 for (
size_t i = 0; i < nrQubits; ++i) res[i] = measured.at(i);
1450 }
else if (simulationType == SimulationType::kPauliPropagator) {
1452 std::iota(qubitsInt.begin(), qubitsInt.end(), 0);
1453 return pp->Sample(qubitsInt);
1456 throw std::runtime_error(
1457 "QCSimState::MeasureNoCollapseMany: Invalid simulation type for "
1458 "measuring all the qubits without collapsing the state.");
1464 SimulationType simulationType =
1465 SimulationType::kStatevector;
1467 std::unique_ptr<QC::QubitRegister<>> state;
1468 std::unique_ptr<QC::TensorNetworks::MPSSimulator>
1470 std::unique_ptr<QC::Clifford::StabilizerSimulator>
1472 std::unique_ptr<TensorNetworks::TensorNetwork>
1474 std::unique_ptr<QcsimPauliPropagator> pp;
1476 size_t nrQubits = 0;
1477 bool limitSize =
false;
1478 bool limitEntanglement =
false;
1479 Eigen::Index chi = 10;
1480 double singularValueThreshold = 0.;
1481 bool enableMultithreading =
true;
1482 bool useMPSMeasureNoCollapse =
1485 int lookaheadDepth = 0;
1486 int lookaheadDepthWithHeuristic = 0;
1487 bool useOptimalMeetingPositionOnly =
false;
1488 std::vector<std::shared_ptr<Circuits::IOperation<>>> upcomingGates;
1489 long long int upcomingGateIndex = 0;
1490 std::unique_ptr<Simulators::MPSDummySimulator> dummySim;
1493 class GateCounterObserver :
public ISimulatorObserver {
1495 GateCounterObserver(
long long int &indexRef) : index(indexRef) {}
1500 long long int &index;
1502 std::shared_ptr<GateCounterObserver> gateCounterObserver;
1504 std::mt19937_64 rng;
1505 std::uniform_real_distribution<double> uniformZeroOne;
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)
size_t Sample(double v) const
uint_fast64_t qubit_t
The type of a qubit.
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.