2#if defined(INCLUDED_BY_FACTORY)
3#include "MPSSimulator.h"
5#define _USE_MATH_DEFINES
11class QCSimMPSSimulator :
public QCSimTensorChainSimulator
14 QCSimMPSSimulator() : QCSimTensorChainSimulator(false)
16 configuration.SetConfiguration(
"method",
"matrix_product_state");
19 const char *MethodName()
const override
21 return "matrix_product_state";
24 void Initialize()
override
26 InvalidateBoundedRouting(
true);
27 RefreshRoutingSettings();
28 InvalidateDummyHistory();
32 mpsSimulator = std::make_unique<QC::TensorNetworks::MPSSimulator>(nrQubits);
33 if (!useOptimalMeetingPosition)
34 mpsSimulator->SetUseOptimalMeetingPosition(
false);
39 for (
const auto &[key, value] : configuration.GetConfigMap())
41 Configure(key.c_str(), value.c_str());
43 RefreshRoutingCallback();
46 void InitializeToBasisState(
size_t num_qubits,
Types::qubit_t basisState)
override
51 nrQubits = num_qubits;
53 mpsSimulator->setToBasisState(
static_cast<size_t>(basisState));
56 void InitializeToBasisState(
size_t num_qubits,
const std::vector<bool> &basisState)
override
61 nrQubits = num_qubits;
63 mpsSimulator->setToBasisState(basisState);
70 mpsSimulator->Clear();
73 upcomingGateIndex = 0;
74 ResetDummySimulator();
77 void SetInitialQubitsMap(
const std::vector<long long int> &initialMap)
override
81 mpsSimulator->SetInitialQubitsMap(initialMap);
82 EnsureDummySimulator(initialMap.size());
83 dummySim->SetInitialQubitsMap(initialMap);
87 void SetUseOptimalMeetingPosition(
bool enable)
override
89 useOptimalMeetingPosition = enable;
90 RefreshRoutingSettings();
92 mpsSimulator->SetUseOptimalMeetingPosition(enable);
93 RefreshRoutingCallback();
96 void Configure(
const char *key,
const char *value)
override
98 if (std::string(
"method") == key)
100 ValidateMethod(value);
101 configuration.SetConfiguration(key, value);
104 if (!configuration.WasApplied(key, value))
105 configuration.SetConfiguration(key, value);
106 RefreshRoutingSettings();
107 if (std::string(
"seed") == key)
109 const uint64_t seed = std::stoull(value);
110 SeedAuxiliaryRng(seed);
114 SeedBackend(mpsSimulator.get(), seed);
119 if (std::string(key) ==
"matrix_product_state_max_bond_dimension")
121 const auto limit = configuration.GetConfigurationAsInt(key);
122 mpsSimulator->setLimitBondDimension(limit);
124 dummySim->SetMaxBondDimension(EffectiveLookaheadMaxBondDimension(dummySim->getNrQubits(), limit));
126 else if (std::string(key) ==
"matrix_product_state_truncation_threshold")
128 const double threshold = configuration.GetConfigurationAsDouble(key);
130 mpsSimulator->setLimitEntanglement(threshold);
132 else if (std::string(key) ==
"matrix_product_state_truncation_mode")
134 if (std::string(value) ==
"relative_max")
135 mpsSimulator->setTruncationMode(QC::TensorNetworks::MPSSimulator::TruncationMode::RelativeToMax);
136 else if (std::string(value) ==
"discarded_weight")
137 mpsSimulator->setTruncationMode(QC::TensorNetworks::MPSSimulator::TruncationMode::DiscardedWeight);
140 if (std::string(key) ==
"pauli_propagator_workers")
142 const auto workers = configuration.GetConfigurationAsUnsigned(key);
144 throw std::invalid_argument(
"pauli_propagator_workers exceeds 1024");
146 RefreshRoutingCallback();
153 const size_t oldNrQubits = nrQubits;
154 nrQubits += num_qubits;
158 void Clear()
override
160 automaticRoutingDepth =
false;
161 InvalidateBoundedRouting(
true);
162 mpsSimulator =
nullptr;
163 ClearDummySimulator();
165 upcomingGateIndex = 0;
166 upcomingGates.clear();
171 InvalidateDummyHistory();
172 if (qubits.size() >
sizeof(
size_t) * 8)
173 std::cerr <<
"Warning: The number of qubits to measure is larger than the "
174 "number of bits in the size_t type, the outcome will be undefined"
180 const std::set<Eigen::Index> qubitsSet(qubits.begin(), qubits.end());
181 auto measured = mpsSimulator->MeasureQubits(qubitsSet);
190 NotifyObservers(qubits);
196 InvalidateDummyHistory();
197 std::vector<bool> res(qubits.size(),
false);
200 const std::set<Eigen::Index> qubitsSet(qubits.begin(), qubits.end());
201 auto measured = mpsSimulator->MeasureQubits(qubitsSet);
202 for (
size_t q = 0; q < qubits.size(); ++q)
203 if (measured[qubits[q]])
207 NotifyObservers(qubits);
213 InvalidateDummyHistory();
216 for (
size_t qubit : qubits)
217 if (mpsSimulator->MeasureQubit(
static_cast<unsigned int>(qubit)))
218 mpsSimulator->ApplyGate(xgate,
static_cast<unsigned int>(qubit));
221 NotifyObservers(qubits);
227 return IState::MoveAtBeginningOfChain(qubits);
228 const auto selected = MPOValidation::Qubits(qubits, nrQubits);
229 const std::set<Eigen::Index> targets(selected.begin(), selected.end());
230 mpsSimulator->MoveAtBeginningOfChain(targets);
231 InvalidateDummyHistory();
234 std::vector<std::complex<double>> GetStateVector()
override
237 return IState::GetStateVector();
240 const auto count = TensorQueries::DenseSize(nrQubits);
241 const auto values = mpsSimulator->getRegisterStorage();
242 if (
static_cast<size_t>(values.size()) != count)
243 throw std::runtime_error(
"QCSim statevector query returned an invalid size");
244 return {values.data(), values.data() + values.size()};
247 std::complex<double> ExpectationValueOperators(
const Types::qubits_vector &qubits,
const std::vector<Eigen::MatrixXcd> &matrices)
override
250 return IState::ExpectationValueOperators(qubits, matrices);
251 TensorQueries::Operators(qubits, matrices, nrQubits);
252 std::vector<QC::Gates::AppliedGate<>> gates;
253 gates.reserve(qubits.size());
254 for (
size_t i = 0; i < qubits.size(); ++i)
255 gates.emplace_back(matrices[i], qubits[i]);
256 return mpsSimulator->ExpectationValue(gates);
261 InvalidateDummyHistory();
263 mpsSimulator->Trim();
265 throw std::runtime_error(
"Trim is only available for QCSim MPS and MPO");
268 void ReCanonicalize()
override
270 InvalidateDummyHistory();
272 mpsSimulator->ReCanonicalize();
274 throw std::runtime_error(
"Canonicalization is only available for QCSim MPS and MPO");
279 return mpsSimulator->getBasisStateProbability(
static_cast<unsigned int>(outcome));
284 return mpsSimulator->getBasisStateAmplitude(
static_cast<unsigned int>(outcome));
287 std::complex<double> ProjectOnZero()
override
289 return mpsSimulator->ProjectOnZero();
294 const Eigen::VectorXcd probs = mpsSimulator->getRegisterStorage().cwiseAbs2();
295 std::vector<double> result(probs.size());
296 for (
int i = 0; i < probs.size(); ++i)
297 result[i] = probs[i].real();
303 std::vector<double> result(qubits.size());
305 for (
int i = 0; i < static_cast<int>(qubits.size()); ++i)
306 result[i] = mpsSimulator->getBasisStateProbability(qubits[i]);
313 if (qubits.empty() || shots == 0)
315 if (qubits.size() >
sizeof(
size_t) * 8)
316 std::cerr <<
"Warning: The number of qubits to measure is larger than the "
317 "number of bits in the size_t type, the outcome will be undefined"
319 std::unordered_map<Types::qubit_t, Types::qubit_t> result;
323 if (!configuration.IsSet(
"mps_sample_measure_algorithm") || configuration.GetConfiguration(
"mps_sample_measure_algorithm") ==
"mps_probabilities")
325 const std::set<Eigen::Index> qset(qubits.begin(), qubits.end());
329 for (
size_t shot = 0; shot < shots; ++shot)
334 for (
auto q : qubits)
336 const size_t qubitMask = 1ULL << q;
337 if (measRaw & qubitMask)
344 else if (qset.size() > 1)
346 mpsSimulator->MoveAtBeginningOfChain(qset);
347 InvalidateDummyHistory();
349 for (
size_t shot = 0; shot < shots; ++shot)
351 const auto measRaw = mpsSimulator->MeasureNoCollapse(qset);
354 for (
auto q : qubits)
363 else if (qset.size() == 1)
366 const auto prob0 = mpsSimulator->GetProbability(qubits[0]);
367 for (
size_t shot = 0; shot < shots; ++shot)
369 const size_t meas = uniformZeroOne(rng) < prob0 ? 0ULL : 1ULL;
371 for (
size_t i = 1; i < qubits.size(); ++i)
382 auto savedState = mpsSimulator->getState();
383 const auto savedHistory = CaptureDummyHistory();
384 for (
size_t shot = 0; shot < shots; ++shot)
386 const size_t meas =
Measure(qubits);
388 mpsSimulator->setState(savedState);
390 RestoreDummyHistory(savedHistory);
394 NotifyObservers(qubits);
400 if (qubits.empty() || shots == 0)
406 if (!configuration.IsSet(
"mps_sample_measure_algorithm") || configuration.GetConfiguration(
"mps_sample_measure_algorithm") ==
"mps_probabilities")
408 const std::set<Eigen::Index> qset(qubits.begin(), qubits.end());
412 for (
size_t shot = 0; shot < shots; ++shot)
414 const auto meas = MeasureNoCollapseMany();
415 std::vector<bool> measVec(qubits.size());
416 for (
size_t i = 0; i < qubits.size(); ++i)
417 measVec[i] = meas[qubits[i]];
421 else if (qset.size() > 1)
423 mpsSimulator->MoveAtBeginningOfChain(qset);
424 InvalidateDummyHistory();
426 for (
size_t shot = 0; shot < shots; ++shot)
428 const auto meas = mpsSimulator->MeasureNoCollapse(qset);
429 std::vector<bool> measVec(qubits.size());
430 for (
size_t i = 0; i < qubits.size(); ++i)
431 measVec[i] = meas.at(qubits[i]);
435 else if (qset.size() == 1)
438 const auto prob0 = mpsSimulator->GetProbability(qubits[0]);
439 for (
size_t shot = 0; shot < shots; ++shot)
441 const size_t meas = uniformZeroOne(rng) < prob0 ? 0ULL : 1ULL;
442 const std::vector<bool> m(qubits.size(), meas);
449 auto savedState = mpsSimulator->getState();
450 const auto savedHistory = CaptureDummyHistory();
451 for (
size_t shot = 0; shot < shots; ++shot)
453 const auto meas = MeasureMany(qubits);
455 mpsSimulator->setState(savedState);
457 RestoreDummyHistory(savedHistory);
461 NotifyObservers(qubits);
465 std::vector<double> ExpectationValues(
const std::vector<std::string> &paulis)
override
467 std::vector<double> result(paulis.size(), 1.);
468 std::vector<std::string> selected;
469 std::vector<size_t> indices;
471 for (
size_t i = 0; i < paulis.size(); ++i)
473 if (paulis[i].empty())
476 for (
size_t q = n; q < paulis[i].size(); ++q)
478 const auto p = toupper(
static_cast<unsigned char>(paulis[i][q]));
479 if (p !=
'I' && p !=
'Z')
490 std::string pauli = paulis[i];
491 pauli.resize(n,
'I');
492 for (
char &p : pauli)
494 p =
static_cast<char>(toupper(
static_cast<unsigned char>(p)));
495 if (p !=
'X' && p !=
'Y' && p !=
'Z')
498 indices.push_back(i);
499 selected.push_back(std::move(pauli));
501 if (selected.empty())
504 for (
size_t i = 0; i < indices.size(); ++i)
505 result[indices[i]] = values[i].real();
509 double ExpectationValue(
const std::string &pauliStringOrig)
override
511 if (pauliStringOrig.empty())
513 std::string pauliString = pauliStringOrig;
518 const auto pauliOp = toupper(pauliString[i]);
519 if (pauliOp !=
'I' && pauliOp !=
'Z')
524 std::vector<QC::Gates::AppliedGate<Eigen::MatrixXcd>> pauliStringVec;
525 pauliStringVec.reserve(pauliString.size());
526 for (
size_t q = 0; q < pauliString.size(); ++q)
528 switch (toupper(pauliString[q]))
531 QC::Gates::AppliedGate<Eigen::MatrixXcd> ag(xgate.getRawOperatorMatrix(),
static_cast<Types::qubit_t>(q));
532 pauliStringVec.emplace_back(std::move(ag));
536 QC::Gates::AppliedGate<Eigen::MatrixXcd> ag(ygate.getRawOperatorMatrix(),
static_cast<Types::qubit_t>(q));
537 pauliStringVec.emplace_back(std::move(ag));
541 QC::Gates::AppliedGate<Eigen::MatrixXcd> ag(zgate.getRawOperatorMatrix(),
static_cast<Types::qubit_t>(q));
542 pauliStringVec.emplace_back(std::move(ag));
551 if (pauliStringVec.empty())
553 return mpsSimulator->ExpectationValue(pauliStringVec).real();
558 return SimulationType::kMatrixProductState;
563 mpsSimulator->SaveState();
569 mpsSimulator->RestoreState();
575 enableMultithreading = multithreading;
577 mpsSimulator->SetMultithreading(multithreading);
583 std::cerr <<
"Warning: The number of qubits to measure is larger than the "
584 "number of bits in the Types::qubit_t type, the outcome will be "
588 const auto measured = mpsSimulator->MeasureNoCollapse();
601 std::vector<bool> MeasureNoCollapseMany()
override
603 const auto measured = mpsSimulator->MeasureNoCollapse();
604 std::vector<bool> res(nrQubits);
605 for (
size_t i = 0; i < nrQubits; ++i)
606 res[i] = measured.at(i);
612 const QC::Gates::AppliedGate<> agate(gate, qubit);
613 mpsSimulator->ApplyGate(agate);
614 NotifyObservers({qubit});
619 if (IsExactSwapMatrix(gate))
621 const QC::Gates::AppliedGate<> agate(gate, qubit0, qubit1);
622 mpsSimulator->ApplyGate(agate);
624 NotifyObservers({qubit0, qubit1});
629 pgate.SetPhaseShift(lambda);
630 mpsSimulator->ApplyGate(pgate,
static_cast<unsigned int>(qubit));
631 NotifyObservers({qubit});
636 mpsSimulator->ApplyGate(xgate,
static_cast<unsigned int>(qubit));
637 NotifyObservers({qubit});
642 mpsSimulator->ApplyGate(ygate,
static_cast<unsigned int>(qubit));
643 NotifyObservers({qubit});
648 mpsSimulator->ApplyGate(zgate,
static_cast<unsigned int>(qubit));
649 NotifyObservers({qubit});
654 mpsSimulator->ApplyGate(h,
static_cast<unsigned int>(qubit));
655 NotifyObservers({qubit});
660 mpsSimulator->ApplyGate(sgate,
static_cast<unsigned int>(qubit));
661 NotifyObservers({qubit});
666 mpsSimulator->ApplyGate(sdggate,
static_cast<unsigned int>(qubit));
667 NotifyObservers({qubit});
672 mpsSimulator->ApplyGate(tgate,
static_cast<unsigned int>(qubit));
673 NotifyObservers({qubit});
678 mpsSimulator->ApplyGate(tdggate,
static_cast<unsigned int>(qubit));
679 NotifyObservers({qubit});
684 mpsSimulator->ApplyGate(sxgate,
static_cast<unsigned int>(qubit));
685 NotifyObservers({qubit});
690 mpsSimulator->ApplyGate(sxdaggate,
static_cast<unsigned int>(qubit));
691 NotifyObservers({qubit});
696 mpsSimulator->ApplyGate(k,
static_cast<unsigned int>(qubit));
697 NotifyObservers({qubit});
702 rxgate.SetTheta(theta);
703 mpsSimulator->ApplyGate(rxgate,
static_cast<unsigned int>(qubit));
704 NotifyObservers({qubit});
709 rygate.SetTheta(theta);
710 mpsSimulator->ApplyGate(rygate,
static_cast<unsigned int>(qubit));
711 NotifyObservers({qubit});
716 rzgate.SetTheta(theta);
717 mpsSimulator->ApplyGate(rzgate,
static_cast<unsigned int>(qubit));
718 NotifyObservers({qubit});
721 void ApplyU(
Types::qubit_t qubit,
double theta,
double phi,
double lambda,
double gamma)
override
723 ugate.SetParams(theta, phi, lambda, gamma);
724 mpsSimulator->ApplyGate(ugate,
static_cast<unsigned int>(qubit));
725 NotifyObservers({qubit});
730 mpsSimulator->ApplyGate(cxgate,
static_cast<unsigned int>(tgt_qubit),
static_cast<unsigned int>(ctrl_qubit));
731 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false, 2.);
732 NotifyObservers({tgt_qubit, ctrl_qubit});
737 mpsSimulator->ApplyGate(cygate,
static_cast<unsigned int>(tgt_qubit),
static_cast<unsigned int>(ctrl_qubit));
738 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false, 2.);
739 NotifyObservers({tgt_qubit, ctrl_qubit});
744 mpsSimulator->ApplyGate(czgate,
static_cast<unsigned int>(tgt_qubit),
static_cast<unsigned int>(ctrl_qubit));
745 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false, 2.);
746 NotifyObservers({tgt_qubit, ctrl_qubit});
751 cpgate.SetPhaseShift(lambda);
752 mpsSimulator->ApplyGate(cpgate,
static_cast<unsigned int>(tgt_qubit),
static_cast<unsigned int>(ctrl_qubit));
753 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false,
ControlledSchmidtRank(2. * std::abs(std::cos(lambda / 2.))));
754 NotifyObservers({tgt_qubit, ctrl_qubit});
759 crxgate.SetTheta(theta);
760 mpsSimulator->ApplyGate(crxgate,
static_cast<unsigned int>(tgt_qubit),
static_cast<unsigned int>(ctrl_qubit));
761 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false,
ControlledSchmidtRank(2. * std::abs(std::cos(theta / 2.))));
762 NotifyObservers({tgt_qubit, ctrl_qubit});
767 crygate.SetTheta(theta);
768 mpsSimulator->ApplyGate(crygate,
static_cast<unsigned int>(tgt_qubit),
static_cast<unsigned int>(ctrl_qubit));
769 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false,
ControlledSchmidtRank(2. * std::abs(std::cos(theta / 2.))));
770 NotifyObservers({tgt_qubit, ctrl_qubit});
775 crzgate.SetTheta(theta);
776 mpsSimulator->ApplyGate(crzgate,
static_cast<unsigned int>(tgt_qubit),
static_cast<unsigned int>(ctrl_qubit));
777 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false,
ControlledSchmidtRank(2. * std::abs(std::cos(theta / 2.))));
778 NotifyObservers({tgt_qubit, ctrl_qubit});
783 mpsSimulator->ApplyGate(ch,
static_cast<unsigned int>(tgt_qubit),
static_cast<unsigned int>(ctrl_qubit));
784 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false, 2.);
785 NotifyObservers({tgt_qubit, ctrl_qubit});
790 mpsSimulator->ApplyGate(csx,
static_cast<unsigned int>(tgt_qubit),
static_cast<unsigned int>(ctrl_qubit));
792 NotifyObservers({tgt_qubit, ctrl_qubit});
797 mpsSimulator->ApplyGate(csxdag,
static_cast<unsigned int>(tgt_qubit),
static_cast<unsigned int>(ctrl_qubit));
799 NotifyObservers({tgt_qubit, ctrl_qubit});
804 mpsSimulator->ApplyGate(swapgate,
static_cast<unsigned int>(qubit1),
static_cast<unsigned int>(qubit0));
805 RecordExecutedTwoQubitGate(qubit0, qubit1,
true, 4.);
806 NotifyObservers({qubit1, qubit0});
812 DecompositionScope scope(*
this);
813 const size_t q1 = qubit0;
814 const size_t q2 = qubit1;
815 const size_t q3 = qubit2;
816 mpsSimulator->ApplyGate(csx,
static_cast<unsigned int>(q3),
static_cast<unsigned int>(q2));
817 RecordExecutedTwoQubitGate(qubit1, qubit2,
false, 2.);
818 NotifyObservers({qubit1, qubit2});
819 mpsSimulator->ApplyGate(cxgate,
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q1));
820 RecordExecutedTwoQubitGate(qubit0, qubit1,
false, 2.);
821 NotifyObservers({qubit0, qubit1});
822 mpsSimulator->ApplyGate(csxdag,
static_cast<unsigned int>(q3),
static_cast<unsigned int>(q2));
823 RecordExecutedTwoQubitGate(qubit1, qubit2,
false, 2.);
824 NotifyObservers({qubit1, qubit2});
825 mpsSimulator->ApplyGate(cxgate,
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q1));
826 RecordExecutedTwoQubitGate(qubit0, qubit1,
false, 2.);
827 NotifyObservers({qubit0, qubit1});
828 mpsSimulator->ApplyGate(csx,
static_cast<unsigned int>(q3),
static_cast<unsigned int>(q1));
829 RecordExecutedTwoQubitGate(qubit0, qubit2,
false, 2.);
830 NotifyObservers({qubit0, qubit2});
832 NotifyObservers({qubit2, qubit1, qubit0});
838 DecompositionScope scope(*
this);
839 const size_t q1 = ctrl_qubit;
840 const size_t q2 = qubit0;
841 const size_t q3 = qubit1;
842 mpsSimulator->ApplyGate(cxgate,
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q3));
843 RecordExecutedTwoQubitGate(qubit1, qubit0,
false, 2.);
844 NotifyObservers({qubit1, qubit0});
845 mpsSimulator->ApplyGate(csx,
static_cast<unsigned int>(q3),
static_cast<unsigned int>(q2));
846 RecordExecutedTwoQubitGate(qubit0, qubit1,
false, 2.);
847 NotifyObservers({qubit0, qubit1});
848 mpsSimulator->ApplyGate(cxgate,
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q1));
849 RecordExecutedTwoQubitGate(ctrl_qubit, qubit0,
false, 2.);
850 NotifyObservers({ctrl_qubit, qubit0});
851 pgate.SetPhaseShift(M_PI);
852 mpsSimulator->ApplyGate(pgate,
static_cast<unsigned int>(q3));
853 NotifyObservers({qubit1});
854 pgate.SetPhaseShift(-M_PI_2);
855 mpsSimulator->ApplyGate(pgate,
static_cast<unsigned int>(q2));
856 NotifyObservers({qubit0});
857 mpsSimulator->ApplyGate(csx,
static_cast<unsigned int>(q3),
static_cast<unsigned int>(q2));
858 RecordExecutedTwoQubitGate(qubit0, qubit1,
false, 2.);
859 NotifyObservers({qubit0, qubit1});
860 mpsSimulator->ApplyGate(cxgate,
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q1));
861 RecordExecutedTwoQubitGate(ctrl_qubit, qubit0,
false, 2.);
862 NotifyObservers({ctrl_qubit, qubit0});
863 pgate.SetPhaseShift(M_PI);
864 mpsSimulator->ApplyGate(pgate,
static_cast<unsigned int>(q3));
865 NotifyObservers({qubit1});
866 mpsSimulator->ApplyGate(csx,
static_cast<unsigned int>(q3),
static_cast<unsigned int>(q1));
867 RecordExecutedTwoQubitGate(ctrl_qubit, qubit1,
false, 2.);
868 NotifyObservers({ctrl_qubit, qubit1});
869 mpsSimulator->ApplyGate(cxgate,
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q3));
870 RecordExecutedTwoQubitGate(qubit1, qubit0,
false, 2.);
871 NotifyObservers({qubit1, qubit0});
873 NotifyObservers({qubit1, qubit0, ctrl_qubit});
878 cugate.SetParams(theta, phi, lambda, gamma);
879 mpsSimulator->ApplyGate(cugate,
static_cast<unsigned int>(tgt_qubit),
static_cast<unsigned int>(ctrl_qubit));
880 RecordExecutedTwoQubitGate(ctrl_qubit, tgt_qubit,
false,
ControlledSchmidtRank(2. * std::abs(std::cos(theta / 2.) * std::cos((phi + lambda) / 2.))));
881 NotifyObservers({tgt_qubit, ctrl_qubit});
884 std::unique_ptr<ISimulator> Clone()
override
886 auto cloned = std::make_unique<QCSimMPSSimulator>();
887 cloned->nrQubits = nrQubits;
888 cloned->enableMultithreading = enableMultithreading;
889 cloned->lookaheadDepth = lookaheadDepth;
890 cloned->automaticRoutingDepth = automaticRoutingDepth;
891 cloned->lookaheadDepthWithHeuristic = lookaheadDepthWithHeuristic;
892 cloned->useOptimalMeetingPosition = useOptimalMeetingPosition;
893 cloned->upcomingGates = upcomingGates;
894 cloned->upcomingGateIndex = upcomingGateIndex;
895 cloned->boundedRoutingOperations = boundedRoutingOperations;
896 cloned->boundedRoutingOperationsQubits = boundedRoutingOperationsQubits;
897 cloned->growthFactorGate = growthFactorGate;
898 cloned->growthFactorSwap = growthFactorSwap;
901 cloned->mpsSimulator = mpsSimulator->Clone();
902 cloned->gateCounterObserver = std::make_shared<GateCounterObserver>(cloned->upcomingGateIndex);
903 cloned->RegisterObserver(cloned->gateCounterObserver);
904 cloned->curMaxBondDim = curMaxBondDim;
905 cloned->mpsSimulator->SetMeetingPositionCallback(cloned->meetingPositionCallback);
908 for (
const auto &[key, value] : configuration.GetConfigMap())
909 cloned->Configure(key.c_str(), value.c_str());
910 cloned->RefreshRoutingSettings();
911 cloned->dummySim = dummySim ? dummySim->Clone() :
nullptr;
912 cloned->dummyHistoryValid = dummyHistoryValid;
913 cloned->savedDummyBondDims = savedDummyBondDims;
914 if (configuration.IsSet(
"seed"))
915 cloned->SetSeed(DeriveSeed(std::stoull(configuration.GetConfiguration(
"seed")), nextSeedStream++));
916 cloned->RefreshRoutingCallback();
921 std::vector<double> CurrentBondDimensions()
const override
925 const auto dims = mpsSimulator->getBondDimensions();
926 return {dims.begin(), dims.end()};
929 std::vector<long long> CurrentRoutingMap()
const override
936 void RefreshRoutingCallback()
override
938 RefreshBoundedRouting();
939 const bool active = IsRoutingLookaheadEnabled() && !upcomingGates.empty();
941 mpsSimulator->SetMeetingPositionCallback(active ? meetingPositionCallback :
nullptr);
944 std::unique_ptr<QC::TensorNetworks::MPSSimulator> mpsSimulator;
int ApplyK(void *sim, int qubit)
double Probability(void *sim, unsigned long long int outcome)
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)
unsigned long int GetNumberOfQubits(void *sim)
double * AllProbabilities(void *sim)
unsigned long long int MeasureNoCollapse(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 SetMultithreading(void *sim, int multithreading)
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)
std::vector< std::complex< double > > TensorExpectationBatch(T &backend, const std::vector< std::string > &paulis)
void InstallBondSummary(T &backend, Callback callback)
std::vector< long long > ReadRoutingMap(const T *simulator)
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.