Maestro 0.1.0
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
20namespace Utils {
21
22class Alias {
23public:
24 Alias() = delete;
25
26 template <class T = Eigen::VectorXcd> Alias(const T &statevector) {
27 std::vector<double> probabilities(statevector.size());
28 double accum = 0.;
29 for (Eigen::Index i = 0; i < static_cast<Eigen::Index>(statevector.size());
30 ++i) {
31 probabilities[i] = std::norm(statevector[i]);
32 accum += probabilities[i];
33 if (accum > 1. - std::numeric_limits<double>::epsilon()) {
34 probabilities.resize(i + 1);
35 break;
36 }
37 }
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 while (!under.empty() && !over.empty()) {
58 const AliasEntry &u = under.back();
59 const AliasEntry &o = over.back();
60
61 const size_t index = o.alias;
62
63 aliasTable[u.alias] = AliasEntry(u.probability, index);
64
65 const double rem = o.probability + u.probability - 1.;
66
67 under.pop_back();
68 over.pop_back();
69
70 if (rem < 1.)
71 under.emplace_back(rem, index);
72 else
73 over.emplace_back(rem, index);
74 }
75
76 const AliasEntry one(1., -1);
77
78 for (; !under.empty(); under.pop_back())
79 aliasTable[under.back().alias] = one;
80
81 for (; !over.empty(); over.pop_back())
82 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
97private:
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:26
Alias()=delete
size_t Sample(double v) const
Definition Alias.h:85
Definition Alias.h:20