2#if defined(INCLUDED_BY_FACTORY)
6#define _USE_MATH_DEFINES
12class QCSimTensorNetworkSimulator :
public QCSimGateSimulator
15 QCSimTensorNetworkSimulator()
17 configuration.SetConfiguration(
"method",
"tensor_network");
20 const char *MethodName()
const override
22 return "tensor_network";
25 void Initialize()
override
30 tensorNetwork = std::make_unique<TensorNetworks::TensorNetwork>(nrQubits);
31 const auto tensorContractor = std::make_shared<TensorNetworks::ForestContractor>();
32 tensorNetwork->SetContractor(tensorContractor);
35 for (
const auto &[key, value] : configuration.GetConfigMap())
37 Configure(key.c_str(), value.c_str());
44 tensorNetwork->Clear();
45 upcomingGateIndex = 0;
48 void Configure(
const char *key,
const char *value)
override
50 if (std::string(
"method") == key)
52 ValidateMethod(value);
53 configuration.SetConfiguration(key, value);
56 if (!configuration.WasApplied(key, value))
57 configuration.SetConfiguration(key, value);
58 if (std::string(
"seed") == key)
60 const uint64_t seed = std::stoull(value);
61 SeedAuxiliaryRng(seed);
65 tensorNetwork->SetSeed(seed);
68 if (std::string(key) ==
"pauli_propagator_workers")
70 const auto workers = configuration.GetConfigurationAsUnsigned(key);
72 throw std::invalid_argument(
"pauli_propagator_workers exceeds 1024");
80 const size_t oldNrQubits = nrQubits;
81 nrQubits += num_qubits;
87 tensorNetwork =
nullptr;
89 upcomingGateIndex = 0;
90 upcomingGates.clear();
95 if (qubits.size() >
sizeof(
size_t) * 8)
96 std::cerr <<
"Warning: The number of qubits to measure is larger than the "
97 "number of bits in the size_t type, the outcome will be undefined"
103 for (
size_t qubit : qubits)
105 if (tensorNetwork->Measure(
static_cast<unsigned int>(qubit)))
111 NotifyObservers(qubits);
117 std::vector<bool> res(qubits.size(),
false);
120 for (
size_t q = 0; q < qubits.size(); ++q)
121 if (tensorNetwork->Measure(
static_cast<unsigned int>(qubits[q])))
125 NotifyObservers(qubits);
133 for (
size_t qubit : qubits)
134 if (tensorNetwork->Measure(
static_cast<unsigned int>(qubit)))
135 tensorNetwork->AddGate(xgate,
static_cast<unsigned int>(qubit));
138 NotifyObservers(qubits);
143 return tensorNetwork->getBasisStateProbability(outcome);
148 throw std::runtime_error(
"QCSimState::Amplitude: Not supported for the "
149 "tensor network simulator.");
154 throw std::runtime_error(
"QCSimState::AllProbabilities: Invalid "
155 "simulation type for obtaining probabilities.");
160 throw std::runtime_error(
"QCSimState::Probabilities: Not implemented yet "
161 "for the tensor network simulator.");
166 if (qubits.empty() || shots == 0)
168 if (qubits.size() >
sizeof(
size_t) * 8)
169 std::cerr <<
"Warning: The number of qubits to measure is larger than the "
170 "number of bits in the size_t type, the outcome will be undefined"
172 std::unordered_map<Types::qubit_t, Types::qubit_t> result;
175 tensorNetwork->SaveState();
176 for (
size_t shot = 0; shot < shots; ++shot)
178 const size_t meas =
Measure(qubits);
180 tensorNetwork->RestoreState();
182 tensorNetwork->ClearSavedState();
185 NotifyObservers(qubits);
191 if (qubits.empty() || shots == 0)
196 tensorNetwork->SaveState();
197 for (
size_t shot = 0; shot < shots; ++shot)
199 const auto meas = MeasureMany(qubits);
201 tensorNetwork->RestoreState();
203 tensorNetwork->ClearSavedState();
206 NotifyObservers(qubits);
210 double ExpectationValue(
const std::string &pauliStringOrig)
override
212 if (pauliStringOrig.empty())
214 std::string pauliString = pauliStringOrig;
219 const auto pauliOp = toupper(pauliString[i]);
220 if (pauliOp !=
'I' && pauliOp !=
'Z')
225 return tensorNetwork->ExpectationValue(pauliString);
230 return SimulationType::kTensorNetwork;
235 tensorNetwork->SaveState();
240 tensorNetwork->RestoreState();
245 enableMultithreading = multithreading;
247 tensorNetwork->SetMultithreading(multithreading);
252 const QC::Gates::AppliedGate<> agate(gate, qubit);
253 tensorNetwork->AddGate(agate, qubit);
254 NotifyObservers({qubit});
259 const QC::Gates::AppliedGate<> agate(gate, qubit0, qubit1);
260 tensorNetwork->AddGate(agate, qubit1, qubit0);
261 NotifyObservers({qubit0, qubit1});
266 pgate.SetPhaseShift(lambda);
267 tensorNetwork->AddGate(pgate,
static_cast<unsigned int>(qubit));
268 NotifyObservers({qubit});
273 tensorNetwork->AddGate(xgate,
static_cast<unsigned int>(qubit));
274 NotifyObservers({qubit});
279 tensorNetwork->AddGate(ygate,
static_cast<unsigned int>(qubit));
280 NotifyObservers({qubit});
285 tensorNetwork->AddGate(zgate,
static_cast<unsigned int>(qubit));
286 NotifyObservers({qubit});
291 tensorNetwork->AddGate(h,
static_cast<unsigned int>(qubit));
292 NotifyObservers({qubit});
297 tensorNetwork->AddGate(sgate,
static_cast<unsigned int>(qubit));
298 NotifyObservers({qubit});
303 tensorNetwork->AddGate(sdggate,
static_cast<unsigned int>(qubit));
304 NotifyObservers({qubit});
309 tensorNetwork->AddGate(tgate,
static_cast<unsigned int>(qubit));
310 NotifyObservers({qubit});
315 tensorNetwork->AddGate(tdggate,
static_cast<unsigned int>(qubit));
316 NotifyObservers({qubit});
321 tensorNetwork->AddGate(sxgate,
static_cast<unsigned int>(qubit));
322 NotifyObservers({qubit});
327 tensorNetwork->AddGate(sxdaggate,
static_cast<unsigned int>(qubit));
328 NotifyObservers({qubit});
333 tensorNetwork->AddGate(k,
static_cast<unsigned int>(qubit));
334 NotifyObservers({qubit});
339 rxgate.SetTheta(theta);
340 tensorNetwork->AddGate(rxgate,
static_cast<unsigned int>(qubit));
341 NotifyObservers({qubit});
346 rygate.SetTheta(theta);
347 tensorNetwork->AddGate(rygate,
static_cast<unsigned int>(qubit));
348 NotifyObservers({qubit});
353 rzgate.SetTheta(theta);
354 tensorNetwork->AddGate(rzgate,
static_cast<unsigned int>(qubit));
355 NotifyObservers({qubit});
358 void ApplyU(
Types::qubit_t qubit,
double theta,
double phi,
double lambda,
double gamma)
override
360 ugate.SetParams(theta, phi, lambda, gamma);
361 tensorNetwork->AddGate(ugate,
static_cast<unsigned int>(qubit));
362 NotifyObservers({qubit});
367 tensorNetwork->AddGate(cxgate,
static_cast<unsigned int>(ctrl_qubit),
static_cast<unsigned int>(tgt_qubit));
368 NotifyObservers({tgt_qubit, ctrl_qubit});
373 tensorNetwork->AddGate(cygate,
static_cast<unsigned int>(ctrl_qubit),
static_cast<unsigned int>(tgt_qubit));
374 NotifyObservers({tgt_qubit, ctrl_qubit});
379 tensorNetwork->AddGate(czgate,
static_cast<unsigned int>(ctrl_qubit),
static_cast<unsigned int>(tgt_qubit));
380 NotifyObservers({tgt_qubit, ctrl_qubit});
385 cpgate.SetPhaseShift(lambda);
386 tensorNetwork->AddGate(cpgate,
static_cast<unsigned int>(ctrl_qubit),
static_cast<unsigned int>(tgt_qubit));
387 NotifyObservers({tgt_qubit, ctrl_qubit});
392 crxgate.SetTheta(theta);
393 tensorNetwork->AddGate(crxgate,
static_cast<unsigned int>(ctrl_qubit),
static_cast<unsigned int>(tgt_qubit));
394 NotifyObservers({tgt_qubit, ctrl_qubit});
399 crygate.SetTheta(theta);
400 tensorNetwork->AddGate(crygate,
static_cast<unsigned int>(ctrl_qubit),
static_cast<unsigned int>(tgt_qubit));
401 NotifyObservers({tgt_qubit, ctrl_qubit});
406 crzgate.SetTheta(theta);
407 tensorNetwork->AddGate(crzgate,
static_cast<unsigned int>(ctrl_qubit),
static_cast<unsigned int>(tgt_qubit));
408 NotifyObservers({tgt_qubit, ctrl_qubit});
413 tensorNetwork->AddGate(ch,
static_cast<unsigned int>(ctrl_qubit),
static_cast<unsigned int>(tgt_qubit));
414 NotifyObservers({tgt_qubit, ctrl_qubit});
419 tensorNetwork->AddGate(csx,
static_cast<unsigned int>(ctrl_qubit),
static_cast<unsigned int>(tgt_qubit));
420 NotifyObservers({tgt_qubit, ctrl_qubit});
425 tensorNetwork->AddGate(csxdag,
static_cast<unsigned int>(ctrl_qubit),
static_cast<unsigned int>(tgt_qubit));
426 NotifyObservers({tgt_qubit, ctrl_qubit});
431 tensorNetwork->AddGate(swapgate,
static_cast<unsigned int>(qubit0),
static_cast<unsigned int>(qubit1));
432 NotifyObservers({qubit1, qubit0});
437 const size_t q1 = qubit0;
438 const size_t q2 = qubit1;
439 const size_t q3 = qubit2;
440 tensorNetwork->AddGate(csx,
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q3));
441 NotifyObservers({qubit1, qubit2});
442 tensorNetwork->AddGate(cxgate,
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q2));
443 NotifyObservers({qubit0, qubit1});
444 tensorNetwork->AddGate(csxdag,
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q3));
445 NotifyObservers({qubit1, qubit2});
446 tensorNetwork->AddGate(cxgate,
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q2));
447 NotifyObservers({qubit0, qubit1});
448 tensorNetwork->AddGate(csx,
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q3));
449 NotifyObservers({qubit0, qubit2});
454 const size_t q1 = ctrl_qubit;
455 const size_t q2 = qubit0;
456 const size_t q3 = qubit1;
457 tensorNetwork->AddGate(cxgate,
static_cast<unsigned int>(q3),
static_cast<unsigned int>(q2));
458 NotifyObservers({qubit1, qubit0});
459 tensorNetwork->AddGate(csx,
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q3));
460 NotifyObservers({qubit0, qubit1});
461 tensorNetwork->AddGate(cxgate,
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q2));
462 NotifyObservers({ctrl_qubit, qubit0});
463 pgate.SetPhaseShift(M_PI);
464 tensorNetwork->AddGate(pgate,
static_cast<unsigned int>(q3));
465 NotifyObservers({qubit1});
466 pgate.SetPhaseShift(-M_PI_2);
467 tensorNetwork->AddGate(pgate,
static_cast<unsigned int>(q2));
468 NotifyObservers({qubit0});
469 tensorNetwork->AddGate(csx,
static_cast<unsigned int>(q2),
static_cast<unsigned int>(q3));
470 NotifyObservers({qubit0, qubit1});
471 tensorNetwork->AddGate(cxgate,
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q2));
472 NotifyObservers({ctrl_qubit, qubit0});
473 pgate.SetPhaseShift(M_PI);
474 tensorNetwork->AddGate(pgate,
static_cast<unsigned int>(q3));
475 NotifyObservers({qubit1});
476 tensorNetwork->AddGate(csx,
static_cast<unsigned int>(q1),
static_cast<unsigned int>(q3));
477 NotifyObservers({ctrl_qubit, qubit1});
478 tensorNetwork->AddGate(cxgate,
static_cast<unsigned int>(q3),
static_cast<unsigned int>(q2));
479 NotifyObservers({qubit1, qubit0});
484 cugate.SetParams(theta, phi, lambda, gamma);
485 tensorNetwork->AddGate(cugate,
static_cast<unsigned int>(ctrl_qubit),
static_cast<unsigned int>(tgt_qubit));
486 NotifyObservers({tgt_qubit, ctrl_qubit});
489 std::unique_ptr<ISimulator> Clone()
override
491 auto cloned = std::make_unique<QCSimTensorNetworkSimulator>();
492 cloned->nrQubits = nrQubits;
493 cloned->enableMultithreading = enableMultithreading;
494 cloned->upcomingGates = upcomingGates;
495 cloned->upcomingGateIndex = upcomingGateIndex;
497 cloned->tensorNetwork = tensorNetwork->Clone();
498 for (
const auto &[key, value] : configuration.GetConfigMap())
499 cloned->Configure(key.c_str(), value.c_str());
500 if (configuration.IsSet(
"seed"))
501 cloned->SetSeed(DeriveSeed(std::stoull(configuration.GetConfiguration(
"seed")), nextSeedStream++));
506 std::unique_ptr<TensorNetworks::TensorNetwork> tensorNetwork;
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)
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)
SimulationType
The type of simulation.
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
uint_fast64_t qubit_t
The type of a qubit.