Maestro 0.2.5
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
QuestState.h
Go to the documentation of this file.
1
13#pragma once
14
15#ifndef _QUESTSTATE_H_
16#define _QUESTSTATE_H_
17
18#ifdef INCLUDED_BY_FACTORY
19
20#include "QuestLibSim.h"
21
22#include <random>
23#include <unordered_map>
24#include <vector>
25
26namespace Simulators {
27namespace Private {
38class QuestState : public ISimulator {
39 public:
40 QuestState() : rng(std::random_device{}()), uniformZeroOne(0, 1) {}
41
49 void Initialize() override {
50 if (!questLib) questLib = SimulatorsFactory::GetQuestLibrary();
51 if (nrQubits && questLib && questLib->IsValid()) {
52 simHandle = questLib->CreateSimulator(static_cast<int>(nrQubits));
53 sim = questLib->GetSimulator(simHandle);
54 if (!sim)
55 throw std::runtime_error(
56 "QuestState::Initialize: Failed to create "
57 "and initialize the statevector state.");
58 }
59 }
60
72 void InitializeState(size_t num_qubits,
73 std::vector<std::complex<double>> &amplitudes) override {
74 throw std::runtime_error(
75 "QuestState::InitializeState: Not supported for Quest simulator.");
76 }
77
89#ifndef NO_QISKIT_AER
90 void InitializeState(size_t num_qubits,
91 AER::Vector<std::complex<double>> &amplitudes) override {
92 throw std::runtime_error(
93 "QuestState::InitializeState: Not supported for Quest simulator.");
94 }
95#endif
96
108 void InitializeState(size_t num_qubits,
109 Eigen::VectorXcd &amplitudes) override {
110 throw std::runtime_error(
111 "QuestState::InitializeState: Not supported for Quest simulator.");
112 }
113
120 void Reset() override {
121 if (sim && questLib) {
122 questLib->DestroySimulator(simHandle);
123 simHandle = questLib->CreateSimulator(static_cast<int>(nrQubits));
124 sim = questLib->GetSimulator(simHandle);
125 }
126 }
127
137 void Configure(const char *key, const char *value) override {
138 // Quest only supports statevector, nothing to configure
139 }
140
148 std::string GetConfiguration(const char *key) const override {
149 if (std::string("method") == key) return "statevector";
150 return "";
151 }
152
160 size_t AllocateQubits(size_t num_qubits) override {
161 if (sim) return 0;
162
163 const size_t oldNrQubits = nrQubits;
164 nrQubits += num_qubits;
165
166 return oldNrQubits;
167 }
168
175 size_t GetNumberOfQubits() const override { return nrQubits; }
176
184 void Clear() override {
185 if (sim && questLib) {
186 questLib->DestroySimulator(simHandle);
187 sim = nullptr;
188 simHandle = 0;
189 }
190 if (savedSim && questLib) {
191 questLib->DestroySimulator(savedSimHandle);
192 savedSim = nullptr;
193 savedSimHandle = 0;
194 }
195 nrQubits = 0;
196 }
197
208 size_t Measure(const Types::qubits_vector &qubits) override {
209 if (qubits.size() > sizeof(size_t) * 8)
210 std::cerr
211 << "Warning: The number of qubits to measure is larger than the "
212 "number of bits in the size_t type, the outcome will be undefined"
213 << std::endl;
214
215 DontNotify();
216
217 std::vector<int> qb(qubits.begin(), qubits.end());
218 const size_t res = static_cast<size_t>(questLib->MeasureQubits(
219 sim, qb.data(), static_cast<int>(qubits.size())));
220
221 Notify();
222 NotifyObservers(qubits);
223
224 return res;
225 }
226
233 std::vector<bool> MeasureMany(const Types::qubits_vector &qubits) override {
234 std::vector<bool> res(qubits.size(), false);
235
236 DontNotify();
237
238 std::vector<int> qb(qubits.begin(), qubits.end());
239 const size_t resm = static_cast<size_t>(questLib->MeasureQubits(
240 sim, qb.data(), static_cast<int>(qubits.size())));
241
242 size_t mask = 1ULL;
243 for (size_t i = 0; i < qubits.size(); ++i) {
244 res[i] = (resm & mask) != 0;
245 mask <<= 1;
246 }
247
248 Notify();
249 NotifyObservers(qubits);
250
251 return res;
252 }
253
260 void ApplyReset(const Types::qubits_vector &qubits) override {
261 DontNotify();
262 std::vector<int> qb(qubits.begin(), qubits.end());
263 const size_t res = static_cast<size_t>(questLib->MeasureQubits(
264 sim, qb.data(), static_cast<int>(qubits.size())));
265 size_t mask = 1ULL;
266 for (size_t i = 0; i < qubits.size(); ++i) {
267 if (res & mask) questLib->ApplyX(sim, static_cast<int>(qubits[i]));
268 mask <<= 1;
269 }
270
271 Notify();
272 NotifyObservers(qubits);
273 }
274
286 double Probability(Types::qubit_t outcome) override {
287 return questLib->GetOutcomeProbability(sim,
288 static_cast<long long int>(outcome));
289 }
290
301 std::complex<double> Amplitude(Types::qubit_t outcome) override {
302 std::complex<double> amplitude;
303 if (questLib->GetAmplitude(sim, static_cast<long long int>(outcome),
304 amplitude)) {
305 return amplitude;
306 }
307 return std::complex<double>(0.0, 0.0);
308 }
309
323 std::complex<double> ProjectOnZero() override {
324 return Amplitude(0);
325 }
326
337 std::vector<double> AllProbabilities() override {
338 if (nrQubits == 0) return {};
339 const size_t numStates = 1ULL << nrQubits;
340 std::vector<std::complex<double>> amplitudes(numStates);
341 questLib->GetAmplitudes(sim, amplitudes);
342
343 std::vector<double> result(numStates);
344 for (size_t i = 0; i < numStates; ++i) result[i] = std::norm(amplitudes[i]);
345 return result;
346 }
347
359 std::vector<double> Probabilities(
360 const Types::qubits_vector &qubits) override {
361 std::vector<double> result(qubits.size());
362 for (size_t i = 0; i < qubits.size(); ++i)
363 result[i] = questLib->GetOutcomeProbability(
364 sim, static_cast<long long int>(qubits[i]));
365 return result;
366 }
367
384 std::unordered_map<Types::qubit_t, Types::qubit_t> SampleCounts(
385 const Types::qubits_vector &qubits, size_t shots = 1000) override {
386 if (qubits.empty() || shots == 0) return {};
387
388 if (qubits.size() > sizeof(Types::qubit_t) * 8)
389 std::cerr
390 << "Warning: The number of qubits to measure is larger than the "
391 "number of bits in the Types::qubit_t type, the outcome will be "
392 "undefined"
393 << std::endl;
394
395 std::unordered_map<Types::qubit_t, Types::qubit_t> result;
396
397 if (shots > 1) {
398 const size_t numStates = 1ULL << nrQubits;
399 std::vector<std::complex<double>> amplitudes(numStates);
400 questLib->GetAmplitudes(sim, amplitudes);
401
402 const Utils::Alias alias(amplitudes);
403
404 for (size_t shot = 0; shot < shots; ++shot) {
405 const double prob = 1. - uniformZeroOne(rng);
406 const size_t measRaw = alias.Sample(prob);
407
408 size_t meas = 0;
409 size_t mask = 1ULL;
410 for (auto q : qubits) {
411 const size_t qubitMask = 1ULL << q;
412 if ((measRaw & qubitMask) != 0) meas |= mask;
413 mask <<= 1ULL;
414 }
415
416 ++result[meas];
417 }
418 } else {
419 for (size_t shot = 0; shot < shots; ++shot) {
420 const size_t measRaw = MeasureNoCollapse();
421 size_t meas = 0;
422 size_t mask = 1ULL;
423
424 for (auto q : qubits) {
425 const size_t qubitMask = 1ULL << q;
426 if ((measRaw & qubitMask) != 0) meas |= mask;
427 mask <<= 1ULL;
428 }
429
430 ++result[meas];
431 }
432 }
433
434 Notify();
435 NotifyObservers(qubits);
436
437 return result;
438 }
439
453 std::unordered_map<std::vector<bool>, Types::qubit_t> SampleCountsMany(
454 const Types::qubits_vector &qubits, size_t shots = 1000) override {
455 if (qubits.empty() || shots == 0) return {};
456
457 std::unordered_map<std::vector<bool>, Types::qubit_t> result;
458
459 if (shots > 1) {
460 const size_t numStates = 1ULL << nrQubits;
461 std::vector<std::complex<double>> amplitudes(numStates);
462 questLib->GetAmplitudes(sim, amplitudes);
463
464 const Utils::Alias alias(amplitudes);
465
466 for (size_t shot = 0; shot < shots; ++shot) {
467 const double prob = 1. - uniformZeroOne(rng);
468 const size_t measRaw = alias.Sample(prob);
469
470 std::vector<bool> meas(qubits.size(), false);
471
472 for (size_t i = 0; i < qubits.size(); ++i)
473 if (((measRaw >> qubits[i]) & 1) == 1) meas[i] = true;
474
475 ++result[meas];
476 }
477 } else {
478 for (size_t shot = 0; shot < shots; ++shot) {
479 const auto measRaw = MeasureNoCollapseMany();
480 std::vector<bool> meas(qubits.size(), false);
481
482 for (size_t i = 0; i < qubits.size(); ++i)
483 if (measRaw[qubits[i]]) meas[i] = true;
484
485 ++result[meas];
486 }
487 }
488
489 Notify();
490 NotifyObservers(qubits);
491
492 return result;
493 }
494
506 double ExpectationValue(const std::string &pauliString) override {
507 return questLib->GetExpectationValue(sim, pauliString.c_str());
508 }
509
517 SimulatorType GetType() const override { return SimulatorType::kQuestSim; }
518
527 SimulationType GetSimulationType() const override {
528 return SimulationType::kStatevector;
529 }
530
537 void Flush() override {}
538
547 void SaveStateToInternalDestructive() override {
548 if (savedSim && questLib) {
549 questLib->DestroySimulator(savedSimHandle);
550 savedSim = nullptr;
551 savedSimHandle = 0;
552 }
553 savedSimHandle = simHandle;
554 simHandle = 0;
555 savedSim = sim;
556 sim = nullptr;
557 }
558
566 if (sim && questLib) questLib->DestroySimulator(simHandle);
567 simHandle = savedSimHandle;
568 sim = savedSim;
569 savedSimHandle = 0;
570 savedSim = nullptr;
571 }
572
581 void SaveState() override {
582 if (savedSim && questLib) {
583 questLib->DestroySimulator(savedSimHandle);
584 savedSim = nullptr;
585 savedSimHandle = 0;
586 }
587 savedSimHandle = questLib->CloneSimulator(sim);
588 savedSim = questLib->GetSimulator(savedSimHandle);
589 }
590
598 void RestoreState() override {
599 if (sim && questLib) questLib->DestroySimulator(simHandle);
600 simHandle = questLib->CloneSimulator(savedSim);
601 sim = questLib->GetSimulator(simHandle);
602 }
603
609 std::complex<double> AmplitudeRaw(Types::qubit_t outcome) override {
610 return Amplitude(outcome);
611 }
612
621 void SetMultithreading(bool multithreading = true) override {
622 // Quest manages its own threading
623 }
624
632 bool GetMultithreading() const override { return true; }
633
641 bool IsQcsim() const override { return false; }
642
657 if (nrQubits > sizeof(Types::qubit_t) * 8)
658 std::cerr
659 << "Warning: The number of qubits to measure is larger than the "
660 "number of bits in the Types::qubit_t type, the outcome will be "
661 "undefined"
662 << std::endl;
663
664 const size_t numStates = 1ULL << nrQubits;
665 std::vector<std::complex<double>> amplitudes(numStates);
666 questLib->GetAmplitudes(sim, amplitudes);
667
668 std::vector<double> probs(numStates);
669 for (size_t i = 0; i < numStates; ++i) probs[i] = std::norm(amplitudes[i]);
670
671 std::discrete_distribution<Types::qubit_t> dist(probs.begin(), probs.end());
672
673 return dist(rng);
674 }
675
687 std::vector<bool> MeasureNoCollapseMany() override {
688 const auto meas = MeasureNoCollapse();
689 std::vector<bool> result(nrQubits, false);
690 for (size_t i = 0; i < nrQubits; ++i) result[i] = ((meas >> i) & 1) == 1;
691 return result;
692 }
693
694 protected:
695 std::shared_ptr<QuestLibSim> questLib;
696 unsigned long int simHandle = 0;
697 void *sim = nullptr;
698 size_t nrQubits = 0;
699 unsigned long int savedSimHandle = 0;
700 void *savedSim = nullptr;
701 std::mt19937_64 rng;
702 std::uniform_real_distribution<double> uniformZeroOne;
703};
704} // namespace Private
705} // namespace Simulators
706
707#endif
708
709#endif // _QUESTSTATE_H_
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)
int IsQcsim(void *sim)
int SaveState(void *sim)
size_t Sample(double v) const
Definition Alias.h:85
uint_fast64_t qubit_t
The type of a qubit.
Definition Types.h:21
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
Definition Types.h:23