-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Entanglement simulation on a grid with custom predicates #90
Changes from 7 commits
f9cc7ac
962f5d6
5b726da
7d1b3fc
1f98123
f9c5f90
b127a3e
cfe1f31
7547205
2943e2e
427e079
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
using Revise | ||
using QuantumSavory | ||
using ResumableFunctions | ||
using ConcurrentSim | ||
using QuantumSavory.ProtocolZoo | ||
using QuantumSavory.ProtocolZoo: EntanglementCounterpart, EntanglementHistory, EntanglementUpdateX, EntanglementUpdateZ | ||
using Graphs | ||
using Test | ||
|
||
if isinteractive() | ||
using Logging | ||
logger = ConsoleLogger(Logging.Debug; meta_formatter=(args...)->(:black,"","")) | ||
global_logger(logger) | ||
println("Logger set to debug") | ||
end | ||
|
||
## Custom Predicates | ||
function top_left(net, node, x) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am waiting on CI and will then merge. However, this is an O(n) check for something that should be O(1). From a node index get its x y coordinates (currently you get only one of them). Then just compare them to verify that you are to the left (one comparison) and to the top (second comparison). No need for a for loop. Submit a PR with the fix and feel free to merge it. It should also make this function much simpler. |
||
n = sqrt(size(net.graph)[1]) # grid size | ||
a = (node ÷ n) + 1 # row number | ||
for i in 1:a-1 | ||
if x == (i-1)*n + i | ||
return true | ||
end | ||
end | ||
return false | ||
end | ||
|
||
function bottom_right(net, node, x) | ||
n = sqrt(size(net.graph)[1]) # grid size | ||
a = (node ÷ n) + 1 # row number | ||
for i in a+1:n | ||
if x == (i-1)*n + i | ||
return true | ||
end | ||
end | ||
return false | ||
end | ||
|
||
## Simulation | ||
|
||
#without entanglement tracker | ||
for i in 1:10 | ||
graph = grid([4, 4]) | ||
add_edge!(graph, 1, 6) | ||
add_edge!(graph, 6, 11) | ||
add_edge!(graph, 11, 16) | ||
|
||
net = RegisterNet(graph, [Register(3) for i in 1:16]) | ||
sim = get_time_tracker(net) | ||
|
||
|
||
entangler1 = EntanglerProt(sim, net, 1, 6; rounds=1) | ||
@process entangler1() | ||
run(sim, 20) | ||
|
||
@test net[1].tags == [[Tag(EntanglementCounterpart, 6, 1)],[],[]] | ||
|
||
|
||
entangler2 = EntanglerProt(sim, net, 6, 11; rounds=1) | ||
@process entangler2() | ||
run(sim, 40) | ||
entangler3 = EntanglerProt(sim, net, 11, 16; rounds=1) | ||
@process entangler3() | ||
run(sim, 60) | ||
|
||
@test net[1].tags == [[Tag(EntanglementCounterpart, 6, 1)],[],[]] | ||
@test net[6].tags == [[Tag(EntanglementCounterpart, 1, 1)],[Tag(EntanglementCounterpart, 11, 1)],[]] | ||
@test net[11].tags == [[Tag(EntanglementCounterpart, 6, 2)],[Tag(EntanglementCounterpart, 16, 1)], []] | ||
@test net[16].tags == [[Tag(EntanglementCounterpart, 11, 2)],[],[]] | ||
|
||
@test [islocked(ref) for i in vertices(net) for ref in net[i]] |> any == false | ||
|
||
l1(x) = top_left(net, 6, x) | ||
h1(x) = bottom_right(net, 6, x) | ||
swapper2 = SwapperProt(sim, net, 6; nodeL=l1, nodeH=h1, rounds=1) | ||
l2(x) = top_left(net, 11, x) | ||
h2(x) = bottom_right(net, 11, x) | ||
swapper3 = SwapperProt(sim, net, 11; nodeL=l2, nodeH=h2, 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, 6, 1)],[],[]] | ||
@test net[6].tags == [[Tag(EntanglementHistory, 1, 1, 11, 1, 2)],[Tag(EntanglementHistory, 11, 1, 1, 1, 1)],[]] | ||
@test net[11].tags == [[Tag(EntanglementHistory, 6, 2, 16, 1, 2)],[Tag(EntanglementHistory, 16, 1, 6, 2, 1)], []] | ||
@test net[16].tags == [[Tag(EntanglementCounterpart, 11, 2)],[],[]] | ||
|
||
@test isassigned(net[1][1]) && isassigned(net[16][1]) | ||
@test !isassigned(net[6][1]) && !isassigned(net[11][1]) | ||
@test !isassigned(net[6][2]) && !isassigned(net[11][2]) | ||
|
||
@test [islocked(ref) for i in vertices(net) for ref in net[i]] |> any == false | ||
|
||
end | ||
|
||
# with entanglement tracker | ||
for n in 4:10 | ||
graph = grid([n,n]) | ||
|
||
diag_pairs = [] | ||
diag_nodes = [] | ||
reg_num = 1 # starting register | ||
for i in 1:n-1 # a grid with n nodes has n-1 pairs of diagonal nodes | ||
push!(diag_pairs, (reg_num, reg_num+n+1)) | ||
push!(diag_nodes, reg_num) | ||
reg_num += n + 1 | ||
end | ||
push!(diag_nodes, n^2) | ||
|
||
for (src, dst) in diag_pairs # need edges down the diagonal to establish cchannels and qchannels between the diagonal nodes | ||
add_edge!(graph, src, dst) | ||
end | ||
|
||
net = RegisterNet(graph, [Register(8) for i in 1:n^2]) | ||
|
||
sim = get_time_tracker(net) | ||
|
||
for (src, dst) in diag_pairs | ||
eprot = EntanglerProt(sim, net, src, dst; rounds=1, randomize=true) | ||
@process eprot() | ||
end | ||
|
||
for i in 2:n-1 | ||
l(x) = top_left(net, diag_nodes[i], x) | ||
h(x) = bottom_right(net, diag_nodes[i], x) | ||
swapper = SwapperProt(sim, net, diag_nodes[i]; nodeL = l, nodeH = h, rounds = 1) | ||
@process swapper() | ||
end | ||
|
||
for v in diag_nodes | ||
tracker = EntanglementTracker(sim, net, v) | ||
@process tracker() | ||
end | ||
|
||
run(sim, 200) | ||
|
||
q1 = query(net[1], EntanglementCounterpart, diag_nodes[n], ❓) | ||
q2 = query(net[diag_nodes[n]], EntanglementCounterpart, 1, ❓) | ||
@test q1.tag[2] == diag_nodes[n] | ||
@test q2.tag[2] == 1 | ||
@test observable((q1.slot, q2.slot), Z⊗Z) ≈ 1 | ||
@test observable((q1.slot, q2.slot), X⊗X) ≈ 1 | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, you are saying I should have removed the underscore. Indeed, the underscore should not be there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, in case of a vector of
NamedTuple
the output is theNamedTuple
, the above snippet takes in a simple vector.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yes, it should be just
il = choose_low(low_nodes)
. Then it all works, right?argmax
has way more signatures than I expected. With that change the random_index function should also work. Apologies for the only partial update.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
argmax
(argmin) returns the tuple: (slot = Slot 9, tag = Entangled to 4.1)we can't use it to index the array of NamedTuple, so it doesn't work like that, if we want to do argmax, we would have to return
il
andih
directlyThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
argmax((n->n.tag[2] for n in low_nodes))
Start from scratch here: what is the point of this change -- it is to make it easy for a user to provide a chooser function that gives you the preferred node to select. You can not have such a function depend on the internals of your code, you can not expect the user to know of it. Apologies for the repeated typos though, those are on me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change totally makes sense. The problem is just that it the way it was implemented before(using
argmax
orargmin
), it didn't work with indexing.The third comment suggests doing
il = choose_low(low_nodes)
, that throws an error:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check my last comment. Does this work:
argmax((n->n.tag[2] for n in low_nodes))
or something to that effect.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation comment also helps with this:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, thanks, I got really confused in the beginning, sorry about that