forked from openqasm/openqasm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmsd.qasm
171 lines (155 loc) · 4.53 KB
/
msd.qasm
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
* Magic state distillation and computation
*/
OPENQASM 3;
include "stdgates.inc";
const buffer_size = 6; // size of magic state buffer
// Y-basis measurement
def ymeasure qubit:q -> bit {
s q;
h q;
return measure q;
}
/*
* Distillation subroutine takes 10 |H> magic states
* and 3 scratch qubits that will be reinitialized.
* The first two input magic states are the outputs.
* The subroutine returns a success bit that is true
* on success and false otherwise (see arXiv:1811.00566).
*/
def distill qubit[10]:magic, qubit[3]:scratch -> bool {
bit temp;
bit checks[3];
// Encode two magic states in the [[4,2,2]] code
reset scratch[0: 1];
h scratch[1];
cx scratch[1], magic[0];
cx magic[1], scratch[0];
cx magic[0], scratch[0];
cx scratch[1], magic[1];
// Body of distillation circuit
cy magic[2], scratch[0];
h magic[1];
temp = ymeasure magic[2];
if(temp == 1) { ry(-pi / 2) scratch[0]; }
reset scratch[2];
h scratch[2];
cz scratch[2], scratch[0];
cy magic[3], scratch[0];
temp = ymeasure magic[3];
if(temp==0) { ry(pi / 2) scratch[0]; }
h scratch[0];
s scratch[0];
cy magic[4], scratch[1];
temp = ymeasure magic[4];
if(temp==1) { ry(-pi / 2) scratch[1]; }
cz scratch[3], scratch[2];
cy magic[5], scratch[1];
temp = ymeasure magic[5];
if(temp==0) { ry(pi / 2) scratch[1]; }
cy scratch[0], magic[1];
inv @ s scratch[1];
cz scratch[0], scratch[1];
h scratch[0];
cy scratch[1], magic[1];
cy magic[6], scratch[0];
temp = ymeasure magic[6];
if(temp == 1) { ry(-pi / 2) scratch[0]; }
cz scratch[2], scratch[1];
cz scratch[2], scratch[0];
cy magic[7], scratch[0];
temp = ymeasure magic[7];
if(temp == 0) ry(pi / 2) scratch[0];
cy magic[8], scratch[1];
temp = ymeasure magic[8];
if(temp==1) { ry(-pi / 2) scratch[1]; }
cz scratch[2], scratch[1];
cy magic[9], scratch[1];
temp = ymeasure magic[9];
if(temp == 0) { ry(pi / 2) scratch[1]; }
h scratch[2];
// Decode [[4,2,2]] code
cx magic[0], scratch[0];
cx scratch[1], magic[1];
cx magic[1], scratch[0];
cx scratch[1], magic[0];
h scratch[1];
checks = measure scratch;
success = ~(bool(checks[0]) | bool(checks[1]) | bool(checks[2]));
return success;
}
// Repeat level-0 distillation until success
def rus_level_0 qubit[10]:magic, qubit[3]:scratch {
bool success;
while(~success) {
reset magic;
ry(pi / 4) magic;
success = distill magic, scratch;
}
}
/*
* Run two levels of 10:2 magic state distillation.
* Both levels have two distillations running in parallel.
* The output pairs from the first level are separated and
* input to different second levels distillation circuits
* because a failure in a first level circuit can lead to
* errors on both outputs.
* Put the requested even number of copies into the buffer.
*/
def distill_and_buffer(int[32]:num) qubit[33]:work, qubit[buffer_size]:buffer {
int[32] index;
bit success_0, success_1;
let magic_lvl0 = work[0: 9];
let magic_lvl1_0 = work[10: 19];
let magic_lvl1_1 = work[20: 29];
let scratch = work[30: 32];
// Run first-level circuits until 10 successes,
// storing the outputs for use in the second level
for i in [0: 9] {
rus_level_0 magic_lvl0, scratch;
swap magic_lvl0[0], magic_lvl1_0[i];
swap magic_lvl0[1], magic_lvl1_1[i];
}
// Run two second level circuits simultaneously
success_0 = distill magic_lvl1_0, scratch_0;
success_1 = distill magic_lvl1_1, scratch_1;
// Move usable magic states into the buffer register
if(success_0 && index < buffer_size) {
swap magic_lvl1_0[0: 1], buffer[index: index + 1];
index += 2;
}
if(success_1 && index < buffer_size) {
swap magic_lvl1_1[0: 1], buffer[index: index + 1];
index += 2;
}
}
// Apply Ry(pi/4) to a qubit by consuming a magic state
// from the magic state buffer at address "addr"
def Ty(int[32]:addr) qubit:q, qubit[buffer_size]:buffer {
bit outcome;
cy buffer[addr], q;
outcome = ymeasure buffer[addr];
if(outcome == 1) ry(pi / 2) q;
}
qubit workspace[33];
qubit buffer[buffer_size];
qubit q[5];
bit c[5];
int[32] address;
// initialize
reset workspace;
reset buffer;
reset q;
distill_and_buffer(buffer_size) workspace, buffer;
// Consume magic states to apply some gates ...
h q[0];
cx q[0], q[1];
Ty(address) q[0], buffer;
address++;
cx q[0], q[1];
Ty(address) q[1], buffer;
address++;
// In principle each Ty gate can execute as soon as the magic
// state is available at the address in the buffer register.
// We can continue alternating state distillation and computation
// to refill and empty a circular buffer.