Skip to content

Commit f834037

Browse files
authored
MBQC Purification (#185)
* Add a mbqc purification example
1 parent 6533bfa commit f834037

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed

examples/purificationMBQC/MBQC.jl

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
using ResumableFunctions
2+
using ConcurrentSim
3+
using Revise
4+
5+
using QuantumSavory
6+
using QuantumSavory.ProtocolZoo
7+
import QuantumSavory: Tag
8+
9+
using Logging
10+
global_logger(ConsoleLogger(stderr, Logging.Debug))
11+
12+
const perfect_pair = (Z1Z1 + Z2Z2) / sqrt(2)
13+
const perfect_pair_dm = SProjector(perfect_pair)
14+
const mixed_dm = MixedState(perfect_pair_dm)
15+
noisy_pair_func_depol(p) = p*perfect_pair_dm + (1-p)*mixed_dm
16+
17+
function noisy_pair_func(F)
18+
p = (4*F-1)/3
19+
return noisy_pair_func_depol(p)
20+
end
21+
22+
@kwdef struct MBQCSetUp
23+
node::Int
24+
end
25+
Base.show(io::IO, tag::MBQCSetUp) = print(io, "Set up is completed on $(tag.node)")
26+
Tag(tag::MBQCSetUp) = Tag(MBQCSetUp, tag.node)
27+
28+
29+
@kwdef struct MBQCMeasurement
30+
node::Int
31+
measurement::Int
32+
end
33+
Base.show(io::IO, tag::MBQCMeasurement) = print(io, "Measurement for register $(tag.node) is $(tag.measurement).")
34+
Tag(tag::MBQCMeasurement) = Tag(MBQCMeasurement, tag.node, tag.measurement)
35+
36+
@kwdef struct PurifiedEntalgementCounterpart
37+
remote_node::Int
38+
remote_slot::Int
39+
end
40+
Base.show(io::IO, tag::PurifiedEntalgementCounterpart) = print(io, "Entangled to $(tag.remote_node).$(tag.remote_slot)")
41+
Tag(tag::PurifiedEntalgementCounterpart) = Tag(PurifiedEntalgementCounterpart, tag.remote_node, tag.remote_slot)
42+
43+
@resumable function MBQC_purification_tracker(sim, net, node)
44+
nodereg = net[node]
45+
mb = messagebuffer(net, node)
46+
while true
47+
local_tag = query(nodereg, MBQCMeasurement, node, ❓) # waits on the measurement result
48+
49+
if isnothing(local_tag)
50+
@yield onchange_tag(net[node])
51+
continue
52+
end
53+
54+
msg = query(mb, MBQCMeasurement, ❓, ❓)
55+
if isnothing(msg)
56+
@debug "Starting message wait at $(now(sim)) with MessageBuffer containing: $(mb.buffer)"
57+
@yield wait(mb)
58+
@debug "Done waiting for message at $(node)"
59+
continue
60+
end
61+
62+
msg = querydelete!(mb, MBQCMeasurement, ❓, ❓)
63+
local_measurement = local_tag.tag.data[3] # it would be better if it can be local_tag.tag.measurement
64+
src, (_, src_node, src_measurement) = msg
65+
66+
if src_measurement == local_measurement
67+
@debug "Purification was successful"
68+
tag!(local_tag.slot, PurifiedEntalgementCounterpart, src_node, 4)
69+
70+
else
71+
@debug "Purification failed."
72+
untag!(local_tag.slot, local_tag.id)
73+
end
74+
end
75+
end
76+
77+
@resumable function MBQC_setup(sim, net, node, duration=0.1, period=0.1)
78+
while true
79+
query_setup = query(net[node], MBQCSetUp, node)
80+
if !isnothing(query_setup) # no need to set up if it already is
81+
if isnothing(period)
82+
@yield onchange_tag(net[node])
83+
else
84+
@yield timeout(sim, period)
85+
end
86+
continue
87+
end
88+
@debug "Setup starting at node $(node)."
89+
# creating cluster states
90+
initialize!(net[node, 3], X1)
91+
initialize!(net[node, 4], X1)
92+
apply!((net[node, 3], net[node, 4]), CPHASE)
93+
@yield timeout(sim, duration)
94+
tag!(net[node][4], MBQCSetUp, node)
95+
@debug "Setup done at node $(node)."
96+
end
97+
end
98+
99+
@resumable function entangler(sim, net; pairstate=noisy_pair, period=0.1)
100+
while true
101+
# entangle 1 to 1 and 2 to 2 (long-range entanglements to be purified)
102+
entangler1 = EntanglerProt(sim, net, 1, 2; pairstate=pairstate, chooseA=1, chooseB=1, rounds=1)
103+
entangler2 = EntanglerProt(sim, net, 1, 2; pairstate=pairstate, chooseA=2, chooseB=2, rounds=1)
104+
p1 = @process entangler1()
105+
@yield p1
106+
p2 = @process entangler2()
107+
@yield p2
108+
@yield timeout(sim, period)
109+
end
110+
end
111+
112+
@resumable function MBQC_purify(sim, net, node, duration=0.1, period=0.1)
113+
while true
114+
# checking whether we have entanglements to purify & setup is completed
115+
query1 = queryall(net[node], EntanglementCounterpart, ❓, ❓; locked=false, assigned=true)
116+
query2 = query(net[node], MBQCSetUp, node)
117+
if length(query1) < 2 || isnothing(query2)
118+
if isnothing(period)
119+
@yield onchange_tag(net[node])
120+
else
121+
@yield timeout(sim, period)
122+
end
123+
continue
124+
end
125+
println(query1)
126+
@debug "Purification starting at node $(node)."
127+
128+
apply!((net[node, 3], net[node, 1]), CPHASE)
129+
apply!((net[node, 3], net[node, 2]), CPHASE)
130+
131+
m1 = project_traceout!(net[node, 1], X)
132+
m2 = project_traceout!(net[node, 3], X)
133+
134+
if m1 == 2
135+
apply!(net[node, 4], Z)
136+
apply!(net[node, 2], Z)
137+
end
138+
if m2 == 2
139+
apply!(net[node, 4], X)
140+
end
141+
untag!(query1[1].slot, query1[1].id)
142+
untag!(query1[2].slot, query1[2].id)
143+
m = project_traceout!(net[node, 2], X)
144+
tag!(net[node][4], MBQCMeasurement, node, m)
145+
146+
if node == 1
147+
other = 2
148+
else
149+
other = 1
150+
end
151+
@debug "Purification done at node $(node)."
152+
put!(channel(net, node=>other), Tag(MBQCMeasurement, node, m))
153+
@yield timeout(sim, duration)
154+
end
155+
end
156+
157+
# Run simulation (infinite rounds)
158+
159+
regL = Register(4)
160+
regR = Register(4)
161+
net = RegisterNet([regL, regR])
162+
sim = get_time_tracker(net)
163+
F = 0.9 # fidelity
164+
165+
@process entangler(sim, net)
166+
@process MBQC_purification_tracker(sim, net, 1)
167+
@process MBQC_purification_tracker(sim, net, 2)
168+
169+
@process MBQC_setup(sim, net, 1)
170+
@process MBQC_setup(sim, net, 2)
171+
172+
@process MBQC_purify(sim, net, 1)
173+
@process MBQC_purify(sim, net, 2)
174+
175+
purified_consumer = EntanglementConsumer(sim, net, 1, 2; period=3, tag=PurifiedEntalgementCounterpart)
176+
@process purified_consumer()
177+
178+
run(sim, 2)
179+
180+
observable([net[1], net[2]], [1, 1], projector(perfect_pair))
181+
observable([net[1], net[2]], [2, 2], projector(perfect_pair))
182+
183+
# has not been consumed yet
184+
observable([net[1], net[2]], [4, 4], projector(perfect_pair))
185+
186+
run(sim, 4)
187+
188+
# should have been consumed and return nothing
189+
observable([net[1], net[2]], [4, 4], projector(perfect_pair))
190+

0 commit comments

Comments
 (0)