2#if defined(INCLUDED_BY_FACTORY) && defined(__linux__)
9class GpuMPSSimulator :
public GpuTensorChainSimulator
12 GpuMPSSimulator() : GpuTensorChainSimulator(false)
14 configuration.SetConfiguration(
"method",
"matrix_product_state");
15 configuration.SetConfiguration(
"matrix_product_state_max_bond_dimension",
"128");
16 configuration.SetConfiguration(
"matrix_product_operator_max_bond_dimension",
"128");
19 const char *MethodName()
const override
21 return "matrix_product_state";
24 void Initialize()
override
26 RefreshRoutingSettings();
27 InvalidateDummyHistory();
30 auto initializationLock = GpuLibrary::GetInstance()->LockInitialization();
31 const int gpuDevice = configuration.IsSet(
"gpu_device") ? Configuration::ParseGpuDevice(configuration.GetConfiguration(
"gpu_device"))
32 : SimulatorsFactory::ResolveGpuDevice();
33 configuration.SetConfiguration(
"gpu_device", std::to_string(gpuDevice));
34 if (!SimulatorsFactory::GetGpuLibrary(gpuDevice))
35 throw std::runtime_error(
"GpuState::Initialize: Unable to initialize GPU device " + std::to_string(gpuDevice));
36 SetSwapGatesRelabelQubits(GpuLibrary::GetInstance()->MPSSwapRelabels());
38 mps = SimulatorsFactory::CreateGpuLibMPSSim(gpuDevice);
41 mps->SetCallbackContext(
static_cast<GpuTensorChainSimulator *
>(
this));
43 mps->InstallBondSummary(&GpuTensorChainSimulator::BondSummaryCallback, &GpuTensorChainSimulator::BondDimCallback);
44 for (
const auto &[key, value] : configuration.GetConfigMap())
46 Configure(key.c_str(), value.c_str());
47 const bool res = mps->Create(nrQubits);
49 throw std::runtime_error(
"GpuState::Initialize: Failed to create "
50 "and initialize the MPS state.");
53 throw std::runtime_error(
"GpuState::Initialize: Failed to create the MPS state.");
54 if (!useOptimalMeetingPosition)
55 mps->SetUseOptimalMeetingPosition(
false);
57 if (GetGpuDevice() != gpuDevice)
58 throw std::runtime_error(
"GpuState::Initialize: GPU plugin did not confirm the requested "
59 "device; update the GPU library");
63 void InitializeToBasisState(
size_t num_qubits,
Types::qubit_t basisState)
override
68 nrQubits = num_qubits;
70 const bool created = mps->CreateWithBasisState(nrQubits,
static_cast<unsigned long long>(basisState));
72 throw std::runtime_error(
"GpuState::InitializeToBasisState: Failed to initialize the "
76 void InitializeToBasisState(
size_t num_qubits,
const std::vector<bool> &basisState)
override
81 nrQubits = num_qubits;
85 std::vector<unsigned char> stateBits(num_qubits, 0);
86 for (
size_t q = 0; q < num_qubits && q < basisState.size(); ++q)
87 stateBits[q] = basisState[q] ? 1 : 0;
88 created = mps->CreateWithBasisStateBits(nrQubits, stateBits);
91 throw std::runtime_error(
"GpuState::InitializeToBasisState: Failed to initialize the "
102 upcomingGateIndex = 0;
103 ResetDummySimulator();
106 void SetInitialQubitsMap(
const std::vector<long long int> &initialMap)
override
110 mps->SetInitialQubitsMap(initialMap);
111 EnsureDummySimulator(initialMap.size());
112 dummySim->SetInitialQubitsMap(initialMap);
116 void SetUseOptimalMeetingPosition(
bool enable)
override
118 useOptimalMeetingPosition = enable;
119 RefreshRoutingSettings();
121 mps->SetUseOptimalMeetingPosition(enable);
122 RefreshRoutingCallback();
125 void Configure(
const char *key,
const char *value)
override
129 if (std::string(
"gpu_device") == key)
131 const int device = Configuration::ParseGpuDevice(value);
132 if ((mps) && device != Configuration::ParseGpuDevice(configuration.GetConfiguration(key)))
133 throw std::invalid_argument(
"gpu_device cannot change after initialization; clear the "
135 configuration.SetConfiguration(key, std::to_string(device));
138 const auto svdGroup = Configuration::GpuSvdSettingGroup(key);
139 if (!svdGroup.empty())
141 const bool enabled = Configuration::ParseGpuSvdFlag(value);
142 const bool gesvd = svdGroup == key;
143 const char algorithm = std::string(key).back();
144 const auto apply = [algorithm, enabled](
auto &backend) {
147 if (algorithm ==
'j')
148 return backend->SetGesvdJ(enabled);
149 if (algorithm ==
'p')
150 return backend->SetGesvdP(enabled);
151 return backend->SetGesvdR(enabled);
153 const auto applyGesvd = [enabled](
auto &backend) {
154 if (!enabled || !backend)
156 return backend->SetGesvdJ(
false) && backend->SetGesvdP(
false) && backend->SetGesvdR(
false);
159 if (svdGroup ==
"matrix_product_state_use_gesvd")
160 applied = gesvd ? applyGesvd(mps) : apply(mps);
162 throw std::runtime_error(std::string(
"GPU library cannot apply ") + key +
"; an updated GPU plugin may be required");
163 configuration.SetConfiguration(key, value);
166 if (std::string(
"method") == key)
168 ValidateMethod(value);
169 configuration.SetConfiguration(key, value);
172 if (std::string(key) ==
"precision" || std::string(key) ==
"use_double_precision")
176 const bool useDouble = Configuration::ParsePrecision(key, value);
177 if ((mps && mps->IsCreated()))
179 if ((mps && !mps->SetDataType(useDouble)))
180 throw std::runtime_error(
"GPU precision configuration failed");
181 configuration.SetConfiguration(key, value);
184 if (!configuration.WasApplied(key, value))
185 configuration.SetConfiguration(key, value);
186 RefreshRoutingSettings();
187 if (std::string(
"seed") == key)
189 const uint64_t seed = std::stoull(value);
190 SeedAuxiliaryRng(seed);
196 if (std::string(
"matrix_product_state_truncation_threshold") == key || std::string(
"matrix_product_operator_truncation_threshold") == key)
198 const double singularValueThreshold = std::stod(value);
199 if (singularValueThreshold >= 0.)
202 mps->SetCutoff(singularValueThreshold);
205 else if (std::string(
"matrix_product_state_truncation_mode") == key || std::string(
"matrix_product_operator_truncation_mode") == key)
207 int truncationMode = -1;
208 if (std::string(
"relative_max") == value)
210 else if (std::string(
"discarded_weight") == value)
212 if (truncationMode >= 0)
215 mps->SetTruncationMode(truncationMode);
218 else if (std::string(
"matrix_product_state_max_bond_dimension") == key || std::string(
"matrix_product_operator_max_bond_dimension") == key)
220 const long long int chi = std::stoi(value);
223 const std::string bondDimension(value);
224 for (
const char *alias : {
"matrix_product_state_max_bond_dimension",
"matrix_product_operator_max_bond_dimension"})
225 if (!configuration.WasApplied(alias, bondDimension))
226 configuration.SetConfiguration(alias, bondDimension);
227 RefreshRoutingSettings();
229 mps->SetMaxExtent(chi);
231 dummySim->SetMaxBondDimension(EffectiveLookaheadMaxBondDimension(dummySim->getNrQubits(), chi));
240 if (std::string(key) ==
"precision" || std::string(key) ==
"use_double_precision")
242 const bool useDouble = mps ? mps->IsDoublePrecision() : configuration.GetConfiguration(
"precision") ==
"double";
243 return std::string(key) ==
"precision" ? (useDouble ?
"double" :
"single") : (useDouble ?
"1" :
"0");
247 const auto svdGroup = Configuration::GpuSvdSettingGroup(key);
248 if (!svdGroup.empty())
252 const auto readGesvd = [](
const auto &backend) {
return !backend->GetGesvdJ() && !backend->GetGesvdP() && !backend->GetGesvdR(); };
253 if (svdGroup ==
"matrix_product_state_use_gesvd" && mps)
254 return readGesvd(mps) ?
"true" :
"false";
256 const char algorithm = std::string(key).back();
257 const auto read = [algorithm](
const auto &backend) {
258 if (algorithm ==
'j')
259 return backend->GetGesvdJ();
260 if (algorithm ==
'p')
261 return backend->GetGesvdP();
262 return backend->GetGesvdR();
264 if (svdGroup ==
"matrix_product_state_use_gesvd" && mps)
265 return read(mps) ?
"true" :
"false";
267 if (std::string(
"method") == key)
269 return configuration.GetConfiguration(key);
276 const size_t oldNrQubits = nrQubits;
277 nrQubits += num_qubits;
281 void Clear()
override
285 ClearDummySimulator();
286 upcomingGateIndex = 0;
287 upcomingGates.clear();
292 InvalidateDummyHistory();
293 if (qubits.size() >
sizeof(
size_t) * 8)
294 std::cerr <<
"Warning: The number of qubits to measure is larger than the "
295 "number of bits in the size_t type, the outcome will be undefined"
301 for (
size_t qubit : qubits)
303 if (mps->Measure(
static_cast<unsigned int>(qubit)))
309 NotifyObservers(qubits);
315 InvalidateDummyHistory();
316 std::vector<bool> res(qubits.size(),
false);
319 for (
size_t i = 0; i < qubits.size(); ++i)
320 res[i] = mps->Measure(
static_cast<unsigned int>(qubits[i]));
323 NotifyObservers(qubits);
329 InvalidateDummyHistory();
332 for (
size_t qubit : qubits)
333 if (mps->Measure(
static_cast<unsigned int>(qubit)))
334 mps->ApplyX(
static_cast<unsigned int>(qubit));
337 NotifyObservers(qubits);
340 std::complex<double> ExpectationValueOperators(
const Types::qubits_vector &qubits,
const std::vector<Eigen::MatrixXcd> &matrices)
override
343 return IState::ExpectationValueOperators(qubits, matrices);
344 TensorQueries::Operators(qubits, matrices, nrQubits);
345 std::vector<int> targets;
346 std::vector<double> raw;
347 targets.reserve(qubits.size());
348 raw.reserve(8 * matrices.size());
349 for (
size_t i = 0; i < qubits.size(); ++i)
351 targets.push_back(TensorQueries::Count(qubits[i]));
352 for (Eigen::Index e = 0; e < 4; ++e)
354 raw.push_back(matrices[i].data()[e].real());
355 raw.push_back(matrices[i].data()[e].imag());
358 return mps->ExpectationValueOperators(targets, raw);
364 return IState::MoveAtBeginningOfChain(qubits);
365 const auto selected = MPOValidation::Qubits(qubits, nrQubits);
366 if (selected.empty())
368 mps->MoveAtBeginningOfChain(selected);
369 InvalidateDummyHistory();
372 std::vector<std::complex<double>> GetStateVector()
override
375 return IState::GetStateVector();
376 return mps->GetStateVector();
381 InvalidateDummyHistory();
385 throw std::runtime_error(
"GPU MPS trim failed");
388 throw std::runtime_error(
"Trim is only available for GPU MPS and MPO");
391 void ReCanonicalize()
override
393 InvalidateDummyHistory();
396 if (!mps->ReCanonicalize())
397 throw std::runtime_error(
"GPU MPS canonicalization failed");
400 throw std::runtime_error(
"Canonicalization is only available for GPU MPS and MPO");
408 std::vector<long int> fixedValues(nrQubits);
409 for (
size_t i = 0; i < nrQubits; ++i)
410 fixedValues[i] = i < std::numeric_limits<Types::qubit_t>::digits ? (outcome >> i) & 1 : 0;
412 if (!mps->Amplitude(nrQubits, fixedValues.data(), &real, &imag) || !std::isfinite(real) || !std::isfinite(imag))
413 throw std::runtime_error(
"GPU MPS amplitude query failed");
416 return std::complex<double>(real, imag);
419 std::complex<double> ProjectOnZero()
override
421 return mps->ProjectOnZero();
429 return mps->AllProbabilities();
430 if (nrQubits >= std::numeric_limits<size_t>::digits)
431 throw std::length_error(
"Full probability enumeration exceeds the basis-index API; query "
432 "selected bit vectors");
433 const size_t numStates =
size_t{1} << nrQubits;
434 std::vector<double> result(numStates);
439 result[i] = std::norm(std::complex<double>(val.real(), val.imag()));
450 throw std::invalid_argument(
"Use SampleCountsMany for more than 64 measured qubits");
451 std::unordered_map<Types::qubit_t, Types::qubit_t> result;
452 for (
const auto &entry : SampleCountsMany(qubits, shots))
455 for (
size_t i = 0; i < entry.first.size(); ++i)
458 result[value] += entry.second;
462 if (qubits.empty() || shots == 0)
465 std::cerr <<
"Warning: The number of qubits to measure is larger than the "
466 "number of bits in the Types::qubit_t type, the outcome will be "
469 std::unordered_map<Types::qubit_t, Types::qubit_t> result;
472 NotifyObservers(qubits);
480 std::vector<unsigned int> selected;
481 for (
auto q : qubits)
483 if (q >= nrQubits || q >
static_cast<size_t>(std::numeric_limits<int>::max()))
484 throw std::out_of_range(
"GPU tensor sampled qubit is out of range");
485 selected.push_back(
static_cast<unsigned int>(q));
487 if (qubits.empty() || shots == 0)
489 std::sort(selected.begin(), selected.end());
490 selected.erase(std::unique(selected.begin(), selected.end()), selected.end());
491 const auto counts = mps->SampleHistogram(shots, std::move(selected));
494 ValidateDummyHistoryMap();
495 const auto positions = SampleBitPositions(qubits);
497 for (
const auto &entry : counts)
499 std::vector<bool> bits(qubits.size());
500 for (
size_t i = 0; i < bits.size(); ++i)
501 bits[i] = entry.first[positions[i]];
502 result[std::move(bits)] += entry.second;
504 NotifyObservers(qubits);
507 if (qubits.empty() || shots == 0)
512 NotifyObservers(qubits);
516 double ExpectationValue(
const std::string &pauliString)
override
519 result = mps->ExpectationValue(pauliString);
523 std::vector<double> ExpectationValues(
const std::vector<std::string> &paulis)
override
526 return IState::ExpectationValues(paulis);
527 std::vector<double> result(paulis.size(), 0.);
528 std::vector<std::string> selected;
529 std::vector<size_t> indices;
530 for (
size_t i = 0; i < paulis.size(); ++i)
532 if (paulis[i].empty())
537 if (paulis[i].size() > nrQubits)
539 auto pauli = paulis[i];
540 for (
char &p : pauli)
541 p =
static_cast<char>(std::toupper(
static_cast<unsigned char>(p)));
542 if (pauli.find_first_not_of(
"IXYZ") != std::string::npos)
544 indices.push_back(i);
545 selected.push_back(std::move(pauli));
547 if (selected.empty())
549 const auto values = mps->ExpectationValues(selected);
550 for (
size_t i = 0; i < indices.size(); ++i)
551 result[indices[i]] = values[i];
555 int GetGpuDevice()
const override
558 return mps->GetGpuDevice();
564 return SimulationType::kMatrixProductState;
569 if (!mps->SaveState())
570 throw std::runtime_error(
"GPU MPS state save failed");
576 if (!mps->RestoreState())
577 throw std::runtime_error(
"GPU MPS state restore failed");
583 const Eigen::Matrix2cd inputFirst = gate.transpose();
584 if (!mps->ApplyOneQubitMatrix(
static_cast<unsigned int>(qubit),
reinterpret_cast<const double *
>(inputFirst.data())))
585 throw std::runtime_error(
"GpuSimulator::ApplyGenericOneQubitGate: Failed to apply the "
586 "generic one-qubit gate on the matrix product state simulator.");
587 NotifyObservers({qubit});
593 const Eigen::Matrix4cd inputFirst = gate.transpose();
594 if (!mps->ApplyTwoQubitMatrix(
static_cast<unsigned int>(qubit0),
static_cast<unsigned int>(qubit1),
595 reinterpret_cast<const double *
>(inputFirst.data())))
596 throw std::runtime_error(
"GpuSimulator::ApplyGenericTwoQubitGate: Failed to apply the "
597 "generic two-qubit gate on the matrix product state simulator.");
598 RecordExecutedTwoQubitGate(qubit0, qubit1, swapGatesRelabelQubits && IsExactSwapMatrix(gate),
EffectiveSchmidtRank(gate));
599 NotifyObservers({qubit0, qubit1});
605 mps->ApplyP(qubit, lambda);
606 NotifyObservers({qubit});
612 NotifyObservers({qubit});
618 NotifyObservers({qubit});
624 NotifyObservers({qubit});
630 NotifyObservers({qubit});
636 NotifyObservers({qubit});
641 mps->ApplySDG(qubit);
642 NotifyObservers({qubit});
648 NotifyObservers({qubit});
653 mps->ApplyTDG(qubit);
654 NotifyObservers({qubit});
660 NotifyObservers({qubit});
665 mps->ApplySXDG(qubit);
666 NotifyObservers({qubit});
672 NotifyObservers({qubit});
677 mps->ApplyRx(qubit, theta);
678 NotifyObservers({qubit});
683 mps->ApplyRy(qubit, theta);
684 NotifyObservers({qubit});
689 mps->ApplyRz(qubit, theta);
690 NotifyObservers({qubit});
693 void ApplyU(
Types::qubit_t qubit,
double theta,
double phi,
double lambda,
double gamma)
override
695 mps->ApplyU(qubit, theta, phi, lambda, gamma);
696 NotifyObservers({qubit});
701 mps->ApplyCX(ctrl_qubit, tgt_qubit);
702 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false, 2.);
703 NotifyObservers({tgt_qubit, ctrl_qubit});
708 mps->ApplyCY(ctrl_qubit, tgt_qubit);
709 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false, 2.);
710 NotifyObservers({tgt_qubit, ctrl_qubit});
715 mps->ApplyCZ(ctrl_qubit, tgt_qubit);
716 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false, 2.);
717 NotifyObservers({tgt_qubit, ctrl_qubit});
722 mps->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
723 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false,
ControlledSchmidtRank(2. * std::abs(std::cos(lambda / 2.))));
724 NotifyObservers({tgt_qubit, ctrl_qubit});
729 mps->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
730 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false,
ControlledSchmidtRank(2. * std::abs(std::cos(theta / 2.))));
731 NotifyObservers({tgt_qubit, ctrl_qubit});
736 mps->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
737 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false,
ControlledSchmidtRank(2. * std::abs(std::cos(theta / 2.))));
738 NotifyObservers({tgt_qubit, ctrl_qubit});
743 mps->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
744 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false,
ControlledSchmidtRank(2. * std::abs(std::cos(theta / 2.))));
745 NotifyObservers({tgt_qubit, ctrl_qubit});
750 mps->ApplyCH(ctrl_qubit, tgt_qubit);
751 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false, 2.);
752 NotifyObservers({tgt_qubit, ctrl_qubit});
757 mps->ApplyCSX(ctrl_qubit, tgt_qubit);
759 NotifyObservers({tgt_qubit, ctrl_qubit});
764 mps->ApplyCSXDG(ctrl_qubit, tgt_qubit);
766 NotifyObservers({tgt_qubit, ctrl_qubit});
771 if (!mps || !mps->ApplySwap(qubit0, qubit1))
772 throw std::runtime_error(
"GpuSimulator::ApplySwap: Failed to apply SWAP on the matrix product state simulator.");
773 RecordExecutedTwoQubitGate(qubit0, qubit1,
true, 4.);
774 NotifyObservers({qubit1, qubit0});
780 DecompositionScope scope(*
this);
781 const size_t q1 = qubit0;
782 const size_t q2 = qubit1;
783 const size_t q3 = qubit2;
784 mps->ApplyCSX(
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q3));
785 RecordExecutedTwoQubitGate(qubit1, qubit2,
false, 2.);
786 NotifyObservers({qubit1, qubit2});
787 mps->ApplyCX(
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q2));
788 RecordExecutedTwoQubitGate(qubit0, qubit1,
false, 2.);
789 NotifyObservers({qubit0, qubit1});
790 mps->ApplyCSXDG(
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q3));
791 RecordExecutedTwoQubitGate(qubit1, qubit2,
false, 2.);
792 NotifyObservers({qubit1, qubit2});
793 mps->ApplyCX(
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q2));
794 RecordExecutedTwoQubitGate(qubit0, qubit1,
false, 2.);
795 NotifyObservers({qubit0, qubit1});
796 mps->ApplyCSX(
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q3));
797 RecordExecutedTwoQubitGate(qubit0, qubit2,
false, 2.);
798 NotifyObservers({qubit0, qubit2});
800 NotifyObservers({qubit2, qubit1, qubit0});
806 DecompositionScope scope(*
this);
807 const size_t q1 = ctrl_qubit;
808 const size_t q2 = qubit0;
809 const size_t q3 = qubit1;
810 mps->ApplyCX(
static_cast<unsigned int>(q3),
static_cast<unsigned int>(q2));
811 RecordExecutedTwoQubitGate(qubit1, qubit0,
false, 2.);
812 NotifyObservers({qubit1, qubit0});
813 mps->ApplyCSX(
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q3));
814 RecordExecutedTwoQubitGate(qubit0, qubit1,
false, 2.);
815 NotifyObservers({qubit0, qubit1});
816 mps->ApplyCX(
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q2));
817 RecordExecutedTwoQubitGate(ctrl_qubit, qubit0,
false, 2.);
818 NotifyObservers({ctrl_qubit, qubit0});
819 mps->ApplyP(
static_cast<unsigned int>(q3), M_PI);
820 NotifyObservers({qubit1});
821 mps->ApplyP(
static_cast<unsigned int>(q2), -M_PI_2);
822 NotifyObservers({qubit0});
823 mps->ApplyCSX(
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q3));
824 RecordExecutedTwoQubitGate(qubit0, qubit1,
false, 2.);
825 NotifyObservers({qubit0, qubit1});
826 mps->ApplyCX(
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q2));
827 RecordExecutedTwoQubitGate(ctrl_qubit, qubit0,
false, 2.);
828 NotifyObservers({ctrl_qubit, qubit0});
829 mps->ApplyP(
static_cast<unsigned int>(q3), M_PI);
830 NotifyObservers({qubit1});
831 mps->ApplyCSX(
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q3));
832 RecordExecutedTwoQubitGate(ctrl_qubit, qubit1,
false, 2.);
833 NotifyObservers({ctrl_qubit, qubit1});
834 mps->ApplyCX(
static_cast<unsigned int>(q3),
static_cast<unsigned int>(q2));
835 RecordExecutedTwoQubitGate(qubit1, qubit0,
false, 2.);
836 NotifyObservers({qubit1, qubit0});
838 NotifyObservers({qubit1, qubit0, ctrl_qubit});
843 mps->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
844 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false,
ControlledSchmidtRank(2. * std::abs(std::cos(theta / 2.) * std::cos((phi + lambda) / 2.))));
845 NotifyObservers({tgt_qubit, ctrl_qubit});
848 std::unique_ptr<ISimulator> Clone()
override
850 auto cloned = std::make_unique<GpuMPSSimulator>();
851 cloned->swapGatesRelabelQubits = swapGatesRelabelQubits;
852 cloned->nrQubits = nrQubits;
853 cloned->lookaheadDepth = lookaheadDepth;
854 cloned->lookaheadDepthWithHeuristic = lookaheadDepthWithHeuristic;
855 cloned->useOptimalMeetingPosition = useOptimalMeetingPosition;
856 cloned->upcomingGates = upcomingGates;
857 cloned->upcomingGateIndex = upcomingGateIndex;
858 cloned->growthFactorGate = growthFactorGate;
859 cloned->growthFactorSwap = growthFactorSwap;
860 cloned->configuration = configuration;
863 cloned->mps = mps->Clone();
864 cloned->gateCounterObserver = std::make_shared<GateCounterObserver>(cloned->upcomingGateIndex);
865 cloned->RegisterObserver(cloned->gateCounterObserver);
866 cloned->curMaxBondDim = curMaxBondDim;
867 cloned->mps->SetCallbackContext(
static_cast<GpuTensorChainSimulator *
>(cloned.get()));
869 cloned->RefreshRoutingSettings();
870 cloned->dummySim = dummySim ? dummySim->Clone() :
nullptr;
871 cloned->dummyHistoryValid = dummyHistoryValid;
872 cloned->savedDummyBondDims = savedDummyBondDims;
873 cloned->RefreshRoutingCallback();
874 if (configuration.IsSet(
"seed"))
875 cloned->SetSeed(DeriveSeed(std::stoull(configuration.GetConfiguration(
"seed")), nextSeedStream++));
880 std::vector<double> CurrentBondDimensions()
const override
884 const auto dims = mps->GetBondDimensions(nrQubits);
885 return {dims.begin(), dims.end()};
888 std::vector<long long> CurrentRoutingMap()
const override
891 return mps->GetQubitsMap();
895 void RefreshRoutingCallback()
override
897 const bool active = IsRoutingLookaheadEnabled() && !upcomingGates.empty();
899 mps->SetMeetingPositionCallback(active ? GetMeetingPositionCallback() :
nullptr);
902 std::unique_ptr<GpuLibMPSSim> mps;
int ApplyK(void *sim, int qubit)
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)
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 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 ApplyT(void *sim, int qubit)
int ApplyCRx(void *sim, int controlQubit, int targetQubit, double theta)
int ApplyGenericOneQubitGate(void *sim, unsigned long q0, const double *buffer)
int ApplyGenericTwoQubitGate(void *sim, unsigned long q0, unsigned long q1, const double *buffer)
SimulationType
The type of simulation.
double EffectiveSchmidtRank(const Eigen::MatrixXcd &u)
double ControlledSchmidtRank(double traceAbs)
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
uint_fast64_t qubit_t
The type of a qubit.