Skip to content

Commit

Permalink
account for change in Pauli frame during swap
Browse files Browse the repository at this point in the history
  • Loading branch information
Krastanov committed Dec 30, 2023
1 parent df61ce5 commit 49f224a
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 44 deletions.
12 changes: 7 additions & 5 deletions src/ProtocolZoo/ProtocolZoo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Tag(tag::EntanglementHistory) = Tag(EntanglementHistory, tag.remote_node, tag.re
new_remote_slot::Int
correction::Int
end
Base.show(io::IO, tag::EntanglementUpdateX) = print(io, "Update slot .$(tag.past_remote_slot) which used to be entangled to $(tag.past_local_node).$(tag.past_local_slot) to be entangled to $(tag.new_remote_node).$(tag.new_remote_slot) and apply correction X$(tag.correction)")
Base.show(io::IO, tag::EntanglementUpdateX) = print(io, "Update slot .$(tag.past_remote_slot) which used to be entangled to $(tag.past_local_node).$(tag.past_local_slot) to be entangled to $(tag.new_remote_node).$(tag.new_remote_slot) and apply correction Z$(tag.correction)")
Tag(tag::EntanglementUpdateX) = Tag(EntanglementUpdateX, tag.past_local_node, tag.past_local_slot, tag.past_remote_slot, tag.new_remote_node, tag.new_remote_slot, tag.correction)

Check warning on line 51 in src/ProtocolZoo/ProtocolZoo.jl

View check run for this annotation

Codecov / codecov/patch

src/ProtocolZoo/ProtocolZoo.jl#L50-L51

Added lines #L50 - L51 were not covered by tests

@kwdef struct EntanglementUpdateZ
Expand All @@ -58,7 +58,7 @@ Tag(tag::EntanglementUpdateX) = Tag(EntanglementUpdateX, tag.past_local_node, ta
new_remote_slot::Int
correction::Int
end
Base.show(io::IO, tag::EntanglementUpdateZ) = print(io, "Update slot .$(tag.past_remote_slot) which used to be entangled to $(tag.past_local_node).$(tag.past_local_slot) to be entangled to $(tag.new_remote_node).$(tag.new_remote_slot) and apply correction Z$(tag.correction)")
Base.show(io::IO, tag::EntanglementUpdateZ) = print(io, "Update slot .$(tag.past_remote_slot) which used to be entangled to $(tag.past_local_node).$(tag.past_local_slot) to be entangled to $(tag.new_remote_node).$(tag.new_remote_slot) and apply correction X$(tag.correction)")
Tag(tag::EntanglementUpdateZ) = Tag(EntanglementUpdateZ, tag.past_local_node, tag.past_local_slot, tag.past_remote_slot, tag.new_remote_node, tag.new_remote_slot, tag.correction)

Check warning on line 62 in src/ProtocolZoo/ProtocolZoo.jl

View check run for this annotation

Codecov / codecov/patch

src/ProtocolZoo/ProtocolZoo.jl#L61-L62

Added lines #L61 - L62 were not covered by tests

"""
Expand Down Expand Up @@ -249,7 +249,7 @@ end
workwasdone = true # waiting is not enough because we might have multiple rounds of work to do
while workwasdone
workwasdone = false
for (updatetagsymbol, updategate) in ((EntanglementUpdateX, X), (EntanglementUpdateZ, Z))
for (updatetagsymbol, updategate) in ((EntanglementUpdateX, Z), (EntanglementUpdateZ, X))

Check warning on line 252 in src/ProtocolZoo/ProtocolZoo.jl

View check run for this annotation

Codecov / codecov/patch

src/ProtocolZoo/ProtocolZoo.jl#L252

Added line #L252 was not covered by tests
# look for EntanglementUpdate? past_remote_slot_idx local_slot_idx, new_remote_node, new_remote_slot_idx correction
msg = querydelete!(mb, updatetagsymbol, ❓, ❓, ❓, ❓, ❓, ❓)
isnothing(msg) && continue
Expand All @@ -272,7 +272,10 @@ end
unlock(localslot)
error("There was an error in the entanglement tracking protocol `EntanglementTracker`. We were attempting to forward a classical message from a node that performed a swap to the remote entangled node. However, on reception of that message it was found that the remote node has lost track of its part of the entangled state although it still keeps a `Tag` as a record of it being present.")

Check warning on line 273 in src/ProtocolZoo/ProtocolZoo.jl

View check run for this annotation

Codecov / codecov/patch

src/ProtocolZoo/ProtocolZoo.jl#L272-L273

Added lines #L272 - L273 were not covered by tests
end
# TODO correction gate
# Pauli frame correction gate
if correction==2
apply!(localslot, updategate)
end
# tag local with updated EntanglementCounterpart new_remote_node new_remote_slot_idx
tag!(localslot, EntanglementCounterpart, newremotenode, newremoteslotid)
unlock(localslot)
Expand All @@ -291,7 +294,6 @@ end
@debug "EntanglementTracker @$(prot.node): history=`$(history)` | message=`$msg` | Sending to $(whoweswappedwith_node).$(whoweswappedwith_slotidx)"
msghist = Tag(updatetagsymbol, pastremotenode, pastremoteslotid, whoweswappedwith_slotidx, newremotenode, newremoteslotid, correction)
put!(channel(prot.net, prot.node=>whoweswappedwith_node; permit_forward=true), msghist)
#println(" history sends to $whoweswappedwith_node: ", msghist)
continue
end
error("`EntanglementTracker` on node $(prot.node) received a message $(msg) that it does not know how to handle (due to the absence of corresponding `EntanglementCounterpart` or `EntanglementHistory` tags). This is a bug in the protocol and should not happen -- please report an issue at QuantumSavory's repository.")
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ println("Starting tests with $(Threads.nthreads()) threads out of `Sys.CPU_THREA
@doset "entanglement_tracker"

@doset "circuitzoo_api"
@doset "circuitzoo_ent_swap"
@doset "circuitzoo_purification"
@doset "circuitzoo_superdense"

Expand Down
57 changes: 57 additions & 0 deletions test/test_circuitzoo_ent_swap.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using QuantumSavory
using QuantumSavory.CircuitZoo
using Test
using QuantumSavory.CircuitZoo: EntanglementSwap, LocalEntanglementSwap

const perfect_pair_stab = StabilizerState("XX ZZ")
const perfect_pair = (Z1Z1 + Z2Z2) / sqrt(2)

for pair in (perfect_pair, perfect_pair_stab), rep in 1:10
net = RegisterNet([Register(1), Register(2), Register(1)])
initialize!((net[1][1], net[2][1]), pair)
initialize!((net[3][1], net[2][2]), pair)
EntanglementSwap()(net[2][1], net[1][1], net[2][2], net[3][1])
@test !isassigned(net[2][1]) && !isassigned(net[2][2])
@test observable((net[1][1], net[3][1]), ZZ) 1
@test observable((net[1][1], net[3][1]), XX) 1
end

for pair in (perfect_pair, perfect_pair_stab), rep in 1:10
net = RegisterNet([Register(1), Register(2), Register(1)])
initialize!((net[1][1], net[2][1]), pair)
initialize!((net[3][1], net[2][2]), pair)
mx, mz = LocalEntanglementSwap()(net[2][1], net[2][2])
mx == 2 && apply!(net[1][1], Z)
mz == 2 && apply!(net[3][1], X)
@test !isassigned(net[2][1]) && !isassigned(net[2][2])
@test observable((net[1][1], net[3][1]), ZZ) 1
@test observable((net[1][1], net[3][1]), XX) 1
end

for pair in (perfect_pair, perfect_pair_stab), n in 3:10, rep in 1:10
net = RegisterNet([Register(2) for i in 1:n])
for i in 1:n-1
initialize!((net[i][1], net[i+1][2]), pair)
end
for i in 2:n-1
EntanglementSwap()(net[i][2], net[1][1], net[i][1], net[i+1][2])
end
@test all(!isassigned(net[i][1]) & !isassigned(net[i][2]) for i in 2:n-1)
@test observable((net[1][1], net[n][2]), ZZ) 1
@test observable((net[1][1], net[n][2]), XX) 1
end

for pair in (perfect_pair, perfect_pair_stab), n in 3:10, rep in 1:10
net = RegisterNet([Register(2) for i in 1:n])
for i in 1:n-1
initialize!((net[i][1], net[i+1][2]), pair)
end
for i in 2:n-1
mx, mz = LocalEntanglementSwap()(net[i][2], net[i][1])
mx == 2 && apply!(net[1][1], Z)
mz == 2 && apply!(net[i+1][2], X)
end
@test all(!isassigned(net[i][1]) & !isassigned(net[i][2]) for i in 2:n-1)
@test observable((net[1][1], net[n][2]), ZZ) 1
@test observable((net[1][1], net[n][2]), XX) 1
end
86 changes: 47 additions & 39 deletions test/test_entanglement_tracker.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,51 +16,55 @@ end

##

net = RegisterNet([Register(3), Register(4), Register(2), Register(3)])
sim = get_time_tracker(net)
# without an entanglement tracker

for i in 1:10

net = RegisterNet([Register(3), Register(4), Register(2), Register(3)])
sim = get_time_tracker(net)

entangler1 = EntanglerProt(sim, net, 1, 2; rounds=1)
@process entangler1()
run(sim, 20)

@test net[1].tags == [[Tag(EntanglementCounterpart, 2, 1)],[],[]]
entangler1 = EntanglerProt(sim, net, 1, 2; rounds=1)
@process entangler1()
run(sim, 20)

@test net[1].tags == [[Tag(EntanglementCounterpart, 2, 1)],[],[]]

entangler2 = EntanglerProt(sim, net, 2, 3; rounds=1)
@process entangler2()
run(sim, 40)
entangler3 = EntanglerProt(sim, net, 4, 3; rounds=1)
@process entangler3()
run(sim, 60)

@test net[1].tags == [[Tag(EntanglementCounterpart, 2, 1)],[],[]]
@test net[2].tags == [[Tag(EntanglementCounterpart, 1, 1)],[Tag(EntanglementCounterpart, 3, 1)],[],[]]
@test net[3].tags == [[Tag(EntanglementCounterpart, 2, 2)],[Tag(EntanglementCounterpart, 4, 1)]]
@test net[4].tags == [[Tag(EntanglementCounterpart, 3, 2)],[],[]]
entangler2 = EntanglerProt(sim, net, 2, 3; rounds=1)
@process entangler2()
run(sim, 40)
entangler3 = EntanglerProt(sim, net, 4, 3; rounds=1)
@process entangler3()
run(sim, 60)

@test [islocked(ref) for i in vertices(net) for ref in net[i]] |> any == false
@test net[1].tags == [[Tag(EntanglementCounterpart, 2, 1)],[],[]]
@test net[2].tags == [[Tag(EntanglementCounterpart, 1, 1)],[Tag(EntanglementCounterpart, 3, 1)],[],[]]
@test net[3].tags == [[Tag(EntanglementCounterpart, 2, 2)],[Tag(EntanglementCounterpart, 4, 1)]]
@test net[4].tags == [[Tag(EntanglementCounterpart, 3, 2)],[],[]]

@test [islocked(ref) for i in vertices(net) for ref in net[i]] |> any == false

swapper2 = SwapperProt(sim, net, 2; rounds=1)
swapper3 = SwapperProt(sim, net, 3; rounds=1)
@process swapper2()
@process swapper3()
run(sim, 80)

# In the absence of an entanglement tracker the tags will not all be updated
@test net[1].tags == [[Tag(EntanglementCounterpart, 2, 1)],[],[]]
@test net[2].tags == [[Tag(EntanglementHistory, 1, 1, 3, 1, 2)],[Tag(EntanglementHistory, 3, 1, 1, 1, 1)],[],[]]
@test net[3].tags == [[Tag(EntanglementHistory, 2, 2, 4, 1, 2)],[Tag(EntanglementHistory, 4, 1, 2, 2, 1)]]
@test net[4].tags == [[Tag(EntanglementCounterpart, 3, 2)],[],[]]
swapper2 = SwapperProt(sim, net, 2; rounds=1)
swapper3 = SwapperProt(sim, net, 3; rounds=1)
@process swapper2()
@process swapper3()
run(sim, 80)

@test isassigned(net[1][1]) && isassigned(net[4][1])
#@test observable((net[1][1], net[4][1]), Z⊗Z) ≈ 1
@test !isassigned(net[2][1]) && !isassigned(net[3][1])
@test !isassigned(net[2][2]) && !isassigned(net[3][2])
# In the absence of an entanglement tracker the tags will not all be updated
@test net[1].tags == [[Tag(EntanglementCounterpart, 2, 1)],[],[]]
@test net[2].tags == [[Tag(EntanglementHistory, 1, 1, 3, 1, 2)],[Tag(EntanglementHistory, 3, 1, 1, 1, 1)],[],[]]
@test net[3].tags == [[Tag(EntanglementHistory, 2, 2, 4, 1, 2)],[Tag(EntanglementHistory, 4, 1, 2, 2, 1)]]
@test net[4].tags == [[Tag(EntanglementCounterpart, 3, 2)],[],[]]

@test [islocked(ref) for i in vertices(net) for ref in net[i]] |> any == false
@test isassigned(net[1][1]) && isassigned(net[4][1])
@test !isassigned(net[2][1]) && !isassigned(net[3][1])
@test !isassigned(net[2][2]) && !isassigned(net[3][2])

@test [islocked(ref) for i in vertices(net) for ref in net[i]] |> any == false

end

##

Expand All @@ -76,15 +80,16 @@ using Random

if isinteractive()
using Logging
logger = ConsoleLogger(Logging.Debug; meta_formatter=(args...)->(:black,"",""))
logger = ConsoleLogger(Logging.Warn; meta_formatter=(args...)->(:black,"",""))
global_logger(logger)
println("Logger set to debug")
end

## same but this time with an entanglement tracker
##

# same but this time with an entanglement tracker

for i in 1:1000
n = rand(2:30)
for i in 1:30, n in 2:30
#@show n, i
net = RegisterNet([Register(j+3) for j in 1:n])
sim = get_time_tracker(net)
Expand All @@ -102,7 +107,10 @@ for i in 1:1000
end
run(sim, 200)

@test query(net[1], EntanglementCounterpart, n, ❓).tag[2] == n
@test query(net[n], EntanglementCounterpart, 1, ❓).tag[2] == 1
# @test observable((net[1][1], net[n][1]), Z⊗Z) ≈ 1
q1 = query(net[1], EntanglementCounterpart, n, ❓)
q2 = query(net[n], EntanglementCounterpart, 1, ❓)
@test q1.tag[2] == n
@test q2.tag[2] == 1
@test observable((q1.slot, q2.slot), ZZ) 1
@test observable((q1.slot, q2.slot), XX) 1
end

0 comments on commit 49f224a

Please sign in to comment.