From 91f2f0d2fbf2e2e2fa0f070abe94182026d0fea4 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 2 Jul 2024 13:18:23 -0400 Subject: [PATCH 1/3] Initial changes for a Simulation type --- src/ProtocolZoo/ProtocolZoo.jl | 16 +++---- src/QuantumSavory.jl | 3 +- src/concurrentsim.jl | 43 +++++++++++++++++++ src/messagebuffer.jl | 4 +- src/networks.jl | 10 ++--- src/states_registers.jl | 2 +- test/test_protocolzoo_entanglement_tracker.jl | 4 +- 7 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index 8f2f37ab..f7c873a9 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -8,7 +8,7 @@ using QuantumSavory.CircuitZoo: EntanglementSwap, LocalEntanglementSwap using DocStringExtensions using Distributions: Geometric -using ConcurrentSim: Simulation, @yield, timeout, @process, now +using ConcurrentSim: Environment, @yield, timeout, @process, now import ConcurrentSim: Process import ResumableFunctions using ResumableFunctions: @resumable @@ -132,7 +132,7 @@ $TYPEDFIELDS """ @kwdef struct EntanglerProt{LT} <: AbstractProtocol where {LT<:Union{Float64,Nothing}} """time-and-schedule-tracking instance from `ConcurrentSim`""" - sim::Simulation # TODO check that + sim::Environment # TODO check that """a network graph of registers""" net::RegisterNet """the vertex index of node A""" @@ -164,7 +164,7 @@ $TYPEDFIELDS end """Convenience constructor for specifying `rate` of generation instead of success probability and time""" -function EntanglerProt(sim::Simulation, net::RegisterNet, nodeA::Int, nodeB::Int; rate::Union{Nothing,Float64}=nothing, kwargs...) +function EntanglerProt(sim::Environment, net::RegisterNet, nodeA::Int, nodeB::Int; rate::Union{Nothing,Float64}=nothing, kwargs...) if isnothing(rate) return EntanglerProt(;sim, net, nodeA, nodeB, kwargs...) else @@ -233,7 +233,7 @@ $TYPEDFIELDS """ @kwdef struct SwapperProt{NL,NH,CL,CH,LT} <: AbstractProtocol where {NL<:Union{Int,<:Function,Wildcard}, NH<:Union{Int,<:Function,Wildcard}, CL<:Function, CH<:Function, LT<:Union{Float64,Nothing}} """time-and-schedule-tracking instance from `ConcurrentSim`""" - sim::Simulation + sim::Environment """a network graph of registers""" net::RegisterNet """the vertex of the node where swapping is happening""" @@ -255,7 +255,7 @@ $TYPEDFIELDS end #TODO "convenience constructor for the missing things and finish this docstring" -function SwapperProt(sim::Simulation, net::RegisterNet, node::Int; kwargs...) +function SwapperProt(sim::Environment, net::RegisterNet, node::Int; kwargs...) return SwapperProt(;sim, net, node, kwargs...) end @@ -326,7 +326,7 @@ $TYPEDFIELDS """ @kwdef struct EntanglementTracker <: AbstractProtocol """time-and-schedule-tracking instance from `ConcurrentSim`""" - sim::Simulation + sim::Environment """a network graph of registers""" net::RegisterNet """the vertex of the node where the tracker is working""" @@ -405,7 +405,7 @@ $FIELDS """ @kwdef struct EntanglementConsumer{LT} <: AbstractProtocol where {LT<:Union{Float64,Nothing}} """time-and-schedule-tracking instance from `ConcurrentSim`""" - sim::Simulation + sim::Environment """a network graph of registers""" net::RegisterNet """the vertex index of node A""" @@ -418,7 +418,7 @@ $FIELDS log::Vector{Tuple{Float64, Float64, Float64}} = Tuple{Float64, Float64, Float64}[] end -function EntanglementConsumer(sim::Simulation, net::RegisterNet, nodeA::Int, nodeB::Int; kwargs...) +function EntanglementConsumer(sim::Environment, net::RegisterNet, nodeA::Int, nodeB::Int; kwargs...) return EntanglementConsumer(;sim, net, nodeA, nodeB, kwargs...) end function EntanglementConsumer(net::RegisterNet, nodeA::Int, nodeB::Int; kwargs...) diff --git a/src/QuantumSavory.jl b/src/QuantumSavory.jl index f32ec294..e6173211 100644 --- a/src/QuantumSavory.jl +++ b/src/QuantumSavory.jl @@ -1,7 +1,6 @@ module QuantumSavory -const glcnt = Ref{Int128}(0) - +glcnt = Ref{Int128}(0) function guid() glcnt[] += 1 end diff --git a/src/concurrentsim.jl b/src/concurrentsim.jl index c79cacb0..43d7ec76 100644 --- a/src/concurrentsim.jl +++ b/src/concurrentsim.jl @@ -53,3 +53,46 @@ end Base.islocked(r::RegRef) = islocked(r.reg.locks[r.idx]) ConcurrentSim.request(r::RegRef) = request(r.reg.locks[r.idx]) Base.unlock(r::RegRef) = unlock(r.reg.locks[r.idx]) + +## + +struct NetworkSimulation <: ConcurrentSim.Environment + sim::Simulation + glcnt::Ref{Int128} +end + +function NetworkSimulation() + return NetworkSimulation(Simulation(), Ref{Int128}(0)) +end + +function Base.show(io::IO, env::NetworkSimulation) + if env.sim.active_proc === nothing + print(io, "$(typeof(env)) time: $(now(env.sim)) active_process: nothing") + else + print(io, "$(typeof(env)) time: $(now(env.sim)) active_process: $(env.sim.active_proc)") + end +end + +function ConcurrentSim.now(env::NetworkSimulation) + env.sim.time +end + +# function ConcurrentSim.BaseEvent(env::NetworkSimulation) +# ConcurrentSim.BaseEvent(env.sim, env.sim.eid+=one(UInt), Vector{Function}(), ConcurrentSim.idle, nothing) +# end + +# function ConcurrentSim.put!(con::ConcurrentSim.Container{N, T}, amount::N; priority=zero(T)) where {N<:Real, T<:Number} +# put_ev = ConcurrentSim.Put(con.env.sim) +# con.put_queue[put_ev] = ConcurrentSim.ContainerKey{N,T}(con.seid+=one(UInt), amount, T(priority)) +# ConcurrentSim.@callback ConcurrentSim.trigger_get(put_ev, con) +# ConcurrentSim.trigger_put(put_ev, con) +# put_ev +# end + +# function ConcurrentSim.get(con::ConcurrentSim.Container{N, T}, amount::N; priority=zero(T)) where {N<:Real, T<:Number} +# get_ev = ConcurrentSim.Get(con.env.sim) +# con.get_queue[get_ev] = ConcurrentSim.ContainerKey(con.seid+=one(UInt), amount, T(priority)) +# ConcurrentSim.@callback ConcurrentSim.trigger_put(get_ev, con) +# ConcurrentSim.trigger_get(get_ev, con) +# get_ev +# end \ No newline at end of file diff --git a/src/messagebuffer.jl b/src/messagebuffer.jl index 27ba2e55..2201f8b7 100644 --- a/src/messagebuffer.jl +++ b/src/messagebuffer.jl @@ -1,5 +1,5 @@ struct MessageBuffer{T} - sim::Simulation + sim::Environment net # TODO ::RegisterNet -- this can not be typed due to circular dependency, see https://github.com/JuliaLang/julia/issues/269 node::Int buffer::Vector{NamedTuple{(:src,:tag), Tuple{Union{Nothing, Int},T}}} @@ -61,7 +61,7 @@ end end function MessageBuffer(net, node::Int, qs::Vector{NamedTuple{(:src,:channel), Tuple{Int, DelayQueue{T}}}}) where {T} - sim = get_time_tracker(net) + sim = get_time_tracker(net).sim signal = IdDict{Resource,Resource}() no_wait = Ref{Int}(0) mb = MessageBuffer{T}(sim, net, node, Tuple{Int,T}[], signal, no_wait) diff --git a/src/networks.jl b/src/networks.jl index a10dc369..05615b0d 100644 --- a/src/networks.jl +++ b/src/networks.jl @@ -16,7 +16,7 @@ end function RegisterNet(graph::SimpleGraph, registers, vertex_metadata, edge_metadata, directed_edge_metadata) env = get_time_tracker(registers[1]) - all_are_at_zero = all(iszero(ConcurrentSim.now(get_time_tracker(r))) && isempty(get_time_tracker(r).heap) && isnothing(get_time_tracker(r).active_proc) for r in registers) + all_are_at_zero = all(iszero(ConcurrentSim.now(get_time_tracker(r))) && isempty(get_time_tracker(r).sim.heap) && isnothing(get_time_tracker(r).sim.active_proc) for r in registers) all_are_same = all(env === get_time_tracker(r) for r in registers) if !all_are_same if all_are_at_zero @@ -42,10 +42,10 @@ function RegisterNet(graph::SimpleGraph, registers, vertex_metadata, edge_metada end for (;src,dst) in edges(graph) - cchannels[src=>dst] = DelayQueue{Tag}(env, 0) - qchannels[src=>dst] = QuantumChannel(env, 0) - cchannels[dst=>src] = DelayQueue{Tag}(env, 0) - qchannels[dst=>src] = QuantumChannel(env, 0) + cchannels[src=>dst] = DelayQueue{Tag}(env.sim, 0) + qchannels[src=>dst] = QuantumChannel(env.sim, 0) + cchannels[dst=>src] = DelayQueue{Tag}(env.sim, 0) + qchannels[dst=>src] = QuantumChannel(env.sim, 0) end for (v,r) in zip(vertices(graph), registers) channels = [(;src=w, channel=cchannels[w=>v]) for w in neighbors(graph, v)] diff --git a/src/states_registers.jl b/src/states_registers.jl index 90121de7..489606a7 100644 --- a/src/states_registers.jl +++ b/src/states_registers.jl @@ -26,7 +26,7 @@ struct Register # TODO better type description end function Register(traits, reprs, bg, sr, si, at) - env = ConcurrentSim.Simulation() + env = NetworkSimulation() Register(traits, reprs, bg, sr, si, at, [ConcurrentSim.Resource(env) for _ in traits], Dict{Int128, Tuple{Tag, Int64, Float64}}(), [], nothing) end Register(traits,reprs,bg,sr,si) = Register(traits,reprs,bg,sr,si,zeros(length(traits))) diff --git a/test/test_protocolzoo_entanglement_tracker.jl b/test/test_protocolzoo_entanglement_tracker.jl index 6656d35a..b602b208 100644 --- a/test/test_protocolzoo_entanglement_tracker.jl +++ b/test/test_protocolzoo_entanglement_tracker.jl @@ -21,7 +21,7 @@ end for i in 1:10 net = RegisterNet([Register(3), Register(4), Register(2), Register(3)]) - sim = get_time_tracker(net) + sim = get_time_tracker(net).sim entangler1 = EntanglerProt(sim, net, 1, 2; rounds=1) @@ -90,7 +90,7 @@ end for i in 1:30, n in 2:30 net = RegisterNet([Register(j+3) for j in 1:n]) - sim = get_time_tracker(net) + sim = get_time_tracker(net).sim for j in vertices(net) tracker = EntanglementTracker(sim, net, j) @process tracker() From 43e852cea48069207bff6b2beefefe946e084b0a Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 2 Jul 2024 13:21:36 -0400 Subject: [PATCH 2/3] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f2a335c..3495b7d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## v0.4.2 - dev +- Add a `NetworkSimulation` for accessing local entanglement id counter - Bump QuantumSymbolics compat bound and bump julia compat to 1.10. ## v0.4.1 - 2024-06-05 From 69d0b36a22d12640b8d53722b4275ce3aef3ad93 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 3 Jul 2024 11:46:15 -0400 Subject: [PATCH 3/3] updates --- Project.toml | 2 + src/ProtocolZoo/ProtocolZoo.jl | 2 +- src/QuantumSavory.jl | 2 +- src/concurrentsim.jl | 49 ++++++++++++------- test/test_protocolzoo_entanglement_tracker.jl | 4 +- 5 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Project.toml b/Project.toml index c6199d51..c5f978c5 100644 --- a/Project.toml +++ b/Project.toml @@ -7,6 +7,7 @@ version = "0.4.2-dev" Cbc = "9961bab8-2fa3-5c5a-9d89-47fab24efd76" Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" ConcurrentSim = "6ed1e86c-fcaf-46a9-97e0-2b26a2cdb499" +DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" @@ -38,6 +39,7 @@ QuantumSavoryMakie = "Makie" Cbc = "1.2" Combinatorics = "1" ConcurrentSim = "1.4.1" +DataStructures = "0.18.15" Distributions = "0.25.90" DocStringExtensions = "0.9" Graphs = "1.9" diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index f7c873a9..be367003 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -26,7 +26,7 @@ abstract type AbstractProtocol end get_time_tracker(prot::AbstractProtocol) = prot.sim -Process(prot::AbstractProtocol, args...; kwargs...) = Process((e,a...;k...)->prot(a...;k...), get_time_tracker(prot), args...; kwargs...) +Process(prot::AbstractProtocol, args...; kwargs...) = Process((e,a...;k...)->prot(a...;k...), get_time_tracker(prot).sim, args...; kwargs...) """ $TYPEDEF diff --git a/src/QuantumSavory.jl b/src/QuantumSavory.jl index e6173211..edebdef8 100644 --- a/src/QuantumSavory.jl +++ b/src/QuantumSavory.jl @@ -24,7 +24,7 @@ import SumTypes using SumTypes: @sum_type, isvariant, @cases import Combinatorics using Combinatorics: powerset - +import DataStructures import QuantumInterface: basis, tensor, ⊗, apply!, traceout!, nsubsystems, AbstractOperator, AbstractKet, AbstractSuperOperator, Basis, SpinBasis diff --git a/src/concurrentsim.jl b/src/concurrentsim.jl index 43d7ec76..d9e50cb9 100644 --- a/src/concurrentsim.jl +++ b/src/concurrentsim.jl @@ -77,22 +77,33 @@ function ConcurrentSim.now(env::NetworkSimulation) env.sim.time end -# function ConcurrentSim.BaseEvent(env::NetworkSimulation) -# ConcurrentSim.BaseEvent(env.sim, env.sim.eid+=one(UInt), Vector{Function}(), ConcurrentSim.idle, nothing) -# end - -# function ConcurrentSim.put!(con::ConcurrentSim.Container{N, T}, amount::N; priority=zero(T)) where {N<:Real, T<:Number} -# put_ev = ConcurrentSim.Put(con.env.sim) -# con.put_queue[put_ev] = ConcurrentSim.ContainerKey{N,T}(con.seid+=one(UInt), amount, T(priority)) -# ConcurrentSim.@callback ConcurrentSim.trigger_get(put_ev, con) -# ConcurrentSim.trigger_put(put_ev, con) -# put_ev -# end - -# function ConcurrentSim.get(con::ConcurrentSim.Container{N, T}, amount::N; priority=zero(T)) where {N<:Real, T<:Number} -# get_ev = ConcurrentSim.Get(con.env.sim) -# con.get_queue[get_ev] = ConcurrentSim.ContainerKey(con.seid+=one(UInt), amount, T(priority)) -# ConcurrentSim.@callback ConcurrentSim.trigger_put(get_ev, con) -# ConcurrentSim.trigger_get(get_ev, con) -# get_ev -# end \ No newline at end of file +function ConcurrentSim.put!(con::ConcurrentSim.Container{N, T}, amount::N; priority=zero(T)) where {N<:Real, T<:Number} + put_ev = ConcurrentSim.Put(con.env.sim) + con.put_queue[put_ev] = ConcurrentSim.ContainerKey{N,T}(con.seid+=one(UInt), amount, T(priority)) + ConcurrentSim.@callback ConcurrentSim.trigger_get(put_ev, con) + ConcurrentSim.trigger_put(put_ev, con) + put_ev +end + +function ConcurrentSim.get(con::ConcurrentSim.Container{N, T}, amount::N; priority=zero(T)) where {N<:Real, T<:Number} + get_ev = ConcurrentSim.Get(con.env.sim) + con.get_queue[get_ev] = ConcurrentSim.ContainerKey(con.seid+=one(UInt), amount, T(priority)) + ConcurrentSim.@callback ConcurrentSim.trigger_put(get_ev, con) + ConcurrentSim.trigger_get(get_ev, con) + get_ev +end + +function ConcurrentSim.timeout(env::Environment, delay::Number=0; priority=0, value::Any=nothing) + ConcurrentSim.schedule(ConcurrentSim.Timeout(env.sim), delay; priority=Int(priority), value) +end + +function ConcurrentSim.step(netsim::NetworkSimulation) + isempty(netsim.sim.heap) && throw(ConcurrentSim.EmptySchedule()) + (bev, key) = DataStructures.peek(netsim.sim.heap) + DataStructures.dequeue!(netsim.sim.heap) + netsim.sim.time = key.time + bev.state = ConcurrentSim.processed + for callback in bev.callbacks + callback() + end +end \ No newline at end of file diff --git a/test/test_protocolzoo_entanglement_tracker.jl b/test/test_protocolzoo_entanglement_tracker.jl index b602b208..6656d35a 100644 --- a/test/test_protocolzoo_entanglement_tracker.jl +++ b/test/test_protocolzoo_entanglement_tracker.jl @@ -21,7 +21,7 @@ end for i in 1:10 net = RegisterNet([Register(3), Register(4), Register(2), Register(3)]) - sim = get_time_tracker(net).sim + sim = get_time_tracker(net) entangler1 = EntanglerProt(sim, net, 1, 2; rounds=1) @@ -90,7 +90,7 @@ end for i in 1:30, n in 2:30 net = RegisterNet([Register(j+3) for j in 1:n]) - sim = get_time_tracker(net).sim + sim = get_time_tracker(net) for j in vertices(net) tracker = EntanglementTracker(sim, net, j) @process tracker()