From 242f8526731b3ec85484327c49c4c1fcd1b2ce06 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt <46929125+Abhishek-1Bhatt@users.noreply.github.com> Date: Tue, 21 May 2024 00:45:46 -0400 Subject: [PATCH] Store time of tagging (#114) --------- Co-authored-by: Stefan Krastanov --- Project.toml | 2 +- src/ProtocolZoo/ProtocolZoo.jl | 20 ++-- src/QuantumSavory.jl | 6 ++ src/queries.jl | 141 +++++++++++++------------ src/states_registers.jl | 5 +- test/test_doctests.jl | 2 +- test/test_entanglement_consumer.jl | 2 +- test/test_entanglement_tracker.jl | 20 ++-- test/test_entanglement_tracker_grid.jl | 30 +++--- test/test_tags_and_queries.jl | 119 ++++++++++++--------- 10 files changed, 188 insertions(+), 159 deletions(-) diff --git a/Project.toml b/Project.toml index b7513985..c6634834 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "QuantumSavory" uuid = "2de2e421-972c-4cb5-a0c3-999c85908079" authors = ["Stefan Krastanov "] -version = "0.3.4" +version = "0.4.0" [deps] Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index ff24c86d..3cb29d98 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -174,7 +174,7 @@ end margin = isentangled ? prot.margin : prot.hardmargin a = findfreeslot(prot.net[prot.nodeA]; randomize=prot.randomize, margin=margin) b = findfreeslot(prot.net[prot.nodeB]; randomize=prot.randomize, margin=margin) - + 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. \n Got:\n \t $a \n \t $b \n retrying..." @@ -253,16 +253,16 @@ end continue end - (q1, tag1) = qubit_pair[1].slot, qubit_pair[1].tag - (q2, tag2) = qubit_pair[2].slot, qubit_pair[2].tag + (q1, id1, tag1) = qubit_pair[1].slot, qubit_pair[1].id, qubit_pair[1].tag + (q2, id2, tag2) = qubit_pair[2].slot, qubit_pair[2].id, qubit_pair[2].tag @yield lock(q1) & lock(q2) # this should not really need a yield thanks to `findswapablequbits`, but it is better to be defensive @yield timeout(prot.sim, prot.local_busy_time) - untag!(q1, tag1) + untag!(q1, id1) # store a history of whom we were entangled to: remote_node_idx, remote_slot_idx, remote_swapnode_idx, remote_swapslot_idx, local_swap_idx tag!(q1, EntanglementHistory, tag1[2], tag1[3], tag2[2], tag2[3], q2.idx) - untag!(q2, tag2) + untag!(q2, id2) # store a history of whom we were entangled to: remote_node_idx, remote_slot_idx, remote_swapnode_idx, remote_swapslot_idx, local_swap_idx tag!(q2, EntanglementHistory, tag2[2], tag2[3], tag1[2], tag1[3], q1.idx) @@ -362,7 +362,7 @@ end ❓) # which local slot used to be entangled with whom we swapped with if !isnothing(history) # @debug "tracker @$(prot.node) history: $(history) | msg: $msg" - _, _, _, whoweswappedwith_node, whoweswappedwith_slotidx, swappedlocal_slotidx = history + _, _, _, whoweswappedwith_node, whoweswappedwith_slotidx, swappedlocal_slotidx = history.tag tag!(localslot, EntanglementHistory, newremotenode, newremoteslotid, whoweswappedwith_node, whoweswappedwith_slotidx, swappedlocal_slotidx) @debug "EntanglementTracker @$(prot.node): history=`$(history)` | message=`$msg` | Sending to $(whoweswappedwith_node).$(whoweswappedwith_slotidx)" msghist = Tag(updatetagsymbol, pastremotenode, pastremoteslotid, whoweswappedwith_slotidx, newremotenode, newremoteslotid, correction) @@ -423,14 +423,14 @@ end continue end end - - q1 = query1.slot + + q1 = query1.slot q2 = query2.slot @yield lock(q1) & lock(q2) @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): queries successful, consuming entanglement" - untag!(q1, query1.tag) - untag!(q2, query2.tag) + untag!(q1, query1.id) + untag!(q2, query2.id) # TODO do we need to add EntanglementHistory and should that be a different EntanglementHistory since the current one is specifically for SwapperProt # TODO currently when calculating the observable we assume that EntanglerProt.pairstate is always (|00⟩ + |11⟩)/√2, make it more general for other states ob1 = real(observable((q1, q2), Z⊗Z)) diff --git a/src/QuantumSavory.jl b/src/QuantumSavory.jl index b6928b1b..9fc95691 100644 --- a/src/QuantumSavory.jl +++ b/src/QuantumSavory.jl @@ -1,5 +1,11 @@ module QuantumSavory +const glcnt = Ref{Int128}(0) + +function guid() + glcnt[] += 1 +end + using Reexport using DocStringExtensions diff --git a/src/queries.jl b/src/queries.jl index 0e110e5d..44d2979e 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -2,28 +2,27 @@ Assign a tag to a slot in a register. -It returns the list of all currently present tags for that register. - See also: [`query`](@ref), [`untag!`](@ref)""" function tag!(ref::RegRef, tag::Tag) - push!(ref.reg.tags[ref.idx], tag) + id = guid() + push!(ref.reg.guids, id) + ref.reg.tag_info[id] = (tag, ref.idx, now(get_time_tracker(ref))) end -tag!(ref, tag) = tag!(ref, Tag(tag)) +tag!(ref, tag) = tag!(ref,Tag(tag)) """$TYPEDSIGNATURES Removes the first instance of tag from the list to tags associated with a [`RegRef`](@ref) in a [`Register`](@ref) -It returns the list of all currently present tags for that register. - See also: [`query`](@ref), [`tag!`](@ref) """ -function untag!(ref::RegRef, tag::Tag) # TODO rather slow implementation. See issue #74 - tags = ref.reg.tags[ref.idx] - i = findfirst(==(tag), tags) - isnothing(i) ? throw(KeyError(tag)) : deleteat!(tags, i) # TODO make sure there is a clear error message +function untag!(ref::RegRef, id::Int128) + i = findfirst(==(id), ref.reg.guids) + isnothing(i) ? throw(KeyError(tag)) : deleteat!(ref.reg.guids, i) # TODO make sure there is a clear error message + delete!(ref.reg.tag_info, id) + nothing end @@ -55,22 +54,22 @@ $TYPEDSIGNATURES A query function that returns all slots of a register that have a given tag, with support for predicates and wildcards. -```jldoctest +```jldoctest; filter = r"id = (\\d*), " julia> r = Register(10); tag!(r[1], :symbol, 2, 3); tag!(r[2], :symbol, 4, 5); julia> queryall(r, :symbol, ❓, ❓) -2-element Vector{@NamedTuple{slot::RegRef, depth::Int64, tag::Tag}}: - (slot = Slot 1, depth = 1, tag = SymbolIntInt(:symbol, 2, 3)::Tag) - (slot = Slot 2, depth = 1, tag = SymbolIntInt(:symbol, 4, 5)::Tag) +2-element Vector{@NamedTuple{slot::RegRef, id::Int128, tag::Tag}}: + (slot = Slot 2, id = 2, tag = SymbolIntInt(:symbol, 4, 5)::Tag) + (slot = Slot 1, id = 1, tag = SymbolIntInt(:symbol, 2, 3)::Tag) julia> queryall(r, :symbol, ❓, >(4)) -1-element Vector{@NamedTuple{slot::RegRef, depth::Int64, tag::Tag}}: - (slot = Slot 2, depth = 1, tag = SymbolIntInt(:symbol, 4, 5)::Tag) +1-element Vector{@NamedTuple{slot::RegRef, id::Int128, tag::Tag}}: + (slot = Slot 2, id = 2, tag = SymbolIntInt(:symbol, 4, 5)::Tag) julia> queryall(r, :symbol, ❓, >(5)) -@NamedTuple{slot::RegRef, depth::Int64, tag::Tag}[] +@NamedTuple{slot::RegRef, id::Int128, tag::Tag}[] ``` """ queryall(args...; filo=true, kwargs...) = query(args..., Val{true}(); filo, kwargs...) @@ -88,14 +87,14 @@ whether the given slot is locked or whether it contains a quantum state. The keyword argument `filo` can be used to specify whether the search should be done in a FIFO or FILO order, defaulting to `filo=true` (i.e. a stack-like behavior). -```jldoctest +```jldoctest; filter = r"id = (\\d*), " julia> r = Register(10); tag!(r[1], :symbol, 2, 3); tag!(r[2], :symbol, 4, 5); julia> query(r, :symbol, 4, 5) -(slot = Slot 2, depth = 1, tag = SymbolIntInt(:symbol, 4, 5)::Tag) +(slot = Slot 2, id = 4, tag = SymbolIntInt(:symbol, 4, 5)::Tag) julia> lock(r[1]); @@ -103,7 +102,7 @@ julia> query(r, :symbol, 4, 5; locked=false) |> isnothing false julia> query(r, :symbol, ❓, 3) -(slot = Slot 1, depth = 1, tag = SymbolIntInt(:symbol, 2, 3)::Tag) +(slot = Slot 1, id = 3, tag = SymbolIntInt(:symbol, 2, 3)::Tag) julia> query(r, :symbol, ❓, 3; assigned=true) |> isnothing true @@ -120,7 +119,7 @@ julia> query(r, Int, 4, >(7)) |> isnothing true julia> query(r, Int, 4, <(7)) -(slot = Slot 5, depth = 1, tag = TypeIntInt(Int64, 4, 5)::Tag) +(slot = Slot 5, id = 5, tag = TypeIntInt(Int64, 4, 5)::Tag) ``` See also: [`queryall`](@ref), [`tag!`](@ref), [`W`](@ref), [`❓`](@ref) @@ -129,12 +128,14 @@ function query(reg::Register, tag::Tag, ::Val{allB}=Val{false}(); locked::Union{ _query(reg, tag, Val{allB}(), Val{filo}(); locked=locked, assigned=assigned) end -function _query(reg::Register, tag::Tag, ::Val{allB}=Val{false}(), ::Val{filoB}=Val{true}(); locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing) where {allB, filoB} - result = NamedTuple{(:slot, :depth, :tag), Tuple{RegRef, Int, Tag}}[] - for i in 1:length(reg) - if _nothingor(locked, islocked(reg[i])) && _nothingor(assigned, isassigned(reg[i])) - for res in _query(reg[i], tag, Val{true}(), Val{filoB}()) - allB ? push!(result, (slot=reg[i],res...)) : return (slot=reg[i],res...) +function _query(reg::Register, tag::Tag, ::Val{allB}=Val{false}(), ::Val{filoB}=Val{true}(); locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, ref=nothing) where {allB, filoB} + result = NamedTuple{(:slot, :id, :tag), Tuple{RegRef, Int128, Tag}}[] + op_guid = filoB ? reverse : identity + for i in op_guid(reg.guids) + slot = reg[reg.tag_info[i][2]] + if reg.tag_info[i][1] == tag && _nothingor(ref, slot) # Need to check slot when calling from `query` dispatch on RegRef + if _nothingor(locked, islocked(slot) && _nothingor(assigned, isassigned(slot))) + allB ? push!(result, (slot=slot, id=i, tag=reg.tag_info[i][1])) : return (slot=slot, id=i, tag=reg.tag_info[i][1]) end end end @@ -147,36 +148,24 @@ $TYPEDSIGNATURES A [`query`](@ref) on a single slot of a register. -```jldoctest +```jldoctest; filter = r"id = (\\d*), " julia> r = Register(5); julia> tag!(r[2], :symbol, 2, 3); julia> query(r[2], :symbol, 2, 3) -(depth = 1, tag = SymbolIntInt(:symbol, 2, 3)::Tag) +(slot = Slot 2, id = 6, tag = SymbolIntInt(:symbol, 2, 3)::Tag) julia> query(r[3], :symbol, 2, 3) === nothing true julia> queryall(r[2], :symbol, 2, 3) -1-element Vector{@NamedTuple{depth::Int64, tag::Tag}}: - (depth = 1, tag = SymbolIntInt(:symbol, 2, 3)::Tag) +1-element Vector{@NamedTuple{slot::RegRef, id::Int128, tag::Tag}}: + (slot = Slot 2, id = 6, tag = SymbolIntInt(:symbol, 2, 3)::Tag) ``` """ -function query(ref::RegRef, tag::Tag, ::Val{allB}=Val{false}(); filo::Bool=true) where {allB} # TODO this should support locked and assigned like query(::Register) - _query(ref, tag, Val{allB}(), Val{filo}()) -end - -function _query(ref::RegRef, tag::Tag, ::Val{allB}=Val{false}(), ::Val{filoB}=Val{true}()) where {allB, filoB} # TODO there is a lot of code duplication here - if allB - i = findall(==(tag), ref.reg.tags[ref.idx]) - i = filoB ? reverse(i) : i - return NamedTuple{(:depth, :tag), Tuple{Int, Tag}}[(depth=i, tag=tag) for i in i] - else - find = filoB ? findlast : findfirst - i = find(==(tag), ref.reg.tags[ref.idx]) - return isnothing(i) ? nothing : (;depth=i, tag=tag) - end +function query(ref::RegRef, tag::Tag, ::Val{allB}=Val{false}(); locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, filo::Bool=true) where {allB} + _query(ref.reg, tag, Val{allB}(), Val{filo}(); locked=locked, assigned=assigned, ref=ref) end @@ -272,17 +261,34 @@ function querydelete!(mb::MessageBuffer, args...) return isnothing(r) ? nothing : popat!(mb.buffer, r.depth) end - - """ $TYPEDSIGNATURES -A [`query`](@ref) for [`RegRef`](@ref) that also deletes the tag from the tag list for the `RegRef`. -Allows the user to specify order of accessing tags to be FILO or FIFO. +A [`query`](@ref) for [`Register`](@ref) or a register slot (i.e. a [`RegRef`](@ref)) that also deletes the tag. + +```jldoctest; filter = r"id = (\\d*), " +julia> reg = Register(3) + tag!(reg[1], :tagA, 1, 2, 3) + tag!(reg[2], :tagA, 10, 20, 30) + tag!(reg[2], :tagB, 6, 7, 8); + +julia> queryall(reg, :tagA, ❓, ❓, ❓) +2-element Vector{@NamedTuple{slot::RegRef, id::Int128, tag::Tag}}: + (slot = Slot 2, id = 4, tag = SymbolIntIntInt(:tagA, 10, 20, 30)::Tag) + (slot = Slot 1, id = 3, tag = SymbolIntIntInt(:tagA, 1, 2, 3)::Tag) + +julia> querydelete!(reg, :tagA, ❓, ❓, ❓) +(slot = Slot 2, id = 4, tag = SymbolIntIntInt(:tagA, 10, 20, 30)::Tag) + +julia> queryall(reg, :tagA, ❓, ❓, ❓) +1-element Vector{@NamedTuple{slot::RegRef, id::Int128, tag::Tag}}: + (slot = Slot 1, id = 3, tag = SymbolIntIntInt(:tagA, 1, 2, 3)::Tag) +``` """ -function querydelete!(ref::RegRef, args...; filo::Bool=true) # TODO there is a lot of code duplication here - r = query(ref, args...; filo) - return isnothing(r) ? nothing : popat!(ref.reg.tags[ref.idx], r.depth) +function querydelete!(reg::Union{Register,RegRef}, args...; kwa...) + r = query(reg, args..., Val{false}(); kwa...) + isnothing(r) || untag!(r.slot, r.id) + return r end @@ -323,16 +329,15 @@ for (tagsymbol, tagvariant) in pairs(tag_types) wild_checks = [:(isa($(args[i]),Wildcard) || $(args[i])(tag[$i])) for i in idx] nonwild_checks = [:(tag[$i]==$(args[i])) for i in complement_idx] newmethod_reg = quote function query(reg::Register, $(argssig_wild...), ::Val{allB}=Val{false}(); locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, filo::Bool=true) where {allB} - res = NamedTuple{(:slot, :depth, :tag), Tuple{RegRef, Int, Tag}}[] - for (reg_idx, tags) in enumerate(reg.tags) - slot = reg[reg_idx] - for depth in (filo ? reverse(keys(tags)) : keys(tags)) - tag = tags[depth] - if isvariant(tag, ($(tagsymbol,))[1]) # a weird workaround for interpolating a symbol as a symbol - (_nothingor(locked, islocked(slot)) && _nothingor(assigned, isassigned(slot))) || continue - if _all($(nonwild_checks...)) && _all($(wild_checks...)) - allB ? push!(res, (;slot, depth, tag)) : return (;slot, depth, tag) - end + res = NamedTuple{(:slot, :id, :tag), Tuple{RegRef, Int128, Tag}}[] + op_guid = filo ? reverse : identity + for i in op_guid(reg.guids) + tag = reg.tag_info[i][1] + slot = reg[reg.tag_info[i][2]] + if isvariant(tag, ($(tagsymbol,))[1]) # a weird workaround for interpolating a symbol as a symbol + (_nothingor(locked, islocked(slot)) && _nothingor(assigned, isassigned(slot))) || continue + if _all($(nonwild_checks...)) && _all($(wild_checks...)) + allB ? push!(res, (slot=slot, id=i, tag=tag)) : return (slot=slot, id=i, tag=tag) end end end @@ -348,13 +353,13 @@ for (tagsymbol, tagvariant) in pairs(tag_types) end end end newmethod_rr = quote function query(ref::RegRef, $(argssig_wild...), ::Val{allB}=Val{false}(); filo::Bool=true) where {allB} - res = NamedTuple{(:depth, :tag), Tuple{Int, Tag}}[] - tags = ref.reg.tags[ref.idx] - for depth in (filo ? reverse(keys(tags)) : keys(tags)) - tag = tags[depth] + res = NamedTuple{(:slot, :id, :tag), Tuple{RegRef, Int128, Tag}}[] + op_guid = filo ? reverse : identity + for i in op_guid(ref.reg.guids) + tag = ref.reg.tag_info[i][1] if isvariant(tag, ($(tagsymbol,))[1]) # a weird workaround for interpolating a symbol as a symbol - if _all($(nonwild_checks...)) && _all($(wild_checks...)) - allB ? push!(res, (;depth, tag)) : return (;depth, tag) + if _all($(nonwild_checks...)) && _all($(wild_checks...)) && (ref.reg[ref.reg.tag_info[i][2]] == ref) + allB ? push!(res, (slot=ref, id=i, tag=tag)) : return (slot=ref, id=i, tag=tag) end end end diff --git a/src/states_registers.jl b/src/states_registers.jl index e5aabe8b..0d721f5a 100644 --- a/src/states_registers.jl +++ b/src/states_registers.jl @@ -20,12 +20,13 @@ struct Register # TODO better type description stateindices::Vector{Int} accesstimes::Vector{Float64} # TODO do not hardcode the type locks::Vector{Any} - tags::Vector{Vector{Tag}} # TODO this is a rather inefficient way to store tags, but at least it provides a FIFO ordering; see issue #74 + tag_info::Dict{Int128, Tuple{Tag, Int64, Union{Float64, Nothing}}} + guids::Vector{Int128} end function Register(traits, reprs, bg, sr, si, at) env = ConcurrentSim.Simulation() - Register(traits, reprs, bg, sr, si, at, [ConcurrentSim.Resource(env) for _ in traits], [Vector{Tag}() for _ in traits]) + Register(traits, reprs, bg, sr, si, at, [ConcurrentSim.Resource(env) for _ in traits], Dict{Int128, Tuple{Tag, Int64, Float64}}(), []) end Register(traits,reprs,bg,sr,si) = Register(traits,reprs,bg,sr,si,zeros(length(traits))) Register(traits,reprs,bg) = Register(traits,reprs,bg,fill(nothing,length(traits)),zeros(Int,length(traits)),zeros(length(traits))) diff --git a/test/test_doctests.jl b/test/test_doctests.jl index 3c60f88c..3f1ee2f3 100644 --- a/test/test_doctests.jl +++ b/test/test_doctests.jl @@ -4,7 +4,7 @@ using QuantumSavory function doctests() @testset "Doctests" begin - DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory; using QuantumSavory.CircuitZoo; using Graphs); recursive=true) + DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory; using QuantumSavory.CircuitZoo; using QuantumSavory.ProtocolZoo; using QuantumSavory.StatesZoo; using Graphs); recursive=true) doctest(QuantumSavory; #fix=true ) diff --git a/test/test_entanglement_consumer.jl b/test/test_entanglement_consumer.jl index 1dc7b5e0..4581bc68 100644 --- a/test/test_entanglement_consumer.jl +++ b/test/test_entanglement_consumer.jl @@ -12,7 +12,7 @@ if isinteractive() end -for i in 1:30, n in 3:30 +for n in 3:30 net = RegisterNet([Register(10) for j in 1:n]) sim = get_time_tracker(net) diff --git a/test/test_entanglement_tracker.jl b/test/test_entanglement_tracker.jl index b75ac758..afc42307 100644 --- a/test/test_entanglement_tracker.jl +++ b/test/test_entanglement_tracker.jl @@ -28,8 +28,7 @@ for i in 1:10 @process entangler1() run(sim, 20) - @test net[1].tags == [[Tag(EntanglementCounterpart, 2, 1)],[],[]] - + @test [net[1].tag_info[i][1] for i in net[1].guids] == [Tag(EntanglementCounterpart, 2, 1)] entangler2 = EntanglerProt(sim, net, 2, 3; rounds=1) @process entangler2() @@ -38,10 +37,10 @@ for i in 1:10 @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)],[],[]] + @test [net[1].tag_info[i][1] for i in net[1].guids] == [Tag(EntanglementCounterpart, 2, 1)] + @test [net[2].tag_info[i][1] for i in net[2].guids] == [Tag(EntanglementCounterpart, 1, 1), Tag(EntanglementCounterpart, 3, 1)] + @test [net[3].tag_info[i][1] for i in net[3].guids] == [Tag(EntanglementCounterpart, 2, 2), Tag(EntanglementCounterpart, 4, 1)] + @test [net[4].tag_info[i][1] for i in net[4].guids] == [Tag(EntanglementCounterpart, 3, 2)] @test [islocked(ref) for i in vertices(net) for ref in net[i]] |> any == false @@ -53,10 +52,10 @@ for i in 1:10 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)],[],[]] + @test [net[1].tag_info[i][1] for i in net[1].guids] == [Tag(EntanglementCounterpart, 2, 1)] + @test [net[2].tag_info[i][1] for i in net[2].guids] == [Tag(EntanglementHistory, 1, 1, 3, 1, 2),Tag(EntanglementHistory, 3, 1, 1, 1, 1)] + @test [net[3].tag_info[i][1] for i in net[3].guids] == [Tag(EntanglementHistory, 2, 2, 4, 1, 2), Tag(EntanglementHistory, 4, 1, 2, 2, 1)] + @test [net[4].tag_info[i][1] for i in net[4].guids] == [Tag(EntanglementCounterpart, 3, 2)] @test isassigned(net[1][1]) && isassigned(net[4][1]) @test !isassigned(net[2][1]) && !isassigned(net[3][1]) @@ -90,7 +89,6 @@ end # same but this time with an entanglement tracker 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) for j in vertices(net) diff --git a/test/test_entanglement_tracker_grid.jl b/test/test_entanglement_tracker_grid.jl index 2bb9969f..a21977b0 100644 --- a/test/test_entanglement_tracker_grid.jl +++ b/test/test_entanglement_tracker_grid.jl @@ -73,7 +73,7 @@ for path in paths @process entangler1() run(sim, 20) - @test net[1].tags == [[Tag(EntanglementCounterpart, path[1], 1)],[],[]] + @test [net[1].tag_info[i][1] for i in net[1].guids] == [Tag(EntanglementCounterpart, path[1], 1)] # For no particular reason we are starting the entangler protocols at different times @@ -94,13 +94,13 @@ for path in paths @process entangler6() run(sim, 120) - @test net[1].tags == [[Tag(EntanglementCounterpart, path[1], 1)],[],[]] - @test net[path[1]].tags == [[Tag(EntanglementCounterpart, 1, 1)],[Tag(EntanglementCounterpart, path[2], 1)],[]] - @test net[path[2]].tags == [[Tag(EntanglementCounterpart, path[1], 2)],[Tag(EntanglementCounterpart, path[3], 1)], []] - @test net[path[3]].tags == [[Tag(EntanglementCounterpart, path[2], 2)],[Tag(EntanglementCounterpart, path[4], 1)], []] - @test net[path[4]].tags == [[Tag(EntanglementCounterpart, path[3], 2)],[Tag(EntanglementCounterpart, path[5], 1)], []] - @test net[path[5]].tags == [[Tag(EntanglementCounterpart, path[4], 2)],[Tag(EntanglementCounterpart, 16, 1)], []] - @test net[16].tags == [[Tag(EntanglementCounterpart, path[5], 2)],[],[]] + @test [net[1].tag_info[i][1] for i in net[1].guids] == [Tag(EntanglementCounterpart, path[1], 1)] + @test [net[path[1]].tag_info[i][1] for i in net[path[1]].guids] == [Tag(EntanglementCounterpart, 1, 1), Tag(EntanglementCounterpart, path[2], 1)] + @test [net[path[2]].tag_info[i][1] for i in net[path[2]].guids] == [Tag(EntanglementCounterpart, path[1], 2), Tag(EntanglementCounterpart, path[3], 1)] + @test [net[path[3]].tag_info[i][1] for i in net[path[3]].guids] == [Tag(EntanglementCounterpart, path[2], 2), Tag(EntanglementCounterpart, path[4], 1)] + @test [net[path[4]].tag_info[i][1] for i in net[path[4]].guids] == [Tag(EntanglementCounterpart, path[3], 2), Tag(EntanglementCounterpart, path[5], 1)] + @test [net[path[5]].tag_info[i][1] for i in net[path[5]].guids] == [Tag(EntanglementCounterpart, path[4], 2), Tag(EntanglementCounterpart, 16, 1)] + @test [net[16].tag_info[i][1] for i in net[16].guids] == [Tag(EntanglementCounterpart, path[5], 2)] @test [islocked(ref) for i in vertices(net) for ref in net[i]] |> any == false @@ -115,13 +115,13 @@ for path in paths run(sim, 200) # In the absence of an entanglement tracker the tags will not all be updated - @test net[1].tags == [[Tag(EntanglementCounterpart, path[1], 1)],[],[]] - @test net[path[1]].tags == [[Tag(EntanglementHistory, 1, 1, path[2], 1, 2)],[Tag(EntanglementHistory, path[2], 1, 1, 1, 1)],[]] - @test net[path[2]].tags == [[Tag(EntanglementHistory, path[1], 2, path[3], 1, 2)],[Tag(EntanglementHistory, path[3], 1, path[1], 2, 1)], []] - @test net[path[3]].tags == [[Tag(EntanglementHistory, path[2], 2, path[4], 1, 2)],[Tag(EntanglementHistory, path[4], 1, path[2], 2, 1)], []] - @test net[path[4]].tags == [[Tag(EntanglementHistory, path[3], 2, path[5], 1, 2)],[Tag(EntanglementHistory, path[5], 1, path[3], 2, 1)], []] - @test net[path[5]].tags == [[Tag(EntanglementHistory, path[4], 2, 16, 1, 2)],[Tag(EntanglementHistory, 16, 1, path[4], 2, 1)], []] - @test net[16].tags == [[Tag(EntanglementCounterpart, path[5], 2)],[],[]] + @test [net[1].tag_info[i][1] for i in net[1].guids] == [Tag(EntanglementCounterpart, path[1], 1)] + @test [net[path[1]].tag_info[i][1] for i in net[path[1]].guids] == [Tag(EntanglementHistory, 1, 1, path[2], 1, 2), Tag(EntanglementHistory, path[2], 1, 1, 1, 1)] + @test [net[path[2]].tag_info[i][1] for i in net[path[2]].guids] == [Tag(EntanglementHistory, path[1], 2, path[3], 1, 2), Tag(EntanglementHistory, path[3], 1, path[1], 2, 1)] + @test [net[path[3]].tag_info[i][1] for i in net[path[3]].guids] == [Tag(EntanglementHistory, path[2], 2, path[4], 1, 2), Tag(EntanglementHistory, path[4], 1, path[2], 2, 1)] + @test [net[path[4]].tag_info[i][1] for i in net[path[4]].guids] == [Tag(EntanglementHistory, path[3], 2, path[5], 1, 2), Tag(EntanglementHistory, path[5], 1, path[3], 2, 1)] + @test [net[path[5]].tag_info[i][1] for i in net[path[5]].guids] == [Tag(EntanglementHistory, path[4], 2, 16, 1, 2), Tag(EntanglementHistory, 16, 1, path[4], 2, 1)] + @test [net[16].tag_info[i][1] for i in net[16].guids] == [Tag(EntanglementCounterpart, path[5], 2)] @test isassigned(net[1][1]) && isassigned(net[16][1]) @test !isassigned(net[path[1]][1]) && !isassigned(net[path[2]][1]) diff --git a/test/test_tags_and_queries.jl b/test/test_tags_and_queries.jl index f83168f2..d0fcc91d 100644 --- a/test/test_tags_and_queries.jl +++ b/test/test_tags_and_queries.jl @@ -5,69 +5,80 @@ using Test @test tag_types.SymbolIntInt(:symbol1, 4, 5) == Tag(:symbol1, 4, 5) +function strip_id(query_result) + return (;slot=query_result.slot, tag=query_result.tag) +end + +strip_id(::Nothing) = nothing + r = Register(10) tag!(r[1], :symbol1, 2, 3) tag!(r[2], :symbol1, 4, 5) +tag!(r[3], :symbol1, 4, 1) tag!(r[5], Int, 4, 5) @test Tag(:symbol1, 2, 3) == tag_types.SymbolIntInt(:symbol1, 2, 3) -@test query(r, :symbol1, 4, ❓) == (slot=r[2], depth=1, tag=tag_types.SymbolIntInt(:symbol1, 4, 5)) -@test query(r, :symbol1, 4, 5) == (slot=r[2], depth=1, tag=tag_types.SymbolIntInt(:symbol1, 4, 5)) -@test query(r, :symbol1, ❓, ❓) == (slot=r[1], depth=1, tag=tag_types.SymbolIntInt(:symbol1, 2, 3)) +@test strip_id(query(r, :symbol1, 4, ❓)) == (slot=r[3], tag=tag_types.SymbolIntInt(:symbol1, 4, 1)) +@test strip_id(query(r, :symbol1, 4, 5)) == (slot=r[2], tag=tag_types.SymbolIntInt(:symbol1, 4, 5)) +@test strip_id(query(r, :symbol1, ❓, ❓)) == (slot=r[3], tag=tag_types.SymbolIntInt(:symbol1, 4, 1)) #returns latest tag in filo order @test query(r, :symbol2, ❓, ❓) == nothing -@test query(r, Int, 4, 5) == (slot=r[5], depth=1, tag=tag_types.TypeIntInt(Int, 4, 5)) +@test strip_id(query(r, Int, 4, 5)) == (slot=r[5], tag=tag_types.TypeIntInt(Int, 4, 5)) @test query(r, Float32, 4, 5) == nothing @test query(r, Int, 4, >(5)) == nothing -@test query(r, Int, 4, <(6)) == (slot=r[5], depth=1, tag=tag_types.TypeIntInt(Int, 4, 5)) +@test strip_id(query(r, Int, 4, <(6))) == (slot=r[5], tag=tag_types.TypeIntInt(Int, 4, 5)) -@test queryall(r, :symbol1, ❓, ❓) == [(slot=r[1], depth=1, tag=tag_types.SymbolIntInt(:symbol1, 2, 3)), (slot=r[2], depth=1, tag=tag_types.SymbolIntInt(:symbol1, 4, 5))] +@test strip_id.(queryall(r, :symbol1, ❓, ❓)) == [(slot=r[3], tag=Tag(:symbol1, 4, 1)), (slot=r[2], tag=Tag(:symbol1, 4, 5)), (slot=r[1], tag=Tag(:symbol1, 2, 3))] # filo by default @test isempty(queryall(r, :symbol2, ❓, ❓)) -@test query(r[2], Tag(:symbol1, 4, 5)) == (depth=1, tag=Tag(:symbol1, 4, 5)) -@test queryall(r[2], Tag(:symbol1, 4, 5)) == [(depth=1, tag=Tag(:symbol1, 4, 5))] -@test query(r[2], :symbol1, 4, 5) == (depth=1, tag=Tag(:symbol1, 4, 5)) -@test queryall(r[2], :symbol1, 4, 5) == [(depth=1, tag=Tag(:symbol1, 4, 5))] +@test strip_id(query(r[2], Tag(:symbol1, 4, 5))) == (slot=r[2], tag=Tag(:symbol1, 4, 5)) +@test strip_id.(queryall(r[2], Tag(:symbol1, 4, 5))) == [(slot=r[2], tag=Tag(:symbol1, 4, 5))] +@test strip_id(query(r[2], :symbol1, 4, 5)) == (slot=r[2], tag=Tag(:symbol1, 4, 5)) +@test strip_id.(queryall(r[2], :symbol1, 4, 5)) == [(slot=r[2], tag=Tag(:symbol1, 4, 5))] -@test query(r[2], :symbol1, 4, ❓) == (depth=1, tag=Tag(:symbol1, 4, 5)) -@test queryall(r[2], :symbol1, 4, ❓) == [(depth=1, tag=Tag(:symbol1, 4, 5))] +@test strip_id(query(r[2], :symbol1, 4, ❓)) == (slot=r[2], tag=Tag(:symbol1, 4, 5)) +@test strip_id.(queryall(r[2], :symbol1, 4, ❓)) == [(slot=r[2], tag=Tag(:symbol1, 4, 5))] -@test querydelete!(r[2], :symbol1, 4, ❓) == Tag(:symbol1, 4, 5) +@test strip_id(querydelete!(r[2], :symbol1, 4, ❓)) == (slot=r[2], tag=Tag(:symbol1, 4, 5)) @test querydelete!(r[2], :symbol1, 4, ❓) === nothing +@test strip_id(querydelete!(r[3], :symbol1, 4, ❓)) == (slot=r[3], tag=Tag(:symbol1, 4, 1)) - +## # tests for fifo and filo order queries (default is filo) # for RegRefs reg = Register(5) tag!(reg[3], EntanglementCounterpart, 1, 10) -tag!(reg[3], EntanglementCounterpart, 2, 20) +tag!(reg[3], EntanglementCounterpart, 2, 21) tag!(reg[3], EntanglementCounterpart, 3, 30) -tag!(reg[3], EntanglementCounterpart, 2, 20) +tag!(reg[3], EntanglementCounterpart, 2, 22) tag!(reg[3], EntanglementCounterpart, 1, 10) tag!(reg[3], EntanglementCounterpart, 6, 60) -tag!(reg[3], EntanglementCounterpart, 2, 20) +tag!(reg[3], EntanglementCounterpart, 2, 23) tag!(reg[3], EntanglementCounterpart, 1, 10) @test query(reg[3], EntanglementCounterpart, 1, 11) === nothing -@test query(reg[3], EntanglementCounterpart, 1, 10) == (depth = 8, tag = Tag(EntanglementCounterpart,1,10)) -@test query(reg[3], EntanglementCounterpart, 1, 10, Val(false); filo=false) == (depth = 1, tag = Tag(EntanglementCounterpart,1,10)) -@test query(reg[3], EntanglementCounterpart, 1, 10, Val(false); filo=true) == (depth = 8, tag = Tag(EntanglementCounterpart,1,10)) +@test strip_id(query(reg[3], EntanglementCounterpart, 1, 10)) == (slot = reg[3], tag = Tag(EntanglementCounterpart,1,10)) +@test strip_id(query(reg[3], EntanglementCounterpart, 1, 10, Val(false); filo=false)) == (slot = reg[3], tag = Tag(EntanglementCounterpart,1,10)) +@test strip_id(query(reg[3], EntanglementCounterpart, 1, 10, Val(false); filo=true)) == (slot = reg[3], tag = Tag(EntanglementCounterpart,1,10)) +@test query(reg[3], EntanglementCounterpart, 1, 10; filo=true).id > query(reg[3], EntanglementCounterpart, 1, 10; filo=false).id +@test query(reg[3], EntanglementCounterpart, 2, ❓; filo=true).tag[3] == 23 +@test query(reg[3], EntanglementCounterpart, 2, ❓; filo=false).tag[3] == 21 -@test query(reg[3], EntanglementCounterpart, 2, ❓) == (depth = 7, tag = Tag(EntanglementCounterpart,2,20)) -@test query(reg[3], EntanglementCounterpart, 2, ❓, Val(false); filo=false) == (depth = 2, tag = Tag(EntanglementCounterpart,2,20)) -@test query(reg[3], EntanglementCounterpart, 2, ❓, Val(false); filo=true) == (depth = 7, tag = Tag(EntanglementCounterpart,2,20)) +@test strip_id(query(reg[3], EntanglementCounterpart, 2, ❓)) == (slot = reg[3], tag = Tag(EntanglementCounterpart,2,23)) +@test strip_id(query(reg[3], EntanglementCounterpart, 2, ❓, Val(false); filo=false)) == (slot = reg[3], tag = Tag(EntanglementCounterpart,2,21)) +@test strip_id(query(reg[3], EntanglementCounterpart, 2, ❓, Val(false); filo=true)) == (slot = reg[3], tag = Tag(EntanglementCounterpart,2,23)) @test queryall(reg, EntanglementCounterpart, 1, 11) == [] -@test queryall(reg[3], EntanglementCounterpart, 1, 10) == [(depth = d, tag = Tag(EntanglementCounterpart,1,10)) for d in (8,5,1)] -@test queryall(reg[3], EntanglementCounterpart, 1, 10; filo=false) == [(depth = d, tag = Tag(EntanglementCounterpart,1,10)) for d in (1,5,8)] -@test queryall(reg[3], EntanglementCounterpart, 1, 10; filo=true) == [(depth = d, tag = Tag(EntanglementCounterpart,1,10)) for d in (8,5,1)] - -@test queryall(reg[3], EntanglementCounterpart, 2, ❓) == [(depth = d, tag = Tag(EntanglementCounterpart,2,20)) for d in (7,4,2)] -@test queryall(reg[3], EntanglementCounterpart, 2, ❓; filo=false) == [(depth = d, tag = Tag(EntanglementCounterpart,2,20)) for d in (2,4,7)] -@test queryall(reg[3], EntanglementCounterpart, 2, ❓; filo=true) == [(depth = d, tag = Tag(EntanglementCounterpart,2,20)) for d in (7,4,2)] - +default_ids = [r.id for r in queryall(reg[3], EntanglementCounterpart, 1, 10)] +@test default_ids == sort(default_ids, rev=true) +fifo_ids = [r.id for r in queryall(reg[3], EntanglementCounterpart, 1, 10; filo=false)] +@test fifo_ids == sort(fifo_ids) +filo_ids = [r.id for r in queryall(reg[3], EntanglementCounterpart, 1, 10; filo=true)] +@test filo_ids == default_ids + +## # tests for fifo and filo order queries (default is filo) -# for RegRefs +# for Register reg = Register(5) for i in 2:4 @@ -82,26 +93,34 @@ for i in 2:4 end @test query(reg, EntanglementCounterpart, 1, 10) === nothing -@test query(reg, EntanglementCounterpart, 1, 12) == (slot = reg[2], depth = 1, tag = Tag(EntanglementCounterpart,1,12)) +@test strip_id(query(reg, EntanglementCounterpart, 1, 12)) == (slot = reg[2], tag = Tag(EntanglementCounterpart,1,12)) @test query(reg, EntanglementCounterpart, 1, 12) == query(reg, EntanglementCounterpart, ==(1), ==(12)) @test query(reg, Tag(EntanglementCounterpart, 1, 10)) === nothing -@test query(reg, Tag(EntanglementCounterpart, 1, 12)) == (slot = reg[2], depth = 1, tag = Tag(EntanglementCounterpart,1,12)) -@test query(reg, EntanglementCounterpart, 1, 12, Val(false); filo=false) == (slot = reg[2], depth = 1, tag = Tag(EntanglementCounterpart,1,12)) -@test query(reg, EntanglementCounterpart, 1, 12, Val(false); filo=true) == (slot = reg[2], depth = 1, tag = Tag(EntanglementCounterpart,1,12)) +@test strip_id(query(reg, Tag(EntanglementCounterpart, 1, 12))) == (slot = reg[2], tag = Tag(EntanglementCounterpart,1,12)) +@test strip_id(query(reg, EntanglementCounterpart, 1, 12, Val(false); filo=false)) == (slot = reg[2], tag = Tag(EntanglementCounterpart,1,12)) +@test strip_id(query(reg, EntanglementCounterpart, 1, 12, Val(false); filo=true)) == (slot = reg[2], tag = Tag(EntanglementCounterpart,1,12)) @test query(reg, EntanglementCounterpart, 1, 12, Val(false); filo=false) == query(reg, EntanglementCounterpart, 1, ==(12), Val(false); filo=false) @test query(reg, EntanglementCounterpart, 1, 12, Val(false); filo=true) == query(reg, EntanglementCounterpart, 1, ==(12), Val(false); filo=true) -@test query(reg, EntanglementCounterpart, 1, ❓, Val(false); filo=false) == (slot = reg[2], depth = 1, tag = Tag(EntanglementCounterpart,1,12)) -@test query(reg, EntanglementCounterpart, 1, ❓, Val(false); filo=true) == (slot = reg[2], depth = 8, tag = Tag(EntanglementCounterpart,1,312)) - -@test queryall(reg, EntanglementCounterpart, 1, ❓) == [(slot = reg[i], depth = d, tag = Tag(EntanglementCounterpart,1,j+i)) for i in 2:4 for (d,j) in ((8,310),(5,110),(1,10))] -@test queryall(reg, EntanglementCounterpart, 1, ❓; filo=true) == [(slot = reg[i], depth = d, tag = Tag(EntanglementCounterpart,1,j+i)) for i in 2:4 for (d,j) in ((8,310),(5,110),(1,10))] -@test queryall(reg, EntanglementCounterpart, 1, ❓; filo=false) == [(slot = reg[i], depth = d, tag = Tag(EntanglementCounterpart,1,j+i)) for i in 2:4 for (d,j) in reverse(((8,310),(5,110),(1,10)))] - -@test query(reg, EntanglementCounterpart, 2, 22) == (slot = reg[2], depth = 7, tag = Tag(EntanglementCounterpart,2,22)) -@test queryall(reg, EntanglementCounterpart, 2, 22) == [(slot = reg[2], depth = 7, tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], depth = 2, tag = Tag(EntanglementCounterpart,2,22))] -@test queryall(reg, Tag(EntanglementCounterpart, 2, 22)) == [(slot = reg[2], depth = 7, tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], depth = 2, tag = Tag(EntanglementCounterpart,2,22))] +@test strip_id(query(reg, EntanglementCounterpart, 1, ❓, Val(false); filo=false)) == (slot = reg[2], tag = Tag(EntanglementCounterpart,1,12)) +@test strip_id(query(reg, EntanglementCounterpart, 1, ❓, Val(false); filo=true)) == (slot = reg[4], tag = Tag(EntanglementCounterpart,1,314)) + +default_res = queryall(reg, EntanglementCounterpart, 1, ❓) +default_res_id = [r.id for r in default_res] +@test strip_id.(default_res) == reverse([(slot = reg[i], tag = Tag(EntanglementCounterpart, 1, j+i)) for i in 2:4 for j in (10,110,310)]) +@test default_res_id == reverse(sort(default_res_id)) +filo_res = queryall(reg, EntanglementCounterpart, 1, ❓; filo=true) +filo_res_id = [r.id for r in filo_res] +@test strip_id.(filo_res) == strip_id.(default_res) +@test filo_res_id == default_res_id +fifo_res = queryall(reg, EntanglementCounterpart, 1, ❓; filo=false) +fifo_res_id = [r.id for r in fifo_res] +@test strip_id.(fifo_res) == reverse(strip_id.(default_res)) +@test fifo_res_id == sort(fifo_res_id) + +@test strip_id.(queryall(reg, EntanglementCounterpart, 2, 22)) == [(slot = reg[2], tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], tag = Tag(EntanglementCounterpart,2,22))] +@test strip_id.(queryall(reg, Tag(EntanglementCounterpart, 2, 22))) == [(slot = reg[2], tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], tag = Tag(EntanglementCounterpart,2,22))] @test queryall(reg, EntanglementCounterpart, 2, 22) == queryall(reg, EntanglementCounterpart, ==(2), ==(22)) == queryall(reg, Tag(EntanglementCounterpart, 2, 22)) -@test queryall(reg, Tag(EntanglementCounterpart, 2, 22); filo=false) == reverse([(slot = reg[2], depth = 7, tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], depth = 2, tag = Tag(EntanglementCounterpart,2,22))]) +@test strip_id.(queryall(reg, Tag(EntanglementCounterpart, 2, 22); filo=false)) == [(slot = reg[2], tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], tag = Tag(EntanglementCounterpart,2,22))] @test queryall(reg, EntanglementCounterpart, 2, 22; filo=false) == queryall(reg, EntanglementCounterpart, ==(2), ==(22); filo=false) == queryall(reg, Tag(EntanglementCounterpart, 2, 22); filo=false) reg = Register(4) @@ -112,8 +131,8 @@ tag!(reg[1], EntanglementCounterpart, 4, 9) tag!(reg[1], EntanglementCounterpart, 2, 3) tag!(reg[1], EntanglementCounterpart, 4, 9) -@test reg.tags[1] == [Tag(EntanglementCounterpart, 4, 9), Tag(EntanglementCounterpart, 5, 2), Tag(EntanglementCounterpart, 7, 7), Tag(EntanglementCounterpart, 4, 9), Tag(EntanglementCounterpart, 2, 3), Tag(EntanglementCounterpart, 4, 9)] +@test [reg.tag_info[i][1] for i in reg.guids] == [Tag(EntanglementCounterpart, 4, 9), Tag(EntanglementCounterpart, 5, 2), Tag(EntanglementCounterpart, 7, 7), Tag(EntanglementCounterpart, 4, 9), Tag(EntanglementCounterpart, 2, 3), Tag(EntanglementCounterpart, 4, 9)] querydelete!(reg[1], EntanglementCounterpart, 4, 9) -@test reg.tags[1] == [Tag(EntanglementCounterpart, 4, 9), Tag(EntanglementCounterpart, 5, 2), Tag(EntanglementCounterpart, 7, 7), Tag(EntanglementCounterpart, 4, 9), Tag(EntanglementCounterpart, 2, 3)] +@test [reg.tag_info[i][1] for i in reg.guids] == [Tag(EntanglementCounterpart, 4, 9), Tag(EntanglementCounterpart, 5, 2), Tag(EntanglementCounterpart, 7, 7), Tag(EntanglementCounterpart, 4, 9), Tag(EntanglementCounterpart, 2, 3)] querydelete!(reg[1], EntanglementCounterpart, 4, 9;filo=false) -@test reg.tags[1] == [Tag(EntanglementCounterpart, 5, 2), Tag(EntanglementCounterpart, 7, 7), Tag(EntanglementCounterpart, 4, 9), Tag(EntanglementCounterpart, 2, 3)] \ No newline at end of file +@test [reg.tag_info[i][1] for i in reg.guids] == [Tag(EntanglementCounterpart, 5, 2), Tag(EntanglementCounterpart, 7, 7), Tag(EntanglementCounterpart, 4, 9), Tag(EntanglementCounterpart, 2, 3)]