-
Notifications
You must be signed in to change notification settings - Fork 15
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
Piecemaker #159
base: master
Are you sure you want to change the base?
Piecemaker #159
Conversation
…delity computation (new observable is projector of nclient-GHZ state)
… consume simulation time
… distribution time and ghz-state fidelity as dataframe
Benchmark ResultJudge resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsA ratio greater than
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfoTarget
Baseline
Target resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Baseline resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Runtime information
Architecture: x86_64
Benchmark ResultJudge resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsA ratio greater than
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfoTarget
Baseline
Target resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Baseline resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Runtime information
Architecture: x86_64
Benchmark ResultJudge resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsA ratio greater than
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfoTarget
Baseline
Target resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Baseline resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Runtime information
Architecture: x86_64
Benchmark ResultJudge resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsA ratio greater than
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfoTarget
Baseline
Target resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Baseline resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Runtime information
Architecture: x86_64
Benchmark ResultJudge resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsA ratio greater than
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfoTarget
Baseline
Target resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Baseline resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Runtime information
Architecture: x86_64
Benchmark ResultJudge resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsA ratio greater than
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfoTarget
Baseline
Target resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Baseline resultBenchmark Report for /home/runner/work/QuantumSavory.jl/QuantumSavory.jlJob Properties
ResultsBelow is a table of this job's results, obtained by running the benchmarks.
Benchmark Group ListHere's a list of all the benchmark groups executed by this job:
Julia versioninfo
Runtime information
Architecture: x86_64 |
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.
This looks great, thank you! Apologies for taking so long to start the review.
I have dropped a bunch of comments in, and there are still things I need to read more carefully, but this already looks very well executed.
When you have a chance, please answer the various questions in the review.
It would be very helpful if you can prepare a few sequence diagrams of what the protocol is doing. I have found mermaid to be a great tool for that https://mermaid.live/edit#pako:eNpt0L0OwiAUhuFbOZ7V9gYYNCYO6urKckK_lib8KIUYY7x3aaubTIfwvCTwYhM7sOIJ94JgcBxlSOJ1oLoObjRod7vtJdqg6ATnIs1zQzY-SBLoGcv-L16ZkTATspBEHl86n7WVtktTLx7XuqHzUiy6Zpv__Ew94GhIkLzhhj2Sl7Grr3jNgeZs4aFZ1bFDL8VlzTq8K5WS4_UZDKucChpOsQyWVS9uqrty6yT_vmAl7w9bXV2O
Would you like to meet next week to review the rest together, to make sure we are on the same page before merging?
@@ -72,3 +72,8 @@ function krausops(d::AmplitudeDamping, Δt, basis) # https://quantumcomputing.st | |||
end | |||
|
|||
# TODO add an amplitude damping example of transduction | |||
|
|||
function krausops(Depol::Depolarization, Δt) |
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.
this would probably benefit from having a cross-check in the tests, e.g. compared against a master equation solver
|
||
""" | ||
Run `queryall(switch, EntanglemetnCounterpart, ...)` | ||
to find out which clients the switch has successfully entangled with. |
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.
This seems to be doing a bit more than what is said in the docstring. Could you document a bit more, both the "what" but also the "why"?
src/ProtocolZoo/ProtocolZoo.jl
Outdated
|
||
$TYPEDFIELDS | ||
""" | ||
@kwdef struct Piecemaker |
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.
Do we need this to be a tag? Is it a piece of information that is transmitted between protocols? If it is not, this can probably just be information given to the constructor of the fusion protocol.
src/ProtocolZoo/ProtocolZoo.jl
Outdated
|
||
$FIELDS | ||
""" | ||
@kwdef struct GHZConsumer{LT} <: AbstractProtocol where {LT<:Union{Float64,Nothing}} |
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 lack of symmetry in the names is noticeable. Can we call both GHZCounterpart and GHZConsumer (or FusionCounterpart and FusionConsumer). If it is just for GHZ for the moment, maybe we can stick to that name.
src/ProtocolZoo/ProtocolZoo.jl
Outdated
|
||
succeed(prot.event_ghz_state) | ||
if state(prot.event_ghz_state) != idle | ||
throw(StopSimulation("GHZ state shared among all users!")) |
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.
Any reason for StopSimulation
instead of just exiting this function? This might be a part of a bigger simulation that is supposed to continue after the consumer runs.
src/ProtocolZoo/ProtocolZoo.jl
Outdated
|
||
$TYPEDFIELDS | ||
""" | ||
@kwdef struct SelectedEntanglerProt{LT} <: AbstractProtocol where {LT<:Union{Float64,Nothing}} |
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.
Why is this necessary over the already existing EntanglerProt?
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.
By the way, after the recently merged PR, you can now set the delay lines to arbitrary latencies: #162
Nice, thanks for the comments! I have made quite a few updates (pushed to this branch) on the objects described above, e.g.,
Your comments are still very relevant, and I will address them asap (plus adjust the code/docstrings). And yes, let's synch next week! I sent an invite for Friday but feel free to propose any time that suits you ! |
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.
these are the comments from our meeting last week
apologies, it seems I never submitted the final review
Project.toml
Outdated
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" | ||
StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" |
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.
These do not seem to be library dependencies, rather just example dependencies. They can go in an example Project.toml or just be left out.
.DS_Store
Outdated
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.
add this file to .gitignore
examples/piecemakerswitch/README.md
Outdated
The fusion operation consists of applying a **CNOT** gate followed by a measurement in the computational basis. This procedure allows the merging of two GHZ states into a single GHZ state, modulo any required Pauli corrections. We iterate over all existing entangled states with the switch node: in each iteration, the piecemaker qubit (initialized in the state \(|+\rangle\)) is fused with one of the existing entangled states. | ||
|
||
# Noise | ||
The memories residing the nodes' `Register`s suffer from depolarizing noise. The latter is modelled via Kraus operators applied to the current state's density matrix. |
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.
in the nodes
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 use of Kraus operators is just the default due to using state vectors. The simulator might decide to not use Kraus operators if it defaults to a different representation (e.g. tableaux)
examples/piecemakerswitch/setup.jl
Outdated
@resumable function init_piecemaker(sim, net, m) | ||
while true | ||
@yield lock(net[1][m]) | ||
if !isassigned(net[1][m]) | ||
initialize!(net[1][m], X1) | ||
tag!(net[1][m], Piecemaker, 1, m) | ||
unlock(net[1][m]) | ||
@yield timeout(sim, 1) | ||
else | ||
unlock(net[1][m]) | ||
@yield timeout(sim, 1) | ||
end | ||
end | ||
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.
delete if not used
examples/piecemakerswitch/setup.jl
Outdated
initialize!(net[1][m], X1) | ||
tag!(net[1][m], Piecemaker, 1, m) |
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.
This should probably just be some flag or entry in the FusionSwitchDiscreteProt
.
src/ProtocolZoo/ProtocolZoo.jl
Outdated
""" | ||
$TYPEDEF | ||
|
||
A protocol that generates entanglement between two nodes. | ||
Whenever the selected client slot and the associated slot on the remote node are free, the protocol locks them | ||
and starts probabilistic attempts to establish entanglement. | ||
|
||
$TYPEDFIELDS | ||
""" | ||
@kwdef struct SelectedEntanglerProt <: AbstractProtocol | ||
"""time-and-schedule-tracking instance from `ConcurrentSim`""" | ||
sim::Simulation # TODO check that | ||
"""a network graph of registers""" | ||
net::RegisterNet | ||
"""the vertex index of node A""" | ||
nodeA::Int | ||
"""the vertex index of node B""" | ||
nodeB::Int | ||
"""the state being generated (supports symbolic, numeric, noisy, and pure)""" | ||
pairstate = StabilizerState("ZZ XX") | ||
"""success probability of one attempt of entanglement generation""" | ||
success_prob::Float64 = 0.001 | ||
"""duration of single entanglement attempt""" | ||
attempt_time::Float64 = 0.001 | ||
"""how many rounds of this protocol to run (`-1` for infinite)""" | ||
rounds::Int = -1 | ||
"""maximum number of attempts to make per round (`-1` for infinite)""" | ||
attempts::Int = -1 | ||
end | ||
|
||
"""Convenience constructor for specifying `rate` of generation instead of success probability and time""" | ||
function SelectedEntanglerProt(sim::Simulation, net::RegisterNet, nodeA::Int, nodeB::Int; rate::Union{Nothing,Float64}=nothing, kwargs...) | ||
if isnothing(rate) | ||
return SelectedEntanglerProt(;sim, net, nodeA, nodeB, kwargs...) | ||
else | ||
return SelectedEntanglerProt(;sim, net, nodeA, nodeB, kwargs..., success_prob=0.001, attempt_time=0.001/rate) | ||
end | ||
end | ||
|
||
#TODO """Convenience constructor for specifying `fidelity` of generation instead of success probability and time""" | ||
|
||
@resumable function (prot::SelectedEntanglerProt)() | ||
rounds = prot.rounds | ||
round = 1 | ||
while rounds != 0 | ||
isentangled = !isnothing(query(prot.net[prot.nodeA], EntanglementCounterpart, prot.nodeB, ❓; assigned=true)) | ||
a = prot.net[prot.nodeA][prot.nodeB-1] | ||
b = prot.net[prot.nodeB][1] | ||
|
||
if isnothing(a) || isnothing(b) | ||
isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO | ||
@debug "EntanglerProt between $(prot.nodeA) and $(prot.nodeB)|round $(round): Failed to find free slots. \nGot:\n1. \t $a \n2.\t $b \n retrying..." | ||
continue | ||
end | ||
|
||
@yield lock(a) & lock(b) # this yield is expected to return immediately | ||
attempts = if isone(prot.success_prob) | ||
1 | ||
else | ||
rand(Geometric(prot.success_prob))+1 | ||
end | ||
|
||
if (prot.attempts == -1 || prot.attempts >= attempts) && !isassigned(b) && !isassigned(a) | ||
|
||
initialize!((a,b), prot.pairstate; time=now(prot.sim)) | ||
@yield timeout(prot.sim, attempts * prot.attempt_time) | ||
|
||
# tag local node a with EntanglementCounterpart remote_node_idx_b remote_slot_idx_b | ||
tag!(a, EntanglementCounterpart, prot.nodeB, b.idx) | ||
# tag local node b with EntanglementCounterpart remote_node_idx_a remote_slot_idx_a | ||
tag!(b, EntanglementCounterpart, prot.nodeA, a.idx) | ||
|
||
@debug "EntanglerProt between $(prot.nodeA) and $(prot.nodeB)|round $(round): Entangled .$(a.idx) and .$(b.idx)" | ||
else | ||
uptotime!((a,b), now(prot.sim)) | ||
@yield timeout(prot.sim, prot.attempts * prot.attempt_time) | ||
@debug "EntanglerProt between $(prot.nodeA) and $(prot.nodeB)|round $(round): Performed the maximum number of attempts and gave up" | ||
end | ||
unlock(a) | ||
unlock(b) | ||
rounds==-1 || (rounds -= 1) | ||
round += 1 | ||
end | ||
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.
this hopefully can be removed by improving EntanglerProt
to have slotA::Union{Int,Wildcard}
-- if it is wildcard it does what it currently does and if not it checks islocked
and isassigned
and proceeds if available.
""" | ||
$TYPEDEF | ||
|
||
Indicates the current entanglement status with a remote node's slot. Added when a new qubit is fused into the GHZ state through [`FusionProt`](@ref). |
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.
adding a sentence or two about who receives this tag and whom the tag points to
src/ProtocolZoo/ProtocolZoo.jl
Outdated
"""event when all users are sharing a ghz state""" | ||
event_ghz_state::Event |
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.
not used anymore
src/ProtocolZoo/ProtocolZoo.jl
Outdated
@resumable function (prot::GHZConsumer)() | ||
if isnothing(prot.period) | ||
error("In `GHZConsumer` we do not yet support waiting on register to make qubits available") # TODO | ||
end | ||
while true | ||
nclients = nsubsystems(prot.net[1])-1 | ||
qparticipating = queryall(prot.piecemaker, FusionCounterpart, ❓, ❓) # TODO Need a `querydelete!` dispatch on `Register` rather than using `query` here followed by `untag!` below | ||
if isnothing(qparticipating) | ||
@debug "GHZConsumer between $(prot.piecemaker): query on piecemaker slot found no entanglement" | ||
#@yield timeout(prot.sim, prot.period) | ||
continue | ||
return | ||
elseif length(qparticipating) == nclients | ||
@debug "All clients are now part of the GHZ state." | ||
client_slots = [prot.net[k][1] for k in 2:nclients+1] | ||
|
||
# Wait for all locks to complete | ||
tasks = [] | ||
for resource in client_slots | ||
push!(tasks, lock(resource)) | ||
end | ||
push!(tasks, lock(prot.piecemaker)) | ||
all_locks = reduce(&, tasks) | ||
@yield all_locks | ||
|
||
@debug "GHZConsumer of $(prot.piecemaker): queries successful, consuming entanglement" | ||
for q in qparticipating | ||
untag!(prot.piecemaker, q.id) | ||
end | ||
|
||
# when all qubits have arrived, we measure out the central qubit | ||
zmeas = project_traceout!(prot.piecemaker, σˣ) | ||
if zmeas == 2 | ||
apply!(prot.net[2][1], Z) # apply correction on arbitrary client slot | ||
end | ||
result = real(observable(client_slots, projector(1/sqrt(2)*(reduce(⊗, [fill(Z2,nclients)...]) + reduce(⊗,[fill(Z1,nclients)...]))))) | ||
@debug "GHZConsumer: expectation value $(result)" | ||
|
||
pm = queryall(prot.piecemaker, ❓, ❓, ❓) | ||
@assert length(pm) < 2 "More than one entry for piecemaker in database." | ||
(slot, id, tag) = pm[1] | ||
@debug "GHZConsumer: piecemaker qubit state real($(observable(slot, X1)))" | ||
untag!(prot.piecemaker, id) | ||
|
||
# delete tags and free client slots | ||
for k in 2:nclients+1 | ||
queries = queryall(prot.net[k], EntanglementCounterpart, ❓, ❓) | ||
for q in queries | ||
untag!(q.slot, q.id) | ||
end | ||
end | ||
|
||
traceout!([prot.net[k][1] for k in 2:nclients+1]...) | ||
for k in 2:nclients+1 | ||
unlock(prot.net[k][1]) | ||
end | ||
unlock(prot.piecemaker) | ||
|
||
# log results | ||
push!(prot.log, (now(prot.sim), result,)) | ||
throw(StopSimulation("GHZ state shared among all users!")) | ||
@yield timeout(prot.sim, prot.period) | ||
end | ||
@yield timeout(prot.sim, prot.period) | ||
end | ||
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.
not fully reviewed yet
while rounds != 0 | ||
rounds==-1 || (rounds -= 1) | ||
|
||
@debug "Node $(prot.switchnode) starts a new entanglement round at time $(now(prot.sim))" | ||
# run entangler without requests (=no assignment) | ||
_switch_entangler_all_selected(prot) | ||
@yield timeout(prot.sim, prot.ticktock/2) | ||
@debug "Node $(prot.switchnode) stops at time $(now(prot.sim))" | ||
# read which entanglements were successful | ||
matches = _switch_successful_entanglements(prot, reverseclientindex) | ||
if isnothing(matches) | ||
@yield timeout(prot.sim, prot.ticktock/2) | ||
continue | ||
end | ||
@debug "Node $(prot.switchnode) performs fusions at time $(now(prot.sim))" | ||
# perform fusions | ||
_switch_run_fusions(prot, matches) | ||
@yield timeout(prot.sim, prot.ticktock/2) | ||
@debug "Node $(prot.switchnode) is done with fusions at time $(now(prot.sim))" | ||
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.
while true
processes = [entangler_followed_by_fusion(i) for i in clients]
wait_on_all_of_them = reduce(&, processes)
@yield wait_on_all_of_them
end
where
@resumable entangler_followed_by_fusion(...)
@yield @process Entangler...
# and then the fusion code
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.
just be careful to make sure slots are locked and unlocked
… in piecemaker env; updated gitignore
This PR adds a new quantum network example: A central switch node connects to n clients. The switch possesses m = n + 1 qubit slots, while each client has a single qubit slot. At each clock tick, the switch initiates entanglement attempts with each of the n clients, resulting in n entanglement processes per cycle. Successful entanglement links are then merged into a GHZ (Greenberger–Horne–Zeilinger) state using an additional "piecemaker" qubit located in the (n + 1)th slot of the switch node. This fusion process is assumed to occur instantaneously. Once all clients went through the fusion operation, the piecemaker qubit is measured out completing one simulation run. The fidelity of the generated GHZ state as well as distribution times of each run are collected.
Changes
uptotime.jl
: implementedstruct Depolarization
noise usingkrausops
which can be applied to aRegister
switches.jl
: addedstruct FusionSwitchDiscreteProt
as the main protocol includingfunction _switch_entangler_all_selected(prot)
and other functions. The latter runs the entangler protocol between all clients and their respective (preselected) slots at the switch node.ProtocolZoo.jl
: added tagsFusionCounterpart
andPiecemaker
indicating/to query a new qubit available to be fused into the GHZ state and the piecemaker qubit, respectively. Addedstruct GHZConsumer
which measures out the piecemaker qubit in the end, tracking the distribution time, as well as the fidelity of the final state with the target GHZ state.CircuitZoo.jl
: addedstruct EntanglementFusion
circuit.setup.jl
: prepares simulation processes.simple_run.jl
: runs simulation and collects results from theGHZConsumer.log
.Troubleshooting
In the current implementation, sending and receiving classical measurement messages is achieved via a
DelayQueue
channel connected toMessageBuffer
s at the nodes. TheMessageBuffer
acts as a buffer that holds incoming messages and manages processes waiting for messages.Important Note: By design, message passing should not involve simulated time delays by default. Messages are expected to be delivered instantaneously in simulation time unless explicitly specified otherwise. However, during simulation, the following debug output from the EntanglementTracker indicates that a delay is being introduced unexpectedly:
@debug "EntanglementTracker @$(prot.node): Starting message wait at $(now(prot.sim)) with MessageBuffer containing: $(mb.buffer)"
in theEntanglementTracker
. This results in distribution times > # rounds of entanglement attempts, which should not be the case.