Maestro 0.1.0
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
Alias.h
Go to the documentation of this file.
1
10#pragma once
11
12#ifndef _ALIAS_H_
13#define _ALIAS_H_
14
15#include <complex>
16#include <vector>
17
18#include <Eigen/Eigen>
19
20namespace Utils {
21
22class Alias {
23 public:
24 Alias() = delete;
25
26 template <class T = Eigen::VectorXcd>
27 Alias(const T &statevector) {
28 std::vector<double> probabilities(statevector.size());
29 double accum = 0.;
30 for (Eigen::Index i = 0; i < static_cast<Eigen::Index>(statevector.size());
31 ++i) {
32 probabilities[i] = std::norm(statevector[i]);
33 accum += probabilities[i];
34 if (accum > 1. - std::numeric_limits<double>::epsilon()) {
35 probabilities.resize(i + 1);
36 break;
37 }
38 }
39
40 aliasTable.resize(probabilities.size());
41
42 std::vector<AliasEntry> under;
43 std::vector<AliasEntry> over;
44
45 // this uses four times the memory of the sampling with the binary search
46 under.reserve(probabilities.size());
47 over.reserve(probabilities.size());
48
49 for (Eigen::Index i = 0;
50 i < static_cast<Eigen::Index>(probabilities.size()); ++i) {
51 const double prob = probabilities[i] * probabilities.size();
52 if (prob < 1.)
53 under.emplace_back(prob, i);
54 else
55 over.emplace_back(prob, i);
56 }
57
58 while (!under.empty() && !over.empty()) {
59 const AliasEntry &u = under.back();
60 const AliasEntry &o = over.back();
61
62 const size_t index = o.alias;
63
64 aliasTable[u.alias] = AliasEntry(u.probability, index);
65
66 const double rem = o.probability + u.probability - 1.;
67
68 under.pop_back();
69 over.pop_back();
70
71 if (rem < 1.)
72 under.emplace_back(rem, index);
73 else
74 over.emplace_back(rem, index);
75 }
76
77 const AliasEntry one(1., -1);
78
79 for (; !under.empty(); under.pop_back())
80 aliasTable[under.back().alias] = one;
81
82 for (; !over.empty(); over.pop_back()) aliasTable[over.back().alias] = one;
83 }
84
85 size_t Sample(double v) const {
86 static const double oneMinusEps =
87 1. - std::numeric_limits<double>::epsilon();
88
89 const double vadj = v * aliasTable.size();
90 const size_t offset = std::min<size_t>(vadj, aliasTable.size() - 1);
91 const double up = std::min<double>(vadj - offset, oneMinusEps);
92
93 return up < aliasTable[offset].probability ? offset
94 : aliasTable[offset].alias;
95 }
96
97 private:
98 class AliasEntry {
99 public:
100 AliasEntry() : probability(1.), alias(-1) {}
101 AliasEntry(double prob, long long int ali)
102 : probability(prob), alias(ali) {}
103
104 double probability;
105 long long int alias;
106 };
107
108 std::vector<AliasEntry> aliasTable;
109};
110
111} // namespace Utils
112
113#endif // _ALIAS_H_
Alias(const T &statevector)
Definition Alias.h:27
Alias()=delete
size_t Sample(double v) const
Definition Alias.h:85
Definition Alias.h:20