Maestro 0.3.1
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
QuestState.h
Go to the documentation of this file.
1
12
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
26#include "Configuration.h"
27
28namespace Simulators {
29namespace Private {
40class QuestState : public ISimulator {
41 public:
42 QuestState() : rng(std::random_device{}()), uniformZeroOne(0, 1) {}
43
51 void Initialize() override {
52 if (!questLib) questLib = SimulatorsFactory::GetQuestLibrary();
53 if (nrQubits && questLib && questLib->IsValid()) {
54 simHandle = questLib->CreateSimulator(static_cast<int>(nrQubits));
55 sim = questLib->GetSimulator(simHandle);
56 if (!sim)
57 throw std::runtime_error(
58 "QuestState::Initialize: Failed to create "
59 "and initialize the statevector state.");
60 }
61 }
62
74 void InitializeState(size_t num_qubits,
75 std::vector<std::complex<double>> &amplitudes) override {
76 throw std::runtime_error(
77 "QuestState::InitializeState: Not supported for Quest simulator.");
78 }
79
91#ifndef NO_QISKIT_AER
92 void InitializeState(size_t num_qubits,
93 AER::Vector<std::complex<double>> &amplitudes) override {
94 throw std::runtime_error(
95 "QuestState::InitializeState: Not supported for Quest simulator.");
96 }
97#endif
98
110 void InitializeState(size_t num_qubits,
111 Eigen::VectorXcd &amplitudes) override {
112 throw std::runtime_error(
113 "QuestState::InitializeState: Not supported for Quest simulator.");
114 }
115
122 void Reset() override {
123 if (sim && questLib) {
124 questLib->DestroySimulator(simHandle);
125 simHandle = questLib->CreateSimulator(static_cast<int>(nrQubits));
126 sim = questLib->GetSimulator(simHandle);
127 }
128 }
129
139 void Configure(const char *key, const char *value) override {
140 // Quest only supports statevector, nothing to configure
141 }
142
150 std::string GetConfiguration(const char *key) const override {
151 if (std::string("method") == key) return "statevector";
152 return "";
153 }
154
162 size_t AllocateQubits(size_t num_qubits) override {
163 if (sim) return 0;
164
165 const size_t oldNrQubits = nrQubits;
166 nrQubits += num_qubits;
167
168 return oldNrQubits;
169 }
170
177 size_t GetNumberOfQubits() const override { return nrQubits; }
178
186 void Clear() override {
187 if (sim && questLib) {
188 questLib->DestroySimulator(simHandle);
189 sim = nullptr;
190 simHandle = 0;
191 }
192 if (savedSim && questLib) {
193 questLib->DestroySimulator(savedSimHandle);
194 savedSim = nullptr;
195 savedSimHandle = 0;
196 }
197 nrQubits = 0;
198 }
199
210 size_t Measure(const Types::qubits_vector &qubits) override {
211 if (qubits.size() > sizeof(size_t) * 8)
212 std::cerr
213 << "Warning: The number of qubits to measure is larger than the "
214 "number of bits in the size_t type, the outcome will be undefined"
215 << std::endl;
216
217 DontNotify();
218
219 std::vector<int> qb(qubits.begin(), qubits.end());
220 const size_t res = static_cast<size_t>(questLib->MeasureQubits(
221 sim, qb.data(), static_cast<int>(qubits.size())));
222
223 Notify();
224 NotifyObservers(qubits);
225
226 return res;
227 }
228
235 std::vector<bool> MeasureMany(const Types::qubits_vector &qubits) override {
236 std::vector<bool> res(qubits.size(), false);
237
238 DontNotify();
239
240 std::vector<int> qb(qubits.begin(), qubits.end());
241 const size_t resm = static_cast<size_t>(questLib->MeasureQubits(
242 sim, qb.data(), static_cast<int>(qubits.size())));
243
244 size_t mask = 1ULL;
245 for (size_t i = 0; i < qubits.size(); ++i) {
246 res[i] = (resm & mask) != 0;
247 mask <<= 1;
248 }
249
250 Notify();
251 NotifyObservers(qubits);
252
253 return res;
254 }
255
262 void ApplyReset(const Types::qubits_vector &qubits) override {
263 DontNotify();
264 std::vector<int> qb(qubits.begin(), qubits.end());
265 const size_t res = static_cast<size_t>(questLib->MeasureQubits(
266 sim, qb.data(), static_cast<int>(qubits.size())));
267 size_t mask = 1ULL;
268 for (size_t i = 0; i < qubits.size(); ++i) {
269 if (res & mask) questLib->ApplyX(sim, static_cast<int>(qubits[i]));
270 mask <<= 1;
271 }
272
273 Notify();
274 NotifyObservers(qubits);
275 }
276
288 double Probability(Types::qubit_t outcome) override {
289 return questLib->GetOutcomeProbability(sim,
290 static_cast<long long int>(outcome));
291 }
292
303 std::complex<double> Amplitude(Types::qubit_t outcome) override {
304 std::complex<double> amplitude;
305 if (questLib->GetAmplitude(sim, static_cast<long long int>(outcome),
306 amplitude)) {
307 return amplitude;
308 }
309 return std::complex<double>(0.0, 0.0);
310 }
311
325 std::complex<double> ProjectOnZero() override {
326 return Amplitude(0);
327 }
328
339 std::vector<double> AllProbabilities() override {
340 if (nrQubits == 0) return {};
341 const size_t numStates = 1ULL << nrQubits;
342 std::vector<std::complex<double>> amplitudes(numStates);
343 questLib->GetAmplitudes(sim, amplitudes);
344
345 std::vector<double> result(numStates);
346 for (size_t i = 0; i < numStates; ++i) result[i] = std::norm(amplitudes[i]);
347 return result;
348 }
349
361 std::vector<double> Probabilities(
362 const Types::qubits_vector &qubits) override {
363 std::vector<double> result(qubits.size());
364 for (size_t i = 0; i < qubits.size(); ++i)
365 result[i] = questLib->GetOutcomeProbability(
366 sim, static_cast<long long int>(qubits[i]));
367 return result;
368 }
369
386 std::unordered_map<Types::qubit_t, Types::qubit_t> SampleCounts(
387 const Types::qubits_vector &qubits, size_t shots = 1000) override {
388 if (qubits.empty() || shots == 0) return {};
389
390 if (qubits.size() > sizeof(Types::qubit_t) * 8)
391 std::cerr
392 << "Warning: The number of qubits to measure is larger than the "
393 "number of bits in the Types::qubit_t type, the outcome will be "
394 "undefined"
395 << std::endl;
396
397 std::unordered_map<Types::qubit_t, Types::qubit_t> result;
398
399 if (shots > 1) {
400 const size_t numStates = 1ULL << nrQubits;
401 std::vector<std::complex<double>> amplitudes(numStates);
402 questLib->GetAmplitudes(sim, amplitudes);
403
404 const Utils::Alias alias(amplitudes);
405
406 for (size_t shot = 0; shot < shots; ++shot) {
407 const double prob = 1. - uniformZeroOne(rng);
408 const size_t measRaw = alias.Sample(prob);
409
410 size_t meas = 0;
411 size_t mask = 1ULL;
412 for (auto q : qubits) {
413 const size_t qubitMask = 1ULL << q;
414 if ((measRaw & qubitMask) != 0) meas |= mask;
415 mask <<= 1ULL;
416 }
417
418 ++result[meas];
419 }
420 } else {
421 for (size_t shot = 0; shot < shots; ++shot) {
422 const size_t measRaw = MeasureNoCollapse();
423 size_t meas = 0;
424 size_t mask = 1ULL;
425
426 for (auto q : qubits) {
427 const size_t qubitMask = 1ULL << q;
428 if ((measRaw & qubitMask) != 0) meas |= mask;
429 mask <<= 1ULL;
430 }
431
432 ++result[meas];
433 }
434 }
435
436 Notify();
437 NotifyObservers(qubits);
438
439 return result;
440 }
441
455 std::unordered_map<std::vector<bool>, Types::qubit_t> SampleCountsMany(
456 const Types::qubits_vector &qubits, size_t shots = 1000) override {
457 if (qubits.empty() || shots == 0) return {};
458
459 std::unordered_map<std::vector<bool>, Types::qubit_t> result;
460
461 if (shots > 1) {
462 const size_t numStates = 1ULL << nrQubits;
463 std::vector<std::complex<double>> amplitudes(numStates);
464 questLib->GetAmplitudes(sim, amplitudes);
465
466 const Utils::Alias alias(amplitudes);
467
468 for (size_t shot = 0; shot < shots; ++shot) {
469 const double prob = 1. - uniformZeroOne(rng);
470 const size_t measRaw = alias.Sample(prob);
471
472 std::vector<bool> meas(qubits.size(), false);
473
474 for (size_t i = 0; i < qubits.size(); ++i)
475 if (((measRaw >> qubits[i]) & 1) == 1) meas[i] = true;
476
477 ++result[meas];
478 }
479 } else {
480 for (size_t shot = 0; shot < shots; ++shot) {
481 const auto measRaw = MeasureNoCollapseMany();
482 std::vector<bool> meas(qubits.size(), false);
483
484 for (size_t i = 0; i < qubits.size(); ++i)
485 if (measRaw[qubits[i]]) meas[i] = true;
486
487 ++result[meas];
488 }
489 }
490
491 Notify();
492 NotifyObservers(qubits);
493
494 return result;
495 }
496
508 double ExpectationValue(const std::string &pauliString) override {
509 return questLib->GetExpectationValue(sim, pauliString.c_str());
510 }
511
519 SimulatorType GetType() const override { return SimulatorType::kQuestSim; }
520
529 SimulationType GetSimulationType() const override {
530 return SimulationType::kStatevector;
531 }
532
539 void Flush() override {}
540
549 void SaveStateToInternalDestructive() override {
550 if (savedSim && questLib) {
551 questLib->DestroySimulator(savedSimHandle);
552 savedSim = nullptr;
553 savedSimHandle = 0;
554 }
555 savedSimHandle = simHandle;
556 simHandle = 0;
557 savedSim = sim;
558 sim = nullptr;
559 }
560
568 if (sim && questLib) questLib->DestroySimulator(simHandle);
569 simHandle = savedSimHandle;
570 sim = savedSim;
571 savedSimHandle = 0;
572 savedSim = nullptr;
573 }
574
583 void SaveState() override {
584 if (savedSim && questLib) {
585 questLib->DestroySimulator(savedSimHandle);
586 savedSim = nullptr;
587 savedSimHandle = 0;
588 }
589 savedSimHandle = questLib->CloneSimulator(sim);
590 savedSim = questLib->GetSimulator(savedSimHandle);
591 }
592
600 void RestoreState() override {
601 if (sim && questLib) questLib->DestroySimulator(simHandle);
602 simHandle = questLib->CloneSimulator(savedSim);
603 sim = questLib->GetSimulator(simHandle);
604 }
605
611 std::complex<double> AmplitudeRaw(Types::qubit_t outcome) override {
612 return Amplitude(outcome);
613 }
614
623 void SetMultithreading(bool multithreading = true) override {
624 // Quest manages its own threading
625 }
626
634 bool GetMultithreading() const override { return true; }
635
643 bool IsQcsim() const override { return false; }
644
659 if (nrQubits > sizeof(Types::qubit_t) * 8)
660 std::cerr
661 << "Warning: The number of qubits to measure is larger than the "
662 "number of bits in the Types::qubit_t type, the outcome will be "
663 "undefined"
664 << std::endl;
665
666 const size_t numStates = 1ULL << nrQubits;
667 std::vector<std::complex<double>> amplitudes(numStates);
668 questLib->GetAmplitudes(sim, amplitudes);
669
670 std::vector<double> probs(numStates);
671 for (size_t i = 0; i < numStates; ++i) probs[i] = std::norm(amplitudes[i]);
672
673 std::discrete_distribution<Types::qubit_t> dist(probs.begin(), probs.end());
674
675 return dist(rng);
676 }
677
689 std::vector<bool> MeasureNoCollapseMany() override {
690 const auto meas = MeasureNoCollapse();
691 std::vector<bool> result(nrQubits, false);
692 for (size_t i = 0; i < nrQubits; ++i) result[i] = ((meas >> i) & 1) == 1;
693 return result;
694 }
695
696 const Configuration& GetConfiguration() const { return configuration; }
697
698 const std::unordered_map<std::string, std::string>& GetConfigMap()
699 const override {
700 return configuration.GetConfigMap();
701 }
702
703 protected:
704 std::shared_ptr<QuestLibSim> questLib;
705 unsigned long int simHandle = 0;
706 void *sim = nullptr;
707 size_t nrQubits = 0;
708 unsigned long int savedSimHandle = 0;
709 void *savedSim = nullptr;
710 std::mt19937_64 rng;
711 std::uniform_real_distribution<double> uniformZeroOne;
712
713 Configuration configuration;
714};
715} // namespace Private
716} // namespace Simulators
717
718#endif
719
720#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:199
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
Definition Types.h:22
uint_fast64_t qubit_t
The type of a qubit.
Definition Types.h:21