forked from cda-tum/mqt-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBernsteinVazirani.cpp
127 lines (108 loc) · 3.19 KB
/
BernsteinVazirani.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "algorithms/BernsteinVazirani.hpp"
namespace qc {
BernsteinVazirani::BernsteinVazirani(const BitString& hiddenString,
const bool dyn)
: s(hiddenString), dynamic(dyn) {
std::size_t msb = 0;
for (std::size_t i = 0; i < s.size(); ++i) {
if (s.test(i)) {
msb = i;
}
}
bitwidth = msb + 1;
createCircuit();
}
BernsteinVazirani::BernsteinVazirani(const std::size_t nq, const bool dyn)
: bitwidth(nq), dynamic(dyn) {
auto distribution = std::bernoulli_distribution();
for (std::size_t i = 0; i < nq; ++i) {
if (distribution(mt)) {
s.set(i);
}
}
createCircuit();
}
BernsteinVazirani::BernsteinVazirani(const BitString& hiddenString,
const std::size_t nq, const bool dyn)
: s(hiddenString), bitwidth(nq), dynamic(dyn) {
createCircuit();
}
std::ostream& BernsteinVazirani::printStatistics(std::ostream& os) const {
os << "BernsteinVazirani (" << bitwidth << ") Statistics:\n";
os << "\tn: " << bitwidth + 1 << "\n";
os << "\tm: " << getNindividualOps() << "\n";
os << "\ts: " << expected << "\n";
os << "\tdynamic: " << dynamic << "\n";
os << "--------------" << "\n";
return os;
}
void BernsteinVazirani::createCircuit() {
expected = s.to_string();
std::reverse(expected.begin(), expected.end());
while (expected.length() > bitwidth) {
expected.pop_back();
}
std::reverse(expected.begin(), expected.end());
name = "bv_" + expected;
addQubitRegister(1, "flag");
if (dynamic) {
addQubitRegister(1, "q");
} else {
addQubitRegister(bitwidth, "q");
}
addClassicalRegister(bitwidth, "c");
// prepare flag qubit
x(0);
if (dynamic) {
// set up initial layout
initialLayout[0] = 1;
initialLayout[1] = 0;
setLogicalQubitGarbage(1);
outputPermutation.erase(0);
outputPermutation[1] = 0;
for (std::size_t i = 0; i < bitwidth; ++i) {
// initial Hadamard
h(1);
// apply controlled-Z gate according to secret bitstring
if (s.test(i)) {
cz(1, 0);
}
// final Hadamard
h(1);
// measure result
measure(1, i);
// reset qubit if not finished
if (i < bitwidth - 1) {
reset(1);
}
}
} else {
// set up initial layout
initialLayout[0] = static_cast<Qubit>(bitwidth);
for (std::size_t i = 1; i <= bitwidth; ++i) {
initialLayout[static_cast<Qubit>(i)] = static_cast<Qubit>(i - 1);
}
setLogicalQubitGarbage(static_cast<Qubit>(bitwidth));
outputPermutation.erase(0);
// initial Hadamard transformation
for (std::size_t i = 1; i <= bitwidth; ++i) {
h(static_cast<Qubit>(i));
}
// apply controlled-Z gates according to secret bitstring
for (std::size_t i = 1; i <= bitwidth; ++i) {
if (s.test(i - 1)) {
cz(static_cast<Qubit>(i), 0);
}
}
// final Hadamard transformation
for (std::size_t i = 1; i <= bitwidth; ++i) {
h(static_cast<Qubit>(i));
}
// measure results
for (std::size_t i = 1; i <= bitwidth; i++) {
measure(static_cast<Qubit>(i), i - 1);
outputPermutation[static_cast<Qubit>(i)] = static_cast<Qubit>(i - 1);
}
}
}
} // namespace qc