Maestro 0.2.11
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
Alias.h
Go to the documentation of this file.
1
9
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
20#include "PathIntegral.h"
21
22namespace Utils {
23
24
26 public:
28 AliasEntry(double prob, long long int ali) : probability(prob), alias(ali) {}
29
31 long long int alias;
32};
33
34class AliasBase {
35 protected:
36 /*
37 void SetAliasTable(std::vector<double>& probabilities)
38 {
39 aliasTable.resize(probabilities.size());
40
41 std::vector<AliasEntry> under;
42 std::vector<AliasEntry> over;
43
44 // this uses four times the memory of the sampling with the binary search
45 under.reserve(probabilities.size());
46 over.reserve(probabilities.size());
47
48 for (Eigen::Index i = 0;
49 i < static_cast<Eigen::Index>(probabilities.size()); ++i) {
50 const double prob = probabilities[i] * probabilities.size();
51 if (prob < 1.)
52 under.emplace_back(prob, i);
53 else
54 over.emplace_back(prob, i);
55 }
56
57 SetAliasTable(under, over);
58 }
59 */
60
61 void SetAliasTable(std::vector<AliasEntry> &under,
62 std::vector<AliasEntry> &over) {
63 while (!under.empty() && !over.empty()) {
64 const AliasEntry &u = under.back();
65 const AliasEntry &o = over.back();
66
67 const size_t index = o.alias;
68
70
71 const double rem = o.probability + u.probability - 1.;
72
73 under.pop_back();
74 over.pop_back();
75
76 if (rem < 1.)
77 under.emplace_back(rem, index);
78 else
79 over.emplace_back(rem, index);
80 }
81
82 const AliasEntry one(1., -1);
83
84 for (; !under.empty(); under.pop_back())
85 aliasTable[under.back().alias] = one;
86
87 for (; !over.empty(); over.pop_back()) aliasTable[over.back().alias] = one;
88 }
89
90 std::vector<AliasEntry> aliasTable;
91 std::vector<long long int> statesTable;
92 static constexpr double oneMinusEps =
93 1. - std::numeric_limits<double>::epsilon();
94};
95
96
97class Alias : public AliasBase {
98 public:
99 Alias() = delete;
100
101 template <class T = Eigen::VectorXcd>
102 Alias(const T &statevector) {
103 /*
104 std::vector<double> probabilities(statevector.size());
105
106 double accum = 0.;
107 for (Eigen::Index i = 0; i < static_cast<Eigen::Index>(statevector.size());
108 ++i) {
109 probabilities[i] = std::norm(statevector[i]);
110 accum += probabilities[i];
111 if (accum > oneMinusEps) {
112 probabilities.resize(i + 1);
113 break;
114 }
115 }
116
117 SetAliasTable(probabilities);
118 */
119
120 long long int numNonZeroStates = 0;
121 double accum = 0.;
122 for (Eigen::Index state = 0;
123 state < static_cast<Eigen::Index>(statevector.size()); ++state) {
124 const double stateProb = std::norm(statevector[state]);
125 if (stateProb < std::numeric_limits<double>::epsilon()) continue;
126
127 ++numNonZeroStates;
128
129 accum += stateProb;
130 if (accum > oneMinusEps) break;
131 }
132
133 std::vector<AliasEntry> under;
134 std::vector<AliasEntry> over;
135 under.reserve(numNonZeroStates);
136 over.reserve(numNonZeroStates);
137
138 statesTable.reserve(numNonZeroStates);
139
140 long long int i = 0;
141 accum = 0.;
142 for (Eigen::Index state = 0; state < static_cast<Eigen::Index>(statevector.size());
143 ++state) {
144 const double stateProb = std::norm(statevector[state]);
145 if (stateProb < std::numeric_limits<double>::epsilon()) continue;
146
147 const double prob = stateProb * numNonZeroStates;
148 if (prob < 1.)
149 under.emplace_back(prob, i);
150 else
151 over.emplace_back(prob, i);
152
153 statesTable.push_back(state);
154
155 accum += stateProb;
156 if (accum > oneMinusEps) break;
157
158 ++i;
159 }
160
161 aliasTable.resize(under.size() + over.size());
162
163 SetAliasTable(under, over);
164 }
165
166 Alias(const std::unordered_map<QC::PathIntegral::FastVectorBool, std::complex<double>,
167 QC::PathIntegral::FastVectorBoolHash> &amplitudesMap) {
168 std::vector<AliasEntry> under;
169 std::vector<AliasEntry> over;
170
171 // this uses four times the memory of the sampling with the binary search
172 under.reserve(amplitudesMap.size());
173 over.reserve(amplitudesMap.size());
174
175 statesTable.reserve(amplitudesMap.size());
176
177 //size_t maxState = 0;
178 long long int i = 0;
179 for (const auto &valPair : amplitudesMap) {
180 const double prob = std::norm(valPair.second) * amplitudesMap.size();
181 const size_t state = valPair.first.getWords()[0];
182 if (prob < 1.)
183 under.emplace_back(prob, i);
184 else
185 over.emplace_back(prob, i);
186
187 //if (state > maxState) maxState = state;
188 statesTable.push_back(state);
189 ++i;
190 }
191
192 //aliasTable.resize(maxState + 1);
193 //std::fill(aliasTable.begin(), aliasTable.end(), AliasEntry(1., -1));
194 aliasTable.resize(under.size() + over.size());
195
196 SetAliasTable(under, over);
197 }
198
199 inline size_t Sample(double v) const {
200 const double vadj = v * aliasTable.size();
201 const size_t offset = std::min<size_t>(static_cast<size_t>(vadj), aliasTable.size() - 1);
202 const double up = std::min<double>(vadj - offset, oneMinusEps);
203
204 return statesTable[up < aliasTable[offset].probability ? offset
205 : aliasTable[offset].alias];
206 }
207
208 private:
209 std::vector<long long int> statesTable;
210};
211
212
213
214class AliasBig : public AliasBase {
215 public:
216 AliasBig() = delete;
217
218 AliasBig(const std::unordered_map<
219 QC::PathIntegral::FastVectorBool, std::complex<double>,
220 QC::PathIntegral::FastVectorBoolHash> &amplitudesMap) {
221 std::vector<AliasEntry> under;
222 std::vector<AliasEntry> over;
223
224 // this uses four times the memory of the sampling with the binary search
225 under.reserve(amplitudesMap.size());
226 over.reserve(amplitudesMap.size());
227
228 statesTable.reserve(amplitudesMap.size());
229
230 // size_t maxState = 0;
231 long long int i = 0;
232 for (const auto &valPair : amplitudesMap) {
233 const double prob = std::norm(valPair.second) * amplitudesMap.size();
234 if (prob < 1.)
235 under.emplace_back(prob, i);
236 else
237 over.emplace_back(prob, i);
238
239 statesTable.emplace_back(std::move(valPair.first.toVector()));
240 ++i;
241 }
242
243 aliasTable.resize(under.size() + over.size());
244
245 SetAliasTable(under, over);
246 }
247
248 inline QC::PathIntegral::FastVectorBool Sample(double v) const {
249 const double vadj = v * aliasTable.size();
250 const size_t offset =
251 std::min<size_t>(static_cast<size_t>(vadj), aliasTable.size() - 1);
252 const double up = std::min<double>(vadj - offset, oneMinusEps);
253
254 return statesTable[up < aliasTable[offset].probability
255 ? offset
256 : aliasTable[offset].alias];
257 }
258
259 private:
260 std::vector<QC::PathIntegral::FastVectorBool> statesTable;
261};
262
263} // namespace Utils
264
265#endif // _ALIAS_H_
std::vector< long long int > statesTable
Definition Alias.h:91
std::vector< AliasEntry > aliasTable
Definition Alias.h:90
void SetAliasTable(std::vector< AliasEntry > &under, std::vector< AliasEntry > &over)
Definition Alias.h:61
static constexpr double oneMinusEps
Definition Alias.h:92
AliasBig()=delete
QC::PathIntegral::FastVectorBool Sample(double v) const
Definition Alias.h:248
AliasBig(const std::unordered_map< QC::PathIntegral::FastVectorBool, std::complex< double >, QC::PathIntegral::FastVectorBoolHash > &amplitudesMap)
Definition Alias.h:218
double probability
Definition Alias.h:30
long long int alias
Definition Alias.h:31
AliasEntry(double prob, long long int ali)
Definition Alias.h:28
Alias(const T &statevector)
Definition Alias.h:102
Alias()=delete
size_t Sample(double v) const
Definition Alias.h:199
Alias(const std::unordered_map< QC::PathIntegral::FastVectorBool, std::complex< double >, QC::PathIntegral::FastVectorBoolHash > &amplitudesMap)
Definition Alias.h:166
Definition Alias.h:22